├── .gitignore ├── .gitmodules ├── Jamfile ├── Jamrules ├── LICENSE ├── README.md ├── TODO.txt ├── bal ├── Jamfile ├── arch │ ├── aarch64 │ │ ├── Config.jam │ │ └── Jamfile │ ├── amd64 │ │ ├── Config.jam │ │ └── Jamfile │ ├── arm │ │ ├── Config.jam │ │ └── Jamfile │ └── ia32 │ │ ├── Config.jam │ │ └── Jamfile ├── device │ ├── bus │ │ └── simple-bus │ │ │ ├── Jamfile │ │ │ └── simple-bus.c │ ├── dt │ │ ├── Jamfile │ │ ├── dt_device.c │ │ ├── dt_system.c │ │ └── dt_tree.c │ ├── fb │ │ ├── Jamfile │ │ └── fb.c │ └── uart │ │ ├── arm_pl011 │ │ ├── Jamfile │ │ └── arm_pl011.c │ │ └── ns16c550 │ │ ├── Jamfile │ │ └── ns16c550.c ├── fs │ └── iso9660 │ │ ├── Jamfile │ │ └── iso9660.c ├── gio.c ├── ioctl.txt ├── ioctl_stubs │ └── gd_ioctl_stub.S ├── mmap.c ├── panic.c ├── platform │ ├── atf │ │ ├── Config.jam │ │ ├── Jamfile │ │ ├── README.md │ │ ├── bal.ld │ │ ├── entry.S │ │ ├── kickstart │ │ │ ├── Jamfile │ │ │ ├── entry.S │ │ │ ├── io_semihosting.c │ │ │ ├── kickstart.c │ │ │ ├── kickstart.h │ │ │ ├── kickstart.ld │ │ │ └── pl011.c │ │ └── main.c │ ├── beaglebone │ │ ├── Config.jam │ │ ├── Jamfile │ │ └── test.c │ └── bios │ │ ├── Config.jam │ │ ├── Jamfile │ │ ├── bal32.ld │ │ ├── bal64.ld │ │ ├── bios_console.c │ │ ├── bios_services.c │ │ ├── device │ │ └── cdrom.c │ │ ├── docs │ │ └── low_mmap.txt │ │ ├── init.c │ │ ├── mmap.c │ │ ├── stage1 │ │ ├── Jamfile │ │ ├── a20.S │ │ ├── abort_boot.S │ │ ├── api.S │ │ ├── eltorito │ │ │ ├── link.ld │ │ │ └── storage.S │ │ ├── init.S │ │ ├── modeswitch.S │ │ ├── output.S │ │ ├── pxe │ │ │ ├── link.ld │ │ │ └── storage.S │ │ └── string.S │ │ ├── tables.c │ │ └── vbe.c ├── soc │ └── am33xx │ │ ├── Config.jam │ │ ├── Jamfile │ │ ├── am33xx.ld │ │ └── entry.S ├── syscall.txt └── syscall_stubs │ └── gd_syscall_stub.S ├── include ├── arch │ ├── aarch64 │ │ ├── aarch64.h │ │ ├── asm_macros.h │ │ └── bal │ │ │ └── gio_arch.h │ ├── arm │ │ └── bal │ │ │ └── gio_arch.h │ └── x86 │ │ └── bal │ │ ├── gio_arch.h │ │ └── portio.h ├── bal │ ├── device │ │ ├── bus.h │ │ ├── bus │ │ │ └── simple-bus.h │ │ ├── dt.h │ │ ├── fb.h │ │ ├── font_data.h │ │ ├── uart.h │ │ └── uart │ │ │ ├── arm_pl011.h │ │ │ └── ns16c550.h │ ├── fs │ │ └── iso9660.h │ ├── gio.h │ ├── gio_generic.h │ ├── misc.h │ └── mmap.h ├── gd_bal.h ├── gd_common.h ├── gd_elf.h ├── gd_queue.h ├── gd_tree.h └── platform │ └── bios │ ├── bal │ ├── bios_console.h │ ├── bios_services.h │ ├── mmap.h │ ├── tables.h │ └── vbe.h │ └── device │ └── cdrom.h ├── lib ├── Jamfile └── libfdt │ └── Jamfile ├── prepare.sh └── tools └── gd_stub_gen /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | *.flp 4 | *.iso 5 | 6 | # Text editor files. 7 | *.sublime-* 8 | 9 | # Kdevelop project files 10 | *.kdev* 11 | 12 | pdclib/ 13 | build/ 14 | 15 | .bochsrc 16 | bochsout.txt 17 | 18 | .DS_Store 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/lib9660"] 2 | path = lib/lib9660 3 | url = https://github.com/gdboot/lib9660.git 4 | [submodule "lib/elfload"] 5 | path = lib/elfload 6 | url = https://github.com/gdboot/elfload.git 7 | [submodule "lib/libfdt/dtc"] 8 | path = lib/libfdt/dtc 9 | url = git://git.kernel.org/pub/scm/utils/dtc/dtc.git 10 | -------------------------------------------------------------------------------- /Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP ; 2 | SubInclude PDCLIB_TOP ; 3 | SubIncludeOnce GD_TOP lib ; 4 | SubIncludeOnce GD_TOP bal ; 5 | -------------------------------------------------------------------------------- /Jamrules: -------------------------------------------------------------------------------- 1 | NOARSCAN = true ; 2 | ALL_LOCATE_TARGET ?= build ; 3 | 4 | ################################################################################ 5 | # Save the host toolset information 6 | 7 | HOST_TOOLSET = $(TOOLSET) ; 8 | HOST_AS = $(AS) ; 9 | HOST_AR = $(AR) ; 10 | HOST_CC = $(CC) ; 11 | HOST_CCFLAGS = $(CCFLAGS) ; 12 | HOST_C++ = $(C++) ; 13 | HOST_C++FLAGS = $(C++FLAGS) ; 14 | HOST_LINK = $(LINK) ; 15 | HOST_LINKFLAGS = $(LINKFLAGS) ; 16 | HOST_LINKLIBS = $(LINKLIBS) ; 17 | HOST_OPTIM = $(OPTIM) ; 18 | HOST_STDHDRS = $(STDHDRS) ; 19 | HOST_SUFEXE = $(SUFEXE) ; 20 | HOST_SUFLIB = $(SUFLIB) ; 21 | HOST_SUFOBJ = $(SUFOBJ) ; 22 | HOST_UNDEFFLAG = $(UNDEFFLAG) ; 23 | HOST_PICFLAGS = $(PICFLAG) ; 24 | 25 | ################################################################################ 26 | # Include a file only once 27 | 28 | rule SubIncludeOnce { 29 | if ! $($(1:J=__)_INCLUDED) { 30 | #ECHO Including $(1) ; 31 | SubInclude $(1) ; 32 | } else { 33 | #ECHO Not including $(1) ; 34 | } 35 | } 36 | 37 | # Set the flag that SubIncludeOnce uses 38 | rule _SubSetIncluded { 39 | #ECHO Included $(1) ; 40 | if ! $($(1:J=__)_INCLUDED) { 41 | $(1:J=__)_INCLUDED = 1 ; 42 | } 43 | } 44 | 45 | # Add the Gandr include dirs to headers 46 | rule _AddHeaders { 47 | PDCLibConfig ; 48 | SUBDIRHDRS += $(GD_INCLUDE_DIRS) ; 49 | } 50 | 51 | ################################################################################ 52 | # PDCLib 53 | 54 | PDCLIB_NO_TEST = 1 ; 55 | PDCLIB_PLATFORM = gandr ; 56 | 57 | ################################################################################ 58 | # Gandr special rules 59 | 60 | # Adds Bal source files 61 | rule GdBalSources { 62 | local _obj = $(1:S=$(SUFOBJ)) ; 63 | MakeLocate $(_obj) : $(LOCATE_TARGET) ; 64 | GD_BAL_OBJECTS += [ FGristFiles $(_obj) ] ; 65 | Objects $(1) ; 66 | ObjectHdrs $(1) : $(GD_INCLUDE_DIRS) ; 67 | } 68 | 69 | 70 | # Add an include dir (Config.jam) 71 | # GdIncludeDir $(GD_TOP) dir dir dir ; 72 | rule GdIncludeDir { 73 | GD_INCLUDE_DIRS += [ FDirName $(1) ] ; 74 | } 75 | 76 | GD_STUB_GEN = [ FDirName $(GD_TOP) tools gd_stub_gen ] ; 77 | # Parse the ioctl definition 78 | # GdIoctls lib : ; 79 | rule GdIoctls { 80 | local files = [ COMMAND $(GD_STUB_GEN) ioctl $(>) -stubdir ioctl_stubs -list ] ; 81 | files = [ FGristFiles $(files) ] ; 82 | ECHO ioctl files are $(files) ; 83 | 84 | GdIoctlGen $(files) gd_ioctl.h : $(>) : include/gd_ioctl.h : include/gd_ioctl_map.h : ioctl_stubs ; 85 | Library $(<) : $(files) ioctl_stubs/gd_ioctl_stub.S ; 86 | } 87 | 88 | # Internal 89 | # GdIoctlGen $(< stubs) : $(> input) : $(3 hdr) : $(4 map) $(5 dir) ; 90 | rule GdIoctlGen { 91 | ECHO $(<) from $(>) ; 92 | MakeLocate $(<) $(3) $(4) $(5) : $(LOCATE_TARGET) ; 93 | DEPENDS $(<) (3) $(4) $(5) : $(>) $(GD_STUB_GEN) ; 94 | DIR on $(<) = [ FDirName $(LOCATE_TARGET) $(5) ] ; 95 | MAP on $(<) = [ FDirName $(LOCATE_TARGET) $(4) ] ; 96 | HDR on $(<) = [ FDirName $(LOCATE_TARGET) $(3) ] ; 97 | } 98 | 99 | actions GdIoctlGen { 100 | $(GD_STUB_GEN) ioctl $(>) -stubdir $(DIR) -stubs -hdr $(HDR) -map $(MAP) 101 | } 102 | 103 | # Parse the syscall definition 104 | # GdIoctls lib : ; 105 | rule GdSyscalls { 106 | local files = [ COMMAND $(GD_STUB_GEN) syscall $(>) -stubdir syscall_stubs -list ] ; 107 | files = [ FGristFiles $(files) ] ; 108 | ECHO syscall files are $(files) ; 109 | 110 | GdSyscallGen $(files) gd_syscall.h gd_syscall.c : $(>) : include/gd_syscall.h : gd_syscall.c : syscall_stubs ; 111 | Library $(<) : $(files) syscall_stubs/gd_syscall_stub.S ; 112 | } 113 | 114 | # Internal 115 | # GdSyscallGen $(< outputs) : $(> input) : $(3 hdr) : $(4 dispatcher) $(5 dir) ; 116 | rule GdSyscallGen { 117 | ECHO $(<) from $(>) ; 118 | MakeLocate $(<) $(3) $(4) $(5) : $(LOCATE_TARGET) ; 119 | DEPENDS $(<) $(3) $(3:D=) $(4) $(5) : $(>) $(GD_STUB_GEN) ; 120 | DIR on $(<) = [ FDirName $(LOCATE_TARGET) $(5) ] ; 121 | DISP on $(<) = [ FDirName $(LOCATE_TARGET) $(4) ] ; 122 | HDR on $(<) = [ FDirName $(LOCATE_TARGET) $(3) ] ; 123 | } 124 | 125 | actions GdSyscallGen { 126 | $(GD_STUB_GEN) syscall $(>) -stubdir $(DIR) -stubs -hdr $(HDR) -dispatcher $(DISP) 127 | } 128 | 129 | ################################################################################ 130 | # Extra rules and toolchain functionality 131 | 132 | # Invoke objcopy 133 | # ObjCopy dest : src : opts ; 134 | rule ObjCopy { 135 | Depends $(<) : $(>) ; 136 | MakeLocate $(<) : $(LOCATE_TARGET) ; 137 | OPTS on $(<) = $(3) ; 138 | } 139 | 140 | actions ObjCopy { 141 | $(OBJCOPY) $(OPTS) $(>) $(<) 142 | } 143 | 144 | # Link using a linker script 145 | # LinkWithScript output : objects : script [: extraflags] ; 146 | rule LinkWithScript { 147 | # Can't use MainFromObjects as it regrists the files 148 | Depends $(<) : $(>) $(3) ; 149 | MakeLocate $(<) : $(LOCATE_TARGET) ; 150 | Clean clean : $(<) ; 151 | LINKFLAGS on $(<) += -T$(3) $(4) ; 152 | } 153 | 154 | # We also generate output useful for debugging 155 | actions LinkWithScript bind NEEDLIBS { 156 | $(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) --cref -Map $(<:S=.map.txt) 157 | $(OBJDUMP) -C -t $(<) > $(<:S=.syms.txt) 158 | $(OBJDUMP) -C -S $(<) > $(<:S=.sdsm.txt) 159 | $(OBJDUMP) -C -d $(<) > $(<:S=.dsm.txt) 160 | $(OBJCOPY) --only-keep-debug $(<) $(<:S=.gdb) 161 | $(STRIP) --strip-debug $(<) 162 | $(OBJCOPY) --add-gnu-debuglink=$(<:S=.gdb) $(<) 163 | } 164 | 165 | # Add support to Jam for .S preprocessed assembly files 166 | # Doesn't recognize S: preprocessed assembly file 167 | rule UserObject { 168 | switch $(>:S) { 169 | case .S : AsCpp $(<) : $(>) ; 170 | } 171 | } 172 | 173 | # Add support for preprocessed assembly 174 | rule AsCpp 175 | { 176 | Depends $(<) : $(>) ; 177 | 178 | ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ; 179 | 180 | CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; 181 | CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; 182 | } 183 | 184 | # Pass them to GCC 185 | actions AsCpp 186 | { 187 | $(CC) -c $(ASFLAGS) $(CCHDRS) $(CCDEFS) -o $(<) $(>) 188 | } 189 | 190 | ################################################################################ 191 | # Platform, SoC, architecture functionality 192 | 193 | # Determine the platform, soc, arch information 194 | # Do so in that order; platform can imply soc can imply arch 195 | 196 | # XXX These paths may need consideration once we have KL! 197 | 198 | GdIncludeDir $(ALL_LOCATE_TARGET) bal include ; 199 | GdIncludeDir $(GD_TOP) include ; 200 | 201 | if ! $(PLATFORM) { 202 | ECHO "Must specify a platform" ; 203 | EXIT ; 204 | } else { 205 | include [ FDirName $(GD_TOP) bal platform $(PLATFORM) Config.jam ] ; 206 | } 207 | 208 | # SoC specification is optional (e.g: i386-bios doesnt' need nor want one) 209 | if $(SOC) { 210 | include [ FDirName $(GD_TOP) bal soc $(SOC) Config.jam ] ; 211 | } 212 | 213 | if ! $(ARCH) { 214 | ECHO "Must specify an architecture " ; 215 | ECHO "Platform supports: " $(SUPPORTED_ARCHITECTURES:J=", ") ; 216 | EXIT ; 217 | } else if ! $(ARCH) in $(SUPPORTED_ARCHITECTURES) { 218 | ECHO "Architecture \"$(ARCH)\" not supported by $(PLATFORM)" ; 219 | ECHO "Supported architectures are: " $(SUPPORTED_ARCHITECTURES:J=", ") ; 220 | EXIT ; 221 | } else { 222 | include [ FDirName $(GD_TOP) bal arch $(ARCH) Config.jam ] ; 223 | } 224 | 225 | # All of our toolchains are GCC-alikes 226 | TOOLSET = gcc ; 227 | CCFLAGS += -ffreestanding -fbuiltin -g ; 228 | C++FLAGS += -ffreestanding -fbuiltin -g ; 229 | 230 | AS = $(TOOLPREFIX)gcc ; 231 | AR = $(TOOLPREFIX)ar cru ; 232 | CC = $(TOOLPREFIX)gcc ; 233 | OPTIM = -Os ; 234 | C++ = $(TOOLPREFIX)g++ ; 235 | LINK = $(TOOLPREFIX)ld ; 236 | STDHDRS = ; 237 | SUFEXE = ; 238 | SUFLIB = .a ; 239 | SUFOBJ = .o ; 240 | UNDEFFLAG = -U ; 241 | PICFLAGS = -fPIC ; 242 | OBJDUMP = $(TOOLPREFIX)objdump ; 243 | OBJCOPY = $(TOOLPREFIX)objcopy ; 244 | STRIP = $(TOOLPREFIX)strip ; 245 | RANLIB = $(TOOLPREFIX)ranlib ; 246 | 247 | # Find libgcc 248 | LIBGCC = [ COMMAND $(CC) $(CCFLAGS) $(OPTIM) $(CCDEFS) -print-libgcc-file-name ] ; 249 | 250 | ################################################################################ 251 | # Include the Jamrules files for our dependencies 252 | SubRules GD_TOP pdclib : PDCLIB_TOP ; 253 | 254 | 255 | # JamBase invokes all rules specified in SUBDIRRULES when a new subdir is 256 | # entered 257 | # 258 | # We deferred adding these till here else _AddHeaders gets invoked by the above 259 | # before PDClibConfig is defined 260 | SUBDIRRULES += _SubSetIncluded _AddHeaders ; 261 | 262 | ################################################################################ 263 | # Work around a bug in Jambase 264 | # XXX This should go into ejam 265 | 266 | # Fix to work on targets in subdirs 267 | rule MakeLocate 268 | { 269 | # Note we grist the directory name with 'dir', 270 | # so that directory path components and other 271 | # targets don't conflict. 272 | 273 | if $(>) 274 | { 275 | for file in $(<) { 276 | local _rev = [ FReverse $(>) ] ; 277 | if $(_rev[1]) = "." { 278 | _rev = $(_rev[2-]) ; 279 | } 280 | local _dir = [ FDirName [ FReverse $(_rev) ] $(file:D) ] ; 281 | 282 | LOCATE on $(file) = [ FDirName $(>) ] ; 283 | Depends $(<) : $(_dir:G=dir) ; 284 | MkDir $(_dir:G=dir) ; 285 | } 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | 3 | Copyright © 2013-2014, The Contributors 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 14 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 | PERFORMANCE OF THIS SOFTWARE. 16 | 17 | < Template for inclusion at the top of C-style source files: > 18 | 19 | /* Copyright © , 20 | * 21 | * Permission to use, copy, modify, and/or distribute this software for any 22 | * purpose with or without fee is hereby granted, provided that the above 23 | * copyright notice appear in all copies. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 26 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 27 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 28 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 29 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 30 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 31 | * PERFORMANCE OF THIS SOFTWARE. 32 | */ 33 | 34 | < Template for inclusion at the top of files with # comments: > 35 | # Copyright © , 36 | # 37 | # Permission to use, copy, modify, and/or distribute this software for any 38 | # purpose with or without fee is hereby granted, provided that the above 39 | # copyright notice appear in all copies. 40 | # 41 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 42 | # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 43 | # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 44 | # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 45 | # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 46 | # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 47 | # PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Gandr 2 | ======= 3 | 4 | Gandr is a cross-platform bootloader project, intended to fill in the gap of a utopic bootloader. 5 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | 0.1: 4 | * Gather boot device information in stage1. 5 | * Fix _PDCLib_allocpages. 6 | -> only allocate in low mem (?) 7 | -> add related type in memory map 8 | * Add proper abort in BAL. 9 | * Add support for "PXE" as boot device in BAL. 10 | * Gather necessary VBE and EDID information. 11 | * Support serial as fallback in case no VGA compatible device present. 12 | * Add mode switching support. 13 | * Add fbcon driver. 14 | * ELF loading. 15 | -------------------------------------------------------------------------------- /bal/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal ; 2 | 3 | GdIoctls libgdioctl.a : [ FDirName $(GD_TOP) bal ioctl.txt ] ; 4 | GdSyscalls libgdsyscall.a : [ FDirName $(GD_TOP) bal syscall.txt ] ; 5 | 6 | GdBalSources 7 | gio.c 8 | mmap.c 9 | panic.c 10 | ; 11 | 12 | 13 | # Include arch, soc, platform headers 14 | SubIncludeOnce GD_TOP bal arch $(ARCH) ; 15 | if $(SOC) { 16 | SubIncludeOnce GD_TOP bal soc $(SOC) ; 17 | } 18 | SubIncludeOnce GD_TOP bal platform $(PLATFORM) ; 19 | 20 | SubDir GD_TOP bal ; 21 | 22 | GdBalBinaries ; 23 | -------------------------------------------------------------------------------- /bal/arch/aarch64/Config.jam: -------------------------------------------------------------------------------- 1 | GdIncludeDir $(GD_TOP) include arch aarch64 ; 2 | 3 | TOOLPREFIX = aarch64-elf- ; 4 | 5 | -------------------------------------------------------------------------------- /bal/arch/aarch64/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal arch aarch64 ; 2 | -------------------------------------------------------------------------------- /bal/arch/amd64/Config.jam: -------------------------------------------------------------------------------- 1 | GdIncludeDir $(GD_TOP) include arch amd64 ; 2 | GdIncludeDir $(GD_TOP) include arch x86 ; 3 | 4 | TOOLPREFIX = x86_64-elf- ; 5 | 6 | ECHO amd64 ; 7 | -------------------------------------------------------------------------------- /bal/arch/amd64/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal arch amd64 ; 2 | -------------------------------------------------------------------------------- /bal/arch/arm/Config.jam: -------------------------------------------------------------------------------- 1 | GdIncludeDir $(GD_TOP) include arch arm ; 2 | 3 | TOOLPREFIX = arm-none-eabi- ; 4 | 5 | ECHO arm ; 6 | -------------------------------------------------------------------------------- /bal/arch/arm/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal arch arm ; 2 | -------------------------------------------------------------------------------- /bal/arch/ia32/Config.jam: -------------------------------------------------------------------------------- 1 | GdIncludeDir $(GD_TOP) include arch ia32 ; 2 | GdIncludeDir $(GD_TOP) include arch x86 ; 3 | 4 | TOOLPREFIX = i386-elf- ; 5 | 6 | ECHO ia32 ; 7 | -------------------------------------------------------------------------------- /bal/arch/ia32/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal arch ia32 ; 2 | -------------------------------------------------------------------------------- /bal/device/bus/simple-bus/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal device bus simple-bus ; 2 | 3 | GdBalSources simple-bus.c ; 4 | 5 | SubIncludeOnce GD_TOP bal device dt ; 6 | -------------------------------------------------------------------------------- /bal/device/bus/simple-bus/simple-bus.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | static int sb_bus_get_child_reg_addr( 24 | struct simple_bus_dev* self, 25 | gd_device_t child, 26 | unsigned idx, 27 | gio_addr *addr, 28 | size_t *len) 29 | { 30 | int rv = 0; 31 | dt_node_t node; 32 | 33 | if ((rv = gd_device_get_dt_node(child, &node))) 34 | return rv; 35 | 36 | uintptr_t base_addr; 37 | size_t base_size; 38 | 39 | if (dt_node_get_reg_range(node, idx, &base_addr, &base_size)) { 40 | *addr = GIO_MMIO_ADDR(base_addr); 41 | *len = base_size; 42 | 43 | return 0; 44 | } else { 45 | return ERANGE; 46 | } 47 | } 48 | 49 | static int sb_bus_get_child_reg_count( 50 | struct simple_bus_dev *self, 51 | gd_device_t child, 52 | unsigned *count) 53 | { 54 | int rv; 55 | dt_node_t node; 56 | if ((rv = gd_device_get_dt_node(child, &node))) 57 | return rv; 58 | 59 | *count = dt_node_get_reg_count(node); 60 | return 0; 61 | } 62 | 63 | 64 | static GD_BEGIN_IOCTL_MAP(struct simple_bus_dev *, simple_bus_ioctl) 65 | GD_MAP_BUS_GET_CHILD_REG_COUNT_IOCTL(sb_bus_get_child_reg_count) 66 | GD_MAP_BUS_GET_CHILD_REG_ADDR_IOCTL(sb_bus_get_child_reg_addr) 67 | GD_END_IOCTL_MAP_FORWARD_BASE(dt_base_ioctl) 68 | 69 | static gd_device_t sb_driver_attach( 70 | dt_node_t node) 71 | { 72 | struct simple_bus_dev *self = malloc(sizeof *self); 73 | if (!self) 74 | return NULL; 75 | self->ioctl = simple_bus_ioctl; 76 | self->node = node; 77 | 78 | unsigned addr_cells = dt_node_get_address_cells(node); 79 | unsigned size_cells = dt_node_get_size_cells(node); 80 | 81 | if (addr_cells < 1 || addr_cells > 2) { 82 | size_t needed; 83 | char path[256]; 84 | gd_device_get_path(self, path, 256, &needed); 85 | 86 | panic("simple-bus \"%s\" with %d address cells", 87 | path, addr_cells); 88 | } 89 | 90 | if (size_cells < 1 || size_cells > 2) { 91 | size_t needed; 92 | char path[256]; 93 | gd_device_get_path(self, path, 256, &needed); 94 | 95 | panic("simple-bus \"%s\" with %d size cells", 96 | path, size_cells); 97 | } 98 | 99 | return &self->dev; 100 | } 101 | 102 | DT_DECLARE_DEVICE_DRIVER(simple_bus_dt_dev, "simple-bus", sb_driver_attach) 103 | -------------------------------------------------------------------------------- /bal/device/dt/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal device dt ; 2 | GdBalSources 3 | dt_tree.c 4 | dt_device.c 5 | dt_system.c ; 6 | -------------------------------------------------------------------------------- /bal/device/dt/dt_device.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static int dt_device_get_name( 7 | gd_device_t dev, 8 | char * buf, 9 | size_t szBuf, 10 | size_t * szNeeded) 11 | { 12 | int rv = 0; 13 | dt_node_t node; 14 | if ((rv = gd_device_get_dt_node(dev, &node))) 15 | return rv; 16 | 17 | *szNeeded = strlcpy(buf, node->name, szBuf); 18 | return 0; 19 | } 20 | 21 | static int dt_device_get_parent( 22 | gd_device_t dev, 23 | gd_device_t *pparent) 24 | { 25 | int rv = 0; 26 | dt_node_t node; 27 | 28 | if ((rv = gd_device_get_dt_node(dev, &node))) 29 | return rv; 30 | 31 | if (node->parent) { 32 | *pparent = node->parent->bound_device; 33 | return 0; 34 | } else { 35 | return ENOENT; 36 | } 37 | } 38 | 39 | static int dt_device_get_path( 40 | gd_device_t dev, 41 | char * buf, 42 | size_t szBuf, 43 | size_t * szNeeded) 44 | { 45 | int rv = 0; 46 | dt_node_t node; 47 | 48 | if ((rv = gd_device_get_dt_node(dev, &node))) 49 | return rv; 50 | 51 | if (node->parent) { 52 | gd_device_t parent = node->parent->bound_device; 53 | if (!parent) { 54 | return ENOENT; 55 | } 56 | 57 | if ((rv = gd_device_get_path(parent, buf, szBuf, szNeeded))) 58 | return rv; 59 | } else { 60 | *szNeeded = strlcpy(buf, "/", szBuf); 61 | } 62 | 63 | *szNeeded += strlen(node->name); 64 | strlcat(buf, node->name, szBuf); 65 | 66 | return 0; 67 | } 68 | 69 | GD_BEGIN_IOCTL_BASE_MAP(gd_device_t, dt_base_ioctl) 70 | GD_MAP_DEVICE_GET_NAME_IOCTL(dt_device_get_name) 71 | GD_MAP_DEVICE_GET_PATH_IOCTL(dt_device_get_path) 72 | GD_MAP_DEVICE_GET_PARENT_IOCTL(dt_device_get_parent) 73 | GD_END_IOCTL_BASE_MAP() 74 | -------------------------------------------------------------------------------- /bal/device/dt/dt_system.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | void *system_fdt; 12 | static dt_node_t dt_root; 13 | 14 | static void print_dtval(const char *val, size_t len) 15 | { 16 | for (size_t i = 0; i < len; i++) { 17 | if(isprint(val[i])) 18 | putc(val[i], stdout); 19 | else 20 | printf("\\x%02x", (unsigned) val[i]); 21 | } 22 | } 23 | 24 | static dt_node_t add_device_fdt(dt_node_t parent, void *fdt, int fdt_node, int depth) 25 | { 26 | const char *name = fdt_get_name(fdt, fdt_node, NULL); 27 | printf("%*cEnumerating \"%s\"\n", depth, ' ', name); 28 | dt_node_t n = dt_node_alloc(parent, name); 29 | if (!n) 30 | panic("Out of memory enumerating node \"%s\"\n", name); 31 | 32 | for (int propoff = fdt_first_property_offset(fdt, fdt_node); 33 | propoff >= 0; 34 | propoff = fdt_next_property_offset(fdt, propoff)) { 35 | int len; 36 | const struct fdt_property *fdt_prop = 37 | fdt_get_property_by_offset(fdt, propoff, &len); 38 | 39 | if (!fdt_prop) { 40 | panic("Error getting property of \"%s\": %s\n", 41 | name, fdt_strerror(len)); 42 | } 43 | 44 | const char *prop_name = fdt_string(fdt, fdt32_to_cpu(fdt_prop->nameoff)); 45 | 46 | printf("%*c \"%s\" = \"", depth, ' ', prop_name); 47 | print_dtval(fdt_prop->data, len); 48 | printf("\"\n"); 49 | 50 | if (!dt_node_set_property(n, prop_name, fdt_prop->data, len)) 51 | panic("Out of memory allocating \"%s\":\"%s\"", 52 | name, prop_name); 53 | } 54 | 55 | for (int suboff = fdt_first_subnode(fdt, fdt_node); 56 | suboff != -FDT_ERR_NOTFOUND; 57 | suboff = fdt_next_subnode(fdt, suboff)) { 58 | add_device_fdt(n, fdt, suboff, depth + 2); 59 | } 60 | 61 | return n; 62 | } 63 | 64 | void dt_platform_init_fdt(void *fdt) 65 | { 66 | int rv; 67 | system_fdt = fdt; 68 | 69 | printf("fdt_platform_init %p\n", fdt); 70 | 71 | // Check header 72 | if ((rv = fdt_check_header(fdt))) { 73 | panic("Bad FDT: %s\n", fdt_strerror(rv)); 74 | } 75 | 76 | // Process memory reservations 77 | printf("rsv %p\n", fdt); 78 | int num_rsv = fdt_num_mem_rsv(fdt); 79 | for (int i = 0; i < num_rsv; i++) { 80 | printf("get\n"); 81 | gd_memory_map_entry ent; 82 | ent.type = gd_reserved_memory_type; 83 | ent.attributes = 0; 84 | fdt_get_mem_rsv(fdt, i, &ent.physical_start, &ent.size); 85 | printf("got\n"); 86 | ent.virtual_start = ent.physical_start; 87 | 88 | printf("Adding reserved memory region: %" PRIX64 " len=%" PRIX64 "\n", 89 | ent.physical_start, ent.size); 90 | 91 | mmap_add_entry(ent); 92 | } 93 | 94 | // Process root note memory entries 95 | printf("root\n"); 96 | int root = fdt_next_node(fdt, -1, NULL); 97 | 98 | unsigned addr_cells = fdt_address_cells(fdt, root); 99 | unsigned size_cells = fdt_size_cells(fdt, root); 100 | unsigned cells = addr_cells + size_cells; 101 | 102 | int mem_offs = fdt_subnode_offset(fdt, root, "memory"); 103 | if (mem_offs < 0) { 104 | panic("Unable to locate memory node (%s)\n", fdt_strerror(mem_offs)); 105 | } 106 | 107 | int memlen; 108 | const uint32_t *p = fdt_getprop(system_fdt, mem_offs, "reg", &memlen); 109 | for (int i = 0; i < memlen / 4; i+= cells) { 110 | uint64_t base_addr = 0, base_size = 0; 111 | if (addr_cells == 1) { 112 | base_addr = fdt32_to_cpu(p[i]); 113 | } else if (addr_cells == 2) { 114 | base_addr = fdt64_to_cpu(((uint64_t) p[i + 1]) << 32 | p[i]); 115 | } 116 | 117 | if (size_cells == 1) { 118 | base_size = fdt32_to_cpu(p[i + addr_cells]); 119 | } else if (size_cells == 2) { 120 | base_size = fdt64_to_cpu(((uint64_t) p[i + addr_cells + 1]) << 32 121 | | p[i + addr_cells]); 122 | } 123 | 124 | printf("Adding memory range %16" PRIX64 " len %16" PRIX64 "\n", 125 | base_addr, base_size); 126 | 127 | gd_memory_map_entry ent = { 0 }; 128 | ent.type = gd_conventional_memory; 129 | ent.attributes = 0; 130 | ent.virtual_start = ent.physical_start = base_addr; 131 | ent.size = base_size; 132 | mmap_add_entry(ent); 133 | } 134 | 135 | dt_root = add_device_fdt(NULL, fdt, root, 0); 136 | } 137 | -------------------------------------------------------------------------------- /bal/device/dt/dt_tree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | RB_GENERATE(dt_properties, dt_property, rbnode, dt_property_cmp) 11 | RB_GENERATE(dt_nodes, dt_node, rbnode, dt_node_cmp) 12 | 13 | int dt_property_cmp(dt_property_t lhs, dt_property_t rhs) 14 | { 15 | return strcmp(lhs->name, rhs->name); 16 | } 17 | 18 | int dt_node_cmp(dt_node_t lhs, dt_node_t rhs) 19 | { 20 | return strcmp(lhs->name, rhs->name); 21 | } 22 | 23 | dt_node_t dt_node_alloc(dt_node_t parent, const char *name) 24 | { 25 | dt_node_t n = malloc(sizeof *n + strlen(name) + 1); 26 | if (!n) return NULL; 27 | 28 | 29 | memset(n, 0, sizeof *n); 30 | n->name = (char*) &n[1]; 31 | n->parent = parent; 32 | 33 | strcpy((char*)n->name, name); 34 | 35 | if (parent) { 36 | RB_INSERT(dt_nodes, &parent->children, n); 37 | } 38 | 39 | return n; 40 | } 41 | 42 | dt_node_t dt_node_find_child(dt_node_t parent, const char *name) 43 | { 44 | struct dt_node nd; 45 | memset(&nd, 0, sizeof nd); 46 | nd.name = name; 47 | return RB_FIND(dt_nodes, &parent->children, &nd); 48 | } 49 | 50 | dt_property_t dt_node_find_property(dt_node_t node, const char *name) 51 | { 52 | struct dt_property pr; 53 | memset(&pr, 0, sizeof pr); 54 | pr.name = name; 55 | return RB_FIND(dt_properties, &node->properties, &pr); 56 | } 57 | 58 | bool dt_node_has_property(dt_node_t node, const char *name) 59 | { 60 | return dt_node_find_property(node, name) != NULL; 61 | } 62 | 63 | const void *dt_node_get_property(dt_node_t node, const char *name) 64 | { 65 | dt_property_t p = dt_node_find_property(node, name); 66 | if (p) { 67 | return p->value; 68 | } else return NULL; 69 | } 70 | 71 | dt_property_t dt_node_set_property( 72 | dt_node_t node, 73 | const char *name, 74 | const void *value, 75 | size_t len) 76 | { 77 | dt_property_t p = dt_node_find_property(node, name); 78 | if (!p) { 79 | void *vp = malloc(len); 80 | if (!vp) return NULL; 81 | 82 | p = malloc(sizeof(*p) + strlen(name) + 1); 83 | if (!p) { 84 | free(vp); 85 | return NULL; 86 | } 87 | 88 | memset(p, 0, sizeof *p); 89 | p->name = (char*) &p[1]; 90 | strcpy((char*) p->name, name); 91 | p->value = vp; 92 | 93 | RB_INSERT(dt_properties, &node->properties, p); 94 | } else if (p->value_len != len) { 95 | void *vp = realloc(p->value, len); 96 | if (!vp) return NULL; 97 | p->value = vp; 98 | } 99 | 100 | p->value_len = len; 101 | memcpy(p->value, value, len); 102 | 103 | return p; 104 | } 105 | 106 | bool dt_node_get_reg_range( 107 | dt_node_t node, 108 | unsigned idx, 109 | uintptr_t *ptr, 110 | size_t *sz) 111 | { 112 | dt_property_t prop = dt_node_find_property(node, "regs"); 113 | if(!prop) 114 | return false; 115 | 116 | uint32_t acells = dt_node_get_address_cells(node->parent); 117 | uint32_t scells = dt_node_get_size_cells(node->parent); 118 | uint32_t cells = acells + scells; 119 | 120 | unsigned baseIdx = idx * cells; 121 | if ((baseIdx + cells) * sizeof(uint32_t) > prop->value_len) 122 | return false; 123 | 124 | const uint32_t *p = prop->value; 125 | 126 | if (acells == 1) { 127 | *ptr = fdt32_to_cpu(p[baseIdx + 0]); 128 | } else if (acells == 2) { 129 | uint64_t v; 130 | memcpy(&v, &p[baseIdx + 0], sizeof v); 131 | v = fdt64_to_cpu(v); 132 | 133 | if (v > UINTPTR_MAX) { 134 | panic("Address out of range (0x%" PRIx64 ") on %s", 135 | v, node->name); 136 | } 137 | 138 | *ptr = v; 139 | } 140 | 141 | if (scells == 1) { 142 | *ptr = fdt32_to_cpu(p[acells]); 143 | } else if (scells == 2) { 144 | uint64_t v; 145 | memcpy(&v, &p[baseIdx + 0], sizeof v); 146 | v = fdt64_to_cpu(v); 147 | 148 | if (v > SIZE_MAX) { 149 | panic("Size out of range (0x%" PRIx64 ") on %s", 150 | v, node->name); 151 | } 152 | 153 | *sz = v; 154 | } 155 | 156 | return true; 157 | } 158 | 159 | unsigned dt_node_get_reg_count(dt_node_t node) 160 | { 161 | dt_property_t prop = dt_node_find_property(node, "regs"); 162 | if(!prop) 163 | return false; 164 | 165 | uint32_t acells = dt_node_get_address_cells(node->parent); 166 | uint32_t scells = dt_node_get_size_cells(node->parent); 167 | uint32_t cells = acells + scells; 168 | 169 | if ((prop->value_len % (cells * sizeof(uint32_t))) != 0) { 170 | panic("dt: node \"%s\": has size %" PRIu32 " which isn't " 171 | "divisible by %" PRIu32 " cells\n", node->name, prop->value_len, cells); 172 | } 173 | 174 | return prop->value_len / (sizeof(uint32_t) * cells); 175 | } 176 | 177 | uint32_t dt_node_get_address_cells(dt_node_t node) 178 | { 179 | dt_property_t p; 180 | if (!(p = dt_node_find_property(node, "#address_cells"))) 181 | panic("Node without address cells"); 182 | 183 | return dt_property_get_uint32(p); 184 | } 185 | 186 | uint32_t dt_node_get_size_cells(dt_node_t node) 187 | { 188 | dt_property_t p; 189 | if (!(p = dt_node_find_property(node, "#size_cells"))) 190 | panic("Node without size cells"); 191 | 192 | return dt_property_get_uint32(p); 193 | } 194 | 195 | uint32_t dt_property_get_uint32(dt_property_t prop) 196 | { 197 | uint32_t v; 198 | if (prop->value_len != sizeof v) { 199 | panic("dt_property_get_uint32: property (%s) not 32-bit", prop->name); 200 | } 201 | 202 | memcpy(&v, prop->value, sizeof v); 203 | return fdt32_to_cpu(v); 204 | } 205 | 206 | uint64_t dt_property_get_uint64(dt_property_t prop) 207 | { 208 | uint64_t v; 209 | if (prop->value_len != sizeof v) { 210 | panic("dt_property_get_uint64: property (%s) not 64-bit", prop->name); 211 | } 212 | 213 | memcpy(&v, prop->value, sizeof v); 214 | return fdt64_to_cpu(v); 215 | } 216 | -------------------------------------------------------------------------------- /bal/device/fb/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal device fb ; 2 | 3 | GdBalSources fb.c ; -------------------------------------------------------------------------------- /bal/device/uart/arm_pl011/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal device uart arm_pl011 ; 2 | 3 | GdBalSources arm_pl011.c ; 4 | 5 | SubIncludeOnce GD_TOP bal device dt ; 6 | -------------------------------------------------------------------------------- /bal/device/uart/arm_pl011/arm_pl011.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | enum reg { 25 | UART_DR = 0, 26 | UART_RSR, 27 | UART_ECR = UART_RSR, 28 | UART_RESV0, UART_RESV1, UART_RESV2, UART_RESV3, 29 | UART_FR, 30 | UART_RESV4, 31 | UART_ILPR, 32 | UART_IBRD, 33 | UART_FBRD, 34 | UART_LCR_H, 35 | UART_CR, 36 | UART_FLS, 37 | UART_IMSC, 38 | UART_RIS, 39 | UART_MIS, 40 | UART_ICR, 41 | UART_DMACR, 42 | }; 43 | 44 | /* UART_FR */ 45 | enum uart_flag_bits { 46 | UART_FR_CTS_BIT = (1 << 0), 47 | UART_FR_DSR_BIT = (1 << 1), 48 | UART_FR_DCD_BIT = (1 << 2), 49 | UART_FR_BUSY_BIT = (1 << 3), 50 | UART_FR_RXFE_BIT = (1 << 4), 51 | UART_FR_TXFF_BIT = (1 << 5), 52 | UART_FR_RXFF_BIT = (1 << 6), 53 | UART_FR_TXFE_BIT = (1 << 7), 54 | UART_FR_RI_BIT = (1 << 8), 55 | }; 56 | 57 | /* UART_CR */ 58 | enum uart_cr_bits { 59 | UART_CR_UARTEN_BIT = (1 << 0), 60 | UART_CR_SIREN_BIT = (1 << 1), 61 | UART_CR_SIRLP_BIT = (1 << 2), 62 | UART_CR_LBE_BIT = (1 << 7), 63 | UART_CR_TXE_BIT = (1 << 8), 64 | UART_CR_RXE_BIT = (1 << 9), 65 | UART_CR_DTR_BIT = (1 << 10), 66 | UART_CR_RTS_BIT = (1 << 11), 67 | UART_CR_OUT1_BIT = (1 << 12), 68 | UART_CR_OUT2_BIT = (1 << 13), 69 | UART_CR_RTSEn_BIT = (1 << 14), 70 | UART_CR_CTSEn_BIT = (1 << 15), 71 | }; 72 | 73 | /* UART_LCR_H */ 74 | enum uart_lcrh_bits { 75 | UART_LCR_H_BRK_BIT = (1 << 0), 76 | UART_LCR_H_PEN_BIT = (1 << 1), 77 | UART_LCR_H_EPS_BIT = (1 << 2), 78 | UART_LCR_H_STP2_BIT = (1 << 3), 79 | UART_LCR_H_FEN_BIT = (1 << 4), 80 | UART_LCR_H_WLEN_BITS = (3 << 5), 81 | UART_LCR_H_WLEN_SHIFT = 5, 82 | UART_LCR_H_SPS_BIT = (1 << 7), 83 | }; 84 | 85 | static int pl011_write(arm_pl011_dev *dev, const char *buf, size_t nbytes, size_t *written) 86 | { 87 | while (gio_read32_index(dev->base, UART_FR) & UART_FR_TXFF_BIT); 88 | 89 | *written = 0; 90 | for (size_t i = 0; i < nbytes; i++) { 91 | if (gio_read32_index(dev->base, UART_FR) & UART_FR_TXFF_BIT) 92 | break; 93 | gio_write32_index(dev->base, UART_DR, buf[i]); 94 | (*written)++; 95 | } 96 | 97 | return 0; 98 | } 99 | 100 | static int pl011_read(arm_pl011_dev *dev, char *buf, size_t nbytes, size_t *read) 101 | { 102 | while (gio_read32_index(dev->base, UART_FR) & UART_FR_RXFE_BIT); 103 | 104 | *read = 0; 105 | for (size_t i = 0; i < nbytes; i++) { 106 | if (gio_read32_index(dev->base, UART_FR) & UART_FR_RXFE_BIT) 107 | break; 108 | buf[i] = gio_read32_index(dev->base, UART_DR); 109 | (*read)++; 110 | } 111 | 112 | return 0; 113 | } 114 | 115 | static int pl011_set_config( 116 | arm_pl011_dev *dev, 117 | const struct gd_uart_config *cfg) 118 | { 119 | /* BRG is 16.6 fixed point register. Calculate and correctly round that */ 120 | uint32_t brg = ((dev->brg_clock) / (cfg->baud * 16 * 128) + 1) / 2; 121 | 122 | uint32_t cr = UART_CR_UARTEN_BIT | UART_CR_RXE_BIT | UART_CR_TXE_BIT; 123 | uint32_t lcrh = UART_LCR_H_FEN_BIT; 124 | switch (cfg->bits) { 125 | case 5: lcrh |= 0 << UART_LCR_H_WLEN_SHIFT; break; 126 | case 6: lcrh |= 1 << UART_LCR_H_WLEN_SHIFT; break; 127 | case 7: lcrh |= 2 << UART_LCR_H_WLEN_SHIFT; break; 128 | case 8: lcrh |= 3 << UART_LCR_H_WLEN_SHIFT; break; 129 | default: return EINVAL; 130 | } 131 | 132 | switch (cfg->parity) { 133 | case GD_UART_NO_PARITY: break; 134 | case GD_UART_ODD_PARITY: lcrh |= UART_LCR_H_PEN_BIT; break; 135 | case GD_UART_EVEN_PARITY: lcrh |= UART_LCR_H_PEN_BIT | UART_LCR_H_EPS_BIT; break; 136 | } 137 | 138 | switch (cfg->stop_bits) { 139 | case 1: break; 140 | case 2: lcrh |= UART_LCR_H_STP2_BIT; break; 141 | default: return EINVAL; 142 | } 143 | 144 | switch (cfg->flow_control) { 145 | case GD_UART_NO_FLOW_CONTROL: 146 | break; 147 | 148 | case GD_UART_RTS_CTS_FLOW_CONTROL: 149 | cr |= UART_CR_CTSEn_BIT | UART_CR_RTS_BIT; 150 | break; 151 | 152 | case GD_UART_RTR_CTS_FLOW_CONTROL: 153 | cr |= UART_CR_CTSEn_BIT | UART_CR_RTSEn_BIT; 154 | break; 155 | } 156 | 157 | /* disable device */ 158 | gio_write32_index(dev->base, UART_CR, 0); 159 | 160 | /* reinit */ 161 | gio_write32_index(dev->base, UART_IBRD, brg >> 6); 162 | gio_write32_index(dev->base, UART_FBRD, brg & 0x3F); 163 | gio_write32_index(dev->base, UART_LCR_H, lcrh); 164 | gio_write32_index(dev->base, UART_CR, cr); 165 | 166 | return 0; 167 | } 168 | 169 | static int pl011_device_get_dt_node(arm_pl011_dev *dev, dt_node_t *pnode) 170 | { 171 | *pnode = dev->node; 172 | return 0; 173 | } 174 | 175 | static GD_BEGIN_IOCTL_MAP(arm_pl011_dev *, arm_pl011_ioctl) 176 | GD_MAP_WRITE_IOCTL(pl011_write) 177 | GD_MAP_READ_IOCTL(pl011_read) 178 | GD_MAP_UART_SET_CONFIG_IOCTL(pl011_set_config) 179 | GD_MAP_DEVICE_GET_DT_NODE_IOCTL(pl011_device_get_dt_node) 180 | GD_END_IOCTL_MAP_FORWARD_BASE(dt_base_ioctl) 181 | 182 | 183 | void arm_pl011_init(arm_pl011_dev *dev) 184 | { 185 | dev->dev.ioctl = arm_pl011_ioctl; 186 | 187 | /* Make sure DMA, interrupts disabled */ 188 | gio_write32_index(dev->base, UART_DMACR, 0); 189 | gio_write32_index(dev->base, UART_IMSC, 0x7FF); 190 | 191 | uint32_t cr = gio_read32_index(dev->base, UART_CR); 192 | if ((cr & UART_CR_UARTEN_BIT) == 0) { 193 | struct gd_uart_config conf = { 194 | .baud = 115200, 195 | .bits = 8, 196 | .parity = GD_UART_NO_PARITY, 197 | .stop_bits = 1, 198 | .flow_control = GD_UART_NO_FLOW_CONTROL 199 | }; 200 | 201 | pl011_set_config(dev, &conf); 202 | } 203 | } 204 | 205 | static gd_device_t arm_pl011_dt_driver_attach(dt_node_t node) 206 | { 207 | int rv; 208 | arm_pl011_dev *self = malloc(sizeof *self); 209 | if (!self) goto err0; 210 | 211 | self->ioctl = arm_pl011_ioctl; 212 | self->node = node; 213 | 214 | gd_device_t parent; 215 | if ((rv = gd_device_get_parent(&self->dev, &parent))) 216 | goto err0; 217 | 218 | size_t regsz; 219 | if (gd_bus_get_child_reg_addr(parent, (gd_device_t) self, 0, &self->base, ®sz)) 220 | goto err1; 221 | 222 | if (regsz < (UART_DMACR * 4)) { 223 | panic("pl011 register window too small"); 224 | } 225 | 226 | arm_pl011_init(self); 227 | return &self->dev; 228 | 229 | err1: 230 | free(self); 231 | err0: 232 | return NULL; 233 | } 234 | 235 | DT_DECLARE_DEVICE_DRIVER(arm_pl011_dt_dev, "arm,pl011", arm_pl011_dt_driver_attach) 236 | -------------------------------------------------------------------------------- /bal/device/uart/ns16c550/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal device uart ns16c550 ; 2 | 3 | GdBalSources ns16c550.c ; -------------------------------------------------------------------------------- /bal/device/uart/ns16c550/ns16c550.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | #include 16 | 17 | //! NS16C550 Registers 18 | enum ns16c550_reg { 19 | UART_DATA = 0, //!< Dtata in/out register 20 | UART_IER = 1, //!< Interrupt Enable Register 21 | 22 | // When DLAB = 1 23 | UART_DIVISOR_LSB = 0, 24 | UART_DIVISOR_MSB = 1, 25 | 26 | UART_IIR = 2, //!< Interrupt Identification Register (RO) 27 | UART_FCR = 2, //!< FIFO Control Register (WO) 28 | UART_LCR = 3, //!< Line Control Register 29 | UART_MCR = 4, //!< Modem Control Register 30 | UART_LSR = 5, //!< Line Status Register 31 | UART_MSR = 6, //!< Modem Status Register 32 | }; 33 | 34 | enum ns16c550_lsr_bit { 35 | //! RX fifo empty 36 | LSR_RX_FIFO_EMPTY = (1 << 0), 37 | //! RX overrun error 38 | LSR_RX_OVERRUN_ERR = (1 << 1), 39 | //! RX parity error 40 | LSR_RX_PARITY_ERR = (1 << 2), 41 | //! RX framing error 42 | LSR_RX_FRAMING_ERR = (1 << 3), 43 | //! RX has break condition 44 | LSR_RX_BREAK = (1 << 4), 45 | //! TX fifo empty 46 | LSR_TX_FIFO_EMPTY = (1 << 5), 47 | //! TX shift register empty 48 | LSR_TX_SR_EMPTY = (1 << 6), 49 | //! RX FIFO contains error 50 | LSR_RX_FIFO_ERR = (1 << 7), 51 | }; 52 | 53 | enum ns16c550_fcr_bit { 54 | FCR_FIFO_EN = (1 << 0), 55 | FCR_RX_FIFO_CLEAR = (1 << 1), 56 | FCR_TX_FIFO_CLEAR = (1 << 2), 57 | FCR_DMA_MODE = (1 << 3), 58 | }; 59 | 60 | static void wrreg(ns16c550_dev *dev, enum ns16c550_reg reg, unsigned char b) 61 | { 62 | gio_write_index(dev->reg_width, dev->base, reg, b); 63 | } 64 | 65 | static unsigned char rdreg(ns16c550_dev *dev, enum ns16c550_reg reg) 66 | { 67 | return gio_read_index(dev->reg_width, dev->base, reg); 68 | } 69 | 70 | void ns16c550_init(ns16c550_dev *dev) 71 | { 72 | // TODO: initialize properly =) 73 | wrreg(dev, UART_FCR, FCR_FIFO_EN | FCR_TX_FIFO_CLEAR | FCR_RX_FIFO_CLEAR); 74 | } 75 | 76 | static int write(ns16c550_dev *dev, const char *buf, size_t nbytes) 77 | { 78 | size_t i = 0; 79 | 80 | // Check FIFO level 81 | do { 82 | if(rdreg(dev, UART_LSR) & LSR_TX_SR_EMPTY) { 83 | // It is - reset the FIFO space variable 84 | dev->fifo_space = dev->fifo_size; 85 | } 86 | } while(dev->fifo_space == 0); 87 | 88 | // ..then write as much as possible 89 | while(i < nbytes && dev->fifo_space) { 90 | wrreg(dev, UART_DATA, buf[i++]); 91 | dev->fifo_space--; 92 | } 93 | 94 | return i; 95 | } 96 | 97 | static int read(ns16c550_dev *dev, char *buf, size_t nbytes) 98 | { 99 | size_t i = 0; 100 | 101 | // Wait until there is something in the FIFO 102 | while((rdreg(dev, UART_LSR) & LSR_RX_FIFO_EMPTY) == 0); 103 | 104 | // Read as much as we can in one go 105 | while(i < nbytes && (rdreg(dev, UART_LSR) & LSR_RX_FIFO_EMPTY) != 0) { 106 | buf[i++] = rdreg(dev, UART_DATA); 107 | } 108 | return i; 109 | } 110 | 111 | GD_BEGIN_IOCTL_MAP(ns16c550_dev *, ns16c550_ioctl) 112 | GD_MAP_WRITE_IOCTL(write) 113 | GD_MAP_READ_IOCTL(read) 114 | GD_END_IOCTL_MAP_FORWARD(uart_base_ioctl) 115 | -------------------------------------------------------------------------------- /bal/fs/iso9660/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal fs iso9660 ; 2 | 3 | SubDirHdrs $(LIB9660_TOP) ; 4 | SubDirCcFlags [ FDefines L9660_HAVE_STDIO ] ; 5 | 6 | GdBalSources iso9660.c ; 7 | -------------------------------------------------------------------------------- /bal/fs/iso9660/iso9660.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | #include 16 | #include 17 | #include 18 | 19 | static int translate_status(l9660_status stat) 20 | { 21 | switch (stat) { 22 | case L9660_OK: return 0; 23 | case L9660_EIO: return EIO; 24 | case L9660_EBADFS: return EIO; 25 | case L9660_ENOENT: return ENOENT; 26 | case L9660_ENOTFILE: return EISDIR; 27 | case L9660_ENOTDIR: return ENOTDIR; 28 | default: return EINVAL; 29 | } 30 | } 31 | 32 | typedef struct { 33 | struct gd_device dev; 34 | l9660_file impl; 35 | } iso9660_file; 36 | 37 | static int file_read(iso9660_file *f, void * buf, size_t nbytes, size_t * nbytesread) 38 | { 39 | return translate_status(l9660_read(&f->impl, buf, nbytes, nbytesread)); 40 | } 41 | 42 | static int file_pread( 43 | iso9660_file *f, 44 | void * buf, 45 | size_t nbytes, 46 | size_t * nbytesread, 47 | uint64_t offset) 48 | { 49 | uint32_t old_offset = l9660_tell(&f->impl); 50 | l9660_status stat = l9660_read(&f->impl, buf, nbytes, nbytesread); 51 | l9660_status seek_stat = l9660_seek(&f->impl, SEEK_SET, old_offset); 52 | 53 | return translate_status(stat ? stat : seek_stat); 54 | } 55 | 56 | static int file_seek(iso9660_file *f, int64_t offset, int whence, int64_t * new_offset) 57 | { 58 | if (offset > UINT32_MAX) 59 | return EINVAL; 60 | 61 | int rv = translate_status(l9660_seek(&f->impl, whence, offset)); 62 | 63 | *new_offset = l9660_tell(&f->impl); 64 | return rv; 65 | } 66 | 67 | static int file_close(iso9660_file *f) 68 | { 69 | free(f); 70 | return 0; 71 | } 72 | 73 | GD_BEGIN_IOCTL_MAP(iso9660_file *, file_ioctl) 74 | GD_MAP_READ_IOCTL(file_read) 75 | GD_MAP_PREAD_IOCTL(file_pread) 76 | GD_MAP_SEEK_IOCTL(file_seek) 77 | GD_MAP_CLOSE_IOCTL(file_close) 78 | GD_END_IOCTL_MAP() 79 | 80 | static int fs_openat(iso9660_fs *fs, gd_device_t *p_fd, const char * name) 81 | { 82 | l9660_status stat; 83 | 84 | iso9660_file *file = malloc(sizeof(*file)); 85 | if (!file) 86 | return ENOMEM; 87 | 88 | file->dev.ioctl = file_ioctl; 89 | 90 | stat = l9660_fs_open_root((l9660_dir*) &file->impl, &fs->impl); 91 | if (stat) goto cleanup; 92 | 93 | stat = l9660_openat(&file->impl, (l9660_dir*) &file->impl, name); 94 | if (stat) goto cleanup; 95 | 96 | *p_fd = &file->dev; 97 | return 0; 98 | 99 | cleanup: 100 | free(file); 101 | return translate_status(stat); 102 | } 103 | 104 | GD_BEGIN_IOCTL_MAP(iso9660_fs *, fs_ioctl) 105 | GD_MAP_OPENAT_IOCTL(fs_openat) 106 | GD_END_IOCTL_MAP() 107 | 108 | static bool read_sector(l9660_fs *ifs, void *buf, uint32_t sector) 109 | { 110 | iso9660_fs *fs = (iso9660_fs *)(((char*) ifs) - offsetof(iso9660_fs, impl)); 111 | 112 | size_t read; 113 | if (gd_pread(fs->blockdev, buf, 2048, &read, sector * 2048)) 114 | return false; 115 | 116 | if (read != 2048) 117 | return false; 118 | 119 | return true; 120 | } 121 | 122 | int iso9660fs_init(iso9660_fs *self, gd_device_t blockdev) 123 | { 124 | self->dev.ioctl = fs_ioctl; 125 | self->blockdev = blockdev; 126 | 127 | return translate_status(l9660_openfs(&self->impl, read_sector)); 128 | } 129 | -------------------------------------------------------------------------------- /bal/gio.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | 18 | void gio_write_index(size_t size, gio_addr base, size_t index, size_t value) 19 | { 20 | switch(size) { 21 | case 8: gio_write8_index (base, index, value); return; 22 | case 16: gio_write16_index(base, index, value); return; 23 | case 32: gio_write32_index(base, index, value); return; 24 | default: for(;;); // todo - abort 25 | } 26 | } 27 | 28 | size_t gio_read_index(size_t size, gio_addr base, size_t index) 29 | { 30 | switch(size) { 31 | case 8: return gio_read8_index (base, index); 32 | case 16: return gio_read16_index(base, index); 33 | case 32: return gio_read32_index(base, index); 34 | default: for(;;); // todo - abort 35 | } 36 | } 37 | 38 | void gio_write(size_t size, gio_addr addr, size_t value) 39 | { gio_write_index(size, addr, 0, value); } 40 | 41 | size_t gio_read(size_t size, gio_addr addr) 42 | { return gio_read_index(size, addr, 0); } 43 | -------------------------------------------------------------------------------- /bal/ioctl.txt: -------------------------------------------------------------------------------- 1 | at 0x00000000 2 | ioctl forward(unsigned num, va_list ap) 3 | ioctl openat(gd_device_t *p_fd, const char *name) 4 | ioctl read(void *buf, size_t nbytes, size_t *nbytesread) 5 | ioctl write(const void *buf, size_t nbytes, size_t *nbyteswritten) 6 | ioctl seek(int64_t offset, int whence, int64_t *new_offset) 7 | ioctl pread(void *buf, size_t nbytes, size_t *nbytesread, uint64_t offset) 8 | ioctl pwrite(const void *buf, size_t nbytes, size_t *nbyteswritten, uint64_t offset) 9 | ioctl close() 10 | 11 | // Device ioctls 12 | at 0x00010000 13 | ioctl device_get_name(char *buf, size_t szBuf, size_t *szNeeded) 14 | ioctl device_get_path(char *buf, size_t szBuf, size_t *szNeeded) 15 | ioctl device_get_parent(gd_device_t *pparent) 16 | 17 | // DT ioctls 18 | at 0x00010100 19 | struct dt_node 20 | ioctl device_get_dt_node(struct dt_node **node) 21 | 22 | // Bus ioctls 23 | at 0x00010200 24 | ioctl bus_get_child_reg_addr(gd_device_t child, unsigned idx, gio_addr *addr, size_t *len) 25 | ioctl bus_get_child_reg_count(gd_device_t child, unsigned *count) 26 | 27 | // Device type specific ioctls 28 | // UART ioctls 29 | at 0x00020100 30 | struct gd_uart_config 31 | ioctl uart_get_config(struct gd_uart_config *config) 32 | ioctl uart_set_config(const struct gd_uart_config *config) 33 | 34 | // I2C ioctls 35 | at 0x00020200 36 | ioctl i2c_start(uint16_t address, bool writing) 37 | ioctl i2c_stop() 38 | -------------------------------------------------------------------------------- /bal/ioctl_stubs/gd_ioctl_stub.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | .global gd_ioctl 17 | 18 | #ifdef __i386__ 19 | gd_ioctl: 20 | mov 4(%esp), %eax 21 | jmp *(%eax) 22 | 23 | #elif defined(__amd64__) 24 | 25 | gd_ioctl: 26 | jmp *(%rsi) 27 | 28 | 29 | #elif defined(__arm__) 30 | 31 | ldr pc, [r0] 32 | 33 | #elif defined(__aarch64__) 34 | 35 | gd_ioctl: 36 | ldr x16, [x0] 37 | br x16 38 | 39 | #else 40 | 41 | #error You need to define an ioctl stub for this arch 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /bal/panic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void panic(const char* fmt, ...) 6 | { 7 | va_list ap; 8 | va_start(ap, fmt); 9 | fprintf(stderr, "PANIC! \n"); 10 | vfprintf(stderr, fmt, ap); 11 | 12 | fprintf(stderr, "\n\nHalted.\n"); 13 | va_end(ap); 14 | 15 | for(;;); 16 | } 17 | -------------------------------------------------------------------------------- /bal/platform/atf/Config.jam: -------------------------------------------------------------------------------- 1 | GdIncludeDir $(GD_TOP) bal platform atf ; 2 | 3 | SUPPORTED_ARCHITECTURES = 4 | aarch64 5 | ; 6 | 7 | CCFLAGS += -fPIC ; 8 | C++FLAGS += -fPIC ; 9 | 10 | 11 | # Generic DeviceTree based support for ARM Trusted Firmware based platforms 12 | 13 | rule GdBalBinaries { 14 | local name = gd_atf64.elf ; 15 | local script = [ FDirName $(GD_TOP) bal platform atf bal.ld ] ; 16 | 17 | LinkWithScript $(name) : $(GD_BAL_OBJECTS) : $(script) : -pie ; 18 | LinkLibraries $(name) : libfdt.a $(PDCLIB) libgdioctl.a $(LIBGCC) ; 19 | Depends exe : $(name) ; 20 | } 21 | -------------------------------------------------------------------------------- /bal/platform/atf/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal platform atf ; 2 | 3 | GdBalSources 4 | entry.S 5 | main.c 6 | ; 7 | 8 | SubIncludeOnce GD_TOP bal platform atf kickstart ; 9 | SubIncludeOnce GD_TOP bal device bus simple-bus ; 10 | SubIncludeOnce GD_TOP bal device uart arm_pl011 ; 11 | -------------------------------------------------------------------------------- /bal/platform/atf/README.md: -------------------------------------------------------------------------------- 1 | # Gandr for ARM Trusted Firmware 2 | 3 | This platform is designed to be the userspace bootloader started after ARM 4 | Trusted Firmware on non-UEFI platforms (if your platform uses ARM Trusted 5 | Firmware and UEFI, this is irrelevant - use a UEFI build of Gandr instead) 6 | 7 | The BAL produced, gd_atf[32|64].elf, is a relocatable ELF file which can be 8 | located wherever appropriate in memory. It is designed to be placed "on disk" 9 | (i.e. in your device's /boot filesystem), to facilitate upgrades. A small loader 10 | is then placed inside your ATF firmware image package as BL3-3, which loads a 11 | device tree binary and the BAL from disk. 12 | 13 | Presently, only the ARM Foundation Virtual Platform is supported. Other 14 | platforms can be supported in the future. Porting to Juno should be reasonably 15 | easy. 16 | 17 | A reference BL3-3, called Kickstart! is provided, which uses semihosting to load 18 | the BAL and DTB from host disk (in the current working directory). This could 19 | be relatively easily adapted to support hardware platforms. 20 | 21 | # BAL Interface Conventions 22 | The BAL shall always be an ELF dynamic (ET_DYN) binary of the appropriate 23 | architecture, bitness and endiannes. 24 | 25 | The BAL shall define a dynamic entry of 'DT_GANDR_ATFKICKSTART_VERSION' 26 | (0x67646b21) defining the maximum interface version supported. 27 | 28 | For the version 0 interface, the register contents on entry to the BAL shall be 29 | the following: 30 | 31 | (aarch32/aarch64 register name) 32 | * r0/w0 - 0x67646b21 ('gdk!') - magic constant identifying that the ATF Kickstart! interface is in use 33 | * r1/w1 - Interface version number (0) 34 | * r2/x2 - pointer to device tree binary 35 | 36 | The BAL will obey the memory and memory reservation declarations inside the 37 | device tree binary. In addition, it will note the memory occupied by its' own 38 | image and by the device tree binary. It will configure its' own stack. It is 39 | expected that the BL3-3 will not be marked as being in used memory and therefore 40 | its memory may be relalocated. 41 | 42 | The processor shall be in either EL1 or EL2. 43 | -------------------------------------------------------------------------------- /bal/platform/atf/bal.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT(elf64-littleaarch64) 2 | OUTPUT_ARCH(aarch64) 3 | 4 | ENTRY(_start) 5 | 6 | SECTIONS 7 | { 8 | stack . (NOLOAD) : ALIGN(4096) { 9 | *(stack) 10 | } 11 | 12 | .dynamic : { 13 | *(gddynamic) 14 | *(.dynamic*) 15 | } 16 | 17 | .text : { 18 | __stext = .; 19 | *(.text*) 20 | *(.rodata*) 21 | 22 | __fdt_drivers_begin = .; 23 | KEEP(*(fdt_drivers)) 24 | __fdt_drivers_end = .; 25 | 26 | __etext = .; 27 | } 28 | 29 | .data . : ALIGN(16) { 30 | __sdata = .; 31 | *(.data*) 32 | __edata = .; 33 | } 34 | 35 | .bss : ALIGN(16) { 36 | __sbss = .; 37 | *(.bss*) 38 | *(COMMON) 39 | __ebss = .; 40 | } 41 | 42 | .rela.init : { *(.rela.init) } 43 | .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } 44 | .rela.fini : { *(.rela.fini) } 45 | .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } 46 | .rela.data.rel.ro : { *(.rela.data.rel.ro .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*) } 47 | .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } 48 | .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } 49 | .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } 50 | .rela.ctors : { *(.rela.ctors) } 51 | .rela.dtors : { *(.rela.dtors) } 52 | .rela.got : { *(.rela.got) } 53 | .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } 54 | .rela.dyn : { *(.rela.dyn*) } 55 | 56 | . = ALIGN(4096); 57 | } 58 | -------------------------------------------------------------------------------- /bal/platform/atf/entry.S: -------------------------------------------------------------------------------- 1 | #include "asm_macros.h" 2 | #include "aarch64.h" 3 | #include "gd_elf.h" 4 | 5 | .global _start 6 | 7 | func _start 8 | stp x0, x1, [sp, #-16]! 9 | mov x0, #0x04 10 | adr x1, hello 11 | hlt #0xF000 12 | ldp x0, x1, [sp], #16 13 | 14 | ldr w8, =DT_GANDR_ATFKICKSTART_VERSION 15 | cmp w0, w8 16 | bne .Lbad_magic 17 | 18 | cmp w1, #0 19 | bne .Lbad_version 20 | 21 | // Set stack pointer 22 | //ldr x0, =__estack 23 | //mov sp, x0 24 | 25 | mov x0, #0x04 26 | adr x1, hello 27 | hlt #0xF000 28 | mov x0, x2 29 | 30 | bl bal_main_atf 31 | 32 | .Lbad_return: mov x0, #0x04 33 | adr x1, .Lbad_return_s 34 | hlt #0xBA0 35 | 1: wfi 36 | b 1b 37 | 38 | 39 | .Lbad_magic: mov x0, #0x04 40 | adr x1, .Lbad_magic_s 41 | 1: wfi 42 | b 1b 43 | 44 | .Lbad_version: mov x0, #0x04 45 | adr x1, .Lbad_version_s 46 | 1: wfi 47 | b 1b 48 | endfunc _start 49 | hello: .asciz "Hello from gdbal\n" 50 | .Lbad_return_s: .asciz "Bad return\n" 51 | .Lbad_magic_s: .asciz "Bad magic\n" 52 | .Lbad_version_s: 53 | .asciz "Bad version\n" 54 | 55 | .section stack 56 | .space 65536 57 | __estack = . 58 | 59 | .section gddynamic 60 | .quad DT_GANDR_ATFKICKSTART_VERSION 61 | .quad 0 62 | -------------------------------------------------------------------------------- /bal/platform/atf/kickstart/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal platform atf kickstart ; 2 | SubDirHdrs $(ELFLOAD_TOP) ; 3 | 4 | rule AtfKickstart { 5 | local objs = ; 6 | 7 | for src in [ FGristFiles $(>) ] { 8 | local obj = $(src:S=$(SUFOBJ)) ; 9 | Object $(obj) : $(src) ; 10 | MakeLocate $(obj) : $(LOCATE_TARGET) ; 11 | objs += $(obj) ; 12 | } 13 | 14 | LinkWithScript $(<).elf : $(objs) : [ FDirName $(GD_TOP) bal platform atf kickstart kickstart.ld ] ; 15 | LinkLibraries $(<).elf : elfload $(PDCLIB) libgdioctl ; 16 | ObjCopy $(<) : $(<).elf : -O binary ; 17 | DEPENDS exe : $(<) ; 18 | } 19 | 20 | AtfKickstart bl33.bin : 21 | entry.S 22 | kickstart.c 23 | pl011.c 24 | io_semihosting.c 25 | ; 26 | -------------------------------------------------------------------------------- /bal/platform/atf/kickstart/entry.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | #include "asm_macros.h" 16 | #include "aarch64.h" 17 | .section entrypoint 18 | .global _start 19 | .global shcall 20 | .global ks_go 21 | 22 | .macro SetupEL ELX 23 | // Little endian FTW 24 | mrs x0, sctlr_\ELX 25 | bic x0, x0, #SCTLR_EE_BIT 26 | msr sctlr_\ELX, x0 27 | isb 28 | 29 | // enable icache, alignment checks, strict alignment checks 30 | mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) 31 | mrs x0, sctlr_\ELX 32 | orr x0, x0, x1 33 | msr sctlr_\ELX, x0 34 | isb 35 | .endm 36 | 37 | func_special _start 38 | // If we are in EL2, set that up 39 | mrs x0, CurrentEL 40 | tbz x0, #3, Lin_el1 41 | 42 | // We are in EL2 43 | 44 | SetupEL EL2 45 | 46 | // Disable trapping from EL1 to EL2 47 | mrs x0, cptr_el2 48 | bic w0, w0, #TCPAC_BIT 49 | bic w0, w0, #TTA_BIT 50 | bic w0, w0, #TFP_BIT 51 | msr cptr_el2, x0 52 | 53 | 54 | Lin_el1: SetupEL EL1 55 | 56 | // Zero BSS 57 | ldr x0, =__sbss 58 | ldr x1, =__ebss 59 | 60 | 1: stp xzr, xzr, [x0], #16 61 | cmp x0, x1 62 | b.lt 1b 63 | 64 | // Set stack pointer 65 | ldr x0, =__estack 66 | mov sp, x0 67 | 68 | bl ks_main 69 | 70 | 1: wfi 71 | b 1b 72 | endfunc _start 73 | 74 | /* Semihosting service call */ 75 | func shcall 76 | hlt #0xF000 77 | ret 78 | endfunc shcall 79 | 80 | func ks_go 81 | br x3 82 | endfunc ks_go 83 | 84 | .section stack 85 | .balign 4096 86 | .space 4096 87 | -------------------------------------------------------------------------------- /bal/platform/atf/kickstart/io_semihosting.c: -------------------------------------------------------------------------------- 1 | #include "kickstart.h" 2 | #include 3 | #include 4 | 5 | /* semihosting file I/O */ 6 | 7 | int io_open(const char *filename) 8 | { 9 | uintptr_t params[3]; 10 | 11 | params[0] = (uintptr_t) filename; 12 | params[1] = 1; 13 | params[2] = (uintptr_t) strlen(filename); 14 | return shcall(SH_OPEN, params); 15 | } 16 | 17 | unsigned io_len(int fd) 18 | { 19 | uintptr_t params[1]; 20 | params[0] = fd; 21 | return shcall(SH_FLEN, params); 22 | } 23 | 24 | int io_seek(int fd, unsigned offset) 25 | { 26 | uintptr_t params[2]; 27 | params[0] = fd; 28 | params[1] = offset; 29 | return !(shcall(SH_SEEK, params) == offset); 30 | } 31 | 32 | int io_read(int fd, void *buf, unsigned len) 33 | { 34 | uintptr_t params[3]; 35 | params[0] = fd; 36 | params[1] = (uintptr_t) buf; 37 | params[2] = len; 38 | 39 | /* WTF return values here! */ 40 | int res = shcall(SH_READ, params); 41 | if (res == 0) 42 | return len; 43 | else if (res == (int) len) 44 | return -1; 45 | else return res; 46 | } 47 | 48 | void io_close(int fd) 49 | { 50 | uintptr_t params[1]; 51 | params[0] = fd; 52 | shcall(SH_CLOSE, params); 53 | } 54 | -------------------------------------------------------------------------------- /bal/platform/atf/kickstart/kickstart.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include "kickstart.h" 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | extern char __startspace[]; 23 | uintptr_t mem_mark = (uintptr_t) &__startspace; 24 | 25 | static void align(uintptr_t *v, size_t align) 26 | { 27 | align -= 1; 28 | 29 | *v = (*v + align) & (~align); 30 | } 31 | 32 | static void fail(const char *reason) 33 | { 34 | printf(ESC_BOLD "%s\n" ESC_NORMAL "Kickstart failed. Halted.\n", reason); 35 | 36 | for(;;); 37 | } 38 | 39 | void ks_main(void) 40 | { 41 | puts("Gandr ATF Kickstart!"); 42 | 43 | unsigned magic = DT_GANDR_ATFKICKSTART_VERSION; 44 | unsigned version = 0; 45 | void *dtb_addr = ks_load_dtb(); 46 | void *entrypoint = ks_load_bal(); 47 | 48 | printf("Preparing to go to %p (dtb=%p)\n", entrypoint, dtb_addr); 49 | 50 | ks_go(magic, version, dtb_addr, entrypoint); 51 | } 52 | 53 | void *ks_load_dtb(void) 54 | { 55 | printf("Loading DTB..."); 56 | int fd = io_open("platform.dtb"); 57 | if (fd == -1) fail(" platform.dtb not found"); 58 | 59 | char *dtbstart = (char*) mem_mark; 60 | unsigned dtb_size = io_len(fd); 61 | 62 | mem_mark += dtb_size; 63 | 64 | for(unsigned i = 0; i < dtb_size; i += 1024) { 65 | uputc('.'); 66 | unsigned to_read = (i + 1024) < dtb_size ? 1024 : dtb_size - i; 67 | int rv = io_read(fd, dtbstart + i, to_read); 68 | if (rv != (int) to_read) 69 | fail(" I/O error"); 70 | } 71 | 72 | io_close(fd); 73 | 74 | printf(ESC_BOLD " Done\n" ESC_NORMAL); 75 | 76 | return dtbstart; 77 | } 78 | 79 | typedef struct { 80 | el_ctx el; 81 | int fd; 82 | } ks_el_ctx; 83 | 84 | 85 | static bool ks_pread(struct el_ctx *ctx, void *dest, size_t nb, size_t offset) 86 | { 87 | int rv; 88 | ks_el_ctx *ksc = (ks_el_ctx*) ctx; 89 | if ((rv = io_seek(ksc->fd, offset))) { 90 | printf(" Seek failed (to 0x%X); %d", (unsigned) offset, rv); 91 | return false; 92 | } 93 | 94 | int read = io_read(ksc->fd, dest, nb); 95 | 96 | if (read != (int) nb) { 97 | printf(" Read failed (0x%X)", (unsigned) nb); 98 | return false; 99 | } 100 | 101 | return true; 102 | } 103 | 104 | static void check_el(el_status res, const char *action) 105 | { 106 | if (res == EL_OK) return; 107 | 108 | puts(ESC_BOLD " ELF loader error" ESC_NORMAL); 109 | printf("While %s: ", action); 110 | switch (res) { 111 | case EL_EIO: fail("I/O error"); 112 | case EL_ENOMEM: fail("Out of memory"); 113 | case EL_NOTELF: fail("Not an ELF file"); 114 | case EL_WRONGBITS: fail("Wrong bitness"); 115 | case EL_WRONGENDIAN: fail("Wrong endian"); 116 | case EL_WRONGARCH: fail("Wrong architecture"); 117 | case EL_WRONGOS: fail("Wrong OS"); 118 | case EL_NOTEXEC: fail("Not executable"); 119 | case EL_NODYN: fail("Not dynamic"); 120 | case EL_BADREL: fail("Bad relocation"); 121 | default: 122 | printf("(%d)", res); 123 | fail("Unknown"); 124 | } 125 | } 126 | 127 | static void *ks_el_alloc( 128 | el_ctx *ctx, 129 | Elf_Addr phys, 130 | Elf_Addr virt, 131 | Elf_Addr size) 132 | { 133 | return (void*) phys; 134 | } 135 | 136 | void *ks_load_bal(void) 137 | { 138 | printf("Loading Gandr BAL..."); 139 | 140 | ks_el_ctx ctx; 141 | ctx.el.pread = ks_pread; 142 | ctx.fd = io_open("gd_atf64.elf"); 143 | if (ctx.fd == -1) 144 | fail(" gd_atf64.elf not found"); 145 | 146 | int len = io_len(ctx.fd); 147 | printf(" (%d bytes)", len); 148 | 149 | check_el(el_init(&ctx.el), "initialising"); 150 | printf( " init"); 151 | 152 | Elf_Dyn dyn; 153 | check_el(el_finddyn(&ctx.el, &dyn, DT_GANDR_ATFKICKSTART_VERSION), 154 | "finding ABI tag"); 155 | 156 | if (dyn.d_tag == 0) 157 | fail(" no ABI tag"); 158 | 159 | printf( " abi"); 160 | 161 | /* No need to check value - we only speak v0 */ 162 | 163 | align(&mem_mark, ctx.el.align); 164 | ctx.el.base_load_paddr = ctx.el.base_load_vaddr = mem_mark; 165 | 166 | check_el(el_load(&ctx.el, ks_el_alloc), "loading"); 167 | printf( " loaded @ %p ", (void*) ctx.el.base_load_paddr); 168 | 169 | check_el(el_relocate(&ctx.el), "perfomring relocations"); 170 | printf( " reloc"); 171 | 172 | io_close(ctx.fd); 173 | 174 | puts(ESC_BOLD " done" ESC_NORMAL); 175 | 176 | return (void*) (ctx.el.ehdr.e_entry + mem_mark); 177 | } 178 | -------------------------------------------------------------------------------- /bal/platform/atf/kickstart/kickstart.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef KICKSTART_H 17 | #define KICKSTART_H 18 | 19 | #define ESC_NORMAL "\033[0m" 20 | #define ESC_BOLD "\033[1m" 21 | 22 | enum semihost_call { 23 | SH_OPEN = 0x01, 24 | SH_CLOSE = 0x02, 25 | SH_WRITEC = 0x03, 26 | SH_WRITE0 = 0x04, 27 | SH_WRITE = 0x05, 28 | SH_READ = 0x06, 29 | SH_READC = 0x07, 30 | SH_ISERROR = 0x08, 31 | SH_ISTTY = 0x09, 32 | SH_SEEK = 0x0A, 33 | SH_FLEN = 0x0C, 34 | SH_TMPNAM = 0x0D, 35 | SH_REMOVE = 0x0E, 36 | SH_RENAME = 0x0F, 37 | SH_CLOCK = 0x10, 38 | SH_TIME = 0x11, 39 | SH_SYSTEM = 0x12, 40 | SH_ERRNO = 0x13, 41 | }; 42 | 43 | /*! semihosting service call*/ 44 | int shcall(enum semihost_call, ...); 45 | 46 | /*! uart functions */ 47 | void uputc(char); 48 | int puts(const char*); 49 | int printf(const char* fmt, ...); 50 | 51 | /*! io functions */ 52 | int io_open(const char *name); 53 | unsigned io_len(int fd); 54 | int io_seek(int fd, unsigned offset); 55 | int io_read(int fd, void *buf, unsigned len); 56 | void io_close(int fd); 57 | 58 | void ks_main(void); 59 | void *ks_load_dtb(void); 60 | void *ks_load_bal(void); 61 | void ks_go(int magic, int version, void *dtb, void *ep); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /bal/platform/atf/kickstart/kickstart.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT(elf64-littleaarch64) 2 | OUTPUT_ARCH(aarch64) 3 | ENTRY(_start) 4 | MEMORY { 5 | RAM (rwx): ORIGIN = 0x88000000, LENGTH = (0x100000000-0x88000000) 6 | } 7 | SECTIONS 8 | { 9 | . = 0x88000000; 10 | .text : { 11 | __stext = .; 12 | *(entrypoint); 13 | *(.text*) 14 | *(.rodata*) 15 | __etext = .; 16 | } >RAM 17 | 18 | .data . : ALIGN(16) { 19 | __sdata = .; 20 | *(.data*) 21 | __edata = .; 22 | } >RAM 23 | 24 | .bss : ALIGN(16) { 25 | __sbss = .; 26 | *(.bss*) 27 | *(COMMON) 28 | __ebss = .; 29 | } >RAM 30 | 31 | stack . (NOLOAD) : { 32 | __sstack = .; 33 | *(stack) 34 | __estack = .; 35 | } >RAM 36 | 37 | . = ALIGN(4096); 38 | 39 | __startspace = .; 40 | __endspace = ORIGIN(RAM) + LENGTH(RAM); 41 | 42 | pl011_regs = 0x001C090000; 43 | } 44 | -------------------------------------------------------------------------------- /bal/platform/atf/kickstart/pl011.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "kickstart.h" 5 | 6 | enum reg { 7 | UART_DR = 0, 8 | UART_RSR, 9 | UART_ECR = UART_RSR, 10 | UART_RESV0, UART_RESV1, UART_RESV2, UART_RESV3, 11 | UART_FR, 12 | UART_RESV4, 13 | UART_ILPR, 14 | UART_IBRD, 15 | UART_FBRD, 16 | UART_LCR_H, 17 | UART_CR, 18 | UART_FLS, 19 | UART_IMSC, 20 | UART_RIS, 21 | UART_MIS, 22 | UART_ICR, 23 | UART_DMACR, 24 | }; 25 | 26 | /* UART_FR */ 27 | enum flag_bits { 28 | UART_FR_CTS_BIT = (1 << 0), 29 | UART_FR_DSR_BIT = (1 << 1), 30 | UART_FR_DCD_BIT = (1 << 2), 31 | UART_FR_BUSY_BIT = (1 << 3), 32 | UART_FR_RXFE_BIT = (1 << 4), 33 | UART_FR_TXFF_BIT = (1 << 5), 34 | UART_FR_RXFF_BIT = (1 << 6), 35 | UART_FR_TXFE_BIT = (1 << 7), 36 | UART_FR_RI_BIT = (1 << 8), 37 | }; 38 | 39 | extern volatile uint32_t pl011_regs[]; 40 | 41 | void uputc(char c) 42 | { 43 | if (c == '\n') { 44 | while(pl011_regs[UART_FR] & UART_FR_TXFF_BIT); 45 | pl011_regs[UART_DR] = (unsigned char) '\r'; 46 | } 47 | 48 | /* wait for FIFO space */ 49 | while(pl011_regs[UART_FR] & UART_FR_TXFF_BIT); 50 | pl011_regs[UART_DR] = (unsigned char) c; 51 | } 52 | 53 | int puts(const char *str) 54 | { 55 | while(*str) 56 | uputc(*str++); 57 | uputc('\n'); 58 | return 0; 59 | } 60 | 61 | static size_t printfcb( void *p, const char *buf, size_t size ) 62 | { 63 | for (size_t i = 0; i < size; i++ ) 64 | uputc(buf[i]); 65 | return size; 66 | } 67 | 68 | int printf(const char* fmt, ...) 69 | { 70 | va_list ap; 71 | va_start(ap, fmt); 72 | int n = _vcbprintf(0, printfcb, fmt, ap); 73 | va_end(ap); 74 | 75 | return n; 76 | } 77 | -------------------------------------------------------------------------------- /bal/platform/atf/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include <_PDCLIB_io.h> 7 | #include 8 | 9 | DEFINE_ARM_PL011(uart0, { (void*) 0x1C090000 }, 24000000); 10 | 11 | static void walk_children(void *fdt, int depth, int offset) 12 | { 13 | printf("%*c -> %s is ", depth, ' ', fdt_get_name(fdt, offset, NULL)); 14 | 15 | int len; 16 | const char* compatible = fdt_getprop(fdt, offset, "compatible", &len); 17 | for (int p = 0; p < len; p += strlen(compatible + p) + 1) { 18 | printf("\"%s\" ", compatible + p); 19 | } 20 | printf("\n"); 21 | 22 | int suboff = fdt_first_subnode(fdt, offset); 23 | while (suboff != -FDT_ERR_NOTFOUND) { 24 | walk_children(fdt, depth+1, suboff); 25 | suboff = fdt_next_subnode(fdt, suboff); 26 | } 27 | } 28 | 29 | void bal_main_atf(void *pdtree); 30 | void bal_main_atf(void *pdtree) 31 | { 32 | arm_pl011_init(&uart0); 33 | stdin->handle = stdout->handle = stderr->handle = ((_PDCLIB_fd_t) {&uart0} ); 34 | 35 | printf("FDT at %p\n", pdtree); 36 | 37 | int rv = fdt_check_header(pdtree); 38 | if (rv) { 39 | printf("Error: %s\n", fdt_strerror(rv)); 40 | } 41 | 42 | for (int i = 0; i < fdt_num_mem_rsv(pdtree); i++) { 43 | uint64_t addr, sz; 44 | fdt_get_mem_rsv(pdtree, i, &addr, &sz); 45 | printf("Reserved mem: %" PRIX64 " len=%" PRIX64 "\n", addr, sz); 46 | } 47 | 48 | printf("Tree:\n"); 49 | walk_children(pdtree, 1, fdt_next_node(pdtree, -1, NULL)); 50 | 51 | dt_platform_init_fdt(pdtree); 52 | 53 | for(;;); 54 | } 55 | -------------------------------------------------------------------------------- /bal/platform/beaglebone/Config.jam: -------------------------------------------------------------------------------- 1 | GdIncludeDir $(GD_TOP) bal platform beaglebone ; 2 | SOC = am33xx ; -------------------------------------------------------------------------------- /bal/platform/beaglebone/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal platform beaglebone ; 2 | 3 | GdBalSources 4 | test.c 5 | ; 6 | 7 | SubIncludeOnce GD_TOP bal device uart ns16c550 ; -------------------------------------------------------------------------------- /bal/platform/beaglebone/test.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | 18 | ns16c550_dev uart0 = { 19 | .base = (void*) 0x44E09000, 20 | .fifo_size = 64, 21 | .reg_width = 32 22 | }; 23 | 24 | void puts(const char* str) 25 | { 26 | while(*str) ns16c550_txbyte(&uart0, *str++); 27 | } 28 | 29 | void main(void) 30 | { 31 | ns16c550_init(&uart0); 32 | for(;;) { 33 | puts("Hello, world!\r\n"); 34 | } 35 | } -------------------------------------------------------------------------------- /bal/platform/bios/Config.jam: -------------------------------------------------------------------------------- 1 | GdIncludeDir $(GD_TOP) include platform bios ; 2 | 3 | SUPPORTED_ARCHITECTURES = 4 | ia32 5 | amd64 6 | ; 7 | 8 | rule GdBalBinaries { 9 | local bits = 32 ; 10 | if $(ARCH) = amd64 { 11 | bits = 64 ; 12 | } 13 | 14 | local name = gd_bal.$(bits) ; 15 | 16 | local script = [ FDirName $(GD_TOP) bal platform bios bal$(bits).ld ] ; 17 | 18 | LinkWithScript $(name).elf : $(GD_BAL_OBJECTS) : $(script) ; 19 | LinkLibraries $(name).elf : lib9660.a $(PDCLIB) libgdioctl.a $(LIBGCC) ; 20 | ObjCopy $(name) : $(name).elf : -O binary ; 21 | Depends exe : $(name) ; 22 | } 23 | 24 | # BiosStage1 output : name ; 25 | rule BiosStage1 { 26 | # Specific sources 27 | local specific_srcs = [ GLOB [ FDirName $(GD_TOP) bal platform bios stage1 $(2) ] : *.S ] ; 28 | 29 | local def = BD_$(2:U) ; 30 | 31 | # General objects 32 | local objs = ; 33 | for src in [ FGristFiles $(STAGE1_SRCS) ] { 34 | local obj = $(src:D=$(2):S=$(SUFOBJ)) ; 35 | Object $(obj) : $(src) ; 36 | MakeLocate $(obj) : $(LOCATE_TARGET) ; 37 | objs += $(obj) ; 38 | } 39 | 40 | # Specific objects 41 | for src in [ FGristFiles $(specific_srcs) ] { 42 | local obj = $(src:D=$(2):S=$(SUFOBJ)) ; 43 | Object $(obj) : $(src) ; 44 | MakeLocate $(obj) : $(LOCATE_TARGET) ; 45 | objs += $(obj) ; 46 | } 47 | 48 | ObjectDefines $(objs) : $(def) ; 49 | LinkWithScript $(<).elf : $(objs) : [ FDirName $(GD_TOP) bal platform bios stage1 $(2) link.ld ] ; 50 | ObjCopy $(<) : $(<).elf : -O binary ; 51 | DEPENDS exe : $(<) ; 52 | } 53 | -------------------------------------------------------------------------------- /bal/platform/bios/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal platform bios ; 2 | 3 | GdBalSources 4 | init.c 5 | bios_console.c 6 | bios_services.c 7 | mmap.c 8 | tables.c 9 | device/cdrom.c 10 | vbe.c 11 | ; 12 | 13 | SubIncludeOnce GD_TOP bal platform bios stage1 ; 14 | SubIncludeOnce GD_TOP bal fs iso9660 ; 15 | SubIncludeOnce GD_TOP bal device fb ; 16 | -------------------------------------------------------------------------------- /bal/platform/bios/bal32.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x10000; 6 | start = .; 7 | 8 | .text : 9 | { 10 | LONG(0x204c4142) /* "BAL " */ 11 | LONG(_start) 12 | LONG(0x00000000) 13 | LONG(0x10000) 14 | LONG(0x00000000) 15 | LONG(bss_start) 16 | LONG(0x00000000) 17 | LONG(bss_end) 18 | LONG(0x00000000) 19 | LONG(0x00000000) /* CRC32 */ 20 | 21 | *(.text*) 22 | *(.rodata*) 23 | } 24 | 25 | .data : 26 | { 27 | *(.data) 28 | } 29 | 30 | .bss : 31 | { 32 | bss_start = .; 33 | *(.bss*) 34 | *(COMMON) 35 | bss_end = .; 36 | } 37 | 38 | end = .; 39 | } 40 | -------------------------------------------------------------------------------- /bal/platform/bios/bal64.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x10000; 6 | start = .; 7 | 8 | .text : 9 | { 10 | LONG(0x204c4142) /* "BAL " */ 11 | LONG(_start) 12 | LONG(0x00000000) 13 | LONG(0x10000) 14 | LONG(0x00000000) 15 | LONG(bss_start) 16 | LONG(0x00000000) 17 | LONG(bss_end) 18 | LONG(0x00000000) 19 | LONG(0x00000000) /* CRC32 */ 20 | 21 | *(.text*) 22 | *(.rodata*) 23 | } 24 | 25 | .data : 26 | { 27 | *(.data) 28 | } 29 | 30 | .bss : 31 | { 32 | bss_start = .; 33 | *(.bss*) 34 | *(COMMON) 35 | bss_end = .; 36 | } 37 | 38 | end = .; 39 | } 40 | -------------------------------------------------------------------------------- /bal/platform/bios/bios_console.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | static int bios_console_write(struct bios_console_dev *dev, const void *buf, size_t sz, size_t *wrote) 20 | { 21 | const unsigned char *cbuf = buf; 22 | 23 | struct bios_registers regs = { 0 }; 24 | 25 | for (size_t i = 0; i < sz; i++) { 26 | unsigned char c = cbuf[i]; 27 | 28 | /*if (c == '\n') { 29 | // BIOS is a CRLF platform 30 | regs.ebx = dev->cur_page << 8; 31 | regs.eax = 0x0E00 | '\r'; 32 | bios_int_call(0x10, ®s); 33 | }*/ 34 | 35 | regs.eax = 0x0E00 | c; 36 | regs.ebx = dev->cur_page << 8; 37 | bios_int_call(0x10, ®s); 38 | } 39 | 40 | return *wrote = sz, 0; 41 | } 42 | 43 | GD_BEGIN_IOCTL_MAP(struct bios_console_dev *, bios_console_ioctl) 44 | GD_MAP_WRITE_IOCTL(bios_console_write) 45 | GD_END_IOCTL_MAP() 46 | 47 | void bios_console_init(struct bios_console_dev *dev) 48 | { 49 | dev->dev.ioctl = bios_console_ioctl; 50 | 51 | struct bios_registers regs = { 0 }; 52 | regs.eax = 0x0F00; 53 | bios_int_call(0x10, ®s); 54 | dev->width = (regs.eax >> 8) & 0xFF; 55 | dev->cur_page = (regs.ebx >> 8) & 0xFF; 56 | } 57 | -------------------------------------------------------------------------------- /bal/platform/bios/bios_services.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #ifdef __i386__ 20 | #define R(x) "%%e" #x 21 | #else 22 | #define R(x) "%%r" #x 23 | #endif 24 | 25 | volatile uint8_t scratch_buffer[4096]; 26 | struct bios_service_table *bios_services; 27 | 28 | static inline void* push(void *restrict *restrict psp, const void *restrict src, size_t len) 29 | { 30 | *psp = ((char*) *psp) - len; 31 | return memcpy(*psp, src, len); 32 | } 33 | 34 | void bios_far_call(uint32_t address, struct bios_registers *regs, const void *stack_data, unsigned stack_size) 35 | { 36 | void *sp = (void*) (uintptr_t) bios_services->rm_stack; 37 | 38 | uint32_t tmp = 0; 39 | 40 | // Reserve space on stack for our esp 41 | void **ret_info_ptr = push(&sp, &tmp, sizeof tmp); 42 | 43 | // Push data onto the stack 44 | push(&sp, stack_data, stack_size); 45 | 46 | // Push address 47 | push(&sp, &address, sizeof address); 48 | 49 | // Copy registers onto the stack 50 | push(&sp, regs, sizeof *regs); 51 | 52 | // Jump into the transition vector 53 | __asm volatile( 54 | #ifdef __i386__ 55 | // Save all regs using pushad 56 | "pushal\n" 57 | #endif 58 | // (On long mode we rely on preservation of r8+ to satifsy the compiler) 59 | 60 | 61 | // Use this rather than push to produce a 32-bit compatible far return 62 | // frame 63 | "sub $8, %%esp\n" 64 | "mov %%cs, %%eax\n" 65 | "mov %%eax, 4(" R(sp) ")\n" 66 | "mov $1f, %%eax\n" 67 | "mov %%eax, 0(" R(sp) ")\n" 68 | 69 | // Stash esp on the real mode stack 70 | "mov %%esp, %[ret_info]\n" 71 | 72 | // Switch to real mode stack and jump in 73 | "mov %[sp], " R(sp) "\n" 74 | "data16 ljmp *%[far_call_tvec]\n" 75 | 76 | "1:\n" 77 | #ifdef __i386__ 78 | "popal\n" 79 | #endif 80 | 81 | : [ret_info] "=m" (*ret_info_ptr) 82 | : [sp] "r" (sp) 83 | , [far_call_tvec] "m" (bios_services->far_call_ptr) 84 | : "cc", "memory" 85 | #ifdef __amd64__ 86 | , "rax", "rbx", "rcx", "rdx" 87 | , "rsi", "rdi", "rbp" 88 | #else 89 | , "eax" 90 | #endif 91 | ); 92 | 93 | // Copy back the registers 94 | memcpy(regs, sp, sizeof *regs); 95 | } 96 | 97 | void bios_int_call(uint8_t num, struct bios_registers *regs) 98 | { 99 | void *sp = (void*) (uintptr_t) bios_services->rm_stack; 100 | 101 | uint32_t tmp = 0; 102 | 103 | // Reserve space on stack for our esp 104 | void ** ret_info_ptr = push(&sp, &tmp, sizeof tmp); 105 | 106 | // Copy registers onto the stack 107 | push(&sp, regs, sizeof *regs); 108 | 109 | // Jump into the transition vector 110 | __asm volatile( 111 | #ifdef __i386__ 112 | // Save all regs using pushad 113 | "pushal\n" 114 | #endif 115 | // (On long mode we rely on preservation of r8+ to satifsy the compiler) 116 | 117 | // Use this rather than push to produce a 32-bit compatible far return 118 | // frame 119 | "sub $8, %%esp\n" 120 | "mov %%cs, %%ebx\n" 121 | "mov %%ebx, 4(" R(sp) ")\n" 122 | "mov $1f, %%ebx\n" 123 | "mov %%ebx, 0(" R(sp) ")\n" 124 | 125 | // Stash esp on the real mode stack 126 | "mov %%esp, %[ret_info]\n" 127 | 128 | // Switch to real mode stack and jump in 129 | "mov %[sp], " R(sp) "\n" 130 | "data16 ljmp *%[int_call_tvec]\n" 131 | 132 | "1:\n" 133 | #ifdef __i386__ 134 | "popal\n" 135 | #endif 136 | 137 | : [ret_info] "=m" (*ret_info_ptr) 138 | , [num] "+a" (num) 139 | : [sp] "r" (sp) 140 | , [int_call_tvec] "m" (bios_services->int_call_ptr) 141 | : "cc", "memory" 142 | #ifdef __amd64__ 143 | , "rbx", "rcx", "rdx" 144 | , "rsi", "rdi", "rbp" 145 | #else 146 | , "ebx" 147 | #endif 148 | ); 149 | 150 | // Copy back the registers 151 | memcpy(regs, sp, sizeof *regs); 152 | } 153 | -------------------------------------------------------------------------------- /bal/platform/bios/device/cdrom.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | static volatile struct { 22 | uint8_t size; 23 | uint8_t reserved; 24 | uint16_t blocks; 25 | uint32_t buffer_far_ptr; 26 | uint64_t lba; 27 | } __attribute__((packed)) lba_packet; 28 | 29 | static int pread(cdrom_dev *dev, void *buf, size_t nbytes, size_t *nbytesread, uint64_t offset) 30 | { 31 | *nbytesread = 0; void *read_buffer = buf; 32 | 33 | if (offset % 2048) 34 | return EINVAL; 35 | 36 | if (!(nbytes &= ~0x7FF)) 37 | return 0; 38 | 39 | if ((uintptr_t) buf > (0x100000 - 2048)) { 40 | read_buffer = (void*)scratch_buffer; 41 | nbytes = nbytes > sizeof scratch_buffer ? 42 | sizeof scratch_buffer & ~0x7FF : nbytes; 43 | } else { 44 | nbytes = nbytes > (0x100000 - (uintptr_t) buf) ? 45 | (0x100000 - (uintptr_t) buf) & ~0x7FF : 46 | nbytes; 47 | } 48 | 49 | lba_packet.size = sizeof lba_packet; 50 | lba_packet.reserved = 0; 51 | lba_packet.blocks = (nbytes / 2048) > 0x7F ? 0x7F : nbytes / 2048; 52 | lba_packet.buffer_far_ptr = rm_far_from_ptr(read_buffer); 53 | lba_packet.lba = offset / 2048; 54 | 55 | struct bios_registers regs = { 56 | .eax = 0x4200, 57 | .edx = dev->drive_number 58 | }; 59 | regs.ds = rm_seg_from_ptr((void*) &lba_packet); 60 | regs.edi = rm_offset_from_ptr((void*) &lba_packet); 61 | bios_int_call(0x13, ®s); 62 | 63 | if (regs.eflags & carry_flag || !lba_packet.blocks) { 64 | if (nbytes > 2048) 65 | return pread(dev, buf, 2048, nbytesread, offset); 66 | else return EIO; 67 | } 68 | 69 | if (read_buffer != buf) 70 | memcpy(buf, read_buffer, lba_packet.blocks * 2048); 71 | 72 | return *nbytesread = lba_packet.blocks * 2048, 0; 73 | } 74 | 75 | GD_BEGIN_IOCTL_MAP(cdrom_dev *, cdrom_ioctl) 76 | GD_MAP_PREAD_IOCTL(pread) 77 | GD_END_IOCTL_MAP() 78 | 79 | void cdrom_init(cdrom_dev *dev, uint8_t drive_number) 80 | { 81 | dev->dev.ioctl = cdrom_ioctl; 82 | dev->drive_number = drive_number; 83 | } 84 | -------------------------------------------------------------------------------- /bal/platform/bios/docs/low_mmap.txt: -------------------------------------------------------------------------------- 1 | === Memory map of low memory (<1MiB) === 2 | 3 | 0x0600 -> 0x2FFF Stage 1 4 | 0x3000 -> 0x6FFF Stage 1.5 5 | 0x7000 -> 0x7FFF Stage 1(.5) stack 6 | 7 | 0x8000 -> 0xBFFF Paging structures (x86_64) 8 | 0xC000 -> 0xFFFF BAL stack 9 | 0x10000 -> 0x2???? BAL 10 | -------------------------------------------------------------------------------- /bal/platform/bios/init.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | #include <_PDCLIB_io.h> 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | struct bios_console_dev bios_console; 27 | 28 | __asm__( 29 | ".globl _start\n" 30 | "_start:\n" 31 | #ifdef __x86_64__ 32 | " mov %edi, %edi\n" 33 | #else 34 | " push %edi\n" 35 | #endif 36 | " call __start\n" 37 | " jmp .\n" 38 | ); 39 | 40 | void __start(struct bios_service_table *pbios_services); 41 | void __start(struct bios_service_table *pbios_services) 42 | { 43 | bios_services = pbios_services; 44 | __asm("xchg %bx, %bx"); 45 | bios_console_init(&bios_console); 46 | stdout->handle.pointer = &bios_console.dev; 47 | 48 | /* Initialize the memory map, find all the tables. */ 49 | mmap_init(); 50 | tables_init(); 51 | vbe_init(); 52 | 53 | /*gd_memory_map_entry mmap[100]; size_t nentries = 100, key = 0; 54 | mmap_get(&mmap, nentries, &nentries, &key); 55 | for (size_t i = 0; i < nentries; i++) { 56 | printf("Entry %d: %llx -> %llx, %d\n", i, mmap[i].physical_start, 57 | mmap[i].physical_start + mmap[i].size, 58 | mmap[i].type); 59 | }*/ 60 | 61 | //extern gd_rsdt_pointer_table rsdt_pointer; 62 | //extern gd_pc_pointer_table pc_pointer; 63 | 64 | //if (rsdt_pointer.header.length) { 65 | // printf("RSDT: %x\nXSDT: %llx\n", rsdt_pointer.rsdt_address, rsdt_pointer.xsdt_address); 66 | //} 67 | 68 | //if (pc_pointer.header.length) { 69 | // printf("MPS: %c%c%c%c\nSMBIOS: %x\n", pc_pointer.mpfp.signature[0], 70 | // pc_pointer.mpfp.signature[1], 71 | // pc_pointer.mpfp.signature[2], 72 | // pc_pointer.mpfp.signature[3], pc_pointer.smbios_entry_point_address); 73 | //} 74 | for(;;); 75 | } 76 | -------------------------------------------------------------------------------- /bal/platform/bios/mmap.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /*! Type conversion from ACPI to gd* types. */ 24 | gd_memory_type acpi_to_gd[] = { 25 | gd_unusable_memory, /* unused */ 26 | gd_conventional_memory, /* address_range_memory */ 27 | gd_unusable_memory, /* address_range_reserved */ 28 | gd_acpi_reclaim_memory, /* address_range_reclaimable */ 29 | gd_acpi_memory_nvs, /* address_range_nvs */ 30 | gd_unusable_memory, /* address_range_unusable */ 31 | gd_unusable_memory /* address_range_disabled */ 32 | }; 33 | 34 | static void add_acpi_range(struct address_range range) 35 | { 36 | if (!(range.attributes & entry_present)) 37 | return; 38 | 39 | gd_memory_map_entry entry; 40 | entry.physical_start = range.physical_start; 41 | entry.virtual_start = 0; 42 | entry.size = range.size; 43 | 44 | /* TODO: handle attributes. */ 45 | entry.attributes = 0; 46 | 47 | if (range.type < (sizeof acpi_to_gd / sizeof (gd_memory_type))) 48 | entry.type = acpi_to_gd[range.type]; 49 | else 50 | entry.type = gd_unusable_memory; 51 | 52 | mmap_add_entry(entry); 53 | } 54 | 55 | /*! Returns true on success, otherwise false. */ 56 | static bool try_e820() 57 | { 58 | struct bios_registers regs = { 59 | .eax = 0x0000E820, 60 | .ebx = 0x00000000, /* continuation value */ 61 | .ecx = 24, /* size of output buffer */ 62 | .edx = 0x534D4150 /* SMAP */ 63 | }; 64 | volatile struct address_range range = { .attributes = entry_present }; 65 | 66 | regs.es = rm_seg_from_ptr((void*) &range); 67 | regs.edi = rm_offset_from_ptr((void*) &range); 68 | bios_int_call(0x15, ®s); 69 | 70 | // Carry flag after first call means unsupported. 71 | if ((regs.eflags & carry_flag) || 72 | (regs.eax != 0x534D4150) || 73 | (regs.ecx < 20)) 74 | return false; 75 | 76 | add_acpi_range(range); 77 | 78 | do { 79 | regs.eax = 0x0000E820; regs.ecx = 24; regs.edx = 0x534D4150; 80 | regs.es = rm_seg_from_ptr((void*) &range); 81 | regs.edi = rm_offset_from_ptr((void*) &range); 82 | 83 | range.attributes = entry_present; 84 | bios_int_call(0x15, ®s); 85 | 86 | // List finished. 87 | if (regs.eflags & carry_flag) 88 | return true; 89 | 90 | // If invalid entry, reset. 91 | if ((regs.eax != 0x534D4150) || (regs.ecx < 20)) { 92 | mmap_clean(); 93 | return false; 94 | } 95 | 96 | add_acpi_range(range); 97 | } while (regs.ebx); 98 | 99 | return true; 100 | } 101 | 102 | /*! Returns true on success, otherwise false. 103 | * \param eax is the exact 0xe8X1 function. 104 | */ 105 | static bool try_e8x1(uint32_t eax) 106 | { 107 | struct bios_registers regs = { .eax = eax }; 108 | bios_int_call(0x15, ®s); 109 | if (regs.eflags & carry_flag) 110 | return false; 111 | 112 | if (eax == 0xE801) { 113 | regs.eax &= 0xFFFF; 114 | regs.ebx &= 0xFFFF; 115 | regs.ecx &= 0xFFFF; 116 | regs.edx &= 0xFFFF; 117 | } 118 | 119 | /*! Linux uses the CX/DX pair, but reverts to AX/BX if they're 120 | * zero. */ 121 | if (!regs.ecx) { 122 | regs.ecx = regs.eax; 123 | regs.edx = regs.ebx; 124 | } 125 | 126 | gd_memory_map_entry entries[] = { 127 | { .physical_start = 0x100000, 128 | .size = regs.ecx * 1024, 129 | .type = gd_conventional_memory }, 130 | 131 | { .physical_start = 0x1000000, 132 | .size = regs.edx * 1024 * 64, /* 64K blocks */ 133 | .type = gd_conventional_memory } 134 | }; 135 | 136 | mmap_add_entry(entries[0]); 137 | mmap_add_entry(entries[1]); 138 | return true; 139 | } 140 | 141 | static bool try_c7() 142 | { 143 | // Use 0xC0 to figure out if 0xC7 is supported. 144 | struct bios_registers regs = { .eax = 0xC0 }; 145 | bios_int_call(0x15, ®s); 146 | 147 | if ((regs.eflags & carry_flag) || (regs.eax & 0xFF00)) 148 | return false; 149 | 150 | uint8_t *rom_table = (uint8_t*)(uintptr_t) (regs.es * 0x10 + (regs.ebx & 0xFFFF)); 151 | 152 | // Bit 4 of second feature byte at offset 6. 153 | if (!(rom_table[6] & (1 << 4))) 154 | return false; 155 | 156 | struct { 157 | uint16_t word; 158 | uint32_t local_memory_1m, local_memory_16m; 159 | uint32_t system_memory_1m, system_memory_16m; 160 | uint32_t cacheable_memory_1m, cacheable_memory_16m; 161 | uint32_t memory_1m, memory_16m; 162 | uint16_t free_block_c0000; uint16_t free_block_size; 163 | uint32_t reserved; 164 | } __attribute__((packed)) *c7_memory_map; 165 | 166 | c7_memory_map = (void*)(uintptr_t) (regs.ds * 0x10 + (regs.esi & 0xFFFF)); 167 | gd_memory_map_entry entries[] = { 168 | { .physical_start = 0x100000, 169 | .size = c7_memory_map->memory_1m * 1024, 170 | .type = gd_conventional_memory }, 171 | 172 | { .physical_start = 0x1000000, 173 | .size = c7_memory_map->memory_16m * 1024, 174 | .type = gd_conventional_memory } 175 | }; 176 | mmap_add_entry(entries[0]); 177 | mmap_add_entry(entries[1]); 178 | return true; 179 | } 180 | 181 | static uint64_t get_extended_memory() 182 | { 183 | struct bios_registers regs = { .eax = 0xDA88 }; 184 | bios_int_call(0x15, ®s); 185 | 186 | if (!(regs.eflags & carry_flag)) { 187 | /* success */ 188 | return (((regs.ecx & 0xFF) << 16) | (regs.ebx & 0xFFFF)) * 1024; 189 | } 190 | 191 | regs.eax = 0x8800; 192 | bios_int_call(0x15, ®s); 193 | 194 | /* AH=0x88 isn't reliable with carry flag setting, 195 | so if AH is either 0x86 (unsupported function) or 0x80 196 | (invalid command) after call, treat as error. */ 197 | if (!(regs.eflags & carry_flag) && 198 | ((regs.eax & 0xFF00) != 0x8600) && 199 | ((regs.eax & 0xFF00) != 0x8000)) { 200 | return (regs.eax & 0xFFFF) * 1024; 201 | } 202 | 203 | regs.eax = 0x8A00; 204 | bios_int_call(0x15, ®s); 205 | 206 | if (!(regs.eflags & carry_flag)) { 207 | return (((regs.edx & 0xFFFF) << 16) | (regs.eax & 0xFFFF)) * 1024; 208 | } 209 | 210 | // CMOS also stores information. 211 | uint8_t low, high; 212 | outb(0x70, 0x30); 213 | low = inb(0x71); 214 | outb(0x70, 0x31); 215 | high = inb(0x71); 216 | 217 | return (low | (high << 8)) * 1024; 218 | } 219 | 220 | /*! Get the amount of base memory, as reported by int 0x12. */ 221 | uint32_t get_base_memory() 222 | { 223 | static uint32_t base_memory = 0; 224 | if (!base_memory) { 225 | struct bios_registers regs = { 0 }; 226 | bios_int_call(0x12, ®s); 227 | base_memory = regs.eax * 1024; 228 | } 229 | 230 | return base_memory; 231 | } 232 | 233 | void mmap_init() 234 | { 235 | if (try_e820() == false) { 236 | /* fallback */ 237 | /* todo: does this need entries for EBDA or BIOS region? */ 238 | gd_memory_map_entry entries[] = { 239 | { .physical_start = 0x00000000, 240 | .size = get_base_memory(), 241 | .type = gd_conventional_memory }, 242 | 243 | // ISA hole. 244 | { .physical_start = 0xF00000, 245 | .size = 0x100000, 246 | .type = gd_unusable_memory } 247 | }; 248 | for (size_t i = 0; i < sizeof entries / sizeof (gd_memory_map_entry); i++) 249 | mmap_add_entry(entries[i]); 250 | 251 | if((try_e8x1(0xe881) == false) && 252 | (try_e8x1(0xe801) == false) && 253 | (try_c7() == false)) { 254 | gd_memory_map_entry entry = { 255 | .physical_start = 0x100000, 256 | .size = get_extended_memory(), 257 | .type = gd_conventional_memory 258 | }; 259 | 260 | mmap_add_entry(entry); 261 | } 262 | } 263 | 264 | /* todo: pxe */ 265 | /* todo: self */ 266 | gd_memory_map_entry low_mem = { 267 | .physical_start = 0x0000, 268 | /*! IVT and BDA (till 0x501). */ 269 | .size = 0x1000, 270 | .type = gd_unusable_memory 271 | }; 272 | 273 | // TODO: make this proper. 274 | gd_memory_map_entry gandr_mem = { 275 | .physical_start = 0x8000, 276 | .size = (0x30000 - 0x8000), 277 | .type = gd_loader_code 278 | }; 279 | 280 | mmap_add_entry(low_mem); mmap_add_entry(gandr_mem); 281 | } 282 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal platform bios stage1 ; 2 | 3 | # General stage 1 sources 4 | STAGE1_SRCS = [ GLOB [ FDirName $(GD_TOP) bal platform bios stage1 ] : *.S ] ; 5 | 6 | # List of stage 1s: 7 | STAGE1_LIST = 8 | pxe 9 | eltorito 10 | ; 11 | 12 | for stage1 in $(STAGE1_LIST) { 13 | local output = [ FDirName $(stage1) stage1_$(stage1) ] ; 14 | BiosStage1 $(output) : $(stage1) ; 15 | } 16 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/a20.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | .code16 17 | .text 18 | 19 | //! Wait till keyboard input buffer is clear. 20 | kyb_wait_input_buf: 21 | in $0x64, %al 22 | test $2, %al // If second bit is 0, then empty. 23 | jnz kyb_wait_input_buf 24 | ret 25 | 26 | //! Waits till keyboard output buffer is clear. 27 | kyb_wait_output_buf: 28 | in $0x64, %al 29 | test $1, %al // If first bit is 0, then empty. 30 | jnz kyb_wait_output_buf 31 | ret 32 | 33 | /*! Try to enable A20. 34 | * \return Aborts boot on failure. 35 | */ 36 | .global a20_enable 37 | a20_enable: 38 | push %ax 39 | pushf 40 | 41 | call a20_check 42 | jc .return 43 | 44 | // Try the BIOS, enable A20 gate. 45 | mov $0x2401, %ax 46 | int $0x15 47 | 48 | jc 0f 49 | test %ah, %ah 50 | jnz 0f 51 | 52 | call a20_check 53 | jc .return 54 | 55 | 0: 56 | // Try the keyboard controller. 57 | cli 58 | call kyb_wait_input_buf 59 | mov $0xAD, %al 60 | out %al, $0x64 // Disable. 61 | 62 | call kyb_wait_input_buf 63 | mov $0xD0, %al 64 | out %al, $0x64 // Read controller output port (bit 1 enables A20). 65 | 66 | call kyb_wait_output_buf 67 | in $0x60, %al 68 | push %ax // Save controller output port. 69 | 70 | call kyb_wait_input_buf 71 | mov $0xD1, %al 72 | out %al, $0x64 // Write to controller output port. 73 | 74 | call kyb_wait_input_buf 75 | pop %ax 76 | or $2, %al 77 | out %al, $0x60 78 | 79 | call kyb_wait_input_buf 80 | mov $0xAE, %al 81 | out %al, $0x64 // Enable. 82 | 83 | call kyb_wait_input_buf 84 | 85 | call a20_check 86 | jc .return 87 | 88 | /* Fast A20 is known to hang the machine, so use "Query A20 Gate Support" 89 | * to figure out whether it is supported or not. 90 | */ 91 | mov $0x2403, %ax 92 | int $0x15 93 | 94 | jc .error 95 | test %ah, %ah 96 | jnz .error 97 | 98 | /* Bit 1 indicates whether I/O port 0x92 is supported or not. */ 99 | test $2, %bx 100 | jz .error 101 | 102 | // Try fast A20. 103 | in $0x92, %al // Get the value from 0x92 port. 104 | test $2, %al // If the fast A20 bit is already set, then unreliable. 105 | jnz .error 106 | 107 | or $2, %al // Enable Fast A20. 108 | and $0xFE, %al // Bit 0 is used for fast reset. 109 | out %al, $0x92 110 | 111 | call a20_check 112 | jnc .error 113 | 114 | .return: 115 | popf 116 | pop %ax 117 | ret 118 | 119 | .error: 120 | mov $a20_error_msg, %si 121 | jmp abort_boot 122 | 123 | a20_error_msg: 124 | .ascii "Cannot enable the A20 gate." 125 | .byte 0 126 | 127 | /*! Checks the status of the A20 line. 128 | * \return Carry set if the A20 line is enabled. 129 | */ 130 | a20_check: 131 | push %si 132 | push %di 133 | push %es 134 | 135 | xor %ax, %ax 136 | not %ax 137 | mov %ax, %es 138 | 139 | mov $0x514, %di // ES:DI points to 0x100504. 140 | mov $0x504, %si // DS:SI points to 0x504. 141 | 142 | movb $0, %ds:(%si) // 0x500 now has 0x00 stored in it. 143 | movb %al, %es:(%di) // Write 0xFF at 0x100504 to see if it overwrites 0x504. 144 | 145 | lodsb 146 | cmp %ah, %al // If overwritten, then A20 is not enabled. 147 | je .disabled 148 | 149 | stc 150 | jmp .ret 151 | 152 | .disabled: 153 | clc 154 | .ret: 155 | pop %es 156 | pop %di 157 | pop %si 158 | ret 159 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/abort_boot.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | .code16 17 | .section base 18 | 19 | .global stage1_error_msg 20 | stage1_error_msg: .ascii "Gandr stage1 fatal error. " 21 | .byte 0 22 | 23 | /*! Abort boot. 24 | * Plays note A, 5th octave, 880Hz. Credits to contrapunctus 25 | * from #music at freenode. 26 | * \param %si points to error string. 27 | */ 28 | .global abort_boot 29 | abort_boot: 30 | push %si 31 | mov $stage1_error_msg, %si 32 | call output_string 33 | pop %si 34 | call output_string 35 | 36 | .global abort_boot_hcf 37 | abort_boot_hcf: 38 | cli 39 | 40 | /* Write to command register (0x43). 41 | * 10XXXXXXb - channel 2. 42 | * 11XXXXb - access mode lobyte/hibyte. 43 | * 011Xb - mode 3, square wave generator. 44 | * 0b - 16-bit binary mode. 45 | */ 46 | mov $0xB6, %al 47 | outb %al, $0x43 48 | 49 | // I/O delay. 50 | jmp . + 2 51 | jmp . + 2 52 | 53 | /* 54 | * reloadValue = 1193180/frequency; (1193180 -> PIT oscillator) 55 | * = 1193180/880 = 0x54C; 56 | */ 57 | 58 | // Write to channel 2, data port (0x42). 59 | // Lower 8-bits. 60 | mov $0x4C, %al 61 | out %al, $0x42 62 | 63 | jmp . + 2 64 | jmp . + 2 65 | 66 | // Upper 8-bits. 67 | mov $0x05, %al 68 | out %al, $0x42 69 | 70 | // Port 0x61 controls gate input for PC speaker. 71 | // Bit 0 enables timer input to PC speaker; bit 1 enables speaker. 72 | in $0x61, %al 73 | or $0x03, %al 74 | out %al, $0x61 75 | 76 | // Can enable interrupts. 77 | sti 78 | 79 | .halt: 80 | hlt 81 | jmp .halt 82 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/api.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Owen Shepherd & Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | 18 | .code16 19 | 20 | .global api_table 21 | .global stack_top, bal_stack_top 22 | 23 | stack_top = 0x8000 24 | bal_stack_top = 0x10000 25 | 26 | .data 27 | api_table: 28 | .ascii "BIOS" 29 | .long api_table_end - api_table 30 | .long stack_top 31 | .word api_far_call, PM_CS16 32 | .word api_int_call, PM_CS16 33 | api_table_end: 34 | 35 | .text 36 | api_far_call: 37 | // Set registers as passed 38 | call pm16_to_rm 39 | popw %ds 40 | popw %es 41 | popw %fs 42 | popw %gs 43 | 44 | popal 45 | popfl 46 | 47 | popl far_call_ptr 48 | lcall *far_call_ptr 49 | 50 | pushfl 51 | pushal 52 | pushw %gs 53 | pushw %fs 54 | pushw %es 55 | pushw %ds 56 | call rm_to_pm16 57 | 58 | // Switch back to normal running 59 | mov $PM_DS32, %ax 60 | mov %ax, %ds 61 | mov %ax, %es 62 | mov %ax, %fs 63 | mov %ax, %gs 64 | mov %ax, %ss 65 | movl stack_top - 4, %esp 66 | // Jump back into (32-bit/64-bit) code 67 | lretl 68 | .comm far_call_ptr, 4 69 | 70 | api_int_call: 71 | call pm16_to_rm 72 | // Patch the int instruction 73 | mov %al, (1f+1) 74 | // Set registers as passed 75 | popw %ds 76 | popw %es 77 | popw %fs 78 | popw %gs 79 | 80 | popal 81 | popfl 82 | 83 | 1: int $0x00 84 | 85 | pushfl 86 | pushal 87 | pushw %gs 88 | pushw %fs 89 | pushw %es 90 | pushw %ds 91 | call rm_to_pm16 92 | 93 | // Switch back to normal running 94 | mov $PM_DS32, %ax 95 | mov %ax, %ds 96 | mov %ax, %es 97 | mov %ax, %fs 98 | mov %ax, %gs 99 | mov %ax, %ss 100 | movl stack_top - 4, %esp 101 | // Jump back into (32-bit/64-bit) code 102 | lretl 103 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/eltorito/link.ld: -------------------------------------------------------------------------------- 1 | LD_FEATURE("SANE_EXPR") 2 | ENTRY(_start) 3 | 4 | MEMORY 5 | { 6 | STAGE1 : ORIGIN = 0x0600, LENGTH = 0x2A00 7 | } 8 | 9 | SECTIONS 10 | { 11 | .text : 12 | { 13 | _bootsector_start = .; 14 | *(base.start) 15 | *(base) 16 | _bootsector_end = .; 17 | *(.text*) 18 | *(.rodata*) 19 | } >STAGE1 20 | 21 | .data : 22 | { 23 | *(.data) 24 | } >STAGE1 25 | 26 | .bss : 27 | { 28 | bss_start = ABSOLUTE(.); 29 | *(.bss*) 30 | *(COMMON) 31 | bss_end = ABSOLUTE(.); 32 | } >STAGE1 33 | 34 | ASSERT(_bootsector_end - _bootsector_start < 2048, "Bootsector must be < 2048 bytes") 35 | } -------------------------------------------------------------------------------- /bal/platform/bios/stage1/init.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Owen Shepherd & Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | 18 | .code16 19 | .section base.start 20 | 21 | #define BAL_LOAD_ADDRESS 0x10000 22 | 23 | /*! Entry point. 24 | * \param dl the drive number 25 | * \param cs:ip the linear address 0x7C00 26 | */ 27 | .global _start 28 | _start: 29 | #ifdef BD_ELTORITO 30 | // Have space for the boot information table passed by mkisofs. 31 | jmp .relocate 32 | 33 | .align 8 34 | .global eltorito_info 35 | eltorito_info: 36 | .long 0 37 | .long 0 38 | .long 0 39 | .long 0 40 | .skip 40, 0 41 | 42 | .relocate: 43 | #endif 44 | // Relocate us down to 0x0600. 45 | #ifdef BD_PXE 46 | push %es 47 | #endif 48 | 49 | xor %ax, %ax 50 | mov %ax, %es 51 | mov %ax, %ds 52 | 53 | mov $0x0600, %di 54 | mov $0x7C00, %si 55 | 56 | #ifdef BD_PXE 57 | mov $(data_end - 0x0600 + 0x01), %cx 58 | shr $1, %cx /* Division in expressions doesn't seem to work in GAS. */ 59 | #elif defined(BD_ELTORITO) 60 | mov $1024, %cx 61 | #else 62 | #error Unsupported boot device. 63 | #endif 64 | 65 | cld 66 | rep movsw 67 | 68 | #ifdef BD_PXE 69 | pop %es 70 | #endif 71 | 72 | // Do a far jump to reset CS to 0x0000. 73 | ljmp $0x0000, $reset_cs 74 | 75 | reset_cs: 76 | #ifndef BD_PXE 77 | // Set the stack just below where we start. 78 | // For PXE, there is already a stack set up. 79 | // And, storage_init requires %ss:%sp to be PXE-sane. 80 | mov %ax, %ss 81 | mov $stack_top, %sp 82 | #endif 83 | 84 | // Clear the BSS. 85 | mov $bss_start, %di 86 | xor %ax, %ax 87 | 88 | mov $(bss_end + 1), %cx 89 | sub $(bss_start), %cx 90 | shr $1, %cx /* Division in expressions doesn't seem to work in GAS. */ 91 | rep stosw 92 | 93 | call output_init 94 | 95 | pushf 96 | pop %ax 97 | 98 | // Only set on 8086 and 80186. 99 | test $0x80, %ah 100 | jnz .error_no_bal 101 | 102 | // Invert the IOPL bits, since on 8086/80186/80286 they are hardwired to 1. 103 | // In real mode on the 286, they are always 0, though. 104 | xor $0x30, %ah 105 | 106 | push %ax 107 | popf 108 | pushf 109 | pop %cx 110 | 111 | // Test if bits changed, or not. 112 | xor %cx, %ax 113 | test $0x30, %ah 114 | jnz .error_not_386 115 | 116 | /* Clear upper half of ESP. */ 117 | movzwl %sp, %esp 118 | call storage_init 119 | 120 | jmp 0f 121 | 122 | .error_not_386: 123 | #ifdef BD_PXE 124 | xor %ax, %ax 125 | mov %ax, %es 126 | #endif 127 | mov $not_386_error_msg, %si 128 | jmp abort_boot 129 | 130 | not_386_error_msg: 131 | .ascii "The CPU is not Intel 80386 compatible." 132 | .byte 0 133 | 134 | // Loaded complete stage1. 135 | .text 136 | 0: 137 | xor %ax, %ax 138 | #ifdef BD_PXE 139 | mov %ax, %es 140 | mov %ax, %ss 141 | mov $stack_top, %esp 142 | #endif 143 | 144 | mov %ax, %fs 145 | mov %ax, %gs 146 | 147 | // Enable A20 gate. 148 | call a20_enable 149 | 150 | pushfl 151 | pop %eax 152 | mov %eax, %ecx 153 | 154 | // CPUID only supportable if bit 21 is modifiable. 155 | xor $0x200000, %eax 156 | push %eax 157 | popfl 158 | 159 | pushfl 160 | pop %eax 161 | xor %ecx, %eax 162 | and $0x200000, %eax 163 | jz .no_cpuid 164 | 165 | // CPUID is supported, figure out if 64-bit is supported. 166 | // Test for extended function 1. 167 | mov $0x80000000, %eax 168 | cpuid 169 | cmp $0x80000001, %eax 170 | jb .no_long_mode 171 | 172 | mov $0x80000001, %eax 173 | cpuid 174 | // Test LM bit. 175 | test $(1 << 29), %edx 176 | jz .no_long_mode 177 | 178 | movw $0x3436 /* 64 */, bal + 7 179 | mov $bal, %esi 180 | call file_open 181 | 182 | test %eax, %eax 183 | jne .no_long_mode 184 | 185 | movb $1, bal_is_64bit 186 | jmp .read_bal 187 | 188 | .no_long_mode: 189 | .no_cpuid: 190 | movb $0, bal_is_64bit 191 | movw $0x3233 /* 32 */, bal + 7 192 | mov $bal, %esi 193 | 194 | call file_open 195 | 196 | test %eax, %eax 197 | jne .error_no_bal 198 | 199 | // Read BAL. 200 | .read_bal: 201 | mov $BAL_LOAD_ADDRESS, %edi 202 | call file_read 203 | 204 | call file_close 205 | 206 | jmp Lgo_stage2 207 | 208 | .hlt: 209 | hlt 210 | jmp .hlt 211 | 212 | .error_no_bal: 213 | mov $no_bal_error_msg, %si 214 | jmp abort_boot 215 | 216 | .data 217 | no_bal_error_msg: 218 | .ascii "No Boot Abstraction Layer found on the boot device." 219 | .byte 0 220 | 221 | .text 222 | Lgo_stage2: 223 | cli 224 | // Load the GDT. 225 | lgdt gdtr 226 | 227 | // Stick the right segment in the jump pointer structure 228 | mov bal_is_64bit, %bl 229 | mov $PM_CS32, %cx 230 | test %bl, %bl 231 | jz Lnot_64bit 232 | mov $PM_CS64, %cx 233 | // TODO: set cr0 flags, and other control registers. 234 | Lnot_64bit: 235 | mov %cx, stage2_entry+4 236 | 237 | mov $BAL_LOAD_ADDRESS >> 4, %cx 238 | mov %cx, %es 239 | es mov (BAL_LOAD_ADDRESS & 0x0F) + 0x04, %eax 240 | mov %eax, stage2_entry 241 | 242 | // Setup (64/32-bit) protected mode and go 243 | call rm_to_pm16 244 | mov $PM_DS32, %cx 245 | mov %cx, %ds 246 | mov %cx, %es 247 | mov %cx, %fs 248 | mov %cx, %gs 249 | mov %cx, %ss 250 | mov $bal_stack_top, %esp 251 | 252 | mov $api_table, %edi 253 | Ljump_to_stage_2: 254 | data32 ljmp *stage2_entry 255 | 256 | .comm stage2_entry, 6 257 | .comm bal_is_64bit, 1 258 | 259 | .data 260 | #ifndef BD_ELTORITO 261 | bal: .ascii "gd_bal. " 262 | .byte 0 263 | #else 264 | bal: .ascii "gd_bal. ;1" 265 | .byte 0 266 | #endif 267 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/modeswitch.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | 18 | .code16 19 | 20 | .section .data 21 | 22 | .global gdtr 23 | gdtr: 24 | .word (8 * 6) - 1 25 | .long gdt 26 | 27 | gdt: 28 | .long 0x00000000, 0x00000000 29 | 30 | // CS16. 31 | .word 0xFFFF, 0x0000 32 | .byte 0x00, 0x9A, 0x0F, 0x00 33 | 34 | // DS16. 35 | .word 0xFFFF, 0x0000 36 | .byte 0x00, 0x92, 0x0F, 0x00 37 | 38 | // CS32. 39 | .word 0xFFFF, 0x0000 40 | .byte 0x00, 0x9A, 0xCF, 0x00 41 | 42 | // DS32. 43 | .word 0xFFFF, 0x0000 44 | .byte 0x00, 0x92, 0xCF, 0x00 45 | 46 | // CS64. 47 | .long 0x00000000 48 | .byte 0x00, 0x98, 0x20, 0x00 49 | 50 | // Bits that need to be set to enter and exit protected mode 51 | // If we are loading a 64-bit BAL, these will be adjusted to set/clear 52 | // CR0.PG as well. 53 | .global pm_cr0_bits, pm_cr0_mask 54 | .align 4 55 | pm_cr0_bits: .long 0x00000001 56 | pm_cr0_mask: .long ~0x00000001 57 | 58 | .section .text 59 | .global rm_to_pm16, pm16_to_rm 60 | 61 | //! Switch to PM16 62 | //! Includes reloading all segment registers 63 | //! FS will be set to DS32 64 | rm_to_pm16: pushf 65 | cli 66 | push %eax 67 | 68 | // Load the GDT in case malcompliant messes with it. 69 | lgdt gdtr 70 | 71 | mov %cr0, %eax 72 | or pm_cr0_bits, %eax 73 | mov %eax, %cr0 74 | 75 | mov $PM_DS16, %ax 76 | mov %ax, %ds 77 | mov %ax, %es 78 | mov %ax, %ss 79 | mov %ax, %gs 80 | mov $PM_DS32, %ax 81 | mov %ax, %fs 82 | 83 | ljmp $PM_CS16, $1f 84 | 1: pop %eax 85 | popf 86 | ret 87 | 88 | //! Switch from PM16 to RM 89 | //! All segments will be reloaded with 16-bit limits 90 | pm16_to_rm: pushf 91 | cli 92 | push %eax 93 | movw $PM_DS16, %ax 94 | movw %ax, %ds 95 | movw %ax, %es 96 | movw %ax, %fs 97 | movw %ax, %gs 98 | movw %ax, %ss 99 | 100 | mov %cr0, %eax 101 | and pm_cr0_mask, %eax 102 | mov %eax, %cr0 103 | 104 | movw $RM_DS, %ax 105 | movw %ax, %ds 106 | movw %ax, %es 107 | movw %ax, %fs 108 | movw %ax, %gs 109 | movw %ax, %ss 110 | 111 | ljmp $RM_CS, $1f 112 | 1: pop %eax 113 | popf 114 | ret 115 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/output.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | .code16 17 | .section base 18 | 19 | active_page: .byte 0 20 | 21 | //! Initiates output. 22 | .global output_init 23 | output_init: 24 | pusha 25 | push %es 26 | 27 | // Set mode (ah = 0x00) to 80*25 text mode (al = 0x03). 28 | mov $0x0003, %ax 29 | int $0x10 30 | 31 | // Point es to video memory. 32 | mov $0xB800, %ax 33 | mov %ax, %es 34 | 35 | // Get active page. 36 | xor %bx, %bx 37 | mov $0x0F, %ah 38 | int $0x10 39 | mov %bh, (active_page) 40 | 41 | // Set the cursor to 00,00. 42 | // ah = 0x02, int 0x10, to set cursor position. 43 | // bh = page number. 44 | // dh = row; dl = column. 45 | xor %dx, %dx 46 | mov $0x02, %ah 47 | int $0x10 48 | 49 | // Hide the cursor. 50 | // ah = 0x01, int 0x10, to set cursor shape. 51 | // cl = bottom scan line containing cursor; ch = 0x10 = invisible cursor. 52 | // al needs to be equal to current mode (0x03). 53 | mov $0x1000, %cx 54 | mov $0x0103, %ax 55 | int $0x10 56 | 57 | // Clear screen to black background, white foreground, spaces. 58 | xor %di, %di 59 | mov $2000, %cx 60 | mov $0x0F20, %ax 61 | rep stosw 62 | 63 | pop %es 64 | popa 65 | ret 66 | 67 | /*! Outputs a null terminated string. 68 | * \param es:si point to null terminated string 69 | */ 70 | .global output_string 71 | output_string: 72 | push %si 73 | push %ax 74 | 75 | // Some BIOS may destroy BP if display is getting scrolled. 76 | push %bp 77 | 78 | .loop: 79 | // Load the value at [es:si] in al. 80 | lodsb 81 | 82 | // Stop if it is the null terminator. 83 | test %al, %al 84 | jz .done 85 | 86 | cmp $0x0A, %al // New line? 87 | jne 0f 88 | 89 | mov $0x0E, %ah 90 | mov (active_page), %bh 91 | int $0x10 92 | 93 | // Output carriage return. 94 | mov $0x0D, %al 95 | 0: 96 | // Output character; ah = 0x0E; al = character; bh = page number; 97 | mov $0x0E, %ah 98 | mov (active_page), %bh 99 | int $0x10 100 | jmp .loop 101 | 102 | .done: 103 | pop %bp 104 | 105 | pop %ax 106 | pop %si 107 | ret 108 | 109 | // Hexadecimal to string buffer. 110 | // 0x30 to get ascii 0. 111 | hexadecimal_buffer: 112 | .byte '0', 'x', 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 113 | .byte 0x00 114 | 115 | /*! Outputs a hexadecimal value. 116 | * \param eax value to output 117 | */ 118 | .global output_hexadecimal 119 | output_hexadecimal: 120 | push %di 121 | push %si 122 | 123 | // +2 for the 0x part. 124 | mov $hexadecimal_buffer + 2, %di 125 | mov $hexadecimal_buffer, %si 126 | call itoa 127 | call output_string 128 | 129 | pop %si 130 | pop %di 131 | ret 132 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/pxe/link.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | MEMORY 4 | { 5 | STAGE1 : ORIGIN = 0x0600, LENGTH = 0x2A00 6 | } 7 | 8 | SECTIONS 9 | { 10 | .text 0x0600 : 11 | { 12 | *(base.start) 13 | *(base) 14 | *(.text*) 15 | *(.rodata*) 16 | } >STAGE1 17 | 18 | .data : 19 | { 20 | *(.data) 21 | data_end = ABSOLUTE(.); 22 | } >STAGE1 23 | 24 | .bss : 25 | { 26 | bss_start = ABSOLUTE(.); 27 | *(.bss*) 28 | *(COMMON) 29 | bss_end = ABSOLUTE(.); 30 | } >STAGE1 31 | } 32 | -------------------------------------------------------------------------------- /bal/platform/bios/stage1/string.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | .code16 17 | .section base 18 | 19 | /*! Convert integer to string (base 16). 20 | * \param %eax the original integer. 21 | * \param %di the destination. 22 | */ 23 | .global itoa 24 | itoa: 25 | push %ebx 26 | push %cx 27 | 28 | mov $8, %cx 29 | 30 | mov $0x30303030, %ebx 31 | movl %ebx, (%di) 32 | movl %ebx, 4(%di) 33 | 34 | add $8, %di 35 | .loop_digits: 36 | dec %di 37 | // Get the lower 4 bits. 38 | mov %al, %bl 39 | and $0x0F, %bl 40 | 41 | // If it is greater than 9, then add 7 to get 'A' (0x41). 42 | cmp $9, %bl 43 | jbe .numeric 44 | 45 | add $7, %bl 46 | 47 | .numeric: 48 | add %bl, (%di) 49 | 50 | // Next value. 51 | ror $4, %eax 52 | loop .loop_digits 53 | 54 | pop %cx 55 | pop %ebx 56 | ret 57 | -------------------------------------------------------------------------------- /bal/platform/bios/tables.c: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | gd_rsdt_pointer_table rsdt_pointer = { .header = { .id = GD_RSDT_POINTER_TABLE_ID } }; 23 | gd_pc_pointer_table pc_pointer = { .header = { .id = GD_PC_POINTER_TABLE_ID } }; 24 | 25 | /*! Checksum a table, and return the checksum. */ 26 | static uint8_t checksum_table(const uint8_t *table, size_t length) 27 | { 28 | uint8_t checksum = 0; 29 | for (size_t i = 0; i < length; i++) checksum += table[i]; 30 | return checksum; 31 | } 32 | 33 | static void search_region(const uint8_t *region, size_t length, bool rsdp_search, 34 | bool mpfp_search, bool smbios_search) 35 | { 36 | for (size_t i = 0; i < length; region += 16, i += 16) { 37 | if (rsdp_search == false && 38 | mpfp_search == false && 39 | smbios_search == false) 40 | return; 41 | 42 | if (rsdp_search == true && 43 | TABLE_SIGNATURE(region[0], region[1], region[2], region[3]) == RSDP_SIGNATURE_LOW && 44 | TABLE_SIGNATURE(region[4], region[5], region[6], region[7]) == RSDP_SIGNATURE_HIGH && 45 | checksum_table(region, sizeof (struct rsdp)) == 0) { 46 | const struct rsdp_extended* rsdp = (struct rsdp_extended *) region; 47 | rsdt_pointer.header.length = sizeof rsdt_pointer; 48 | rsdt_pointer.rsdt_address = rsdp->rsdt_address; 49 | 50 | if (rsdp->revision > 0 /* XSDT supported */ && 51 | checksum_table(region, rsdp->length) == 0) { 52 | rsdt_pointer.xsdt_address = rsdp->xsdt_address; 53 | } 54 | rsdp_search = false; 55 | } 56 | 57 | if (mpfp_search == true && 58 | TABLE_SIGNATURE(region[0], region[1], region[2], region[3]) == MPFP_SIGNATURE && 59 | checksum_table(region, ((mpfp_structure *) region)->length * 0x10) == 0) { 60 | pc_pointer.header.length = sizeof pc_pointer; 61 | 62 | /* Only copy till as much space as we reserve. */ 63 | memcpy(&pc_pointer.mpfp, region, ((mpfp_structure *) region)->length * 0x10 > sizeof (mpfp_structure) ? 64 | sizeof (mpfp_structure) : ((mpfp_structure *) region)->length * 0x10); 65 | mpfp_search = false; 66 | } 67 | 68 | if (smbios_search == true && 69 | TABLE_SIGNATURE(region[0], region[1], region[2], region[3]) == SMBIOS_ENTRY_POINT_SIGNATURE && 70 | checksum_table(region, ((struct smbios_entry_point *) region)->length) == 0) { 71 | 72 | pc_pointer.header.length = sizeof pc_pointer; 73 | pc_pointer.smbios_entry_point_address = (uintptr_t) region; 74 | smbios_search = false; 75 | } 76 | } 77 | } 78 | 79 | /*! Find all the available tables. The respective gd_* tables have non-zero 80 | * size if any tables they describe have been located. */ 81 | void tables_init() 82 | { 83 | /*! ACPI: 84 | * first kilobyte of EBDA. 85 | * BIOS ROM address space, 0xE0000 to 0xFFFFF. 86 | * 87 | * MPFP: 88 | * first kilobyte of EBDA. 89 | * last kilobyte of system base memory. 90 | * BIOS ROM address space, 0xE0000 to 0xFFFFF. 91 | * 92 | * SMBIOS: 93 | * BIOS ROM address space, 0xF0000 to 0xFFFFF. 94 | */ 95 | 96 | /* The BDA is supposed to contain a pointer to the EBDA. */ 97 | uintptr_t ebda = *((uint16_t*) 0x40E) << 4; 98 | uintptr_t base_memory = get_base_memory(); 99 | 100 | if (ebda && ebda > base_memory && ebda < 0xA0000) { 101 | search_region((uint8_t*) ebda, 1024, true, true, false); 102 | } else { 103 | /*! Assume EBDA to start at end of base memory. */ 104 | search_region((uint8_t*) base_memory, 1024, true, true, false); 105 | } 106 | 107 | /* Search in last kilobyte of system base memory. */ 108 | search_region((uint8_t*) (base_memory - 1024), 1024, false, true && !pc_pointer.mpfp.length, false); 109 | 110 | /* Search in the BIOS ROM address space. */ 111 | search_region((uint8_t*) 0xE0000, 0x10000, true && !rsdt_pointer.header.length, 112 | true && !pc_pointer.mpfp.length, 113 | false); 114 | 115 | /* Search in the BIOS ROM address space. */ 116 | search_region((uint8_t*) 0xF0000, 0x10000, true && !rsdt_pointer.header.length, 117 | true && !pc_pointer.mpfp.length, 118 | true); 119 | } 120 | -------------------------------------------------------------------------------- /bal/soc/am33xx/Config.jam: -------------------------------------------------------------------------------- 1 | GdIncludeDir $(GD_TOP) soc am33xx ; 2 | 3 | SUPPORTED_ARCHITECTURES = arm ; 4 | ARCH ?= arm ; 5 | 6 | AM33XX_LINKERSCRIPT = [ FDirName $(GD_TOP) bal soc am33xx am33xx.ld ] ; 7 | 8 | rule GdBalBinaries { 9 | LinkWithScript gd_$(PLATFORM).elf : $(GD_BAL_OBJECTS) : $(AM33XX_LINKERSCRIPT) ; 10 | #LinkLibraries gd_$(PLATFORM).elf : $(PDCLIB) ; 11 | ObjCopy gd_$(PLATFORM).bin : gd_$(PLATFORM).elf : -O binary ; 12 | Depends exe : gd_$(PLATFORM).bin ; 13 | } -------------------------------------------------------------------------------- /bal/soc/am33xx/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP bal soc am33xx ; 2 | 3 | GdBalSources 4 | entry.S 5 | ; 6 | -------------------------------------------------------------------------------- /bal/soc/am33xx/am33xx.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 3 | * Copyright (C) 2013 Owen Shepherd - http://owenshepherd.net/ 4 | */ 5 | /* 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 13 | * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the 16 | * distribution. 17 | * 18 | * Neither the name of Texas Instruments Incorporated nor the names of 19 | * its contributors may be used to endorse or promote products derived 20 | * from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | /* Linker script for Gandr on TI AM33XX SoCs. Derived from the Starterware 37 | * linkerscript 38 | */ 39 | 40 | MEMORY 41 | { 42 | IRAM_MEM : o = 0x402F0400, l = 0x1FBFF /* 127k internal Memory */ 43 | } 44 | 45 | OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 46 | OUTPUT_ARCH(arm) 47 | 48 | SECTIONS 49 | { 50 | .ti_hdr : { 51 | _start = .; 52 | LONG(_image_size); 53 | LONG(_start); 54 | } >IRAM_MEM 55 | 56 | .text : 57 | { 58 | . = ALIGN(4); 59 | *(entry) 60 | 61 | /* Force us past the first 64kB of SRAM 62 | * The debug TAP can't see into it - OpenOCD bug perhaps? 63 | */ 64 | . += 65536; 65 | *(.text*) 66 | *(.rodata*) 67 | } >IRAM_MEM 68 | 69 | .data : 70 | { 71 | . = ALIGN(4); 72 | *(.data*) 73 | _end = .; 74 | } >IRAM_MEM 75 | 76 | .bss : 77 | { 78 | . = ALIGN(4); 79 | _bss_start = .; 80 | *(.bss*) 81 | *(COMMON) 82 | _bss_end = .; 83 | } >IRAM_MEM 84 | 85 | _image_size = _end - _start; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /bal/soc/am33xx/entry.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | .syntax unified 17 | .arm 18 | .section entry 19 | .globl _entry 20 | _entry: ldr sp, =(stack + 0x1000) 21 | b main 22 | 23 | .comm stack, 0x1000 -------------------------------------------------------------------------------- /bal/syscall.txt: -------------------------------------------------------------------------------- 1 | // core syscalls 2 | at 0x00000000 3 | syscall alloc_pages(gd_memory_type type, void **presult, size_t count) 4 | syscall free_pages(void *start_address, size_t count) 5 | -------------------------------------------------------------------------------- /bal/syscall_stubs/gd_syscall_stub.S: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | .global gd_syscall 17 | 18 | #if defined(__i386__) || defined(__amd64__) 19 | 20 | gd_syscall: 21 | jmp *(gd_syscall_p) 22 | 23 | #elif defined(__arm__) 24 | ldr r5, =gd_syscall_p 25 | ldr pc, [r5] 26 | 27 | #elif defined(__aarch64__) 28 | 29 | gd_ioctl: 30 | ldr x16, =gd_syscall_p 31 | ldr x16, [x16] 32 | br x16 33 | 34 | #else 35 | 36 | #error You need to define an ioctl stub for this arch 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/arch/aarch64/asm_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef ASM_MACROS_H 2 | #define ASM_MACROS_H 3 | 4 | .macro func_special name 5 | .type \name, @function 6 | \name: 7 | .endm 8 | 9 | .macro func name 10 | .section .text.\name 11 | func_special \name 12 | .endm 13 | 14 | .macro endfunc name 15 | .size \name, .-\name 16 | .endm 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/arch/aarch64/bal/gio_arch.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/arch/arm/bal/gio_arch.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/arch/x86/bal/gio_arch.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GIO_ARCH_H 17 | #define GIO_ARCH_H 18 | #include 19 | #include 20 | #include 21 | 22 | /* GIO implementation for x86 */ 23 | 24 | /* Always 8 bytes, even on i386 25 | * 26 | * Discriminator is MSB of 8 byte address, i.e. type field. AMD64 has 27 | * architecturally defined paddr limit of 56-bits, which leaves the upper 8 bits 28 | * for us to play with (and anyway we could only address 48-bits of RAM). Store 29 | * a tag there. 30 | * 31 | * For efficiency reasons, let type == 0 be MMIO. x86 only has one other I/O 32 | * type, port IO, which is type != 0. 33 | */ 34 | typedef union { 35 | uint64_t _ensure_size_and_pad; 36 | 37 | volatile void *mmio_base; 38 | 39 | struct { 40 | uint16_t portio_base; 41 | uint8_t _portio_pad[5]; 42 | uint8_t type; 43 | }; 44 | } gio_addr; 45 | 46 | #define GIO_MMIO_ADDR(_addr) ((gio_addr){ .mmio_base = (void*) (_addr) }) 47 | #define GIO_PORTIO_ADDR(_addr) ((gio_addr){ .portio_base = (_addr), .type = 1}) 48 | 49 | static inline void gio_write8_offset(gio_addr addr, size_t offs, uint8_t val) 50 | { 51 | if(addr.type == 0) { 52 | volatile uint8_t *ptr = ((volatile uint8_t*) addr.mmio_base) + offs; 53 | *ptr = val; 54 | } else outb(addr.portio_base + offs, val); 55 | } 56 | 57 | static inline void gio_write16_offset(gio_addr addr, size_t offs, uint16_t val) 58 | { 59 | if(addr.type == 0) { 60 | volatile uint16_t *ptr = (volatile uint16_t*) (((volatile char*)addr.mmio_base) + offs); 61 | *ptr = val; 62 | } else outw(addr.portio_base + offs, val); 63 | } 64 | 65 | static inline void gio_write32_offset(gio_addr addr, size_t offs, uint32_t val) 66 | { 67 | if(addr.type == 0) { 68 | volatile uint32_t *ptr = (volatile uint32_t*) (((volatile char*)addr.mmio_base) + offs); 69 | *ptr = val; 70 | } else outl(addr.portio_base + offs, val); 71 | } 72 | 73 | static inline uint8_t gio_read8_offset(gio_addr addr, size_t offs) 74 | { 75 | if(addr.type == 0) { 76 | volatile uint8_t *ptr = ((volatile uint8_t*) addr.mmio_base) + offs; 77 | return *ptr; 78 | } else return inb(addr.portio_base + offs); 79 | } 80 | 81 | static inline uint16_t gio_read16_offset(gio_addr addr, size_t offs) 82 | { 83 | if(addr.type == 0) { 84 | volatile uint16_t *ptr = (volatile uint16_t*) (((volatile char*)addr.mmio_base) + offs); 85 | return *ptr; 86 | } else return inw(addr.portio_base + offs); 87 | } 88 | 89 | static inline uint32_t gio_read32_offset(gio_addr addr, size_t offs) 90 | { 91 | if(addr.type == 0) { 92 | volatile uint32_t *ptr = (volatile uint32_t*) (((volatile char*)addr.mmio_base) + offs); 93 | return *ptr; 94 | } else return inl(addr.portio_base + offs); 95 | } 96 | 97 | static inline void gio_write8_index(gio_addr addr, size_t idx, uint8_t val) 98 | { gio_write8_offset(addr, idx, val); } 99 | 100 | static inline void gio_write16_index(gio_addr addr, size_t idx, uint16_t val) 101 | { gio_write16_offset(addr, idx * 2, val); } 102 | 103 | static inline void gio_write32_index(gio_addr addr, size_t idx, uint32_t val) 104 | { gio_write32_offset(addr, idx * 4, val); } 105 | 106 | static inline uint8_t gio_read8_index(gio_addr addr, size_t idx) 107 | { return gio_read8_offset(addr, idx); } 108 | 109 | static inline uint16_t gio_read16_index(gio_addr addr, size_t idx) 110 | { return gio_read16_offset(addr, idx * 2); } 111 | 112 | static inline uint32_t gio_read32_index(gio_addr addr, size_t idx) 113 | { return gio_read32_offset(addr, idx * 4); } 114 | 115 | static inline void gio_write8(gio_addr addr, uint8_t val) 116 | { gio_write8_offset(addr, 0, val); } 117 | 118 | static inline void gio_write16(gio_addr addr, uint16_t val) 119 | { gio_write16_offset(addr, 0, val); } 120 | 121 | static inline void gio_write32(gio_addr addr, uint32_t val) 122 | { gio_write32_offset(addr, 0, val); } 123 | 124 | static inline uint8_t gio_read8(gio_addr addr) 125 | { return gio_read8_offset(addr, 0); } 126 | 127 | static inline uint16_t gio_read16(gio_addr addr) 128 | { return gio_read16_offset(addr, 0); } 129 | 130 | static inline uint32_t gio_read32(gio_addr addr) 131 | { return gio_read32_offset(addr, 0); } 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /include/arch/x86/bal/portio.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef PORTIO_H 17 | #define PORTIO_H 18 | #include 19 | 20 | static inline void outb(uint16_t port, uint8_t val) 21 | { 22 | __asm volatile( "out %0, %1" : : "a"(val), "Nd"(port) ); 23 | } 24 | 25 | static inline uint8_t inb(uint16_t port) 26 | { 27 | uint8_t val; 28 | __asm volatile( "in %1, %0" : "=a"(val) : "Nd"(port) ); 29 | return val; 30 | } 31 | 32 | static inline void outw(uint16_t port, uint16_t val) 33 | { 34 | __asm volatile( "out %0, %1" : : "a"(val), "Nd"(port) ); 35 | } 36 | 37 | static inline uint16_t inw(uint16_t port) 38 | { 39 | uint16_t val; 40 | __asm volatile( "in %1, %0" : "=a"(val) : "Nd"(port) ); 41 | return val; 42 | } 43 | 44 | static inline void outl(uint16_t port, uint32_t val) 45 | { 46 | __asm volatile( "out %0, %1" : : "a"(val), "Nd"(port) ); 47 | } 48 | 49 | static inline uint32_t inl(uint16_t port) 50 | { 51 | uint32_t val; 52 | __asm volatile( "in %1, %0" : "=a"(val) : "Nd"(port) ); 53 | return val; 54 | } 55 | 56 | #ifdef __amd64__ 57 | static inline void outq(uint16_t port, uint64_t val) 58 | { 59 | __asm volatile( "out %0, %1" : : "a"(val), "Nd"(port) ); 60 | } 61 | 62 | static inline uint64_t inq(uint16_t port) 63 | { 64 | uint64_t val; 65 | __asm volatile( "in %1, %0" : "=a"(val) : "Nd"(port) ); 66 | return val; 67 | } 68 | #endif 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/bal/device/bus.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | #ifndef BAL_DEVICE_BUS_H 16 | #define BAL_DEVICE_BUS_H 17 | #endif 18 | -------------------------------------------------------------------------------- /include/bal/device/bus/simple-bus.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | #ifndef BAL_DEVICE_BUS_SIMPLE_BUS_H 16 | #define BAL_DEVICE_BUS_SIMPLE_BUS_H 17 | #include 18 | #include 19 | 20 | struct simple_bus_dev { 21 | GD_DEVICE; 22 | dt_node_t node; 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/bal/device/dt.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef BAL_DEVICE_DT_H 17 | #define BAL_DEVICE_DT_H 18 | #include 19 | #include 20 | 21 | typedef struct dt_property { 22 | RB_ENTRY(dt_property) rbnode; 23 | size_t value_len; 24 | const char * name; 25 | void *value; 26 | } *dt_property_t; 27 | 28 | typedef struct dt_node { 29 | RB_ENTRY(dt_node) rbnode; 30 | RB_HEAD(dt_nodes, dt_node) children; 31 | RB_HEAD(dt_properties, dt_property) properties; 32 | struct dt_node *parent; 33 | gd_device_t bound_device; 34 | const char *name; 35 | } *dt_node_t; 36 | 37 | int dt_property_cmp(dt_property_t lhs, dt_property_t rhs); 38 | int dt_node_cmp(dt_node_t lhs, dt_node_t rhs); 39 | 40 | RB_PROTOTYPE(dt_properties, dt_property, rbnode, dt_property_cmp) 41 | RB_PROTOTYPE(dt_nodes, dt_node, rbnode, dt_node_cmp) 42 | 43 | dt_node_t dt_node_alloc(dt_node_t parent, const char *name); 44 | dt_node_t dt_node_find_child(dt_node_t parent, const char *name); 45 | dt_property_t dt_node_find_property(dt_node_t node, const char *name); 46 | bool dt_node_has_property(dt_node_t node, const char *name); 47 | const void *dt_node_get_property(dt_node_t node, const char *name); 48 | dt_property_t dt_node_set_property( 49 | dt_node_t node, 50 | const char *name, 51 | const void *value, 52 | size_t len); 53 | bool dt_node_get_reg_range( 54 | dt_node_t node, 55 | unsigned idx, 56 | uintptr_t *ptr, 57 | size_t *sz); 58 | 59 | unsigned dt_node_get_reg_count( 60 | dt_node_t node); 61 | uint32_t dt_node_get_address_cells(dt_node_t node); 62 | uint32_t dt_node_get_size_cells(dt_node_t node); 63 | uint32_t dt_property_get_uint32(dt_property_t prop); 64 | uint64_t dt_property_get_uint64(dt_property_t prop); 65 | dt_node_t dt_root_node(void); 66 | 67 | typedef gd_device_t (*dt_driver_attach)(dt_node_t node); 68 | 69 | /*! Structure which identifies a device driver. Place 70 | * BAL_FDT_DECLARE_DEVICE_DRIVER in your driver code in order to declare a 71 | * driver for a device 72 | */ 73 | struct dt_driver { 74 | /*! DeviceTree compatible string */ 75 | const char *compatible; 76 | 77 | /*! Driver attach function */ 78 | dt_driver_attach attach; 79 | }; 80 | 81 | #define DT_DECLARE_DEVICE_DRIVER(sym, name, func) \ 82 | struct dt_driver sym \ 83 | __attribute__((section("dt_drivers"), unused)) = \ 84 | { name, func }; 85 | 86 | int dt_base_ioctl(gd_device_t dev, unsigned ioctl, va_list *pap); 87 | void dt_platform_init_fdt(void *fdt); 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /include/bal/device/fb.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_FB_H 17 | #define GD_BAL_FB_H 18 | 19 | #include 20 | #include 21 | 22 | struct mode_info { 23 | uint32_t mode_identifier; 24 | uint16_t mode_type; 25 | uint32_t mode_attributes; 26 | 27 | uint16_t width; /* In pixels (graphics) or characters (text). */ 28 | uint16_t height; /* In pixels (graphics) or characters (text). */ 29 | uint8_t width_of_char_cell; /* In pixels. */ 30 | uint8_t height_of_char_cell; /* In pixels. */ 31 | uint8_t depth; 32 | uint32_t bytes_per_scanline; 33 | 34 | uint8_t red_mask_size; 35 | uint8_t red_field_pos; 36 | uint8_t green_mask_size; 37 | uint8_t green_field_pos; 38 | uint8_t blue_mask_size; 39 | uint8_t blue_field_pos; 40 | uint8_t reserved_mask_size; 41 | uint8_t reserved_field_pos; 42 | 43 | uint64_t lfb_address; 44 | uint32_t max_pixel_clock; 45 | }; 46 | 47 | enum mode_attributes { 48 | ATTR_RESERVED_FIELD_USABLE = (1 << 0), 49 | ATTR_DOUBLE_SCAN_MODE_SUPPORTED = (1 << 1), 50 | ATTR_INTERLACE_MODE_SUPPORTED = (1 << 2), 51 | ATTR_VGA_COMPATIBLE = (1 << 3) 52 | }; 53 | 54 | enum mode_type { 55 | DIRECT_COLOR_MODE = 0, 56 | PACKED_PIXEL_MODE = 1, 57 | VGA_TEXT_MODE = 2 58 | }; 59 | 60 | enum flags { 61 | CONTIG_SCANLINES = (1 << 0) 62 | }; 63 | 64 | struct pixel_color { 65 | uint8_t red, green, blue; 66 | uint32_t pixel; 67 | }; 68 | 69 | struct fb_dev { 70 | struct gd_device dev; 71 | struct mode_info cur_mode; 72 | 73 | uint32_t max_width, max_height; 74 | uint32_t cur_x, cur_y; 75 | 76 | uint8_t *back_buffer, *front_buffer; 77 | uint32_t back_buffer_start; /*! treat back buffer as circular buffer */ 78 | uint32_t front_dirty_start, front_dirty_end; /*! char lines dirty, not inclusive of end */ 79 | 80 | uint32_t flags; 81 | struct pixel_color foreground, background; 82 | 83 | void (*fb_write_char_depth)(struct fb_dev*, char c); 84 | }; 85 | 86 | void fb_init(struct fb_dev *dev, struct mode_info mode); 87 | 88 | #endif -------------------------------------------------------------------------------- /include/bal/device/uart.h: -------------------------------------------------------------------------------- 1 | #ifndef GD_BAL_UART_H 2 | #define GD_BAL_UART_H 3 | 4 | enum gd_uart_parity { 5 | GD_UART_NO_PARITY = 0, 6 | GD_UART_ODD_PARITY = 1, 7 | GD_UART_EVEN_PARITY = 2, 8 | }; 9 | 10 | enum gd_uart_flow_control { 11 | //! Serial port operating without flow control 12 | GD_UART_NO_FLOW_CONTROL = 0, 13 | //! RTS, CTS flow control (asymmetric). 14 | GD_UART_RTS_CTS_FLOW_CONTROL, 15 | //! RTR, CTS flow control (symmetric) 16 | GD_UART_RTR_CTS_FLOW_CONTROL 17 | }; 18 | 19 | #define GD_FLOW_CONTROL_BIT(bit) (1U << ((unsigned)(bit))) 20 | 21 | struct gd_uart_capabilities { 22 | unsigned fifo_bytes; 23 | unsigned max_baud; 24 | unsigned flow_control_support; 25 | }; 26 | 27 | struct gd_uart_config { 28 | unsigned baud; 29 | unsigned char bits; 30 | enum gd_uart_parity parity; 31 | unsigned char stop_bits; 32 | enum gd_uart_flow_control flow_control; 33 | }; 34 | 35 | int gd_uart_base_ioctl(gd_device_t dev, unsigned, ...); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/bal/device/uart/arm_pl011.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_DEVICE_ARM_PL011_H 17 | #define GD_BAL_DEVICE_ARM_PL011_H 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | typedef struct { 24 | GD_DEVICE; 25 | //! DT node 26 | dt_node_t node; 27 | //! Base address 28 | gio_addr base; 29 | //! BRG clock speed 30 | uint32_t brg_clock; 31 | } arm_pl011_dev; 32 | 33 | #define DEFINE_ARM_PL011(name, base_, brg_clock_) \ 34 | arm_pl011_dev name = { .base = base_, .brg_clock = brg_clock_} 35 | 36 | void arm_pl011_init(arm_pl011_dev *dev); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/bal/device/uart/ns16c550.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef NS16C550_H 17 | #define NS16C550_H 18 | #include 19 | #include 20 | #include 21 | 22 | typedef struct { 23 | struct gd_device dev; 24 | 25 | //! Base address 26 | gio_addr base; 27 | //! FIFO size 28 | uint16_t fifo_size; 29 | //! Known available FIFO space 30 | uint16_t fifo_space; 31 | 32 | //! Register width 33 | uint8_t reg_width; 34 | } ns16c550_dev; 35 | 36 | #define DEFINE_NS16C550(name, base, fifo_size, reg_width) \ 37 | struct ns16c550_dev name = {{&ns16c550_ioctl}, base, fifo_size, 0, reg_width}; 38 | 39 | void ns16c550_init(ns16c550_dev *dev); 40 | int ns16c550_ioctl(gd_device_t dev, unsigned, ...); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/bal/fs/iso9660.h: -------------------------------------------------------------------------------- 1 | #ifndef GD_BAL_FS_ISO9660_H 2 | #define GD_BAL_FS_ISO9660_H 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | struct gd_device dev; 9 | gd_device_t blockdev; 10 | l9660_fs impl; 11 | } iso9660_fs; 12 | 13 | int iso9660fs_init(iso9660_fs *self, gd_device_t blockdev); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/bal/gio.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GIO_H 17 | #define GIO_H 18 | #include 19 | #include 20 | 21 | /*! \defgroup gio Generic I/O 22 | * GIO provides an interface which abstracts the details of the various I/O 23 | * methods possible on the target platform from the driver in question. 24 | * 25 | * The primary example of this is the i386 distinction between port and memory 26 | * mapped I/O. 27 | * 28 | * On all platforms, a \p gio_addr structure can be initialized from a memory 29 | * mapped I/O address by using \p GIO_MMIO_ADDR. Other platforms may define 30 | * other initialization mechanisms. For example, i386 defines 31 | * \p GIO_PORTIO_ADDR. 32 | * 33 | * \{ 34 | */ 35 | 36 | /***** Platform dependent portion *********************************************/ 37 | 38 | //! Write the 8-bit value \p val to (\p addr + \p offs) 39 | void gio_write8_offset(gio_addr addr, size_t offs, uint8_t val); 40 | //! Write the 16-bit value \p val to (\p addr + \p offs) 41 | void gio_write16_offset(gio_addr addr, size_t offs, uint16_t val); 42 | //! Write the 32-bit value \p val to (\p addr + \p offs) 43 | void gio_write32_offset(gio_addr addr, size_t offs, uint32_t val); 44 | 45 | //! Read an 8-bit value from (\p addr + \p offs) 46 | uint8_t gio_read8_offset(gio_addr addr, size_t offs); 47 | //! Read a 16-bit value from (\p addr + \p offs) 48 | uint16_t gio_read16_offset(gio_addr addr, size_t offs); 49 | //! Read a 32-bit value from (\p addr + \p offs) 50 | uint32_t gio_read32_offset(gio_addr addr, size_t offs); 51 | 52 | //! Write an 8-bit value \p val to (\p addr + \p idx * sizeof(uint8_t)) 53 | void gio_write8_index(gio_addr addr, size_t idx, uint8_t val); 54 | //! Write a 16-bit value \p val to (\p addr + \p idx * sizeof(uint16_t)) 55 | void gio_write16_index(gio_addr addr, size_t idx, uint16_t val); 56 | //! Write a 32-bit value \p val to (\p addr + \p idx * sizeof(uint32_t)) 57 | void gio_write32_index(gio_addr addr, size_t idx, uint32_t val); 58 | 59 | //! Read an 8-bit value from (\p addr + \p idx * sizeof(uint8_t)) 60 | uint8_t gio_read8_index(gio_addr addr, size_t idx); 61 | //! Read a 16-bit value from (\p addr + \p idx * sizeof(uint16_t)) 62 | uint16_t gio_read16_index(gio_addr addr, size_t idx); 63 | //! Read a 32-bit value from (\p addr + \p idx * sizeof(uint32_t)) 64 | uint32_t gio_read32_index(gio_addr addr, size_t idx); 65 | 66 | //! Write an 8-bit value \p val to \p addr 67 | void gio_write8(gio_addr addr, uint8_t val); 68 | //! Write a 16-bit value \p val to \p addr 69 | void gio_write16(gio_addr addr, uint16_t val); 70 | //! Write a 32-bit value \p val to \p addr 71 | void gio_write32(gio_addr addr, uint32_t val); 72 | 73 | //! Read an 8-bit value from \p addr 74 | uint8_t gio_read8(gio_addr addr); 75 | //! Read a 16-bit value from \p addr 76 | uint16_t gio_read16(gio_addr addr); 77 | //! Read a 32-bit value from \p addr 78 | uint32_t gio_read32(gio_addr addr); 79 | 80 | /***** Platform independent portion *******************************************/ 81 | 82 | /*! Reinterpret \p value as a \p size bit quantity, then write the resulting 83 | * value to (\p base + \p index * sizeof(\p value)), where the sizeof operator 84 | * is computed after reinterpretation 85 | */ 86 | void gio_write_index(size_t size, gio_addr base, size_t index, size_t value); 87 | /*! Read from the address (\p base + \p index * sizeof(uintN_t)), where the N 88 | * in uintN_t is defined to be one of (8, 16, 32) as given by the size 89 | * parameter, where the size of the read in bits is given by \p size, and 90 | * return the result 91 | */ 92 | size_t gio_read_index(size_t size, gio_addr base, size_t index); 93 | 94 | // XXX: gio_[read|write]_offset 95 | 96 | /*! Write \p value to the address \p base wherein \p value is reinterpreted as 97 | * a value of one of the types (uint8_t, uint16_t, uint32_t) in which the bit 98 | * width is given by the value of \p size 99 | */ 100 | void gio_write(size_t size, gio_addr base, size_t value); 101 | 102 | /*! Read from the address \p base wherein the read performed is 8, 16 or 32 bits 103 | * and given by size 104 | */ 105 | size_t gio_read(size_t size, gio_addr base); 106 | 107 | /*! \} */ 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /include/bal/gio_generic.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GIO_GENERIC_H 17 | #define GIO_GENERIC_H 18 | #include 19 | #include 20 | 21 | /* GIO implementation for platforms which use only MMIO. These functions are 22 | * thin wrappers around memory accesses. 23 | */ 24 | 25 | typedef struct { 26 | volatile void *base; 27 | } gio_addr; 28 | 29 | #define GIO_MMIO_ADDR(_addr) ((gio_addr){ (void*) (_addr) }) 30 | 31 | static inline void gio_write8_offset(gio_addr addr, size_t offs, uint8_t val) 32 | { 33 | volatile uint8_t *ptr = ((volatile uint8_t*) addr.base) + offs; 34 | *ptr = val; 35 | } 36 | 37 | static inline void gio_write16_offset(gio_addr addr, size_t offs, uint16_t val) 38 | { 39 | volatile uint16_t *ptr = (volatile uint16_t*) (((volatile char*)addr.base) + offs); 40 | *ptr = val; 41 | } 42 | 43 | static inline void gio_write32_offset(gio_addr addr, size_t offs, uint32_t val) 44 | { 45 | volatile uint32_t *ptr = (volatile uint32_t*) (((volatile char*)addr.base) + offs); 46 | *ptr = val; 47 | } 48 | 49 | static inline uint8_t gio_read8_offset(gio_addr addr, size_t offs) 50 | { 51 | volatile uint8_t *ptr = ((volatile uint8_t*) addr.base) + offs; 52 | return *ptr; 53 | } 54 | 55 | static inline uint16_t gio_read16_offset(gio_addr addr, size_t offs) 56 | { 57 | volatile uint16_t *ptr = (volatile uint16_t*) (((volatile char*)addr.base) + offs); 58 | return *ptr; 59 | } 60 | 61 | static inline uint32_t gio_read32_offset(gio_addr addr, size_t offs) 62 | { 63 | volatile uint32_t *ptr = (volatile uint32_t*) (((volatile char*)addr.base) + offs); 64 | return *ptr; 65 | } 66 | 67 | static inline void gio_write8_index(gio_addr addr, size_t idx, uint8_t val) 68 | { gio_write8_offset(addr, idx, val); } 69 | 70 | static inline void gio_write16_index(gio_addr addr, size_t idx, uint16_t val) 71 | { gio_write16_offset(addr, idx * 2, val); } 72 | 73 | static inline void gio_write32_index(gio_addr addr, size_t idx, uint32_t val) 74 | { gio_write32_offset(addr, idx * 4, val); } 75 | 76 | static inline uint8_t gio_read8_index(gio_addr addr, size_t idx) 77 | { return gio_read8_offset(addr, idx); } 78 | 79 | static inline uint16_t gio_read16_index(gio_addr addr, size_t idx) 80 | { return gio_read16_offset(addr, idx * 2); } 81 | 82 | static inline uint32_t gio_read32_index(gio_addr addr, size_t idx) 83 | { return gio_read32_offset(addr, idx * 4); } 84 | 85 | static inline void gio_write8(gio_addr addr, uint8_t val) 86 | { gio_write8_offset(addr, 0, val); } 87 | 88 | static inline void gio_write16(gio_addr addr, uint16_t val) 89 | { gio_write16_offset(addr, 0, val); } 90 | 91 | static inline void gio_write32(gio_addr addr, uint32_t val) 92 | { gio_write32_offset(addr, 0, val); } 93 | 94 | static inline uint8_t gio_read8(gio_addr addr) 95 | { return gio_read8_offset(addr, 0); } 96 | 97 | static inline uint16_t gio_read16(gio_addr addr) 98 | { return gio_read16_offset(addr, 0); } 99 | 100 | static inline uint32_t gio_read32(gio_addr addr) 101 | { return gio_read32_offset(addr, 0); } 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /include/bal/misc.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef BAL_MISC_H 17 | #define BAL_MISC_H 18 | #include 19 | 20 | void panic(const char *fmt, ...) __attribute__((__noreturn__)); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/bal/mmap.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef BAL_MMAP_H 17 | #define BAL_MMAP_H 18 | #include 19 | 20 | /*! Add an entry to the memory map */ 21 | void mmap_add_entry(gd_memory_map_entry entry); 22 | 23 | /*! Empty the memory map */ 24 | void mmap_clean(void); 25 | 26 | /*! Gets the memory map 27 | * 28 | * \param tab destination table 29 | * \param nentries number of spaces in table 30 | * \param *needed number of entries in whole memory map 31 | * \param *key key to pass to gd_exit_boot_services 32 | */ 33 | void mmap_get( 34 | gd_memory_map_entry *tab, 35 | size_t nentries, 36 | size_t *needed, 37 | size_t *key); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/gd_bal.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Owen Shepherd & Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_H 17 | #define GD_BAL_H 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "gd_common.h" 23 | #include "bal/gio.h" 24 | 25 | #define GD_CONCAT_(a, b) a##b 26 | #define GD_CONCAT(a, b) GD_CONCAT_(a, b) 27 | 28 | #define GD_UNPACK_(...) __VA_ARGS__ 29 | #define GD_UNPACK(x) GD_UNPACK_ x 30 | 31 | typedef struct gd_device { 32 | int (*ioctl)(struct gd_device *, unsigned, ...); 33 | } *gd_device_t; 34 | 35 | #define GD_DEVICE union { \ 36 | struct gd_device dev; \ 37 | int (*ioctl)(struct gd_device *, unsigned, ...); \ 38 | } 39 | 40 | int (*gd_syscall_p)(unsigned, ...); 41 | int gd_ioctl(gd_device_t, unsigned, ...); 42 | int gd_syscall(unsigned, ...); 43 | 44 | #include "gd_syscall.h" 45 | #include "gd_ioctl.h" 46 | #include "gd_ioctl_map.h" 47 | #define GD_BEGIN_IOCTL_MAP(_type, _name) \ 48 | int _name(gd_device_t dev_, unsigned ioctl, ...); \ 49 | int _name(gd_device_t dev_, unsigned ioctl, ...) \ 50 | { \ 51 | int rv = 0; \ 52 | _type dev = (_type) dev_; \ 53 | va_list ap, *pap = ≈ \ 54 | va_start(ap, ioctl); \ 55 | postForward: \ 56 | switch(ioctl) { \ 57 | case GD_FORWARD_IOCTL: { \ 58 | ioctl = va_arg(*pap, unsigned); \ 59 | pap = va_arg(*pap, va_list *); \ 60 | goto postForward; \ 61 | } 62 | 63 | #define GD_BEGIN_IOCTL_BASE_MAP(_type, _name) \ 64 | int _name(gd_device_t dev_, unsigned ioctl, va_list *pap) \ 65 | { \ 66 | int rv = 0; \ 67 | _type dev = (_type) dev_; \ 68 | postForward: \ 69 | switch(ioctl) { \ 70 | case GD_FORWARD_IOCTL: { \ 71 | ioctl = va_arg(*pap, unsigned); \ 72 | pap = va_arg(*pap, va_list *); \ 73 | goto postForward; \ 74 | } 75 | 76 | #define GD_END_IOCTL_MAP() \ 77 | default: \ 78 | /*errno = EINVAL;*/ \ 79 | rv = -1; \ 80 | } \ 81 | va_end(ap); \ 82 | return rv; \ 83 | } 84 | 85 | #define GD_END_IOCTL_BASE_MAP() \ 86 | default: \ 87 | /*errno = EINVAL;*/ \ 88 | rv = -1; \ 89 | } \ 90 | return rv; \ 91 | } 92 | 93 | 94 | #define GD_END_IOCTL_MAP_FORWARD(_forwardTo) \ 95 | default: \ 96 | rv = (_forwardTo)(dev_, GD_FORWARD_IOCTL, ioctl, pap); \ 97 | } \ 98 | va_end(ap); \ 99 | return rv; \ 100 | } 101 | 102 | #define GD_END_IOCTL_MAP_FORWARD_BASE(_forwardTo) \ 103 | default: \ 104 | rv = (_forwardTo)(dev_, ioctl, pap); \ 105 | } \ 106 | va_end(ap); \ 107 | return rv; \ 108 | } 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /include/gd_common.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd & Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_COMMON_H 17 | #define GD_COMMON_H 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /*! A Gandr table header. 25 | * 26 | * All tables are aligned to 8 byte boundaries. When processing multiple 27 | * sequential tables, e.g. the boot information directory, the next table is 28 | * found at the address 29 | * ((const char*)&table) + (table.length + 7 & ~7) 30 | * 31 | * You should verify that the size of each table is at least that 32 | * specified by the specification. You must accept longer tables, 33 | * ignoring their extra content, to facilitate future specification revisions. 34 | * 35 | * Any table with an identifier starting with a lower case letter is boot 36 | * services only and a kernel loader can discard it when preparing the data 37 | * to pass to the kernel. 38 | */ 39 | typedef struct { 40 | /*! Identifier of the table */ 41 | uint32_t id; 42 | 43 | /*! Length of the table, in bytes, including this header */ 44 | uint32_t length; 45 | } gd_table; 46 | 47 | #define GD_TABLE_ID(a, b, c, d) \ 48 | ((uint32_t) ((a << 24) | (b << 16) | (c << 8) | (d))) 49 | 50 | /*! Copies the table ID to the passed buffer, in "natural reading order" 51 | * The passed buffer must at least 5 bytes in size, as this function 52 | * null terminates it 53 | */ 54 | static inline void gd_table_id_to_string(char *buf, const gd_table *table) 55 | { 56 | buf[0] = (char) (table->id >> 24 & 0xFF); 57 | buf[1] = (char) (table->id >> 16 & 0xFF); 58 | buf[2] = (char) (table->id >> 8 & 0xFF); 59 | buf[3] = (char) (table->id & 0xFF); 60 | buf[4] = 0; 61 | } 62 | 63 | /*! Returns a pointer to the next table */ 64 | static inline gd_table *gd_next_table(const gd_table *table) 65 | { 66 | return (gd_table*) (((char*) table) + ((table->length + 7) & ~7)); 67 | } 68 | 69 | /*! Defined types of a memory region. 70 | * 71 | * Type codes 0x0000_0000 - 0x7FFF_FFFF are taken from the UEFI specification. 72 | * Type codes 0x8000_0000 - 0xFFFF_FFFF are Gandr defined 73 | */ 74 | typedef enum { 75 | gd_reserved_memory_type = 0, 76 | gd_loader_code, 77 | gd_loader_data, 78 | gd_boot_services_code, 79 | gd_boot_services_data, 80 | gd_runtime_services_code, 81 | gd_runtime_services_data, 82 | gd_conventional_memory, 83 | gd_unusable_memory, 84 | gd_acpi_reclaim_memory, 85 | gd_acpi_memory_nvs, 86 | gd_mmio, 87 | gd_mmio_port_space, 88 | gd_pal_code, 89 | 90 | /*! ARM EABI and similar make enum sizes dependent upon their max value 91 | * Force this enum to 32-bits 92 | */ 93 | gd_memory_force_size = INT_MAX 94 | } gd_memory_type; 95 | 96 | /*! A memory map entry. This format is aligned with, but not the same as that 97 | * used by the UEFI specification. In particular, UEFI uses a pageCount member; 98 | * Gandr uses a size member; 99 | */ 100 | typedef struct { 101 | /*! The type of the memory region. */ 102 | gd_memory_type type; 103 | 104 | /*! Physical address at which the region begins */ 105 | uint64_t physical_start; 106 | 107 | /*! Virtual address at which the loader mapped this region, if it was mapped */ 108 | uint64_t virtual_start; 109 | 110 | /*! Size, in bytes, of the region */ 111 | uint64_t size; 112 | 113 | /*! Attribute bits 114 | * \see gd_memory_map_attribute 115 | */ 116 | uint64_t attributes; 117 | } gd_memory_map_entry; 118 | 119 | /*! System memory map 120 | */ 121 | typedef struct { 122 | gd_table header; 123 | gd_memory_map_entry entries[]; 124 | } gd_memory_map_table; 125 | #define GD_MEMORY_MAP_TABLE_ID GD_TABLE_ID('M', 'M', 'A', 'P') 126 | 127 | static inline size_t gd_mmap_get_size(gd_memory_map_table *table) 128 | { 129 | return (table->header.length - sizeof (gd_table)) / sizeof (gd_memory_map_entry); 130 | } 131 | 132 | /*! ACPI Root System Description Table Pointer. 133 | * 134 | * On ACPI systems, Gandr will retrieve the RSDT Pointer from the system 135 | * firmware and place it in this table. 136 | * 137 | * These addresses are always physical addresses (??? even EFI) 138 | */ 139 | typedef struct { 140 | gd_table header; 141 | /*! If the system is ACPI 2.0 or later compliant, the system XSDT address 142 | * will be placed here. Otherwise, this will be zero */ 143 | uint64_t xsdt_address; 144 | /*! The ACPI 1.0 RSDT address will be placed here */ 145 | uint32_t rsdt_address; 146 | } gd_rsdt_pointer_table; 147 | #define GD_RSDT_POINTER_TABLE_ID GD_TABLE_ID('R', 'S', 'D', 'T') 148 | 149 | typedef struct { 150 | uint8_t signature[4]; 151 | uint32_t mp_config_table; 152 | uint8_t length; 153 | uint8_t version; 154 | uint8_t checksum; 155 | uint8_t feature_bytes[5]; 156 | } mpfp_structure; 157 | 158 | /*! Pointers to description tables common to IBM-PC compatibles. 159 | * 160 | * This table does not point to tables that are common to other platforms. 161 | */ 162 | typedef struct { 163 | gd_table header; 164 | 165 | /*! The MultiProcessor Floating Point structure. The structure can 166 | be present in system base memory, so if it is found, it is copied 167 | here. All fields null if not found. */ 168 | mpfp_structure mpfp; 169 | 170 | /*! Pointer to the SMBIOS entry point table. Zero if not found. */ 171 | uint32_t smbios_entry_point_address; 172 | } gd_pc_pointer_table; 173 | #define GD_PC_POINTER_TABLE_ID GD_TABLE_ID('P', 'C', 'T', 'B') 174 | 175 | #endif 176 | -------------------------------------------------------------------------------- /include/gd_elf.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_ELF_H 17 | #define GD_ELF_H 18 | 19 | /* magic constants used in Gandr elf files */ 20 | 21 | /*! For the ARM Trusted FIrmware Kickstart! interface, declares that the binary 22 | * loaded implements said interface. d_val field contains the maximum supported 23 | * interface version 24 | */ 25 | #define DT_GANDR_ATFKICKSTART_VERSION 0x67646b21 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/platform/bios/bal/bios_console.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Owen Shepherd. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_BIOS_CONSOLE_H 17 | #define GD_BAL_BIOS_CONSOLE_H 18 | #include 19 | 20 | struct bios_console_dev { 21 | struct gd_device dev; 22 | unsigned char width; 23 | unsigned char cur_page; 24 | }; 25 | 26 | void bios_console_init(struct bios_console_dev *dev); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/platform/bios/bal/bios_services.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2013-2014, Owen Shepherd. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_BIOS_SERVICES_H 17 | #define GD_BAL_BIOS_SERVICES_H 18 | 19 | #define RM_CS 0x00 20 | #define RM_DS 0x00 21 | #define PM_CS16 0x08 22 | #define PM_DS16 0x10 23 | #define PM_CS32 0x18 24 | #define PM_DS32 0x20 25 | #define PM_CS64 0x28 26 | #define PM_DS64 PM_DS32 27 | 28 | #ifndef __ASSEMBLER__ 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | struct bios_registers { 35 | uint16_t ds; 36 | uint16_t es; 37 | uint16_t fs; 38 | uint16_t gs; 39 | uint32_t edi; 40 | uint32_t esi; 41 | uint32_t ebp; 42 | uint32_t esp; 43 | uint32_t ebx; 44 | uint32_t edx; 45 | uint32_t ecx; 46 | uint32_t eax; 47 | uint32_t eflags; 48 | }; 49 | 50 | typedef enum { 51 | carry_flag = (1 << 0), 52 | parity_flag = (1 << 2), 53 | adjust_flag = (1 << 4), 54 | zero_flag = (1 << 6), 55 | sign_flag = (1 << 7), 56 | trap_flag = (1 << 8), 57 | interrupt_enable_flag = (1 << 9), 58 | direction_flag = (1 << 10), 59 | overflow_flag = (1 << 11) 60 | } eflags; 61 | 62 | struct bios_service_table { 63 | uint32_t magic; //!< 'BIOS' 64 | uint32_t size; //!< sizeof(*this); 65 | 66 | uint32_t rm_stack; //!< Pointer to real mode stack 67 | 68 | uint32_t far_call_ptr; //!< Far pointer to far call entrypoint 69 | uint32_t int_call_ptr; //!< Far pointer to int call entrypoint 70 | }; 71 | 72 | extern struct bios_service_table *bios_services; 73 | 74 | void bios_far_call(uint32_t address, struct bios_registers *regs, const void* stack_data, unsigned stack_size); 75 | void bios_int_call(uint8_t num, struct bios_registers *regs); 76 | 77 | extern volatile uint8_t scratch_buffer[4096]; 78 | 79 | /*! Get a real mode segment from the given linear address */ 80 | static inline uint16_t rm_seg_from_ptr(const void *p) 81 | { 82 | uintptr_t v = (uintptr_t) p; 83 | return (v >> 4); 84 | } 85 | 86 | /*! Get a real mode offset from the given linear address */ 87 | static inline uint16_t rm_offset_from_ptr(const void *p) 88 | { 89 | uintptr_t v = (uintptr_t) p; 90 | return (v & 0x000F); 91 | } 92 | 93 | /*! Get a real mode far pointer from the given linear address */ 94 | static inline uint32_t rm_far_from_ptr(const void *p) 95 | { 96 | uintptr_t v = (uintptr_t) p; 97 | uint32_t fp = (v << 12 & 0xFFFF0000) | (v & 0x0F); 98 | return fp; 99 | } 100 | 101 | /*! Convert a real mode far pointer to a linear address */ 102 | static inline void* rm_ptr_from_far(uint32_t fp) { 103 | uintptr_t v = (fp >> 12 & 0x000FFFF0) + (fp & 0xFFFF); 104 | return (void*) v; 105 | } 106 | 107 | 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /include/platform/bios/bal/mmap.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_BIOS_MMAP_H 17 | #define GD_BAL_BIOS_MMAP_H 18 | 19 | #include 20 | #include 21 | 22 | /*! The address range types defined by ACPI. */ 23 | typedef enum { 24 | address_range_memory = 1, 25 | address_range_reserved, 26 | address_range_reclaimable, 27 | address_range_nvs, 28 | address_range_unusable, 29 | address_range_disabled, 30 | 31 | acpi_memory_force_size = INT_MAX 32 | } acpi_memory_type; 33 | 34 | /* The attributes defined by ACPI. */ 35 | typedef enum { 36 | entry_present = (1 << 0), 37 | address_range_non_volatile = (1 << 1), 38 | address_range_slow_access = (1 << 2), 39 | address_range_error_log = (1 << 3), 40 | 41 | acpi_attributes_force_size = INT_MAX 42 | } acpi_attributes; 43 | 44 | struct address_range { 45 | uint64_t physical_start; 46 | uint64_t size; 47 | acpi_memory_type type; 48 | acpi_attributes attributes; 49 | } __attribute__((packed)); 50 | 51 | /*! Get the amount of base memory, as reported by int 0x12. */ 52 | uint32_t get_base_memory(); 53 | 54 | void mmap_init(); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/platform/bios/bal/tables.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_BIOS_TABLES_H 17 | #define GD_BAL_BIOS_TABLES_H 18 | 19 | #include 20 | #include 21 | 22 | #define TABLE_SIGNATURE(a, b, c, d) \ 23 | ((uint32_t) ((a << 24) | (b << 16) | (c << 8) | (d))) 24 | 25 | struct rsdp { 26 | uint8_t signature[8]; 27 | uint8_t checksum; 28 | uint8_t oemid[6]; 29 | uint8_t revision; 30 | uint32_t rsdt_address; 31 | } __attribute__((packed)); 32 | 33 | struct rsdp_extended { 34 | /*! ACPI 2.0 and above extended version. */ 35 | uint8_t signature[8]; 36 | uint8_t checksum; 37 | uint8_t oemid[6]; 38 | uint8_t revision; 39 | uint32_t rsdt_address; 40 | 41 | uint32_t length; 42 | uint64_t xsdt_address; 43 | uint8_t extended_checksum; 44 | uint8_t reserved[3]; 45 | } __attribute__((packed)); 46 | 47 | #define RSDP_SIGNATURE_LOW TABLE_SIGNATURE('R', 'S', 'D', ' ') 48 | #define RSDP_SIGNATURE_HIGH TABLE_SIGNATURE('P', 'T', 'R', ' ') 49 | 50 | struct smbios_entry_point { 51 | uint8_t signature[4]; 52 | uint8_t checksum; 53 | uint8_t length; 54 | uint8_t major_version; 55 | uint8_t minor_version; 56 | 57 | uint16_t max_struct_size; 58 | uint8_t entry_point_revision; 59 | uint8_t formatted_area[5]; 60 | 61 | uint8_t signature_dmi[5]; 62 | uint8_t checksum_dmi; 63 | uint16_t table_length; 64 | uint32_t table_address; 65 | uint16_t number_of_structs; 66 | uint8_t bcd_revision; 67 | } __attribute__((packed)); 68 | 69 | #define SMBIOS_ENTRY_POINT_SIGNATURE TABLE_SIGNATURE('_', 'S', 'M', '_') 70 | #define MPFP_SIGNATURE TABLE_SIGNATURE('_', 'M', 'P', '_') 71 | 72 | /*! Find all the available tables. The respective gd_* tables have non-zero 73 | * size if any tables they describe have been located. */ 74 | void tables_init(); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/platform/bios/bal/vbe.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_VBE_H 17 | #define GD_BAL_VBE_H 18 | 19 | #include 20 | #include 21 | 22 | struct vbe_info_block { 23 | uint8_t signature[4]; 24 | uint16_t version; 25 | uint32_t oem_string_ptr; 26 | uint8_t capabilities[4]; 27 | uint32_t video_modes_ptr; 28 | uint16_t total_memory; 29 | 30 | // Added with VBE 2.0+. 31 | uint16_t oem_software_rev; 32 | uint32_t oem_vendor_name_ptr; 33 | uint32_t oem_product_name_ptr; 34 | uint32_t oem_product_rev_ptr; 35 | 36 | uint8_t reserved[222]; 37 | uint8_t oem_data[256]; 38 | } __attribute__((packed)); 39 | 40 | struct vbe_mode_info { 41 | uint16_t attributes; 42 | uint8_t window_a_attr; 43 | uint8_t window_b_attr; 44 | uint16_t window_granularity; /* In KiB. */ 45 | uint16_t window_size; /* In KiB. */ 46 | uint16_t window_a_seg; 47 | uint16_t window_b_seg; 48 | uint32_t window_position_func; /* Equivalent to AX=4F05h, int 0x10. */ 49 | uint16_t bytes_per_scanline; 50 | 51 | /* Optional for VESA modes in v1.0/1.1. */ 52 | /* VBE v1.2+. */ 53 | uint16_t width; /* In pixels (graphics) or characters (text). */ 54 | uint16_t height; /* In pixels (graphics) or characters (text). */ 55 | uint8_t width_of_char_cell; /* In pixels. */ 56 | uint8_t height_of_char_cell; /* In pixels. */ 57 | uint8_t memory_planes; 58 | uint8_t bpp; 59 | uint8_t banks; 60 | uint8_t memory_model; 61 | uint8_t size_of_bank; /* In KiB. */ 62 | uint8_t image_pages; 63 | uint8_t reserved_0; /* 0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0. */ 64 | 65 | uint8_t red_mask_size; 66 | uint8_t red_field_pos; 67 | uint8_t green_mask_size; 68 | uint8_t green_field_pos; 69 | uint8_t blue_mask_size; 70 | uint8_t blue_field_pos; 71 | uint8_t reserved_mask_size; 72 | uint8_t reserved_field_pos; 73 | uint8_t direct_color_attr; 74 | 75 | /* VBE 2.0+. */ 76 | uint32_t lfb_address; 77 | uint32_t reserved_1; 78 | uint16_t reserved_2; 79 | 80 | /* VBE 3.0+. */ 81 | uint16_t lin_bytes_per_scanline; 82 | uint8_t banked_num_images; 83 | uint8_t lin_num_images; 84 | uint8_t lin_red_mask_size; 85 | uint8_t lin_red_field_pos; 86 | uint8_t lin_green_mask_size; 87 | uint8_t lin_green_field_pos; 88 | uint8_t lin_blue_mask_size; 89 | uint8_t lin_blue_field_pos; 90 | uint8_t lin_reserved_mask_size; 91 | uint8_t lin_reserved_field_pos; 92 | uint32_t max_pixel_clock; 93 | 94 | uint8_t reserved_3[190]; 95 | } __attribute__((packed)); 96 | 97 | enum vbe_mode_attributes { 98 | VBE_MODE_ATTR_SUPPORTED = (1 << 0), 99 | VBE_MODE_ATTR_EXTENDED_INFORMATION_AVAILABLE = (1 << 1), 100 | VBE_MODE_ATTR_TTY_BIOS_SUPPORT = (1 << 2), 101 | VBE_MODE_ATTR_COLOR_MODE = (1 << 3), 102 | VBE_MODE_ATTR_GRAPHICS_MODE = (1 << 4), 103 | VBE_MODE_ATTR_NOT_VGA_COMPATIBLE = (1 << 5), 104 | VBE_MODE_ATTR_NO_VGA_COMPATIBLE_WINDOW = (1 << 6), 105 | VBE_MODE_ATTR_LINEAR_FRAME_BUFFER_MODE = (1 << 7), 106 | VBE_MODE_ATTR_DOUBLE_SCAN_MODE = (1 << 8), 107 | VBE_MODE_ATTR_INTERLACE_MODE = (1 << 9), 108 | VBE_MODE_ATTR_HARDWARE_TRIPLE_BUFFER = (1 << 10), 109 | VBE_MODE_ATTR_HARDWARE_STEREOSCOPIC_DISPLAY = (1 << 11), 110 | VBE_MODE_ATTR_DUAL_DISPLAY_START_ADDRESS = (1 << 12) 111 | }; 112 | 113 | enum vbe_window_attributes { 114 | VBE_WINDOW_ATTR_SUPPORTED = (1 << 0), 115 | VBE_WINDOW_ATTR_READABLE = (1 << 1), 116 | VBE_WINDOW_ATTR_WRITEABLE = (1 << 2) 117 | }; 118 | 119 | enum vbe_direct_color_attrs { 120 | VBE_DC_ATTR_COLOR_RAMP_PROGRAMMABLE = (1 << 0), 121 | VBE_DC_ATTR_RESERVED_FIELD_USABLE = (1 << 1) 122 | }; 123 | 124 | enum vbe_memory_model { 125 | VBE_MM_TEXT_MODE = 0, 126 | VBE_MM_CGA_GRAPHICS, 127 | VBE_MM_HERCULES_GRAPHICS, 128 | VBE_MM_PLANAR, 129 | VBE_MM_PACKED_PIXEL, 130 | VBE_MM_NON_CHAIN_256_COLOR, 131 | VBE_MM_DIRECT_COLOR, 132 | VBE_MM_YUV 133 | }; 134 | 135 | enum mode_identifier_flags { 136 | VBE_ID_USE_SPECIFIED_CRTC_VALUES = (1 << 11), 137 | VBE_ID_USE_LFB = (1 << 14), 138 | VBE_ID_DONT_CLEAR_MEMORY = (1 << 15) 139 | }; 140 | 141 | void vbe_init(); 142 | 143 | /*! Switch to given mode. */ 144 | int vbe_switch_mode(struct mode_info mode); 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /include/platform/bios/device/cdrom.h: -------------------------------------------------------------------------------- 1 | /* Copyright © 2014, Shikhin Sethi. 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | * PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef GD_BAL_BIOS_DEVICE_CDROM_H 17 | #define GD_BAL_BIOS_DEVICE_CDROM_H 18 | 19 | #include 20 | 21 | typedef struct { 22 | struct gd_device dev; 23 | uint8_t drive_number; 24 | } cdrom_dev; 25 | 26 | void cdrom_init(cdrom_dev *dev, uint8_t drive_number); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /lib/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir GD_TOP lib ; 2 | 3 | LIB9660_OPTS = [ FDefines L9660_HAVE_STDIO ] ; 4 | 5 | SubIncludeOnce GD_TOP lib lib9660 ; 6 | SubIncludeOnce GD_TOP lib elfload ; 7 | SubIncludeOnce GD_TOP lib libfdt ; 8 | -------------------------------------------------------------------------------- /lib/libfdt/Jamfile: -------------------------------------------------------------------------------- 1 | SubDir LIBFDT_TOP ; 2 | GdIncludeDir $(LIBFDT_TOP) dtc libfdt ; 3 | SubDir LIBFDT_TOP ; 4 | 5 | SubDirCcFlags -Wno-pedantic -Wno-sign-compare ; 6 | 7 | Library libfdt : 8 | dtc/libfdt/fdt.c 9 | dtc/libfdt/fdt_addresses.c 10 | dtc/libfdt/fdt_empty_tree.c 11 | dtc/libfdt/fdt_ro.c 12 | dtc/libfdt/fdt_rw.c 13 | dtc/libfdt/fdt_strerror.c 14 | dtc/libfdt/fdt_sw.c 15 | dtc/libfdt/fdt_wip.c 16 | ; 17 | -------------------------------------------------------------------------------- /prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | echo -- Checking out PDCLib 4 | hg clone https://bitbucket.org/pdclib/pdclib 5 | -------------------------------------------------------------------------------- /tools/gd_stub_gen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright © 2013, 2014 Owen Shepherd 3 | # 4 | # Permission to use, copy, modify, and/or distribute this software for any 5 | # purpose with or without fee is hereby granted, provided that the above 6 | # copyright notice appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 | # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | # PERFORMANCE OF THIS SOFTWARE. 15 | 16 | import argparse 17 | import re 18 | import sys 19 | 20 | class Function: 21 | def __init__(self, num, name, params): 22 | self.num = num 23 | self.name = name 24 | self.params = params 25 | 26 | def stubname(self, stubdir): 27 | if not stubdir: 28 | stubdir = '' 29 | elif not stubdir.endswith('/'): 30 | stubdir += '/' 31 | return "%s%s.c" % (stubdir, self.name) 32 | 33 | 34 | patterns = {} 35 | def match(regex): 36 | regex = re.compile('^%s$' % regex) 37 | def _(fn): 38 | patterns[regex] = fn 39 | return fn 40 | return _ 41 | 42 | class Parser: 43 | 44 | def __init__(self, mode): 45 | self.mode = mode 46 | self.line = 1 47 | self.ctl_num = 0 48 | self.line = 0 49 | self.functions = [] 50 | self.predefined = [] 51 | self.errors = 0 52 | 53 | def error(self, str): 54 | print("Line %d: %s" % (self.line, str)) 55 | self.errors += 1 56 | 57 | @match(r'\s*') 58 | def whitespace(self): 59 | pass 60 | 61 | @match(r'//.*') 62 | def comment(self): 63 | pass 64 | 65 | param_re = re.compile('^\s*(\w+(?:\s+\w+)*\s*(?:\s+|(?:\*\s*)+))(\w+)\s*$') 66 | @match(r'(\w+)\s+(\w+)\(([^)]*)\)\s*') 67 | def function(self, mode, name, paramstr): 68 | if self.mode != mode: 69 | return self.error('Bad "%s% declaration' % mode) 70 | 71 | params = [] 72 | paramstr = paramstr.strip() 73 | if len(paramstr) and paramstr != "void": 74 | for p in paramstr.split(','): 75 | m = self.param_re.match(p) 76 | if m: 77 | (type_, name_) = m.groups() 78 | params.append((type_, name_)) 79 | else: 80 | return self.error("Bad parameter declaration \"%s\"" % p) 81 | self.functions.append(Function(self.ctl_num, name, params)) 82 | self.ctl_num += 1 83 | 84 | @match(r'at\s+(0x[0-9a-fA-F]{8})\s*') 85 | def at(self, id): 86 | self.ctl_num = int(id, base=16) 87 | 88 | @match(r'((?:struct|union|enum)\s+\w+)\s*') 89 | def predef(self, def_): 90 | self.predefined.append(def_) 91 | 92 | def process_line(self, line): 93 | for regex, func in patterns.items(): 94 | m = regex.match(line) 95 | if m: 96 | return func(self, *m.groups()) 97 | return self.error("Bad line '%s'" % line) 98 | 99 | def parse_file(self, file): 100 | for line in options.file: 101 | self.line += 1 102 | self.process_line(line.strip()) 103 | if self.errors: 104 | print("Failing after %d errors" % self.errors) 105 | sys.exit(1) 106 | 107 | def list_stubs(self, stubdir): 108 | for func in self.functions: 109 | print(func.stubname(stubdir)) 110 | 111 | @property 112 | def TYPE(self): 113 | return self.mode.upper() 114 | 115 | @property 116 | def selfparam(self): 117 | if self.mode == 'ioctl': 118 | return 'gd_device_t dev_' 119 | else: 120 | return '' 121 | 122 | def make_header(self, file): 123 | for func in self.functions: 124 | file.write('#define GD_%s_%s %d\n' % 125 | (func.name.upper(), self.TYPE, func.num)) 126 | for line in self.predefined: 127 | file.write('%s;\n' % line) 128 | for func in self.functions: 129 | file.write('int gd_%s(%s' % (func.name, self.selfparam)) 130 | if self.mode == 'ioctl' and len(func.params): 131 | file.write(', ') 132 | file.write(', '.join('%s %s' % p for p in func.params)) 133 | file.write(');\n') 134 | 135 | def make_stubs(self, dir): 136 | for func in self.functions: 137 | file = open(func.stubname(dir), 'w') 138 | file.write("#include \n\n") 139 | 140 | file.write('int gd_%s(%s' % (func.name, self.selfparam)) 141 | if self.mode == 'ioctl' and len(func.params): 142 | file.write(', ') 143 | file.write(', '.join('%s %s' % p for p in func.params)) 144 | file.write(')\n{\n') 145 | 146 | if self.mode == 'ioctl': 147 | file.write(' return dev_->ioctl(dev_, ') 148 | else: 149 | file.write(' return (*gd_syscall_p)(') 150 | file.write('GD_%s_%s' % (func.name.upper(), self.TYPE)) 151 | if len(func.params): 152 | file.write(', ') 153 | file.write(', '.join(p[1] for p in func.params)) 154 | file.write(');\n') 155 | file.write('}\n') 156 | file.close() 157 | 158 | def make_map(self, file): 159 | for func in self.functions: 160 | file.write('#define GD_MAP_%s_IOCTL(_name) \\\n' % func.name.upper()) 161 | file.write(' case GD_%s_IOCTL: {\\\n' % func.name.upper()) 162 | for i in range(0, len(func.params)): 163 | file.write(' %s _arg%d = va_arg(*pap, %s);\\\n' % 164 | (func.params[i][0], i, func.params[i][0])) 165 | file.write(' rv = _name(dev') 166 | if len(func.params): 167 | file.write(', ') 168 | file.write(', '.join('_arg%d' % i for i in range(0, len(func.params)))) 169 | file.write(');\\\n') 170 | file.write(' break;\\\n') 171 | file.write(' }\n\n') 172 | 173 | def make_dispatcher(self, file): 174 | file.write("#include \n") 175 | file.write("#include \n\n") 176 | file.write("int gd_syscall(unsigned syscall, ...)\n") 177 | file.write("{\n") 178 | file.write(" va_list ap;\n") 179 | file.write(" va_start(ap, syscall);\n") 180 | file.write(" switch (syscall) {\n") 181 | for func in self.functions: 182 | file.write(" case GD_%s_SYSCALL: {\n " % func.name.upper()) 183 | for i in range(0, len(func.params)): 184 | file.write(' %s _arg%d = va_arg(ap, %s);\\\n' % 185 | (func.params[i][0], i, func.params[i][0])) 186 | file.write(" return gd_%s(" % func.name) 187 | file.write(', '.join('_arg%d' % i for i in range(0, len(func.params)))) 188 | file.write(");\n") 189 | file.write(" }\n") 190 | file.write(" }\n") 191 | file.write("}\n") 192 | 193 | 194 | if __name__ == '__main__': 195 | parser = argparse.ArgumentParser( 196 | description='Generate ioctl/syscall stubs and headers') 197 | 198 | parser.add_argument("mode", choices=['ioctl', 'syscall']) 199 | parser.add_argument("file", type=argparse.FileType('r')) 200 | parser.add_argument("-list", action='store_true') 201 | parser.add_argument("-stubs", action='store_true') 202 | parser.add_argument("-stubdir", type=str) 203 | parser.add_argument("-hdr", type=argparse.FileType('w')) 204 | parser.add_argument("-map", type=argparse.FileType('w')) 205 | parser.add_argument("-dispatcher", type=argparse.FileType('w')) 206 | options = parser.parse_args() 207 | 208 | parse = Parser(options.mode) 209 | parse.parse_file(options.file) 210 | 211 | if options.list: 212 | parse.list_stubs(options.stubdir) 213 | 214 | if options.hdr: 215 | parse.make_header(options.hdr) 216 | 217 | if options.stubs: 218 | parse.make_stubs(options.stubdir) 219 | 220 | if options.map: 221 | if options.mode != 'ioctl': 222 | print('map option only makes sense for ioctl') 223 | sys.exit(1) 224 | parse.make_map(options.map) 225 | 226 | if options.dispatcher: 227 | if options.mode != 'syscall': 228 | print('dispatcher option only makes sense for syscall') 229 | sys.exit(1) 230 | parse.make_dispatcher(options.dispatcher) 231 | --------------------------------------------------------------------------------