├── COPYING ├── Changelog ├── Makefile ├── README ├── TODO ├── Timestamp └── src ├── bios.h ├── bloc.c ├── boot.S ├── boot.ld ├── bootinfos.c ├── char.c ├── dev ├── bus │ └── adb.h └── char │ ├── char.h │ ├── kbd.c │ ├── kbd.h │ ├── kbdadb.c │ └── pckbd.c ├── libc ├── include │ ├── ctype.h │ ├── endian.h │ ├── errno.h │ ├── fcntl.h │ ├── stddef.h │ ├── stdint.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ ├── strings.h │ └── unistd.h └── src │ ├── errno.c │ ├── format.c │ ├── malloc.c │ ├── mem.c │ └── str.c ├── libexec ├── chrp.c ├── core.c ├── elf.c ├── exec.h ├── macho.c ├── pef.c ├── prep.c └── xcoff.c ├── libfs ├── core.c ├── ext2.c ├── hfs.c ├── isofs.c ├── libfs.h └── raw.c ├── libpart ├── apple.c ├── core.c ├── isofs.c ├── libpart.h └── prep.c ├── main.c ├── main.ld ├── mm.c ├── nvram.c ├── of.c ├── pci.c ├── start.S ├── vectors.S ├── vectors.ld ├── vga.c └── vgafont.h /Changelog: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | # Changelog for Open Hack'Ware. 5 | # 6 | # Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr) 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License V2 10 | # as published by the Free Software Foundation 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | 2005-04-06: 22 | * Change 2nd MacIO ide controller IRQ, in coordination with Qemu patch. 23 | 24 | 2005-03-18: 25 | * Added Mandrake 10.1 CHRP script CRC. 26 | 27 | 2005-03-17: 28 | * Start bloc device / partition management APIs cleanup. 29 | * Fix PREP boot 30 | * Fix memory image boot 31 | 32 | 2005-03-15: 33 | * Tested rock linux, then updated README 34 | 35 | 2005-03-14: 36 | * Yet another fix for CHRP boot file load. 37 | * Add more CHRP boot scripts CRCs. 38 | * Make all debug printf be printed on the serial port (ie debug console). 39 | * Build 04-pre2 preview. 40 | 41 | 2005-03-11: 42 | * Fix foolish license informations: this code is clearly distributed under 43 | the GNU GPL V2. 44 | 45 | 2005-03-06: 46 | * CHRP boot file loader: 47 | - yet another boot file path fix 48 | - add Debian sarge on hard-drive yaboot start script signature 49 | * enable FPU at startup (may compile with -msoft float as well...) 50 | 51 | 2005-03-01: 52 | * Add dprintf/vdprintf routines for debug console. 53 | * Fix CHRP boot file path resolution 54 | * Fix OF PCI devices reg properties 55 | (bug reported by Thayne Harbaugh ) 56 | * Fix OF property with no value (value len is zero). 57 | * Update TODO list 58 | 59 | 2005-02-18: 60 | * Merge HFS rework by Thayne Harbaugh 61 | * Merge generic and new ADB keyboard driver 62 | * Add '\b' support in VGA console. 63 | * Disable xcoff embedded binary support to make NetBSD start booting again. 64 | * Register VGA console when a PCI VGA device is found 65 | * Register and initialise CUDA when device is found 66 | 67 | 2005-02-15: 68 | * Bugfix in toupper by Thayne Harbaugh 69 | 70 | 2005-02-11: 71 | * Hack OF_serial_read to use console_read 72 | * Add '\r' support in vga_putchar. 73 | * Remove old console code and activate new one. 74 | * Register PC serial port. 75 | * Show OHW prompt after all hardware has been initialized. 76 | * New PC kbd code, reworked from Matthew Wood 's proposal 77 | 78 | 2005-02-10: 79 | * Merge Motorola Raven PCI bridge support on PREP 80 | by Thayne Harbaugh 81 | * Bugfix in pci code: pci_main was not initialized to NULL. 82 | 83 | 2005-02-09: 84 | * Merge fixes reported by Thayne Harbaugh 85 | and Matthew S. Wood : 86 | - many typos 87 | - bugfix in pci.c:pci_check_host (bad returned value) 88 | - bugfix in of.c:OF_lds (debug message) 89 | - Improve serial code + add serial_readb 90 | - Add error message if parent node if NULL in of.c:OF_node_create 91 | - Avoid duplication of properties if of.c:OF_blockdev_set_boot_device 92 | is called twice 93 | - Use console_read in of.c:OF_serial_read instead of using a harcoded 94 | "answer" string. 95 | - comment "Apple_patition_map" match 96 | in libpart/apple.c:Apple_probe_partitions (was a mistake ?) 97 | + more precise message if no bootable partition was found 98 | - Never try to register multiple boot partitions (bloc.c:bd_set_boot_part) 99 | - Do most of OF tree initialisation before parsing bloc devices (main.c:main) 100 | * Commit a TODO list. 101 | 102 | 2005-02-08: 103 | * Update BIOS version (should have been done before...). 104 | * A few HFS fixes (still more needed) 105 | * new xcoff embedded file loader. 106 | * New OF "forth" function for Mac OS X 10.3 107 | * cosmetics & typos 108 | * update copyright infos. 109 | 110 | 2004-12-20: 111 | * Great API and structure rework: 112 | - add libc subset (to be completed) 113 | - split part.c into libpart 114 | - split fs.c into libfs 115 | - split exec.c into libexec 116 | - add preliminary version of memory management routines 117 | - add more consistency checks (NULL pointers, ...) 118 | * partition management: 119 | - Fixes in apple partition management with new API 120 | * filesystems support: 121 | - Fixes in HFS/HFS+ support 122 | * boot file formats support: 123 | - extract CHRP boot file format from HFS code + fixes 124 | - add PEF file loader (untested) 125 | - add Mach-O file loader. 126 | * OpenFirmware emulation: 127 | - Fix some (of the) OF bugs 128 | - Fix machine name in OF tree: "Qemu" wasn't recognized by OSes. 129 | * misc: 130 | - avoid gcc compilation time warnings 131 | 132 | 2004-07-14: 133 | * More sanity checks. 134 | * First version of character devices drivers. 135 | 136 | 2004-07-07: version 0.3: 137 | * OpenFirmware emulation: 138 | - Fix OF_lds and OF_sts 139 | - Fix OF_env initialisation. 140 | - Add more run-time checks in OF management. 141 | - Fix OF naming scheme. 142 | - Add OF methods arguments. 143 | - Change Copyright string to make Mac OS 9 happy. 144 | - New mmu_map method 145 | - Fix serial_write & serial_read methods. 146 | - Add block devices package. 147 | - New OF_interpret hashes for yaboot support. 148 | * partition management: 149 | - hide part_t structure. 150 | - improve partitions registration 151 | * filesystems support: 152 | - Fix inode cache management. 153 | - Fix special inodes management. 154 | - HFS support rework. 155 | * misc: 156 | - keep OF private pointer in PCI IDE structures. 157 | - change all xxx_DEBUG defines into DEBUG_xxx 158 | - add missing copyright and license in pci.c 159 | 160 | 2004-05-22: 161 | - cleanup Makefile 162 | - add COPYING 163 | - fix license informations 164 | - discard unwanted output sections in bootloaders linker scripts 165 | - created Changelog -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | # Makefile for Open Hack'Ware. 5 | # 6 | # Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr) 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License V2 10 | # as published by the Free Software Foundation 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | 22 | #DEBUG=1 23 | 24 | CROSS_COMPILE?=powerpc-linux- 25 | CC:= $(CROSS_COMPILE)gcc -m32 26 | LD:= $(CROSS_COMPILE)ld -m elf32ppc 27 | OBJCOPY:= $(CROSS_COMPILE)objcopy 28 | MKDIR:= mkdir 29 | CAT:= cat 30 | TAR:= tar 31 | RM:= rm -rf -- 32 | ECHO:= echo 33 | ifeq ("$(DEBUG)", "1") 34 | DEBUG:= $(ECHO) 35 | else 36 | DEBUG:= \# 37 | endif 38 | 39 | BUILD_DATE:= $(shell date -u +%F) 40 | BUILD_TIME:= $(shell date -u +%T) 41 | 42 | OBJDIR:= .objs 43 | DISTDIR:= . 44 | SRCDIR:= src 45 | 46 | CC_BASE:= $(shell $(CC) -print-search-dirs | grep install | sed -e 's/.*\ //') 47 | CFLAGS= -Wall -W -Werror -O2 -g -fno-builtin -fno-common -nostdinc -mregnames 48 | # Disable a few warnings that would just create needless code churn 49 | CFLAGS+= -Wno-pointer-sign -Wno-unused-but-set-variable 50 | CFLAGS+= -DBUILD_DATE=$(BUILD_DATE) -DBUILD_TIME=$(BUILD_TIME) 51 | CFLAGS+= -I$(SRCDIR)/ -I$(SRCDIR)/libc/include -I$(CC_BASE)/include 52 | CFLAGS+= -I$(SRCDIR)/dev -I$(SRCDIR)/dev/block -I$(SRCDIR)/dev/char 53 | CFLAGS+= -I$(SRCDIR)/dev/bus 54 | LDFLAGS= -O2 -g -nostdlib 55 | 56 | BIOS_IMAGE_BITS:= 20 57 | BIOS_IMAGE_SIZE:= $(shell echo $$(( 1 << $(BIOS_IMAGE_BITS) )) ) 58 | 59 | BOOT_SIZE := 0x00000200 60 | VECTORS_BASE := 0x00000000 61 | VECTORS_SIZE := $(shell echo $$(( 0x00004000 - $(BOOT_SIZE) )) ) 62 | VECTORS_END := $(shell echo $$(( $(VECTORS_BASE) + $(VECTORS_SIZE) )) ) 63 | BIOS_BASE := 0x05800000 64 | BIOS_SIZE := $(shell echo $$(( $(BIOS_IMAGE_SIZE) - $(BOOT_SIZE) - $(VECTORS_SIZE) )) ) 65 | BIOS_END := $(shell echo $$(( $(BIOS_BASE) + $(BIOS_SIZE) )) ) 66 | 67 | LOAD_IMAGE_BASE:= 0x04000000 68 | 69 | # boot.bin build options 70 | boot.o_CFLAGS:= -DBOOT_SIZE=$(BOOT_SIZE) 71 | boot.o_CFLAGS+= -DVECTORS_BASE=$(VECTORS_BASE) -DVECTORS_SIZE=$(VECTORS_SIZE) 72 | boot.o_CFLAGS+= -DBIOS_IMAGE_BITS=$(BIOS_IMAGE_BITS) 73 | boot.out_LDFLAGS+= -T $(SRCDIR)/boot.ld 74 | # vectors.bin build options 75 | vectors.o_CFLAGS:= -DBIOS_BASE=$(BIOS_BASE) -DBIOS_SIZE=$(BIOS_SIZE) 76 | vectors.out_LDFLAGS+= -T $(SRCDIR)/vectors.ld 77 | vectors.bin_OPTIONS:= --pad-to $(VECTORS_END) 78 | # main.bin build options 79 | main.o_CFLAGS:= -DLOAD_IMAGE_BASE=$(LOAD_IMAGE_BASE) 80 | main.out_LDFLAGS:= -T $(SRCDIR)/main.ld 81 | main.out_OBJS:= main.o bootinfos.o bloc.o pci.o of.o start.o nvram.o vga.o mm.o char.o 82 | main.out_OBJS:= $(addprefix $(OBJDIR)/, $(main.out_OBJS)) 83 | # Pseudo-libc objects 84 | FORMAT_FUNCS:= _vprintf printf sprintf snprintf vprintf vsprintf vsnprintf 85 | FORMAT_FUNCS+= dprintf vdprintf 86 | MEM_FUNCS:= memcpy memccpy mempcpy memmove memcmove mempmove 87 | MEM_FUNCS+= memset memcmp memchr rawmemchr memrchr memmem 88 | STR_FUNCS:= strcpy strdup strndup stpcpy stpncpy strcat strncat 89 | STR_FUNCS+= strcmp strcasecmp strncmp strncasecmp strchr strchrnul strrchr 90 | STR_FUNCS+= basename dirname 91 | STR_FUNCS+= strlen strnlen 92 | MODULES:= format mem str 93 | format_OBJS:=$(addsuffix .o, $(FORMAT_FUNCS)) 94 | mem_OBJS:=$(addsuffix .o, $(MEM_FUNCS)) 95 | str_OBJS:=$(addsuffix .o, $(STR_FUNCS)) 96 | pseudo_libc_OBJS:= malloc.o errno.o $(format_OBJS) $(mem_OBJS) $(str_OBJS) 97 | #pseudo_libc_OBJS:= errno.o $(format_OBJS) $(mem_OBJS) $(str_OBJS) 98 | main.out_OBJS+= $(addprefix $(OBJDIR)/, $(pseudo_libc_OBJS)) 99 | # libexec objects 100 | libexec_OBJS:= core.o elf.o xcoff.o macho.o chrp.o prep.o pef.o 101 | main.out_OBJS+= $(addprefix $(OBJDIR)/exec_, $(libexec_OBJS)) 102 | # libfs objects 103 | libfs_OBJS:= core.o raw.o ext2.o isofs.o hfs.o 104 | main.out_OBJS+= $(addprefix $(OBJDIR)/fs_, $(libfs_OBJS)) 105 | # libpart objects 106 | libpart_OBJS:= core.o apple.o isofs.o prep.o 107 | main.out_OBJS+= $(addprefix $(OBJDIR)/part_, $(libpart_OBJS)) 108 | # char devices drivers 109 | chardev_OBJS:= pckbd.o kbdadb.o kbd.o 110 | # bloc devices drivers 111 | blocdev_OBJS:= 112 | # devices drivers 113 | dev_OBJS:= $(addprefix bloc_, $(blocdev_OBJS)) 114 | dev_OBJS+= $(addprefix char_, $(chardev_OBJS)) 115 | main.out_OBJS+= $(addprefix $(OBJDIR)/dev_, $(dev_OBJS)) 116 | 117 | CUR= $(notdir $@) 118 | CFLAGS+= $($(CUR)_CFLAGS) 119 | LDFLAGS+= $($(CUR)_LDFLAGS) 120 | 121 | BIN_TARGETS:= $(OBJDIR)/vectors.bin $(OBJDIR)/main.bin $(OBJDIR)/boot.bin 122 | TARGET:= ppc_rom.bin 123 | main.bin_OPTIONS:= --gap-fill 0xFF --pad-to $(BIOS_END) 124 | 125 | CURDIR:= $(shell basename `pwd`) 126 | SOURCES:= boot.S vectors.S start.S main.c of.c 127 | SOURCES+= vga.c vgafont.h bootinfos.c nvram.c file.c fs.c part.c bloc.c pci.c bios.h 128 | LD_SCRIPTS:= boot.ld vectors.ld main.ld 129 | MISC_FILES:= Makefile COPYING README Changelog Timestamp 130 | SVN_DIRS:= $(shell find . -type d -name .svn) 131 | TARBALL:= OpenHackWare.tar.bz2 132 | TARFILES:= $(addprefix $(SRCDIR)/, $(SOURCES) $(LD_SCRIPTS)) $(MISC_FILES) 133 | SVN_TARBALL:= OpenHackWare_svn.tar.bz2 134 | DISTFILE:= OpenHackWare_bin.tar.bz2 135 | 136 | #all: print 137 | all: $(OBJDIR) $(DISTDIR) $(addprefix $(DISTDIR)/, $(TARGET)) 138 | 139 | dist: all $(CURDIR)/Timestamp 140 | cd $(DISTDIR) && $(TAR) -cjf $(DISTFILE) $(DISTDIR)/$(TARGET) Timestamp 141 | 142 | print: 143 | @$(DEBUG) "BOOT_SIZE = $(BOOT_SIZE)" 144 | @$(DEBUG) "VECTORS_BASE = $(VECTORS_BASE)" 145 | @$(DEBUG) "VECTORS_SIZE = $(VECTORS_SIZE)" 146 | @$(DEBUG) "VECTORS_END = $(VECTORS_END)" 147 | @$(DEBUG) "BIOS_BASE = $(BIOS_BASE)" 148 | @$(DEBUG) "BIOS_SIZE = $(BIOS_SIZE)" 149 | @$(DEBUG) "BIOS_END = $(BIOS_END)" 150 | 151 | $(OBJDIR) $(DISTDIR): 152 | @$(MKDIR) $@ 153 | 154 | $(DISTDIR)/$(TARGET): $(BIN_TARGETS) 155 | $(CAT) $^ > $@ 156 | 157 | $(OBJDIR)/%.bin: $(OBJDIR)/%.out 158 | $(OBJCOPY) -O binary $($(notdir $@)_OPTIONS) $< $@ 159 | 160 | $(OBJDIR)/%.out: $(OBJDIR)/%.o $(SRCDIR)/%.ld 161 | $(LD) $(LDFLAGS) -o $@ $< 162 | 163 | $(OBJDIR)/main.out: $(main.out_OBJS) $(SRCDIR)/main.ld 164 | $(LD) $(LDFLAGS) -o $@ $(main.out_OBJS) 165 | 166 | $(OBJDIR)/%.o: $(SRCDIR)/%.c $(SRCDIR)/bios.h 167 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 168 | $(CC) -c $(CFLAGS) -o $@ $< 169 | 170 | $(OBJDIR)/%.o: $(SRCDIR)/%.S $(SRCDIR)/bios.h 171 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 172 | $(CC) -c $(CFLAGS) -Wa,-mregnames -o $@ $< 173 | 174 | $(CC) $(CFLAGS) -D__USE_$(subst .o,,$(@F))__ -c -o $@ $< 175 | 176 | # Pseudo libc objects 177 | $(OBJDIR)/%.o: $(SRCDIR)/libc/src/%.c 178 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 179 | $(CC) -c $(CFLAGS) -o $@ $< 180 | 181 | $(OBJDIR)/mem%.o: $(SRCDIR)/libc/src/mem.c 182 | $(CC) $(CFLAGS) -D__USE_$(subst .o,,$(@F))__ -c -o $@ $< 183 | 184 | $(OBJDIR)/rawmemchr.o: $(SRCDIR)/libc/src/mem.c 185 | $(CC) $(CFLAGS) -D__USE_$(subst .o,,$(@F))__ -c -o $@ $< 186 | 187 | $(OBJDIR)/str%.o: $(SRCDIR)/libc/src/str.c 188 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 189 | $(CC) $(CFLAGS) -D__USE_$(subst .o,,$(@F))__ -c -o $@ $< 190 | 191 | $(OBJDIR)/stp%.o: $(SRCDIR)/libc/src/str.c 192 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 193 | $(CC) $(CFLAGS) -D__USE_$(subst .o,,$(@F))__ -c -o $@ $< 194 | 195 | $(OBJDIR)/basename.o: $(SRCDIR)/libc/src/str.c 196 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 197 | $(CC) $(CFLAGS) -D__USE_$(subst .o,,$(@F))__ -c -o $@ $< 198 | 199 | $(OBJDIR)/dirname.o: $(SRCDIR)/libc/src/str.c 200 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 201 | $(CC) $(CFLAGS) -D__USE_$(subst .o,,$(@F))__ -c -o $@ $< 202 | 203 | $(OBJDIR)/%rintf.o: $(SRCDIR)/libc/src/format.c 204 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 205 | $(CC) $(CFLAGS) -D__USE_$(subst .o,,$(@F))__ -c -o $@ $< 206 | 207 | # libexec objects 208 | $(OBJDIR)/exec_%.o: $(SRCDIR)/libexec/%.c 209 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 210 | $(CC) -c $(CFLAGS) -o $@ $< 211 | 212 | # libfs objects 213 | $(OBJDIR)/fs_%.o: $(SRCDIR)/libfs/%.c 214 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 215 | $(CC) -c $(CFLAGS) -o $@ $< 216 | 217 | # libpart objects 218 | $(OBJDIR)/part_%.o: $(SRCDIR)/libpart/%.c 219 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 220 | $(CC) -c $(CFLAGS) -o $@ $< 221 | 222 | # Devices drivers 223 | $(OBJDIR)/dev_%.o: $(SRCDIR)/dev/%.c 224 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 225 | $(CC) -c $(CFLAGS) -o $@ $< 226 | # Char devices drivers 227 | $(OBJDIR)/dev_char_%.o: $(SRCDIR)/dev/char/%.c 228 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 229 | $(CC) -c $(CFLAGS) -o $@ $< 230 | # Bloc devices drivers 231 | $(OBJDIR)/dev_bloc_%.o: $(SRCDIR)/dev/bloc/%.c 232 | @$(DEBUG) "CFLAGS = $(CFLAGS)" 233 | $(CC) -c $(CFLAGS) -o $@ $< 234 | 235 | # Other targets 236 | tarball: $(CURDIR)/Timestamp 237 | cd .. && $(TAR) -cjf $(CURDIR)/$(TARBALL) \ 238 | $(addprefix $(CURDIR)/, $(TARFILES)) 239 | 240 | svntarball: $(CURDIR)/Timestamp 241 | cd .. && $(TAR) -cjf $(CURDIR)/$(SVN_TARBALL) \ 242 | $(addprefix $(CURDIR)/, $(TARFILES) $(SVN_DIRS)) 243 | 244 | $(CURDIR)/Timestamp: force 245 | @cd .. && echo "$(BUILD_DATE) at $(BUILD_TIME)" > $@ 246 | 247 | clean: 248 | $(RM) $(OBJDIR) $(addprefix $(DISTDIR)/, $(TARGETS)) 249 | $(RM) $(DISTFILE) $(CURDIR)/$(TARBALL) 250 | 251 | cleansrc: clean 252 | $(RM) *~ src/*~ .*~ src/.*~ 253 | 254 | # Keep all intermediary files 255 | .PRECIOUS: $(OBJDIR)/%.o $(OBJDIR)/%.out 256 | 257 | .PHONY: all dist print tarball clean cleansrc 258 | 259 | force: 260 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | =============================================================================== 2 | 3 | OpenHackWare started as a tiny BIOS that I wrote to launch Linux 4 | under Qemu-PPC for PREP emulation. 5 | Then I merged some work I some times ago, which was able to emulate 6 | some OpenFirmware functionalities to be able to launch some other 7 | Linux kernels. 8 | I then tried to improve it to be able to launch MacOSX. 9 | 10 | It's released under the GNU General Public License version 2 11 | 12 | =============================================================================== 13 | STATUS: 14 | PowerMac emulation: 15 | * Linux: 16 | - Debian: 17 | x 3.0-r1: 18 | install & install_safe crash at startup 19 | install24 & install24_safe boot but installer crashes. 20 | x same goes for 3.0-r4. 21 | x same goes for woody. 22 | x sarge_netinstall installs with some limitations: 23 | if you don't have a DHCP server, expert installation type is needed 24 | linux 2.6 framebuffer driver is buggy, so you'd better use a 2.4 kernel 25 | top is buggy: it complains it can't read /proc/stat 26 | => this seems to be a known propcps bug: 27 | "old" top used with recent kernels misunderstand "/proc/stat" format. 28 | mol does not display anything 29 | + of course, Power3 & Power4 install crashes (unsupported opcodes). 30 | - Gentoo: 31 | x 1.2-r1 ISO CDROM boots and runs 32 | x 1.4.1 live CDROM boots with no problem. 33 | x 2004.1 & 2004.3 CROMs use Linux 2.6, then have frame-buffer problems. 34 | - Mandrake 35 | x 9.1 boots and installer starts 36 | Seems to get stuck during some hardware probe 37 | x 10.1 starts booting, using 2.6 kernel. 38 | Seems to get stuck somewhere inside the kernel. 39 | x 10.2 acts the same way. 40 | - crux 41 | x 1.3 boot but crashes: looks like an i386-only ISOFS bootable CDROM. 42 | x 1.3.1 uses Linux 2.6. I guess I'm stuck during hardware probe or 43 | it panics. 44 | x 2.0 seems to react the same way as 1.3.1. 45 | - knoppix 46 | x 2003-07-13_4 boots but does not detect the hardware the right way: 47 | it wants to use the VESA driver for X. If you are patient, 48 | after a few tries, it will fallback to fbdev driver. 49 | But then, the mouse is broken (uses the Microsoft serial protocol) 50 | and the keyboard is set to german. 51 | x k-mib-ppc-beta uses 2.6 kernel. 52 | - gnoppix hoary boots kernel 2.6, then framebuffer is buggy 53 | (colors are broken: should detect 15 bpp fb, but uses 16 bpp). 54 | - sysrescue boots kernel 2.6 so framebuffer is buggy 55 | (no output but the penguin). 56 | - Fedora Core 3 uses 2.6 kernel then ... 57 | ... seems to stay stuck into a small infinite loop inside the kernel. 58 | - Fedora Core 4 does the same. 59 | - unbuntu does not load: we don't find any bootable file on the HFS partition. 60 | - yellow dog 4.0 boots with 2.6 kernel. 61 | - rock linux: it boots and installs. Unfortunatelly, there seem to be some 62 | bugs in this distribution: I did select the minimal installation, 63 | then it forgot the "hfsutils" package and so yaboot did not install itself. 64 | * NetBSD: 65 | - 1.5.2 fails to boot. 66 | - 1.6.1, 1.6.2 & 2.0 boot-loader loads but stops 67 | (missing available memory property). 68 | * OpenBSD: 69 | - boot-loader cannot run because it's a gzipped ELF file. 70 | (tried 3.4, 3.5 & 3.6 macppc CDROMs). 71 | * Darwin: 72 | - Darwin 7.01 and gnuDarwin 2.3 beta dont run: boot-loader crashes: 73 | seems to rely on special values in registers (or entry point is false...). 74 | looks like Mach-O embedded in XCOFF (?). 75 | - Darwin 6.02 and OpenDarwin 6.6.1, 6.6.2 & 20030212 load 76 | but seem not to like the OF tree as it's shown then crash. 77 | - Darwin 1.41, MacOS X 10.2 & gnuDarwin 2.3 boot 78 | but fail to mount the boot device. Seems related to the OF tree. 79 | - gnuDarwin 7.01 does not boot at all (cannot find the boot file). 80 | - OpenDarwin 7.2.1 does not boot (no boot partition found). 81 | * MacOS: 82 | - Mac OS X 10.2: fails to mount its root device. 83 | - Mac OS X 10.3 crashes: 84 | seems to try to use Altivec instructions. As my CDROM is one for G5, 85 | this may be normal. 86 | - Mac OS 9.2 installation CDROM starts to load then crashes. 87 | - Ibook Restore CDROM loads & starts booting but crashes 88 | - Ibook OS Restore CDROM does not boot (Mac OS X 10.2): 89 | does not find any boot partition. 90 | - Ibook hw check CDROM boots but crashes: 91 | boot loader need its relocations to be resolved by OHW. 92 | - IMac G5 hw check CDROM does not boot: 93 | OHW is unable to find any boot file in the boot directory. 94 | * BeOS: 95 | - not tested for now. Should not load, as fs may be ISOFS. 96 | 97 | PREP emulation: 98 | * Linux: 99 | XXX: to be completed 100 | * Windows NT 4: 101 | - XCoff file loader merges to be done for Microsoft format to be understood. 102 | * AIX: 103 | - The PREP boot image is well located at startup but it seems there are 104 | "magic" values to put in registers. Then, for now, it crashes. 105 | Seeking for informations about this executable format (starting with 106 | "AIXM"). 107 | Tested 4.3.3 and 5.1. I don't even know if they would run on a real PREP ;-) 108 | 109 | CHRP emulation: 110 | TODO (no support in qemu). 111 | 112 | MVME emulation: 113 | TODO (no support in qemu). 114 | 115 | Pegasos emulation: 116 | TODO (no support in qemu). 117 | 118 | =============================================================================== 119 | 120 | Known problems: 121 | 122 | --- 123 | RedHat make 3.79 is fully buggy. You may have several problems trying to build 124 | OpenHackWare using it. You'd better update to make 3.80 or recompile it from 125 | regular sources (ie not RedHat sources). Please don't complain if you aren't 126 | able to build the BIOS using this package. 127 | 128 | =============================================================================== 129 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | # TODO list for Open Hack'Ware. 5 | # 6 | # Copyright (C) 2005 Jocelyn Mayer (l_indien@magic.fr) 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License V2 10 | # as published by the Free Software Foundation 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | 22 | This TODO list is still quite unordered. 23 | Any other ideas are welcome. 24 | 25 | * Features needed for 0.5 release: 26 | - 2.6 Linux kernel boot for PMac & PREP targets 27 | - 2.2 Linux kernel boot for PMac & PREP targets 28 | 29 | * Features needed for 1.0 release: 30 | - Mac OS X boot for PMac target 31 | - Mac OS 9 boot for PMac target 32 | - NetBSD boot for PMac & PREP targets 33 | - OpenBSD boot for PMac & PREP targets 34 | - AIX boot for PREP target 35 | - Windows NT boot for PREP target 36 | - user should be able to tune the boot process: 37 | x choose boot partition 38 | x give special arguments to the bootloader 39 | 40 | * Short term fixes: 41 | - ASAP: as soon as qemu floppy work again, check floppy boot process. 42 | - 2.6 kernel boot. 43 | - OSX / Darwin boot 44 | - video output is mostly broken for PREP target 45 | (reported by Bruce Beare (bbeare) ) 46 | 47 | * Fixes: 48 | - fix the OF tree. 49 | - fix the bootinfos (seem buggy and are incomplete) 50 | - check why OF_blockdev_set_boot_device may be called more than once. 51 | 52 | * Features to be tested: 53 | - PEF loader 54 | 55 | * New features: 56 | - User prompt is needed when multiple bootable partitions are found. 57 | - in libfs 58 | x ext2 support 59 | x isofs support 60 | x more filesystems ? 61 | - in libpart 62 | x Fix IBM PREP CDROMs boot for AIX & WinNT for PREP 63 | x add more partition mappings (BSD slices and ?) 64 | - in libexec 65 | x Windows NT xcoff support (code exists but is to be merged and tested) 66 | x Add dynamic linker (needed to boot Apple hardware check CDROMs) 67 | - new libfilter: 68 | x compression & encryption (gzip for OpenBSD boot, ...). 69 | - in libc 70 | x Add missing string and memory functions 71 | x Add filename/URL manipulation routines (canonicalize, ...) 72 | x nls support (code exists but isn't merged). 73 | x Add hashed objects support with special cases for strings & unicode strings 74 | (code exists, need to be tested and integrated). 75 | - New architectures support (generic CHRP, MVME, pegasos, ...). 76 | To be coordinated with Qemu improvments. 77 | 78 | * Future direction for OpenHackWare: 79 | - Improve code split & structuration: 80 | x split all device drivers 81 | x make OF interface _really_ optional: currently, some devices won't be 82 | registered/initialized if OF is not present. 83 | For this to be, we should have an internal representation for all devices 84 | and OF should become just an interface to this internal tree. 85 | - Improve memory management. 86 | - Add unitary tests for most library functions 87 | - Improve exception vectors 88 | - Add virtual devices support for RTAS (virtual SCSI & ethernet) 89 | (preliminary code exists but is far from being usable). 90 | - Use unicode for internal strings (UTF-8 or UTF-32 ?). 91 | - Improve build system (current one is really ugly). 92 | - Real forth support (preliminary code exists...). 93 | - Accurate terminal emulation (some code exists). 94 | - Add a generic device cache (related to improved memory management...). 95 | -------------------------------------------------------------------------------- /Timestamp: -------------------------------------------------------------------------------- 1 | 2005-04-06 at 21:44:49 2 | -------------------------------------------------------------------------------- /src/boot.S: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * First stage BIOS loader for Open Hack'Ware. 5 | * 6 | * Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr) 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | * THE SOFTWARE. 29 | */ 30 | /* 31 | * setup one RAM bank then 32 | * relocate the one page BIOS second stage into RAM. 33 | * 34 | * We consider that we know nothing about the CPU state 35 | * at the time we enter this code. 36 | * 37 | */ 38 | 39 | #define ASSEMBLY_CODE 40 | #include "bios.h" 41 | 42 | .section .rom, "ax" 43 | .align 2 44 | _boot_start: 45 | /* Minimal setup */ 46 | li r0, 0 ; 47 | /* r11 is _boot_start address */ 48 | mflr r11 ; 49 | addi r11, r11, (_boot_start - _start - 4) ; 50 | /* Disable MMU and interruptions */ 51 | addi r12, r11, (_boot_no_mmu - _boot_start) ; 52 | mtspr SRR0, r12 ; 53 | mfmsr r12 ; 54 | lis r13, 0x0004 ; 55 | ori r13, r13, 0xEF71 ; 56 | andc r15, r12, r13 ; 57 | mtspr SRR1, r12 ; 58 | rfi ; 59 | _boot_no_mmu: 60 | /* TODO: initialize physical RAM (we need at least one page) 61 | * before doing anything else. 62 | * This may be machine dependent code. 63 | */ 64 | _boot_copy: 65 | /* Copy the second stage bootloader into RAM 66 | * We may need a tiny driver if we need to boot from special device 67 | * (ie disc-on-chip, ...) 68 | */ 69 | lis r12, (VECTORS_SIZE / 4)@h ; 70 | ori r12, r12, (VECTORS_SIZE / 4)@l ; 71 | mtctr r12 ; 72 | clrrwi r12, r11, BIOS_IMAGE_BITS ; 73 | addis r3, r12, VECTORS_SIZE@h ; 74 | addi r3, r3, VECTORS_SIZE@l ; 75 | subi r12, r12, 4 ; 76 | lis r13, VECTORS_BASE@h ; 77 | ori r13, r13, VECTORS_BASE@l ; 78 | mtlr r13 ; 79 | subi r13, r13, 4 ; 80 | _boot_copy_loop: 81 | lwzu r14, 4(r12) ; 82 | stwu r14, 4(r13) ; 83 | bdnz _boot_copy_loop ; 84 | /* Synchronize the whole execution context */ 85 | addi r12, r11, (_boot_sync - _boot_start) ; 86 | mtspr SRR0, r12 ; 87 | mfmsr r12 ; 88 | mtspr SRR1, r12 ; 89 | rfi ; 90 | _boot_sync: 91 | /* All done, jump into the loaded code */ 92 | blrl ; 93 | /* If we ever return, reboot */ 94 | b _start ; 95 | 96 | .space BOOT_SIZE - 4 - (. - _boot_start), 0xFF 97 | /* Reset entry point */ 98 | . = 0x1FC 99 | _start: 100 | bl _boot_start ; 101 | -------------------------------------------------------------------------------- /src/boot.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * First stage BIOS loader for Open Hack'Ware linker script. 5 | * 6 | * Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr) 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | OUTPUT_ARCH(powerpc:common) 23 | 24 | MEMORY 25 | { 26 | /* NOTE: some old ld do not support wrapping to zero, 27 | so we set a dummy address different from 0xFFFFFE00 */ 28 | rom (rx) : ORIGIN = 0xEFFFFE00, LENGTH = 512 29 | } 30 | 31 | SECTIONS 32 | { 33 | .rom : { *(.rom) } > rom 34 | /DISCARD/ : { *(.text) } 35 | /DISCARD/ : { *(.rodata) } 36 | /DISCARD/ : { *(.data) } 37 | /DISCARD/ : { *(.bss) } 38 | /DISCARD/ : { *(.sbss) } 39 | /DISCARD/ : { *(.sdata) } 40 | /DISCARD/ : { *(.sdata2) } 41 | /DISCARD/ : { *(.stab) } 42 | /DISCARD/ : { *(.stabstr) } 43 | /DISCARD/ : { *(.comment) } 44 | /DISCARD/ : { *(.note) } 45 | } 46 | -------------------------------------------------------------------------------- /src/bootinfos.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Generate boot informations (bootinfos for Linux and residual data). 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include "bios.h" 24 | 25 | #define BI_FIRST 0x1010 /* first record - marker */ 26 | #define BI_LAST 0x1011 /* last record - marker */ 27 | #define BI_CMD_LINE 0x1012 28 | #define BI_BOOTLOADER_ID 0x1013 29 | #define BI_INITRD 0x1014 30 | #define BI_SYSMAP 0x1015 31 | #define BI_MACHTYPE 0x1016 32 | #define BI_MEMSIZE 0x1017 33 | #define BI_BOARD_INFO 0x1018 34 | 35 | static inline void put_long (void *addr, uint32_t l) 36 | { 37 | char *pos = addr; 38 | pos[0] = (l >> 24) & 0xFF; 39 | pos[1] = (l >> 16) & 0xFF; 40 | pos[2] = (l >> 8) & 0xFF; 41 | pos[3] = l & 0xFF; 42 | } 43 | 44 | static void *set_bootinfo_tag (void *addr, uint32_t tag, uint32_t size, 45 | void *data) 46 | { 47 | char *pos = addr; 48 | 49 | put_long(pos, tag); 50 | pos += 4; 51 | put_long(pos, size + 8); 52 | pos += 4; 53 | memcpy(pos, data, size); 54 | pos += size; 55 | 56 | return pos; 57 | } 58 | 59 | void prepare_bootinfos (void *p, uint32_t memsize, 60 | void *cmdline, void *initrd, uint32_t initrd_size) 61 | { 62 | uint32_t tmpi[2]; 63 | 64 | /* BI_FIRST */ 65 | p = set_bootinfo_tag(p, BI_FIRST, 0, NULL); 66 | /* BI_CMD_LINE */ 67 | if (cmdline != 0) { 68 | p = set_bootinfo_tag(p, BI_CMD_LINE, strlen(cmdline), cmdline); 69 | } else { 70 | p = set_bootinfo_tag(p, BI_CMD_LINE, 0, NULL); 71 | } 72 | /* BI_MEM_SIZE */ 73 | p = set_bootinfo_tag(p, BI_MEMSIZE, 4, &memsize); 74 | /* BI_INITRD */ 75 | tmpi[0] = (uint32_t)initrd; 76 | tmpi[1] = initrd_size; 77 | p = set_bootinfo_tag(p, BI_INITRD, 8, tmpi); 78 | /* BI_LAST */ 79 | p = set_bootinfo_tag(p, BI_LAST, 0, 0); 80 | } 81 | 82 | /* Residual data */ 83 | #define MAX_CPUS 16 84 | #define MAX_SEGS 64 85 | #define MAX_MEMS 64 86 | #define MAX_DEVS 256 87 | 88 | typedef struct vital_t { 89 | /* Motherboard dependents */ 90 | uint8_t model[32]; 91 | uint8_t serial[64]; 92 | uint16_t version; 93 | uint16_t revision; 94 | uint32_t firmware; 95 | uint32_t NVRAM_size; 96 | uint32_t nSIMMslots; 97 | uint32_t nISAslots; 98 | uint32_t nPCIslots; 99 | uint32_t nPCMCIAslots; 100 | uint32_t nMCAslots; 101 | uint32_t nEISAslots; 102 | uint32_t CPUHz; 103 | uint32_t busHz; 104 | uint32_t PCIHz; 105 | uint32_t TBdiv; 106 | /* CPU infos */ 107 | uint32_t wwidth; 108 | uint32_t page_size; 109 | uint32_t ChBlocSize; 110 | uint32_t GrSize; 111 | /* Cache and TLBs */ 112 | uint32_t cache_size; 113 | uint32_t cache_type; 114 | uint32_t cache_assoc; 115 | uint32_t cache_lnsize; 116 | uint32_t Icache_size; 117 | uint32_t Icache_assoc; 118 | uint32_t Icache_lnsize; 119 | uint32_t Dcache_size; 120 | uint32_t Dcache_assoc; 121 | uint32_t Dcache_lnsize; 122 | uint32_t TLB_size; 123 | uint32_t TLB_type; 124 | uint32_t TLB_assoc; 125 | uint32_t ITLB_size; 126 | uint32_t ITLB_assoc; 127 | uint32_t DTLB_size; 128 | uint32_t DTLB_assoc; 129 | void *ext_vital; 130 | } vital_t; 131 | 132 | typedef struct PPC_CPU_t { 133 | uint32_t pvr; 134 | uint32_t serial; 135 | uint32_t L2_size; 136 | uint32_t L2_assoc; 137 | } PPC_CPU_t; 138 | 139 | typedef struct map_t { 140 | uint32_t usage; 141 | uint32_t base; 142 | uint32_t count; 143 | } map_t; 144 | 145 | typedef struct PPC_mem_t { 146 | uint32_t size; 147 | } PPC_mem_t; 148 | 149 | typedef struct PPC_device_t { 150 | uint32_t busID; 151 | uint32_t devID; 152 | uint32_t serial; 153 | uint32_t flags; 154 | uint32_t type; 155 | uint32_t subtype; 156 | uint32_t interface; 157 | uint32_t spare; 158 | } PPC_device_t; 159 | 160 | typedef struct residual_t { 161 | uint32_t length; 162 | uint16_t version; 163 | uint16_t revision; 164 | vital_t vital; 165 | uint32_t nCPUs; 166 | PPC_CPU_t CPUs[MAX_CPUS]; 167 | uint32_t max_mem; 168 | uint32_t good_mem; 169 | uint32_t nmaps; 170 | map_t maps[MAX_SEGS]; 171 | uint32_t nmems; 172 | PPC_mem_t memories[MAX_MEMS]; 173 | uint32_t ndevices; 174 | PPC_device_t devices[MAX_DEVS]; 175 | /* TOFIX: No PNP devices */ 176 | } residual_t; 177 | 178 | void residual_build (void *p, uint32_t memsize, 179 | uint32_t load_base, uint32_t load_size, 180 | uint32_t last_alloc) 181 | { 182 | const unsigned char model[] = "Qemu\0PPC\0"; 183 | residual_t *res = p; 184 | int i; 185 | 186 | if (res == NULL) 187 | return; 188 | res->length = sizeof(residual_t); 189 | res->version = 1; 190 | res->revision = 0; 191 | memcpy(res->vital.model, model, sizeof(model)); 192 | res->vital.version = 1; 193 | res->vital.revision = 0; 194 | res->vital.firmware = 0x1D1; 195 | res->vital.NVRAM_size = 0x2000; 196 | res->vital.nSIMMslots = 1; 197 | res->vital.nISAslots = 0; 198 | res->vital.nPCIslots = 0; 199 | res->vital.nPCMCIAslots = 0; 200 | res->vital.nMCAslots = 0; 201 | res->vital.nEISAslots = 0; 202 | res->vital.CPUHz = 200 * 1000 * 1000; 203 | res->vital.busHz = 100 * 1000 * 1000; 204 | res->vital.PCIHz = 33 * 1000 * 1000; 205 | res->vital.TBdiv = 1000; 206 | res->vital.wwidth = 32; 207 | res->vital.page_size = 4096; 208 | res->vital.ChBlocSize = 32; 209 | res->vital.GrSize = 32; 210 | res->vital.cache_size = 0; 211 | res->vital.cache_type = 0; /* No cache */ 212 | res->vital.cache_assoc = 8; /* Same as 601 */ 213 | res->vital.cache_lnsize = 32; 214 | res->vital.Icache_size = 0; 215 | res->vital.Icache_assoc = 8; 216 | res->vital.Icache_lnsize = 32; 217 | res->vital.Dcache_size = 0; 218 | res->vital.Dcache_assoc = 8; 219 | res->vital.Dcache_lnsize = 32; 220 | res->vital.TLB_size = 0; 221 | res->vital.TLB_type = 0; /* None */ 222 | res->vital.TLB_assoc = 2; 223 | res->vital.ITLB_size = 0; 224 | res->vital.ITLB_assoc = 2; 225 | res->vital.DTLB_size = 0; 226 | res->vital.DTLB_assoc = 2; 227 | res->vital.ext_vital = NULL; 228 | res->nCPUs = 1; 229 | res->CPUs[0].pvr = mfpvr(); 230 | res->CPUs[0].serial = 0; 231 | res->CPUs[0].L2_size = 0; 232 | res->CPUs[0].L2_assoc = 8; 233 | /* Memory infos */ 234 | res->max_mem = memsize; 235 | res->good_mem = memsize; 236 | /* Memory mappings */ 237 | /* First segment: firmware */ 238 | last_alloc = (last_alloc + 4095) & ~4095; 239 | res->maps[0].usage = 0x0007; 240 | res->maps[0].base = 0x00000000; 241 | res->maps[0].count = last_alloc >> 12; 242 | i = 1; 243 | if (last_alloc != load_base) { 244 | /* Free memory between firmware and boot image */ 245 | res->maps[1].usage = 0x0010; 246 | res->maps[1].base = last_alloc >> 12; 247 | res->maps[1].count = (load_base - last_alloc) >> 12; 248 | i++; 249 | } 250 | /* Boot image */ 251 | load_size = (load_size + 4095) & ~4095; 252 | res->maps[i].usage = 0x0008; 253 | res->maps[i].base = load_base >> 12; 254 | res->maps[i].count = load_size >> 12; 255 | i++; 256 | /* Free memory */ 257 | res->maps[i].usage = 0x0010; 258 | res->maps[i].base = (load_base + load_size) >> 12; 259 | res->maps[i].count = (memsize >> 12) - res->maps[i].base; 260 | i++; 261 | /* ISA IO region : 8MB */ 262 | res->maps[i].usage = 0x0040; 263 | res->maps[i].base = 0x80000000 >> 12; 264 | res->maps[i].count = 0x00800000 >> 12; 265 | i++; 266 | /* System registers : 8MB */ 267 | res->maps[i].usage = 0x0200; 268 | res->maps[i].base = 0xBF800000 >> 12; 269 | res->maps[i].count = 0x00800000 >> 12; 270 | i++; 271 | /* System ROM : 64 kB */ 272 | res->maps[i].usage = 0x2000; 273 | res->maps[i].base = 0xFFFF0000 >> 12; 274 | res->maps[i].count = 0x00010000 >> 12; 275 | i++; 276 | res->nmaps = i; 277 | /* Memory SIMMs */ 278 | res->nmems = 1; 279 | res->memories[0].size = memsize; 280 | /* Describe no devices */ 281 | res->ndevices = 0; 282 | } 283 | -------------------------------------------------------------------------------- /src/dev/bus/adb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ADB bus definitions for Open Hack'Ware 3 | * 4 | * Copyright (c) 2004-2005 Jocelyn Mayer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License V2 8 | * as published by the Free Software Foundation 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #if !defined(__OHW_ADB_H__) 21 | #define __OHW_ADB_H__ 22 | 23 | typedef struct adb_bus_t adb_bus_t; 24 | typedef struct adb_dev_t adb_dev_t; 25 | 26 | #define ADB_BUF_SIZE 8 27 | struct adb_bus_t { 28 | void *host; 29 | int (*req)(void *host, const uint8_t *snd_buf, int len, uint8_t *rcv_buf); 30 | adb_dev_t *devices; 31 | }; 32 | 33 | struct adb_dev_t { 34 | adb_dev_t *next; 35 | adb_bus_t *bus; 36 | uint8_t addr; 37 | uint8_t type; 38 | uint32_t state; 39 | }; 40 | 41 | #define ADB_BUF_SIZE 8 42 | 43 | /* ADB commands */ 44 | enum { 45 | ADB_SEND_RESET = 0x00, 46 | ADB_FLUSH = 0x01, 47 | ADB_LISTEN = 0x08, 48 | ADB_TALK = 0x0C, 49 | }; 50 | /* ADB default IDs before relocation */ 51 | enum { 52 | ADB_PROTECT = 0x01, 53 | ADB_KEYBD = 0x02, 54 | ADB_MOUSE = 0x03, 55 | ADB_ABS = 0x04, 56 | ADB_MODEM = 0x05, 57 | ADB_RES = 0x06, 58 | ADB_MISC = 0x07, 59 | }; 60 | /* ADB special device handlers IDs */ 61 | enum { 62 | ADB_CHADDR = 0x00, 63 | ADB_CHADDR_ACTIV = 0xFD, 64 | ADB_CHADDR_NOCOLL = 0xFE, 65 | ADB_SELF_TEST = 0xFF, 66 | }; 67 | 68 | int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg, 69 | uint8_t *buf, int len); 70 | void adb_bus_reset (adb_bus_t *bus); 71 | adb_bus_t *adb_bus_new (void *host, 72 | int (*req)(void *host, const uint8_t *snd_buf, 73 | int len, uint8_t *rcv_buf)); 74 | int adb_bus_init (adb_bus_t *bus); 75 | 76 | static inline int adb_reset (adb_bus_t *bus) 77 | { 78 | adb_dev_t fake_device; 79 | 80 | memset(&fake_device, 0, sizeof(adb_dev_t)); 81 | fake_device.bus = bus; 82 | 83 | return adb_cmd(&fake_device, ADB_SEND_RESET, 0, NULL, 0); 84 | } 85 | 86 | static inline int adb_flush (adb_dev_t *dev) 87 | { 88 | return adb_cmd(dev, ADB_FLUSH, 0, NULL, 0); 89 | } 90 | 91 | static inline int adb_reg_get (adb_dev_t *dev, uint8_t reg, uint8_t *buf) 92 | { 93 | return adb_cmd(dev, ADB_TALK, reg, buf, 0); 94 | } 95 | 96 | static inline int adb_reg_set (adb_dev_t *dev, uint8_t reg, 97 | uint8_t *buf, int len) 98 | { 99 | return adb_cmd(dev, ADB_LISTEN, reg, buf, len); 100 | } 101 | 102 | #endif /* !defined(__OHW_ADB_H__) */ 103 | -------------------------------------------------------------------------------- /src/dev/char/char.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS misc char devices definitions. 5 | * 6 | * Copyright (c) 2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_DEV_CHAR_H__) 23 | #define __OHW_DEV_CHAR_H__ 24 | 25 | /* Keyboard devices registration */ 26 | int pckbd_register (void); 27 | void *adb_kbd_new (void *private); 28 | 29 | #endif /* !defined (__OHW_DEV_CHAR_H__) */ 30 | -------------------------------------------------------------------------------- /src/dev/char/kbd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS generic keyboard input translation. 5 | * 6 | * Copyright (c) 2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "kbd.h" 26 | 27 | //#define DEBUG_KBD 28 | #ifdef DEBUG_KBD 29 | #define KBD_DPRINTF(fmt, args...) \ 30 | do { dprintf("KBD - %s: " fmt, __func__ , ##args); } while (0) 31 | #else 32 | #define KBD_DPRINTF(fmt, args...) do { } while (0) 33 | #endif 34 | 35 | void *kbd_new (int len) 36 | { 37 | kbd_t *kbd; 38 | 39 | if (len < (int)sizeof(kbd_t)) { 40 | kbd = NULL; 41 | } else { 42 | kbd = malloc(len); 43 | if (kbd != NULL) 44 | memset(kbd, 0, len); 45 | } 46 | 47 | return kbd; 48 | } 49 | 50 | int kbd_set_keymap (kbd_t *kbd, int nb_keys, keymap_t *keymap) 51 | { 52 | kbd->nb_keys = nb_keys; 53 | kbd->keymap = keymap; 54 | 55 | return 0; 56 | } 57 | 58 | int kbd_translate_key (kbd_t *kbd, int keycode, int up_down) 59 | { 60 | keymap_t *keyt; 61 | int mod_state, key, type; 62 | int ret; 63 | 64 | ret = -1; 65 | /* Get key table */ 66 | if (keycode < kbd->nb_keys) { 67 | keyt = &kbd->keymap[keycode]; 68 | /* Get modifier state */ 69 | mod_state = (kbd->mod_state | (kbd->mod_state >> 8)) & 0xFF; 70 | /* Adjust with lock */ 71 | if (keyt->lck_shift >= 0) { 72 | if ((kbd->mod_state >> (16 + keyt->lck_shift)) & 0x01) { 73 | KBD_DPRINTF("adjust with lock %02x => %02x (%d %08x)\n", 74 | mod_state, 75 | mod_state ^ ((kbd->mod_state >> 76 | (16 + keyt->lck_shift)) & 77 | 0x01), 78 | keyt->lck_shift, kbd->mod_state); 79 | } 80 | mod_state ^= (kbd->mod_state >> (16 + keyt->lck_shift)) & 0x01; 81 | } 82 | key = keyt->trans[mod_state]; 83 | type = key & 0xFF000000; 84 | key &= ~0xFF000000; 85 | switch (type) { 86 | case KBD_TYPE_REGULAR: 87 | if (!up_down) { 88 | /* We don't care about up events on "normal" keys */ 89 | ret = key; 90 | } 91 | break; 92 | case KBD_TYPE_LOCK: 93 | if (!up_down) { 94 | kbd->mod_state ^= key; 95 | ret = -2; 96 | KBD_DPRINTF("Change modifier type %d key %04x %s => %08x\n", 97 | type, key, up_down ? "up" : "down", 98 | kbd->mod_state); 99 | } 100 | break; 101 | case KBD_TYPE_LMOD: 102 | case KBD_TYPE_RMOD: 103 | if (up_down) 104 | kbd->mod_state &= ~key; 105 | else 106 | kbd->mod_state |= key; 107 | KBD_DPRINTF("Change modifier type %d key %04x %s => %08x\n", 108 | type, key, up_down ? "up" : "down", kbd->mod_state); 109 | ret = -2; /* The caller may know the key was a modifier */ 110 | break; 111 | default: 112 | KBD_DPRINTF("Unknown key: keycode=%02x mod_state=%02x (%08x)\n", 113 | keycode, mod_state, kbd->mod_state); 114 | break; 115 | } 116 | } else { 117 | KBD_DPRINTF("Unmanaged key: keycode=%02x mod_state %08x\n", 118 | keycode, kbd->mod_state); 119 | } 120 | 121 | return ret; 122 | } 123 | -------------------------------------------------------------------------------- /src/dev/char/kbd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS generic keyboard management definitions. 5 | * 6 | * Copyright (c) 2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_KBD_H__) 23 | #define __OHW_KBD_H__ 24 | 25 | typedef struct kbd_t kbd_t; 26 | typedef struct keymap_t keymap_t; 27 | struct kbd_t { 28 | uint32_t mod_state; 29 | /* Modifier state 30 | * 0x00 kk ll rr 31 | * | | | | 32 | * Not used for now -+ | | | 33 | * Locks ---------------+ | | 34 | * Left modifiers ---------+ | 35 | * Right modifiers -----------+ 36 | */ 37 | int nb_keys; 38 | keymap_t *keymap; 39 | }; 40 | 41 | /* Modifiers */ 42 | typedef enum { 43 | KBD_MOD_SHIFT = 0x01, 44 | KBD_MOD_CTRL = 0x02, 45 | KBD_MOD_ALT = 0x04, 46 | KBD_MOD_CMD = 0x08, 47 | KBD_MOD_OPT = 0x10, 48 | } kbd_modifiers; 49 | 50 | /* Locks */ 51 | typedef enum { 52 | KBD_LCK_CAPS = 0x01, 53 | KBD_LCK_NUM = 0x02, 54 | KBD_LCK_SCROLL = 0x04, 55 | } kbd_locks; 56 | 57 | /* Lock shifts */ 58 | typedef enum { 59 | KBD_SH_NONE = -1, 60 | KBD_SH_CAPS = 0, 61 | KBD_SH_NUML = 1, 62 | KBD_SH_SCRL = 2, 63 | } kbd_lck_shifts; 64 | 65 | enum { 66 | KBD_TYPE_REGULAR = 0 << 24, 67 | KBD_TYPE_LMOD = 1 << 24, 68 | KBD_TYPE_RMOD = 2 << 24, 69 | KBD_TYPE_LOCK = 3 << 24, 70 | }; 71 | 72 | #define KBD_MOD_MAP(mod) \ 73 | KBD_SH_NONE, { (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \ 74 | (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \ 75 | (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \ 76 | (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), } 77 | #define KBD_MOD_MAP_LSHIFT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_SHIFT) 78 | #define KBD_MOD_MAP_RSHIFT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_SHIFT << 8)) 79 | #define KBD_MOD_MAP_LCTRL KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_CTRL) 80 | #define KBD_MOD_MAP_RCTRL KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_CTRL << 8)) 81 | #define KBD_MOD_MAP_LALT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_ALT) 82 | #define KBD_MOD_MAP_RALT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_ALT << 8)) 83 | #define KBD_MOD_MAP_LCMD KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_CMD) 84 | #define KBD_MOD_MAP_RCMD KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_CMD << 8)) 85 | #define KBD_MOD_MAP_LOPT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_OPT) 86 | #define KBD_MOD_MAP_ROPT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_OPT << 8)) 87 | #define KBD_MOD_MAP_CAPS KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_CAPS << 16)) 88 | #define KBD_MOD_MAP_NUML KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_NUML << 16)) 89 | #define KBD_MOD_MAP_SCROLL KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_SCRL << 16)) 90 | #define KBD_MAP_NONE KBD_MOD_MAP(-1) 91 | 92 | /* Keymap definition */ 93 | struct keymap_t { 94 | /* Set the lock which applies to this key (if any) */ 95 | int lck_shift; 96 | /* Key translations */ 97 | uint32_t trans[32]; 98 | }; 99 | 100 | void *kbd_new (int len); 101 | int kbd_set_keymap (kbd_t *kbd, int nb_keys, keymap_t *keymap); 102 | int kbd_translate_key (kbd_t *kbd, int keycode, int up_down); 103 | 104 | #endif /* !defined (__OHW_KBD_H__) */ 105 | -------------------------------------------------------------------------------- /src/dev/char/pckbd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS PC keyboard driver. 5 | * 6 | * Copyright (c) 2005 Jocelyn Mayer 7 | * 8 | * This code is a rework (mostly simplification) from code 9 | * proposed by Matthew Wood 10 | * 11 | * This program is free software; you can redistribute it and/or 12 | * modify it under the terms of the GNU General Public License V2 13 | * as published by the Free Software Foundation 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #include 26 | #include 27 | #include "bios.h" 28 | 29 | /* IO definitions */ 30 | #define PCKBD_IO_BASE 0x60 31 | #define PCKBD_COMMAND_OFFSET 0x4 32 | #define PCKBD_STATUS_OFFSET 0x4 33 | 34 | /* Indexes for keyboard state */ 35 | #define SHIFT 0x1 36 | #define CTRL 0x2 37 | #define ALT 0x4 38 | 39 | /* Scan codes */ 40 | #define L_SHIFT 0x2a 41 | #define R_SHIFT 0x36 42 | #define L_CTRL 0x1d 43 | /* XXX: R_CTRL ? */ 44 | #define L_ALT 0x38 45 | /* XXX: missing capslock */ 46 | /* XXX: TODO: add keypad/numlock ... (pc105 kbd) */ 47 | 48 | typedef struct kbdmap_t kbdmap_t; 49 | struct kbdmap_t { 50 | char translate[8]; 51 | }; 52 | 53 | typedef struct pckbd_t pckbd_t; 54 | struct pckbd_t { 55 | int modifiers; 56 | kbdmap_t *map; 57 | int maplen; 58 | int io_base; 59 | }; 60 | 61 | /* XXX: should not be here cause it's locale dependent */ 62 | static kbdmap_t pc_map_us[] = { 63 | /* 0x00 */ 64 | { { -1, -1, -1, -1, -1, -1, -1, -1, }, }, 65 | { { 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, }, }, 66 | { { '1', '!', -1, -1, '1', '!', -1, -1, }, }, 67 | { { '2', '\'', '\'', -1, -1, '2', '\'', '\'', }, }, 68 | { { '3', '#', -1, -1, '3', '#', -1, -1, }, }, 69 | { { '4', '$', -1, -1, '4', '$', -1, -1, }, }, 70 | { { '5', '%', -1, -1, '5', '%', -1, -1, }, }, 71 | { { '6', '^', -1, -1, '6', '^', -1, -1, }, }, 72 | /* 0x08 */ 73 | { { '7', '&', -1, -1, '7', '&', -1, -1, }, }, 74 | { { '8', '*', -1, -1, '8', '*', -1, -1, }, }, 75 | { { '9', '(', -1, -1, '9', '(', -1, -1, }, }, 76 | { { '0', ')', -1, -1, '0', ')', -1, -1, }, }, 77 | { { '-', '_', -1, -1, '-', '_', -1, -1, }, }, 78 | { { '=', '+', -1, -1, '=', '+', -1, -1, }, }, 79 | { { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, }, }, 80 | { { 0x2a, -1, -1, -1, 0x2a, -1, -1, -1, }, }, 81 | /* 0x10 */ 82 | { { 'q', 'Q', -1, -1, 'q', 'Q', -1, -1, }, }, 83 | { { 'w', 'W', -1, -1, 'w', 'W', -1, -1, }, }, 84 | { { 'e', 'E', -1, -1, 'e', 'E', -1, -1, }, }, 85 | { { 'r', 'R', -1, -1, 'r', 'R', -1, -1, }, }, 86 | { { 't', 'T', -1, -1, 't', 'T', -1, -1, }, }, 87 | { { 'y', 'Y', -1, -1, 'y', 'Y', -1, -1, }, }, 88 | { { 'u', 'U', -1, -1, 'u', 'U', -1, -1, }, }, 89 | { { 'i', 'I', -1, -1, 'i', 'I', -1, -1, }, }, 90 | /* 0x18 */ 91 | { { 'o', 'O', -1, -1, 'o', 'O', -1, -1, }, }, 92 | { { 'p', 'P', -1, -1, 'p', 'P', -1, -1, }, }, 93 | { { '[', '{', 0x1b, 0x1b, '[', '{', 0x1b, 0x1b, }, }, 94 | { { ']', '}', -1, -1, ']', '}', -1, -1, }, }, 95 | { { 0x0d, 0x0d, '\r', '\r', 0x0d, 0x0d, '\r', '\r', }, }, 96 | { { -1, -1, -1, -1, -1, -1, -1, -1, }, }, 97 | { { 'a', 'A', -1, -1, 'a', 'A', -1, -1, }, }, 98 | { { 's', 'S', -1, -1, 's', 'S', -1, -1, }, }, 99 | /* 0x20 */ 100 | { { 'd', 'D', -1, -1, 'd', 'D', -1, -1, }, }, 101 | { { 'f', 'F', -1, -1, 'f', 'F', -1, -1, }, }, 102 | { { 'g', 'G', 0x07, 0x07, 'g', 'G', 0x07, 0x07, }, }, 103 | { { 'h', 'H', 0x08, 0x08, 'h', 'H', 0x08, 0x08, }, }, 104 | { { 'j', 'J', '\r', '\r', 'j', 'J', '\r', '\r', }, }, 105 | { { 'k', 'K', -1, -1, 'k', 'K', -1, -1, }, }, 106 | { { 'l', 'L', -1, -1, 'l', 'L', -1, -1, }, }, 107 | { { ';', ':', -1, -1, ';', ':', -1, -1, }, }, 108 | /* 0x28 */ 109 | { { '\'', '"', -1, -1, '\'', '"', -1, -1, }, }, 110 | { { '`', '~', -1, -1, '`', '~', -1, -1, }, }, 111 | { { 0x02, -1, -1, -1, -1, -1, -1, -1, }, }, 112 | { { '\\', '|', -1, -1, '\\', '|', -1, -1, }, }, 113 | { { 'z', 'Z', -1, -1, 'z', 'Z', -1, -1, }, }, 114 | { { 'x', 'X', -1, -1, 'x', 'X', -1, -1, }, }, 115 | { { 'c', 'C', -1, -1, 'c', 'C', -1, -1, }, }, 116 | { { 'v', 'V', 0x16, 0x16, 'v', 'V', -1, -1, }, }, 117 | /* 0x30 */ 118 | { { 'b', 'B', -1, -1, 'b', 'B', -1, -1, }, }, 119 | { { 'n', 'N', -1, -1, 'n', 'N', -1, -1, }, }, 120 | { { 'm', 'M', 0x0d, 0x0d, 'm', 'M', 0x0d, 0x0d, }, }, 121 | { { ',', '<', -1, -1, ',', '<', -1, -1, }, }, 122 | { { '.', '>', -1, -1, '.', '>', -1, -1, }, }, 123 | { { '/', '?', -1, -1, '/', '?', -1, -1, }, }, 124 | { { -1, -1, -1, -1, -1, -1, -1, -1, }, }, 125 | { { '*', '*', -1, -1, '*', '*', -1, -1, }, }, 126 | /* 0x38 */ 127 | { { -1, -1, -1, -1, -1, -1, -1, -1, }, }, 128 | { { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, }, 129 | }; 130 | 131 | static int pckbd_open (unused void *private) 132 | { 133 | return 0; 134 | } 135 | 136 | static int pckbd_close (unused void *private) 137 | { 138 | return 0; 139 | } 140 | 141 | static int pckbd_readb (void *private) 142 | { 143 | pckbd_t *kbd = private; 144 | int status, key, up, mod; 145 | int ret; 146 | 147 | for (ret = -1; ret < 0; ) { 148 | status = inb(kbd->io_base + PCKBD_STATUS_OFFSET); 149 | if (!(status & 1)) { 150 | /* No more data available */ 151 | break; 152 | } 153 | key = inb(kbd->io_base); 154 | up = (key & 0x80) != 0; 155 | key &= ~0x80; 156 | switch (key) { 157 | case 0: 158 | break; 159 | case L_ALT: 160 | mod = ALT; 161 | goto set_modifiers; 162 | case L_SHIFT: 163 | case R_SHIFT: 164 | mod = SHIFT; 165 | goto set_modifiers; 166 | case L_CTRL: 167 | #if 0 /* XXX: missing definition */ 168 | case R_CTRL: 169 | #endif 170 | mod = CTRL; 171 | set_modifiers: 172 | if (up) 173 | kbd->modifiers &= ~mod; 174 | else 175 | kbd->modifiers |= mod; 176 | break; 177 | default: 178 | /* We don't care about up events or unknown keys */ 179 | if (!up && key < kbd->maplen) 180 | ret = kbd->map[key].translate[kbd->modifiers]; 181 | break; 182 | } 183 | } 184 | 185 | return ret; 186 | } 187 | 188 | static cops_t pckbd_ops = { 189 | &pckbd_open, 190 | &pckbd_close, 191 | &pckbd_readb, 192 | NULL, 193 | }; 194 | 195 | int pckbd_register (void) 196 | { 197 | pckbd_t *kbd; 198 | 199 | kbd = malloc(sizeof(pckbd_t)); 200 | if (kbd == NULL) 201 | return -1; 202 | memset(kbd, 0, sizeof(pckbd_t)); 203 | /* Set IO base */ 204 | /* XXX: should be a parameter... */ 205 | kbd->io_base = PCKBD_IO_BASE; 206 | /* Set default keymap */ 207 | kbd->map = pc_map_us; 208 | kbd->maplen = sizeof(pc_map_us) / sizeof(kbdmap_t); 209 | /* Reset modifiers state */ 210 | kbd->modifiers = 0x00; 211 | chardev_register(CHARDEV_KBD, &pckbd_ops, kbd); 212 | 213 | return 0; 214 | } 215 | -------------------------------------------------------------------------------- /src/libc/include/ctype.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS POSIX like ctype definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_CTYPE_H__) 23 | #define __OHW_CTYPE_H__ 24 | 25 | /* Beware that those routines only support ASCII */ 26 | static inline int islower (int c) 27 | { 28 | return c >= 'a' && c <= 'z'; 29 | } 30 | 31 | static inline int isupper (int c) 32 | { 33 | return c >= 'A' && c <= 'Z'; 34 | } 35 | 36 | static inline int isalpha (int c) 37 | { 38 | return islower(c) || isupper(c); 39 | } 40 | 41 | static inline int isdigit (int c) 42 | { 43 | return c >= '0' && c <= '9'; 44 | } 45 | 46 | static inline int isalnum (int c) 47 | { 48 | return isalpha(c) || isdigit(c); 49 | } 50 | 51 | static inline int isxdigit (int c) 52 | { 53 | return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); 54 | } 55 | 56 | static inline int isspace (int c) 57 | { 58 | return c == ' ' || c == '\f' || c == '\n' || c == '\r' || 59 | c == '\t' || c == '\v'; 60 | } 61 | 62 | static inline int isgraph (int c) 63 | { 64 | return (c >= 0x21 && c <= 0x7E) || (c >= 0xA1 && c <= 0xFF); 65 | } 66 | 67 | static inline int isprint (int c) 68 | { 69 | return isgraph(c) && c != ' '; 70 | } 71 | 72 | static inline int ispunct (int c) 73 | { 74 | return isprint(c) && !isalpha(c) && !isspace(c); 75 | } 76 | 77 | static inline int isblank (int c) 78 | { 79 | return c == ' ' || c == '\t'; 80 | } 81 | 82 | static inline int iscntrl (int c) 83 | { 84 | return !isprint(c); 85 | } 86 | 87 | static inline int isascii (int c) 88 | { 89 | return (c & 0x80) == 0; 90 | } 91 | 92 | static inline int tolower (int c) 93 | { 94 | if (isupper(c)) 95 | c |= 0x20; 96 | 97 | return c; 98 | } 99 | 100 | static inline int toupper (int c) 101 | { 102 | if (islower(c)) 103 | c &= ~0x20; 104 | 105 | return c; 106 | } 107 | 108 | static inline int toascii (int c) 109 | { 110 | return c & ~0x80; 111 | } 112 | 113 | #endif /* !defined (__OHW_CTYPE_H__) */ 114 | -------------------------------------------------------------------------------- /src/libc/include/errno.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS errno management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #if !defined (__OHW_ERRNO_H__) 22 | #define __OHW_ERRNO_H__ 23 | 24 | struct task { 25 | int errno; 26 | }; 27 | 28 | extern struct task cur_task; 29 | 30 | void *get_current_stack (void); 31 | 32 | static inline int *errno_location (void) 33 | { 34 | /* XXX: to fix */ 35 | #if 0 36 | struct task *taskp; 37 | 38 | taskp = get_current_stack(); 39 | 40 | return &taskp->errno; 41 | #else 42 | return &cur_task.errno; 43 | #endif 44 | } 45 | 46 | static inline void set_errno (int errnum) 47 | { 48 | *(errno_location()) = errnum; 49 | } 50 | 51 | static inline int get_errno (void) 52 | { 53 | return *(errno_location()); 54 | } 55 | 56 | #define errno get_errno() 57 | 58 | enum { 59 | ENOMEM, 60 | }; 61 | 62 | #endif /* !defined (__OHW_ERRNO_H__) */ 63 | -------------------------------------------------------------------------------- /src/libc/include/fcntl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: subset of POSIX fcntl definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_FCNTL_H__) 23 | #define __OHW_FCNTL_H__ 24 | 25 | enum { 26 | O_RDONLY = 0x0001, 27 | O_WRONLY = 0x0002, 28 | O_RDWR = 0x0003, 29 | O_CREAT = 0x0010, 30 | O_EXCL = 0x0020, 31 | }; 32 | 33 | #endif /* !defined (__OHW_FCNTL_H__) */ 34 | -------------------------------------------------------------------------------- /src/libc/include/stddef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: subset of POSIX standard definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_STDDEF_H__) 23 | #define __OHW_STDDEF_H__ 24 | 25 | #include 26 | 27 | typedef signed long ptrdiff_t; 28 | typedef unsigned long size_t; 29 | typedef signed long ssize_t; 30 | typedef signed long off_t; 31 | 32 | /* We use unicode UCS-4 as the standard character set */ 33 | typedef uint32_t wchar_t; 34 | 35 | /* XXX: to be moveed elsewhere */ 36 | typedef uint32_t mode_t; 37 | 38 | #endif /* !defined (__OHW_STDDEF_H__) */ 39 | -------------------------------------------------------------------------------- /src/libc/include/stdint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: arch dependent basic types 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_STDINT_H__) 23 | #define __OHW_STDINT_H__ 24 | 25 | #if defined (__i386__) 26 | 27 | typedef unsigned char uint8_t; 28 | typedef signed char int8_t; 29 | typedef unsigned short uint16_t; 30 | typedef signed short int16_t; 31 | typedef unsigned int uint32_t; 32 | typedef signed int int32_t; 33 | typedef unsigned long long uint64_t; 34 | typedef signed long long int64_t; 35 | 36 | #elif defined (__x86_64__) 37 | 38 | typedef unsigned char uint8_t; 39 | typedef signed char int8_t; 40 | typedef unsigned short uint16_t; 41 | typedef signed short int16_t; 42 | typedef unsigned int uint32_t; 43 | typedef signed int int32_t; 44 | typedef unsigned long uint64_t; 45 | typedef signed long int64_t; 46 | 47 | #elif defined (__powerpc__) || defined (_ARCH_PPC) 48 | 49 | typedef unsigned char uint8_t; 50 | typedef signed char int8_t; 51 | typedef unsigned short uint16_t; 52 | typedef signed short int16_t; 53 | typedef unsigned int uint32_t; 54 | typedef signed int int32_t; 55 | typedef unsigned long long uint64_t; 56 | typedef signed long long int64_t; 57 | 58 | #elif defined (__powerpc64__) || defined (_ARCH_PPC64) 59 | 60 | typedef unsigned char uint8_t; 61 | typedef signed char int8_t; 62 | typedef unsigned short uint16_t; 63 | typedef signed short int16_t; 64 | typedef unsigned int uint32_t; 65 | typedef signed int int32_t; 66 | typedef unsigned long uint64_t; 67 | typedef signed long int64_t; 68 | #else 69 | 70 | #error "unsupported CPU architecture" 71 | 72 | #endif 73 | 74 | #endif /* !defined (__OHW_STDINT_H__) */ 75 | -------------------------------------------------------------------------------- /src/libc/include/stdio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: subset of POSIX stdio definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_STDIO_H__) 23 | #define __OHW_STDIO_H__ 24 | 25 | /* va_list is defined here */ 26 | #include 27 | /* size_t is defined here */ 28 | #include 29 | 30 | #define EOF ((int)-1) 31 | 32 | int printf (const char *format, ...); 33 | int dprintf (const char *format, ...); 34 | int sprintf (char *str, const char *format, ...); 35 | int snprintf (char *str, size_t size, const char *format, ...); 36 | int vprintf (const char *format, va_list ap); 37 | int vdprintf (const char *format, va_list ap); 38 | int vsprintf (char *str, const char *format, va_list ap); 39 | int vsnprintf (char *str, size_t size, const char *format, va_list ap); 40 | 41 | int rename (const char *oldpath, const char *newpath); 42 | 43 | #endif /* !defined (__OHW_STDIO_H__) */ 44 | -------------------------------------------------------------------------------- /src/libc/include/stdlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: subset of POSIX stdlib definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_STDLIB_H__) 23 | #define __OHW_STDLIB_H__ 24 | 25 | #define NULL ((void *)0) 26 | 27 | /* size_t is declared here */ 28 | #include 29 | 30 | void *malloc (size_t size); 31 | void free (void *ptr); 32 | void *realloc (void *ptr, size_t size); 33 | 34 | /* memset is declared here */ 35 | #include 36 | 37 | static inline void *calloc (size_t nmemb, size_t size) 38 | { 39 | void *ret; 40 | 41 | ret = malloc(nmemb * size); 42 | if (ret != NULL) 43 | memset(ret, 0, nmemb * size); 44 | 45 | return ret; 46 | } 47 | 48 | int mkstemp (char *template); 49 | 50 | #endif /* !defined (__OHW_STDLIB_H__) */ 51 | -------------------------------------------------------------------------------- /src/libc/include/string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: subset of POSIX string definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_STRING_H__) 23 | #define __OHW_STRING_H__ 24 | 25 | /* size_t is declared here */ 26 | #include 27 | 28 | void *memcpy (void *dest, const void *src, size_t n); 29 | void *memccpy (void *dest, const void *src, int c, size_t n); 30 | void *mempcpy (void *dest, const void *src, size_t n); 31 | void *memmove (void *dest, const void *src, size_t n); 32 | void *memcmove (void *dest, const void *src, int c, size_t n); 33 | void *mempmove (void *dest, const void *src, size_t n); 34 | void *memset (void *s, int c, size_t n); 35 | int memcmp (const void *s1, const void *s2, size_t n); 36 | void *memchr (const void *s, int c, size_t n); 37 | void *rawmemchr (const void *s, int c); 38 | void *memrchr (const void *s, int c, size_t n); 39 | void *memmem (const void *haystack, size_t haystacklen, 40 | const void *needle, size_t neddlelen); 41 | void *strcpy (char *dest, const char *src); 42 | void *strncpy (char *dest, const char *src, size_t n); 43 | char *strdup (const char *s); 44 | char *strndup (const char *s, size_t n); 45 | void *stpcpy (char *dest, const char *src); 46 | void *stpncpy (char *dest, const char *src, size_t n); 47 | char *strcat (char *dest, const char *src); 48 | char *strncat (char *dest, const char *src, size_t n); 49 | int strcmp (const char *s1, const char *s2); 50 | int strcasecmp (const char *s1, const char *s2); 51 | int strncmp (const char *s1, const char *s2, size_t n); 52 | int strncasecmp (const char *s1, const char *s2, size_t n); 53 | char *strchr (const char *s, int c); 54 | char *strchrnul (const char *s, int c); 55 | char *strrchr (const char *s, int c); 56 | char *strstr (const char *haystack, const char *needle); 57 | char *strcasestr (const char *haystack, const char *needle); 58 | #if 0 // TODO 59 | size_t strspn (const char *s, const char *accept); 60 | size_t strcspn (const char *s, const char *reject); 61 | char *strpbrk (const char *s, const char *accept); 62 | char *strtok (char *s, const char *delim); 63 | char *strtok_r (char *s, const char *delim, char **ptrptr); 64 | char *strsep (char **stringp, const char *delim); 65 | #endif // TODO 66 | char *basename (char *path); 67 | char *dirname (char *path); 68 | size_t strlen (const char *s); 69 | size_t strnlen (const char *s, size_t maxlen); 70 | 71 | #if 0 72 | static inline int ffs (int value) 73 | { 74 | int tmp; 75 | 76 | __asm__ __volatile__ ("cntlzw %0, %1" : "=r" (tmp) : "r" (value)); 77 | 78 | return 32 - tmp; 79 | } 80 | #endif 81 | 82 | static inline int ffs (int value) 83 | { 84 | return __builtin_ffs(value); 85 | } 86 | 87 | int ffsl (long i); 88 | int ffsll (long long i); 89 | 90 | #endif /* !defined (__OHW_STRING_H__) */ 91 | -------------------------------------------------------------------------------- /src/libc/include/strings.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: Fake header for POSIX compatibility 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_STRINGS_H__) 23 | #define __OHW_STRINGS_H__ 24 | 25 | #include 26 | 27 | #endif /* !defined (__OHW_STRINGS_H__) */ 28 | -------------------------------------------------------------------------------- /src/libc/include/unistd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: subset of POSIX unistd definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_UNISTD_H__) 23 | #define __OHW_UNISTD_H__ 24 | 25 | /* size_t is defined here */ 26 | /* mode_t is defined here (SHOULD NOT !) */ 27 | /* off_t is defined here */ 28 | #include 29 | 30 | int open (const char *pathname, int flags, mode_t mode); 31 | int close (int fd); 32 | ssize_t read (int fd, void *buf, size_t count); 33 | ssize_t write (int fd, const void *buf, size_t count); 34 | enum { 35 | SEEK_SET = 0x01, 36 | SEEK_CUR = 0x02, 37 | SEEK_END = 0x03, 38 | }; 39 | off_t lseek (int fd, off_t offset, int whence); 40 | int truncate (const char *path, off_t length); 41 | int ftruncate (int fd, off_t length); 42 | 43 | #endif /* !defined (__OHW_UNISTD_H__) */ 44 | -------------------------------------------------------------------------------- /src/libc/src/errno.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: errno management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include "errno.h" 23 | 24 | /* XXX: to fix */ 25 | struct task cur_task; 26 | -------------------------------------------------------------------------------- /src/libc/src/mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: mem functions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | /* functions prototypes are here */ 23 | #include 24 | /* NULL is declared here */ 25 | #include 26 | 27 | /* mem___ functions */ 28 | #if defined (__USE_memcpy__) 29 | void *memcpy (void *dest, const void *src, size_t n) 30 | { 31 | const char *p; 32 | char *q; 33 | 34 | p = src; 35 | q = dest; 36 | for (; n != 0; n--) 37 | *q++ = *p++; 38 | 39 | return dest; 40 | } 41 | #endif 42 | 43 | #if defined (__USE_memccpy__) 44 | void *memccpy (void *dest, const void *src, int c, size_t n) 45 | { 46 | const char *p; 47 | char *q, *r; 48 | 49 | p = src; 50 | q = dest; 51 | r = NULL; 52 | for (; n != 0; n--, q++) { 53 | *q = *p++; 54 | if (*q == c) { 55 | r = q; 56 | break; 57 | } 58 | } 59 | 60 | return r; 61 | } 62 | #endif 63 | 64 | #if defined (__USE_mempcpy__) 65 | /* GNU extension */ 66 | void *mempcpy (void *dest, const void *src, size_t n) 67 | { 68 | const char *p; 69 | char *q; 70 | 71 | p = src; 72 | q = dest; 73 | for (; n != 0; n--) 74 | *q++ = *p++; 75 | 76 | return q; 77 | } 78 | #endif 79 | 80 | #if defined (__USE_memmove__) 81 | void *memmove (void *dest, const void *src, size_t n) 82 | { 83 | const char *p; 84 | char *q; 85 | 86 | p = src; 87 | q = dest; 88 | if (dest <= src) { 89 | for (; n != 0; n--) 90 | *q++ = *p++; 91 | } else { 92 | p += n; 93 | q += n; 94 | for (; n != 0; n--) 95 | *--q = *--p; 96 | } 97 | 98 | return dest; 99 | } 100 | #endif 101 | 102 | #if defined (__USE_memcmove__) 103 | /* OHW extension */ 104 | void *memcmove (void *dest, const void *src, int c, size_t n) 105 | { 106 | const char *p; 107 | char *q, *r; 108 | 109 | p = src; 110 | q = dest; 111 | r = NULL; 112 | if (dest <= src) { 113 | for (; n != 0; n--, q++) { 114 | *q++ = *p++; 115 | if (*q == c) { 116 | r = q; 117 | break; 118 | } 119 | } 120 | } else { 121 | p += n; 122 | q += n; 123 | for (; n != 0; n--, q--) { 124 | *--q = *--p; 125 | if (*q == c) { 126 | r = q; 127 | break; 128 | } 129 | } 130 | } 131 | 132 | return dest; 133 | } 134 | #endif 135 | 136 | #if defined (__USE_mempmove__) 137 | /* OHW extension */ 138 | void *mempmove (void *dest, const void *src, size_t n) 139 | { 140 | const char *p; 141 | char *q, *r; 142 | 143 | p = src; 144 | q = dest; 145 | r = q + n; 146 | if (dest <= src) { 147 | for (; n != 0; n--) 148 | *q++ = *p++; 149 | } else { 150 | p += n; 151 | q = r; 152 | for (; n != 0; n--) 153 | *--q = *--p; 154 | } 155 | 156 | return r; 157 | } 158 | #endif 159 | 160 | #if defined (__USE_memset__) 161 | void *memset (void *s, int c, size_t n) 162 | { 163 | char *p; 164 | 165 | for (p = s; n != 0; n--) 166 | *p++ = c; 167 | 168 | return s; 169 | } 170 | #endif 171 | 172 | #if defined (__USE_memcmp__) 173 | int memcmp (const void *s1, const void *s2, size_t n) 174 | { 175 | const char *p, *q; 176 | int ret; 177 | 178 | p = s1; 179 | q = s2; 180 | for (ret = 0; n != 0 && ret == 0; n--) 181 | ret = *p++ - *q++; 182 | 183 | return ret; 184 | } 185 | #endif 186 | 187 | #if defined (__USE_memchr__) 188 | void *memchr (const void *s, int c, size_t n) 189 | { 190 | const char *p, *r; 191 | 192 | r = NULL; 193 | for (p = s; n != 0; n--, p++) { 194 | if (*p == c) { 195 | r = p; 196 | break; 197 | } 198 | } 199 | 200 | return (void *)r; 201 | } 202 | #endif 203 | 204 | #if defined (__USE_rawmemchr__) 205 | /* GNU extension */ 206 | void *rawmemchr (const void *s, int c) 207 | { 208 | const char *p; 209 | 210 | for (p = s; *p != c; p++) 211 | continue; 212 | 213 | return (void *)p; 214 | } 215 | #endif 216 | 217 | #if defined (__USE_memrchr__) 218 | void *memrchr (const void *s, int c, size_t n) 219 | { 220 | const char *p, *r; 221 | 222 | r = NULL; 223 | for (p = s + n; n != 0; n--, p--) { 224 | if (*p == c) { 225 | r = p; 226 | break; 227 | } 228 | } 229 | 230 | return (void *)r; 231 | } 232 | #endif 233 | 234 | #if defined (__USE_memmem__) 235 | /* GNU extension */ 236 | void *memmem (const void *haystack, size_t haystacklen, 237 | const void *needle, size_t neddlelen) 238 | { 239 | const char *p, *r; 240 | 241 | r = NULL; 242 | for (p = haystack; haystacklen > neddlelen; haystacklen--, p++) { 243 | if (memcmp(p, needle, neddlelen) == 0) { 244 | r = p; 245 | break; 246 | } 247 | } 248 | 249 | return (void *)r; 250 | } 251 | #endif 252 | -------------------------------------------------------------------------------- /src/libc/src/str.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: str functions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | /* functions prototypes are here */ 23 | #include 24 | /* NULL is defined here */ 25 | /* malloc is defined here */ 26 | #include 27 | /* toupper is defined here */ 28 | #include 29 | 30 | /* str___ functions */ 31 | #if defined (__USE_strcpy__) 32 | void *strcpy (char *dest, const char *src) 33 | { 34 | char *q; 35 | 36 | q = dest; 37 | for (; ; q++) { 38 | *q = *src++; 39 | if (*q == '\0') 40 | break; 41 | } 42 | 43 | return dest; 44 | } 45 | #endif 46 | 47 | #if defined (__USE_strncpy__) 48 | void *strncpy (char *dest, const char *src, size_t n) 49 | { 50 | char *q; 51 | 52 | q = dest; 53 | for (; n != 0; n--, q++) { 54 | *q = *src++; 55 | if (*q == '\0') 56 | break; 57 | } 58 | 59 | return dest; 60 | } 61 | #endif 62 | 63 | #if defined (__USE_strdup__) 64 | char *strdup (const char *s) 65 | { 66 | char *dest; 67 | size_t len; 68 | 69 | len = strlen(s) + 1; 70 | dest = malloc(len); 71 | if (dest != NULL) 72 | memcpy(dest, s, len); 73 | 74 | return dest; 75 | } 76 | #endif 77 | 78 | #if defined (__USE_strndup__) 79 | /* GNU extension */ 80 | char *strndup (const char *s, size_t n) 81 | { 82 | char *dest; 83 | size_t len; 84 | 85 | len = strlen(s) + 1; 86 | if (len > n) 87 | len = n; 88 | dest = malloc(len); 89 | if (dest != NULL) { 90 | memcpy(dest, s, len - 1); 91 | dest[len - 1] = '\0'; 92 | } 93 | 94 | return dest; 95 | } 96 | #endif 97 | 98 | #if defined (__USE_stpcpy__) 99 | void *stpcpy (char *dest, const char *src) 100 | { 101 | char *q; 102 | 103 | q = dest; 104 | for (; ; q++) { 105 | *q = *src++; 106 | if (*q == '\0') 107 | break; 108 | } 109 | 110 | return q; 111 | } 112 | #endif 113 | 114 | #if defined (__USE_stpncpy__) 115 | void *stpncpy (char *dest, const char *src, size_t n) 116 | { 117 | char *q; 118 | 119 | q = dest; 120 | for (; n != 0; n--, q++) { 121 | *q = *src++; 122 | if (*q == '\0') 123 | break; 124 | } 125 | 126 | return q; 127 | } 128 | #endif 129 | 130 | #if defined (__USE_strcat__) 131 | char *strcat (char *dest, const char *src) 132 | { 133 | char *q; 134 | 135 | for (q = dest + strlen(dest); ; q++) { 136 | *q = *src++; 137 | if (*q == '\0') 138 | break; 139 | } 140 | 141 | return dest; 142 | } 143 | #endif 144 | 145 | #if defined (__USE_strncat__) 146 | char *strncat (char *dest, const char *src, size_t n) 147 | { 148 | char *q; 149 | 150 | for (q = dest + strlen(dest); n != 0; n--, q++) { 151 | *q = *src++; 152 | if (*q == '\0') 153 | break; 154 | } 155 | 156 | return dest; 157 | } 158 | #endif 159 | 160 | #if defined (__USE_strcmp__) 161 | int strcmp (const char *s1, const char *s2) 162 | { 163 | int ret; 164 | 165 | for (ret = 0; ret == 0; s1++) { 166 | ret = *s1 - *s2++; 167 | if (*s1 == '\0') 168 | break; 169 | } 170 | 171 | return ret; 172 | } 173 | #endif 174 | 175 | #if defined (__USE_strcasecmp__) 176 | int strcasecmp (const char *s1, const char *s2) 177 | { 178 | int ret; 179 | 180 | for (ret = 0; ret == 0; s1++) { 181 | ret = toupper(*s1) - toupper(*s2++); 182 | if (*s1 == '\0') 183 | break; 184 | } 185 | 186 | return ret; 187 | } 188 | #endif 189 | 190 | #if defined (__USE_strncmp__) 191 | int strncmp (const char *s1, const char *s2, size_t n) 192 | { 193 | int ret; 194 | 195 | for (ret = 0; ret == 0 && n != 0; n--, s1++) { 196 | ret = *s1 - *s2++; 197 | if (*s1 == '\0') 198 | break; 199 | } 200 | 201 | return ret; 202 | } 203 | #endif 204 | 205 | #if defined (__USE_strncasecmp__) 206 | int strncasecmp (const char *s1, const char *s2, size_t n) 207 | { 208 | int ret; 209 | 210 | for (ret = 0; ret == 0 && n != 0; n--, s1++) { 211 | ret = toupper(*s1) - toupper(*s2++); 212 | if (*s1 == '\0') 213 | break; 214 | } 215 | 216 | return ret; 217 | } 218 | #endif 219 | 220 | #if defined (__USE_strchr__) 221 | char *strchr (const char *s, int c) 222 | { 223 | const char *r; 224 | 225 | for (r = NULL; *s != '\0'; s++) { 226 | if (*s == c) { 227 | r = s; 228 | break; 229 | } 230 | } 231 | 232 | return (char *)r; 233 | } 234 | #endif 235 | 236 | #if defined (__USE_strchrnul__) 237 | /* GNU extension */ 238 | char *strchrnul (const char *s, int c) 239 | { 240 | for (; *s != '\0' && *s != c; s++) 241 | continue; 242 | 243 | return (char *)s; 244 | } 245 | #endif 246 | 247 | #if defined (__USE_strrchr__) 248 | char *strrchr (const char *s, int c) 249 | { 250 | const char *p, *r; 251 | 252 | r = NULL; 253 | for (p = s + strlen(s); p != s; p--) { 254 | if (*p == c) { 255 | r = p; 256 | break; 257 | } 258 | } 259 | 260 | return (char *)r; 261 | } 262 | #endif 263 | 264 | #if defined (__USE_strstr__) 265 | char *strstr (const char *haystack, const char *needle) 266 | { 267 | const char *r; 268 | size_t hlen, nlen; 269 | 270 | if (*needle == '\0') 271 | return (char *)haystack; 272 | r = NULL; 273 | hlen = strlen(haystack); 274 | nlen = strlen(needle); 275 | for (; hlen > nlen; hlen--, haystack++) { 276 | if (memcmp(haystack, needle, nlen) == 0) { 277 | r = haystack; 278 | break; 279 | } 280 | } 281 | 282 | return (char *)r; 283 | } 284 | #endif 285 | 286 | #if defined (__USE_strcasestr__) 287 | char *strcasestr (const char *haystack, const char *needle) 288 | { 289 | const char *p, *q, *r; 290 | size_t hlen, nlen, n; 291 | 292 | if (*needle == '\0') 293 | return (char *)haystack; 294 | r = NULL; 295 | hlen = strlen(haystack); 296 | nlen = strlen(needle); 297 | for (; hlen > nlen; hlen--, haystack++) { 298 | p = haystack; 299 | q = needle; 300 | for (n = nlen; n != 0; n--) { 301 | if (toupper(*p++) != toupper(*q++)) 302 | break; 303 | } 304 | if (n == 0) { 305 | r = haystack; 306 | break; 307 | } 308 | } 309 | 310 | return (char *)r; 311 | } 312 | #endif 313 | 314 | #if defined (__USE_strspn__) 315 | #error "TODO" 316 | size_t strspn (const char *s, const char *accept) 317 | { 318 | } 319 | #endif 320 | 321 | #if defined (__USE_strcspn__) 322 | #error "TODO" 323 | size_t strcspn (const char *s, const char *reject) 324 | { 325 | } 326 | #endif 327 | 328 | #if defined (__USE_strpbrk__) 329 | #error "TODO" 330 | char *strpbrk (const char *s, const char *accept) 331 | { 332 | } 333 | #endif 334 | 335 | #if defined (__USE_strtok__) 336 | #error "TODO" 337 | char *strtok (char *s, const char *delim) 338 | { 339 | } 340 | #endif 341 | 342 | #if defined (__USE_strtok_r__) 343 | #error "TODO" 344 | char *strtok_r (char *s, const char *delim, char **ptrptr) 345 | { 346 | } 347 | #endif 348 | 349 | #if defined (__USE_strsep__) 350 | #error "TODO" 351 | char *strsep (char **stringp, const char *delim) 352 | { 353 | } 354 | #endif 355 | 356 | #if defined (__USE_basename__) 357 | char *basename (char *path) 358 | { 359 | char *sl; 360 | size_t len; 361 | 362 | if (path == NULL || (len = strlen(path)) == 0) 363 | return strdup("."); 364 | sl = path + len - 1; 365 | if (*sl == '/') 366 | sl--; 367 | for (; sl != path; sl--) { 368 | if (*sl == '/') 369 | break; 370 | } 371 | 372 | return strdup(sl + 1); 373 | } 374 | #endif 375 | 376 | #if defined (__USE_dirname__) 377 | char *dirname (char *path) 378 | { 379 | char *sl, *ret; 380 | size_t len; 381 | 382 | if (path == NULL || (len = strlen(path)) == 0) { 383 | ret = strdup("."); 384 | } else { 385 | sl = path + len - 1; 386 | if (*sl == '/') 387 | sl--; 388 | for (; sl != path; sl--) { 389 | if (*sl == '/') 390 | break; 391 | } 392 | len = sl - path; 393 | if (len == 0) { 394 | ret = strdup("."); 395 | } else { 396 | ret = malloc(len + 1); 397 | if (ret != NULL) { 398 | memcpy(path, ret, len); 399 | path[len] = '\0'; 400 | } 401 | } 402 | } 403 | 404 | return ret; 405 | } 406 | #endif 407 | 408 | #if defined (__USE_strlen__) 409 | size_t strlen (const char *s) 410 | { 411 | size_t len; 412 | 413 | for (len = 0; *s != '\0'; len++) 414 | s++; 415 | 416 | return len; 417 | } 418 | #endif 419 | 420 | #if defined (__USE_strnlen__) 421 | size_t strnlen (const char *s, size_t maxlen) 422 | { 423 | size_t len; 424 | 425 | for (len = 0; maxlen != 0 && *s != '\0'; maxlen--, len++) 426 | s++; 427 | 428 | return len; 429 | } 430 | #endif 431 | -------------------------------------------------------------------------------- /src/libexec/core.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS executable file loader 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "exec.h" 26 | 27 | /*****************************************************************************/ 28 | uint32_t file_seek (inode_t *file, uint32_t pos) 29 | { 30 | uint32_t blocsize, bloc, offset; 31 | 32 | if (file == NULL) 33 | return -1; 34 | blocsize = part_blocsize(fs_inode_get_part(file)); 35 | bloc = pos / blocsize; 36 | offset = pos % blocsize; 37 | 38 | return fs_seek(file, bloc, offset); 39 | } 40 | 41 | /*****************************************************************************/ 42 | /* Executable file loaders */ 43 | 44 | enum { 45 | FILE_TYPE_ELF = 0, 46 | FILE_TYPE_XCOFF, 47 | FILE_TYPE_MACHO, 48 | FILE_TYPE_PEF, 49 | FILE_TYPE_CHRP, 50 | FILE_TYPE_PREP, 51 | FILE_TYPE_FLAT, 52 | }; 53 | 54 | uint32_t fs_inode_get_size (inode_t *inode); 55 | unsigned int part_get_entry (part_t *part); 56 | /*****************************************************************************/ 57 | /* Generic boot file loader */ 58 | int _bootfile_load (inode_t *file, void **dest, void **entry, void **end, 59 | uint32_t loffset, int type) 60 | { 61 | int (*do_load)(inode_t *file, void **dest, void **entry, void **end, 62 | uint32_t loffset); 63 | uint32_t size; 64 | int ret; 65 | int i; 66 | 67 | if (type == -1) 68 | i = 0; 69 | else 70 | i = type; 71 | for (;; i++) { 72 | switch (i) { 73 | case FILE_TYPE_ELF: 74 | do_load = &exec_load_elf; 75 | break; 76 | case FILE_TYPE_XCOFF: 77 | do_load = &exec_load_xcoff; 78 | break; 79 | case FILE_TYPE_MACHO: 80 | do_load = &exec_load_macho; 81 | break; 82 | case FILE_TYPE_PEF: 83 | do_load = &exec_load_pef; 84 | break; 85 | case FILE_TYPE_CHRP: 86 | do_load = &exec_load_chrp; 87 | break; 88 | case FILE_TYPE_PREP: 89 | do_load = &exec_load_prep; 90 | break; 91 | default: 92 | if (*dest == NULL) 93 | *dest = (void *)DEFAULT_LOAD_DEST; 94 | if (*entry == NULL) { 95 | if (part_get_entry(fs_inode_get_part(file)) != 0 || 1) { 96 | *entry = (char *)*dest + 97 | part_get_entry(fs_inode_get_part(file)); 98 | dprintf("dest %p entry %08x => %p\n", 99 | *dest, part_get_entry(fs_inode_get_part(file)), 100 | *entry); 101 | } else { 102 | *entry = *dest + 0xC; 103 | } 104 | } 105 | size = fs_inode_get_size(file); 106 | *end = (char *)*dest + size - loffset; 107 | printf("Load raw file into memory at %p %d (%08x) %d (%08x)\n", 108 | *dest, size, size, loffset, loffset); 109 | file_seek(file, loffset); 110 | set_loadinfo(*dest, size); 111 | if ((uint32_t)fs_read(file, *dest, size) != size) { 112 | ERROR("Error loading file...\n"); 113 | ret = -1; 114 | } else { 115 | ret = 0; 116 | } 117 | goto out; 118 | } 119 | DPRINTF("Check file type %d at offset %d %p\n", i, loffset, do_load); 120 | ret = (*do_load)(file, dest, entry, end, loffset); 121 | if (ret >= -1 || type == i) { 122 | if (type == i) 123 | ret = -2; 124 | break; 125 | } 126 | } 127 | out: 128 | 129 | return ret; 130 | } 131 | 132 | int bootfile_load (void **dest, void **entry, void **end, 133 | part_t *part, int type, const unsigned char *fname, 134 | uint32_t loffset) 135 | { 136 | inode_t *file; 137 | int ret; 138 | 139 | DPRINTF("Load file '%s' %p %p type: %d offset: %0x => %d %p\n", 140 | fname, part, part_fs(part), type, loffset, part_blocsize(part), *dest); 141 | if (fname == NULL) 142 | file = fs_get_bootfile(part_fs(part)); 143 | else 144 | file = fs_open(part_fs(part), fname); 145 | if (file == NULL) 146 | return -1; 147 | ret = _bootfile_load(file, dest, entry, end, loffset, type); 148 | fs_close(file); 149 | 150 | return ret; 151 | } 152 | -------------------------------------------------------------------------------- /src/libexec/elf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS ELF executable file loader 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "exec.h" 26 | 27 | uint32_t fs_inode_get_size (inode_t *inode); 28 | 29 | /* ELF executable loader */ 30 | typedef uint16_t Elf32_Half; 31 | typedef uint32_t Elf32_Word; 32 | typedef uint32_t Elf32_Off; 33 | typedef uint32_t Elf32_Addr; 34 | 35 | #define EI_NIDENT 16 36 | 37 | typedef struct elf32_hdr_t { 38 | unsigned char e_ident[EI_NIDENT]; 39 | Elf32_Half e_type; 40 | Elf32_Half e_machine; 41 | Elf32_Word e_version; 42 | Elf32_Addr e_entry; /* Entry point */ 43 | Elf32_Off e_phoff; 44 | Elf32_Off e_shoff; 45 | Elf32_Word e_flags; 46 | Elf32_Half e_ehsize; 47 | Elf32_Half e_phentsize; 48 | Elf32_Half e_phnum; 49 | Elf32_Half e_shentsize; 50 | Elf32_Half e_shnum; 51 | Elf32_Half e_shstrndx; 52 | } Elf32_Ehdr_t; 53 | 54 | typedef struct elf32_phdr_t { 55 | Elf32_Word p_type; 56 | Elf32_Off p_offset; 57 | Elf32_Addr p_vaddr; 58 | Elf32_Addr p_paddr; 59 | Elf32_Word p_filesz; 60 | Elf32_Word p_memsz; 61 | Elf32_Word p_flags; 62 | Elf32_Word p_align; 63 | } Elf32_Phdr_t; 64 | 65 | #define EI_MAG0 0 /* e_ident[] indexes */ 66 | #define EI_MAG1 1 67 | #define EI_MAG2 2 68 | #define EI_MAG3 3 69 | #define EI_CLASS 4 70 | #define EI_DATA 5 71 | #define EI_VERSION 6 72 | #define EI_OSABI 7 73 | #define EI_PAD 8 74 | 75 | #define ELFMAG0 0x7f /* EI_MAG */ 76 | #define ELFMAG1 'E' 77 | #define ELFMAG2 'L' 78 | #define ELFMAG3 'F' 79 | 80 | #define ELFCLASSNONE 0 /* EI_CLASS */ 81 | #define ELFCLASS32 1 82 | #define ELFCLASS64 2 83 | #define ELFCLASSNUM 3 84 | 85 | #define ELFDATANONE 0 /* e_ident[EI_DATA] */ 86 | #define ELFDATA2LSB 1 87 | #define ELFDATA2MSB 2 88 | 89 | #define EV_NONE 0 /* e_version, EI_VERSION */ 90 | #define EV_CURRENT 1 91 | #define EV_NUM 2 92 | 93 | /* These constants define the different elf file types */ 94 | #define ET_NONE 0 95 | #define ET_REL 1 96 | #define ET_EXEC 2 97 | #define ET_DYN 3 98 | #define ET_CORE 4 99 | #define ET_LOPROC 0xff00 100 | #define ET_HIPROC 0xffff 101 | 102 | /* These constants define the various ELF target machines */ 103 | #define EM_NONE 0 104 | #define EM_M32 1 105 | #define EM_SPARC 2 106 | #define EM_386 3 107 | #define EM_68K 4 108 | #define EM_88K 5 109 | #define EM_486 6 /* Perhaps disused */ 110 | #define EM_860 7 111 | #define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ 112 | #define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ 113 | #define EM_PARISC 15 /* HPPA */ 114 | #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ 115 | #define EM_PPC 20 /* PowerPC */ 116 | #define EM_PPC64 21 /* PowerPC64 */ 117 | #define EM_SH 42 /* SuperH */ 118 | #define EM_SPARCV9 43 /* SPARC v9 64-bit */ 119 | #define EM_IA_64 50 /* HP/Intel IA-64 */ 120 | #define EM_X86_64 62 /* AMD x86-64 */ 121 | #define EM_S390 22 /* IBM S/390 */ 122 | #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ 123 | #define EM_V850 87 /* NEC v850 */ 124 | #define EM_H8_300H 47 /* Hitachi H8/300H */ 125 | #define EM_H8S 48 /* Hitachi H8S */ 126 | /* 127 | * This is an interim value that we will use until the committee comes 128 | * up with a final number. 129 | */ 130 | #define EM_ALPHA 0x9026 131 | /* Bogus old v850 magic number, used by old tools. */ 132 | #define EM_CYGNUS_V850 0x9080 133 | /* 134 | * This is the old interim value for S/390 architecture 135 | */ 136 | #define EM_S390_OLD 0xA390 137 | 138 | int exec_load_elf (inode_t *file, void **dest, void **entry, void **end, 139 | uint32_t loffset) 140 | { 141 | Elf32_Ehdr_t ehdr; 142 | Elf32_Phdr_t phdr; 143 | void *address, *first, *last; 144 | uint32_t offset, fsize, msize; 145 | int i; 146 | 147 | file_seek(file, loffset); 148 | if (fs_read(file, &ehdr, sizeof(Elf32_Ehdr_t)) < 0) { 149 | ERROR("Cannot load first bloc of file...\n"); 150 | return -1; 151 | } 152 | DPRINTF("Check ELF file\n"); 153 | /* Check ident */ 154 | if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || 155 | ehdr.e_ident[EI_MAG1] != ELFMAG1 || 156 | ehdr.e_ident[EI_MAG2] != ELFMAG2 || 157 | ehdr.e_ident[EI_MAG3] != ELFMAG3) { 158 | DPRINTF("Not an ELF file %0x\n", *(uint32_t *)ehdr.e_ident); 159 | return -2; 160 | } 161 | if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { 162 | ERROR("Not a 32 bits ELF file\n"); 163 | return -2; 164 | } 165 | if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB) { 166 | ERROR("Not a big-endian ELF file\n"); 167 | return -2; 168 | } 169 | if (ehdr.e_ident[EI_VERSION] != EV_CURRENT /*|| 170 | ehdr->e_version != EV_CURRENT*/) { 171 | ERROR("Invalid ELF executable version %d %08x\n", 172 | ehdr.e_ident[EI_VERSION], ehdr.e_version); 173 | return -2; 174 | } 175 | if (ehdr.e_type != ET_EXEC) { 176 | ERROR("Not an executable ELF file\n"); 177 | return -2; 178 | } 179 | if (ehdr.e_machine != EM_PPC) { 180 | ERROR("Not a PPC ELF executable\n"); 181 | return -2; 182 | } 183 | /* All right, seems to be a regular ELF program for PPC */ 184 | *entry = (void *)ehdr.e_entry; 185 | DPRINTF("ELF file found entry = %p\n", *entry); 186 | last = NULL; 187 | first = last - 4; 188 | fsize = msize = 0; 189 | offset = ehdr.e_phoff; 190 | for (i = 0; i < ehdr.e_phnum; i++) { 191 | #if 0 192 | if (offset > fs_inode_get_size(file)) { 193 | ERROR("ELF program header %d offset > file size %d %d\n", i, 194 | offset, fs_inode_get_size(file)); 195 | return -1; 196 | } 197 | #endif 198 | DPRINTF("Load program header %d from %08x\n", i, offset); 199 | file_seek(file, offset + loffset); 200 | if (fs_read(file, &phdr, sizeof(Elf32_Phdr_t)) < 0) { 201 | ERROR("Cannot load ELF program header %d...\n", i); 202 | return -1; 203 | } 204 | DPRINTF("Load program header %d %08x %08x %08x %08x\n", i, 205 | phdr.p_offset, phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz); 206 | #if 0 207 | if (phdr.p_offset > fs_inode_get_size(file)) { 208 | ERROR("ELF program %d offset > file size %d %d\n", 209 | i, phdr.p_offset, fs_inode_get_size(file)); 210 | return -1; 211 | } 212 | #endif 213 | /* As we won't remap memory, load it at it's virtual address (!) */ 214 | address = (void *)phdr.p_vaddr; 215 | if (address < first) 216 | first = address; 217 | fsize = phdr.p_filesz; 218 | msize = phdr.p_memsz; 219 | if (address + msize > last) 220 | last = address + msize; 221 | file_seek(file, phdr.p_offset + loffset); 222 | set_loadinfo((void *)first, last - first); 223 | if (fs_read(file, address, fsize) < 0) { 224 | ERROR("Cannot load ELF program %d...\n", i); 225 | return -1; 226 | } 227 | if (msize > fsize) { 228 | memset(address + fsize, 0, msize - fsize); 229 | } 230 | offset += ehdr.e_phentsize; 231 | } 232 | *dest = (void *)first; 233 | *end = (void *)last; 234 | DPRINTF("ELF file loaded at %p => %p fsize %08x msize %08x " 235 | "(%08x %08x)\n", *dest, *entry, fsize, msize, 236 | *(uint32_t *)entry, *((uint32_t *)entry + 1)); 237 | 238 | return 0; 239 | } 240 | -------------------------------------------------------------------------------- /src/libexec/exec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: executable files loader definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined(__OHW_EXEC_H__) 23 | #define __OHW_EXEC_H__ 24 | 25 | int _bootfile_load (inode_t *file, void **dest, void **entry, void **end, 26 | uint32_t loffset, int type); 27 | int exec_load_elf (inode_t *file, void **dest, void **entry, void **end, 28 | uint32_t loffset); 29 | int exec_load_xcoff (inode_t *file, void **dest, void **entry, void **end, 30 | uint32_t loffset); 31 | int exec_load_macho (inode_t *file, void **dest, void **entry, void **end, 32 | uint32_t loffset); 33 | int exec_load_pef (inode_t *file, void **dest, void **entry, void **end, 34 | uint32_t loffset); 35 | int exec_load_prep (inode_t *file, void **dest, void **entry, void **end, 36 | uint32_t loffset); 37 | int exec_load_chrp (inode_t *file, void **dest, void **entry, void **end, 38 | uint32_t loffset); 39 | 40 | #endif /* !defined(__OHW_EXEC_H__) */ 41 | -------------------------------------------------------------------------------- /src/libexec/pef.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS Classic MacOS executable file loader 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "exec.h" 26 | 27 | /* PEF (old MacOS executable format) */ 28 | typedef struct PEF_container_t PEF_container_t; 29 | struct PEF_container_t { 30 | uint32_t tag1; 31 | uint32_t tag2; 32 | uint32_t arch; 33 | uint32_t version; 34 | uint32_t timestamp; 35 | uint32_t oldDefVersion; 36 | uint32_t oldImpVersion; 37 | uint32_t currentVersion; 38 | uint16_t nb_sections; 39 | uint16_t nb_inst_sections; 40 | uint32_t pad; 41 | } __attribute__ (( packed )); 42 | 43 | typedef struct PEF_section_t PEF_section_t; 44 | struct PEF_section_t { 45 | int32_t name_offset; 46 | uint32_t address; 47 | uint32_t total_size; 48 | uint32_t unpacked_size; 49 | uint32_t packed_size; 50 | uint32_t container_offset; 51 | uint8_t section_kind; 52 | uint8_t share_kind; 53 | uint8_t align; 54 | uint8_t pad; 55 | } __attribute__ (( packed )); 56 | 57 | typedef struct PEF_loader_t PEF_loader_t; 58 | struct PEF_loader_t { 59 | int32_t main_section; 60 | uint32_t main_offset; 61 | int32_t init_section; 62 | uint32_t init_offset; 63 | int32_t term_section; 64 | uint32_t term_offset; 65 | uint32_t nb_import_libs; 66 | uint32_t nb_import_symbols; 67 | uint32_t nb_reloc_sections; 68 | uint32_t reloc_instr_offset; 69 | uint32_t loader_strings_offset; 70 | uint32_t export_hash_offset; 71 | uint32_t export_hashtable_power; 72 | uint32_t nb_export_symbols; 73 | } __attribute__ (( packed )); 74 | 75 | enum { 76 | PEF_SECTION_CODE = 0, 77 | PEF_SECTION_UNPDATA = 1, 78 | PEF_SECTION_INIDATA = 2, 79 | PEF_SECTION_CONSTANT = 3, 80 | PEF_SECTION_LOADER = 4, 81 | PEF_SECTION_DEBUG = 5, 82 | PEF_SECTION_EXEC = 6, 83 | PEF_SECTION_EXCP = 7, 84 | PEF_SECTION_TRACE = 8, 85 | }; 86 | 87 | enum { 88 | PEF_SHARE_PROCESS = 1, 89 | PEF_SHARE_GLOBAL = 4, 90 | PEF_SHARE_PROTECTED = 5, 91 | }; 92 | 93 | int exec_load_pef (inode_t *file, void **dest, void **entry, void **end, 94 | uint32_t loffset) 95 | { 96 | PEF_container_t container; 97 | PEF_section_t section; 98 | PEF_loader_t loader; 99 | void *first, *last, *addr, **sections; 100 | uint32_t pos, padsize, size, lpos, main_offset; 101 | uint8_t opcode; 102 | int nb_sections, nb_inst_sections, main_section, i, n; 103 | 104 | file_seek(file, loffset); 105 | if (fs_read(file, &container, sizeof(PEF_container_t)) < 0) { 106 | ERROR("Cannot load container header\n"); 107 | return -1; 108 | } 109 | pos = sizeof(PEF_container_t); 110 | /* Check tags and architecture */ 111 | if (memcmp(&container.tag1, "Joy!", 4) != 0) { 112 | DPRINTF("No joy, no PEF\n"); 113 | return -2; 114 | } 115 | if (memcmp(&container.tag2, "peff", 4) != 0) { 116 | DPRINTF("No PEFF file\n"); 117 | return -2; 118 | } 119 | if (memcmp(&container.arch, "pwpc", 4) != 0) { 120 | DPRINTF("PEFF file not for PPC\n"); 121 | return -2; 122 | } 123 | if (get_be32(&container.version) != 1) { 124 | DPRINTF("Unknown PEFF container version\n"); 125 | return -2; 126 | } 127 | nb_sections = get_be32(&container.nb_sections); 128 | sections = malloc(nb_sections * sizeof(void *)); 129 | if (sections == NULL) { 130 | ERROR("Cannot allocate sections\n"); 131 | return -1; 132 | } 133 | nb_inst_sections = get_be32(&container.nb_inst_sections); 134 | first = (void *)0xFFFFFFFF; 135 | last = NULL; 136 | main_section = -1; 137 | main_offset = 0; 138 | for (i = 0, n = 0; i < nb_sections; i++) { 139 | file_seek(file, loffset + pos); 140 | if (fs_read(file, §ion, sizeof(PEF_section_t)) < 0) { 141 | ERROR("Cannot read section %d\n", i); 142 | return -1; 143 | } 144 | pos += sizeof(PEF_section_t); 145 | addr = (void *)get_be32(§ion.address); 146 | sections[i] = addr; 147 | if (addr < first) 148 | first = addr; 149 | size = get_be32(§ion.total_size); 150 | lpos = get_be32(§ion.container_offset); 151 | file_seek(file, loffset + lpos); 152 | switch (section.section_kind) { 153 | case PEF_SECTION_CODE: 154 | case PEF_SECTION_UNPDATA: 155 | /* Load as raw data */ 156 | padsize = get_be32(§ion.unpacked_size) - size; 157 | file_seek(file, loffset + lpos); 158 | if (fs_read(file, addr, size) < 0) { 159 | ERROR("Cannot load section %d\n", i); 160 | return -1; 161 | } 162 | addr = (char *)addr + size; 163 | memset(addr, 0, padsize); 164 | addr = (char *)addr + padsize; 165 | break; 166 | case PEF_SECTION_INIDATA: 167 | case PEF_SECTION_CONSTANT: 168 | case PEF_SECTION_EXEC: 169 | /* Load as compressed data */ 170 | for (;;) { 171 | void *ref; 172 | uint32_t total; 173 | uint8_t bsize, csize, count, j; 174 | 175 | if (fs_read(file, &opcode, 1) < 0) { 176 | ERROR("Cannot get opcode\n"); 177 | return -1; 178 | } 179 | bsize = opcode & 0x1F; 180 | switch (opcode >> 5) { 181 | case 0x0: 182 | /* Initialize size bytes to zero */ 183 | memset(addr, 0, bsize); 184 | addr = (char *)addr + bsize; 185 | total = bsize; 186 | break; 187 | case 0x1: 188 | /* Copy bloc */ 189 | if (fs_read(file, addr, bsize) < 0) { 190 | ERROR("Cannot copy bloc\n"); 191 | return -1; 192 | } 193 | addr = (char *)addr + bsize; 194 | total = bsize; 195 | break; 196 | case 0x2: 197 | /* Repeat bloc */ 198 | if (fs_read(file, &count, 1) < 0) { 199 | ERROR("Cannot read bloc size\n"); 200 | return -1; 201 | } 202 | total = 0; 203 | if (count == 0) { 204 | break; 205 | } 206 | if (fs_read(file, addr, bsize) < 0) { 207 | ERROR("Cannot read repeat bloc\n"); 208 | return -1; 209 | } 210 | ref = addr; 211 | addr = (char *)addr + bsize; 212 | for (j = 1; j < count; j++) { 213 | memcpy(addr, ref, bsize); 214 | total += bsize; 215 | addr = (char *)addr + bsize; 216 | } 217 | break; 218 | case 0x3: 219 | /* Interleave repeat bloc with bloc copy */ 220 | if (fs_read(file, &csize, 1) < 0 || 221 | fs_read(file, &count, 1) < 0) { 222 | ERROR("Cannot read repeat params\n"); 223 | return -1; 224 | } 225 | ref = addr; 226 | if (fs_read(file, addr, bsize) < 0) { 227 | ERROR("Cannot read common data\n"); 228 | return -1; 229 | } 230 | addr = (char *)addr + bsize; 231 | total = bsize; 232 | for (j = 0; j < count; j++) { 233 | if (fs_read(file, addr, csize) < 0) { 234 | ERROR("Cannot read custom data\n"); 235 | return -1; 236 | } 237 | addr = (char *)addr + csize; 238 | memcpy(addr, ref, bsize); 239 | addr = (char *)addr + bsize; 240 | total += csize + bsize; 241 | } 242 | break; 243 | case 0x4: 244 | /* Interleave repeat bloc with zero */ 245 | if (fs_read(file, &csize, 1) < 0 || 246 | fs_read(file, &count, 1) < 0) { 247 | ERROR("Cannot read repeat params\n"); 248 | return -1; 249 | } 250 | total = 0; 251 | for (j = 0; j < count; j++) { 252 | memset(addr, 0, bsize); 253 | addr = (char *)addr + bsize; 254 | if (fs_read(file, addr, csize) < 0) { 255 | ERROR("Cannot read repeat data\n"); 256 | return -1; 257 | } 258 | addr = (char *)addr + csize; 259 | total += csize + bsize; 260 | } 261 | memset(addr, 0, bsize); 262 | addr = (char *)addr + bsize; 263 | total += bsize; 264 | break; 265 | default: 266 | ERROR("Unknown opcode\n"); 267 | return -1; 268 | } 269 | if (addr > last) 270 | last = addr; 271 | if (total >= size) 272 | break; 273 | size -= total; 274 | } 275 | break; 276 | case PEF_SECTION_LOADER: 277 | /* find entry point */ 278 | if (fs_read(file, &loader, sizeof(PEF_loader_t)) < 0) { 279 | ERROR("Cannot read loader header\n"); 280 | return -1; 281 | } 282 | main_section = get_be32(&loader.main_section); 283 | main_offset = get_be32(&loader.main_offset); 284 | if (main_section >= nb_sections) { 285 | ERROR("Invalid main section\n"); 286 | return -1; 287 | } 288 | break; 289 | case PEF_SECTION_DEBUG: 290 | case PEF_SECTION_EXCP: 291 | case PEF_SECTION_TRACE: 292 | break; 293 | default: 294 | return -2; 295 | } 296 | } 297 | *dest = first; 298 | *end = last; 299 | if (main_section == -1) { 300 | *entry = first; 301 | } else { 302 | *entry = (char *)sections[main_section] + main_offset; 303 | } 304 | free(sections); 305 | 306 | return 0; 307 | } 308 | -------------------------------------------------------------------------------- /src/libexec/prep.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS PREP executable file loader 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "exec.h" 26 | 27 | /* PREP boot loader */ 28 | int exec_load_prep (inode_t *file, unused void **dest, 29 | unused void **entry, unused void **end, 30 | unused uint32_t loffset) 31 | { 32 | unsigned char buffer[512]; 33 | 34 | file_seek(file, loffset); 35 | if (fs_read(file, buffer, 512) < 0) { 36 | ERROR("Cannot load first bloc of file...\n"); 37 | return -2; 38 | } 39 | if (buffer[0x1FE] != 0x55 || buffer[0x1FF] != 0xAA) { 40 | DPRINTF("Not a PREP file\n"); 41 | return -2; 42 | } 43 | 44 | return -2; 45 | } 46 | -------------------------------------------------------------------------------- /src/libexec/xcoff.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS XCOFF executable file loader 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "exec.h" 26 | 27 | uint32_t fs_inode_get_size (inode_t *inode); 28 | 29 | /* XCOFF executable loader */ 30 | typedef struct COFF_filehdr_t { 31 | uint16_t f_magic; /* magic number */ 32 | uint16_t f_nscns; /* number of sections */ 33 | uint32_t f_timdat; /* time & date stamp */ 34 | uint32_t f_symptr; /* file pointer to symtab */ 35 | uint32_t f_nsyms; /* number of symtab entries */ 36 | uint16_t f_opthdr; /* sizeof(optional hdr) */ 37 | uint16_t f_flags; /* flags */ 38 | } COFF_filehdr_t; 39 | 40 | /* IBM RS/6000 */ 41 | #define U802WRMAGIC 0730 /* writeable text segments **chh** */ 42 | #define U802ROMAGIC 0735 /* readonly sharable text segments */ 43 | #define U802TOCMAGIC 0737 /* readonly text segments and TOC */ 44 | 45 | /* 46 | * Bits for f_flags: 47 | * 48 | * F_RELFLG relocation info stripped from file 49 | * F_EXEC file is executable (i.e. no unresolved external 50 | * references) 51 | * F_LNNO line numbers stripped from file 52 | * F_LSYMS local symbols stripped from file 53 | * F_MINMAL this is a minimal object file (".m") output of fextract 54 | * F_UPDATE this is a fully bound update file, output of ogen 55 | * F_SWABD this file has had its bytes swabbed (in names) 56 | * F_AR16WR this file has the byte ordering of an AR16WR 57 | * (e.g. 11/70) machine 58 | * F_AR32WR this file has the byte ordering of an AR32WR machine 59 | * (e.g. vax and iNTEL 386) 60 | * F_AR32W this file has the byte ordering of an AR32W machine 61 | * (e.g. 3b,maxi) 62 | * F_PATCH file contains "patch" list in optional header 63 | * F_NODF (minimal file only) no decision functions for 64 | * replaced functions 65 | */ 66 | 67 | #define COFF_F_RELFLG 0000001 68 | #define COFF_F_EXEC 0000002 69 | #define COFF_F_LNNO 0000004 70 | #define COFF_F_LSYMS 0000010 71 | #define COFF_F_MINMAL 0000020 72 | #define COFF_F_UPDATE 0000040 73 | #define COFF_F_SWABD 0000100 74 | #define COFF_F_AR16WR 0000200 75 | #define COFF_F_AR32WR 0000400 76 | #define COFF_F_AR32W 0001000 77 | #define COFF_F_PATCH 0002000 78 | #define COFF_F_NODF 0002000 79 | 80 | typedef struct COFF_aouthdr_t { 81 | uint16_t magic; /* type of file */ 82 | uint16_t vstamp; /* version stamp */ 83 | uint32_t tsize; /* text size in bytes, padded to FW bdry */ 84 | uint32_t dsize; /* initialized data " " */ 85 | uint32_t bsize; /* uninitialized data " " */ 86 | uint32_t entry; /* entry pt. */ 87 | uint32_t text_start; /* base of text used for this file */ 88 | uint32_t data_start; /* base of data used for this file */ 89 | uint32_t o_toc; /* address of TOC */ 90 | uint16_t o_snentry; /* section number of entry point */ 91 | uint16_t o_sntext; /* section number of .text section */ 92 | uint16_t o_sndata; /* section number of .data section */ 93 | uint16_t o_sntoc; /* section number of TOC */ 94 | uint16_t o_snloader; /* section number of .loader section */ 95 | uint16_t o_snbss; /* section number of .bss section */ 96 | uint16_t o_algntext; /* .text alignment */ 97 | uint16_t o_algndata; /* .data alignment */ 98 | uint16_t o_modtype; /* module type (??) */ 99 | uint16_t o_cputype; /* cpu type */ 100 | uint32_t o_maxstack; /* max stack size (??) */ 101 | uint32_t o_maxdata; /* max data size (??) */ 102 | char o_resv2[12]; /* reserved */ 103 | } COFF_aouthdr_t; 104 | 105 | #define AOUT_MAGIC 0x010b 106 | 107 | typedef struct COFF_scnhdr_t { 108 | char s_name[8]; /* section name */ 109 | uint32_t s_paddr; /* physical address, aliased s_nlib */ 110 | uint32_t s_vaddr; /* virtual address */ 111 | uint32_t s_size; /* section size */ 112 | uint32_t s_scnptr; /* file ptr to raw data for section */ 113 | uint32_t s_relptr; /* file ptr to relocation */ 114 | uint32_t s_lnnoptr; /* file ptr to line numbers */ 115 | uint16_t s_nreloc; /* number of relocation entries */ 116 | uint16_t s_nlnno; /* number of line number entries */ 117 | uint32_t s_flags; /* flags */ 118 | } COFF_scnhdr_t; 119 | 120 | int exec_load_xcoff (inode_t *file, void **dest, void **entry, void **end, 121 | uint32_t loffset) 122 | { 123 | COFF_filehdr_t fhdr; 124 | COFF_aouthdr_t ahdr; 125 | COFF_scnhdr_t shdr; 126 | void *first, *last; 127 | uint32_t offset; 128 | int i; 129 | 130 | file_seek(file, loffset); 131 | if (fs_read(file, &fhdr, sizeof(COFF_filehdr_t)) < 0) { 132 | ERROR("Cannot load first bloc of file...\n"); 133 | return -1; 134 | } 135 | if (fhdr.f_magic != U802WRMAGIC && fhdr.f_magic != U802ROMAGIC && 136 | fhdr.f_magic != U802TOCMAGIC && fhdr.f_magic != 0x01DF) { 137 | DPRINTF("Not a XCOFF file %02x %08x\n", fhdr.f_magic, 138 | *(uint32_t *)&fhdr.f_magic); 139 | return -2; 140 | } 141 | if (fhdr.f_magic != 0x01DF && (fhdr.f_flags & COFF_F_EXEC) == 0) { 142 | ERROR("Not an executable XCOFF file %02x\n", fhdr.f_flags); 143 | return -2; 144 | } 145 | if (fhdr.f_opthdr != sizeof(COFF_aouthdr_t)) { 146 | ERROR("AOUT optional error size missmactch in XCOFF file\n"); 147 | return -2; 148 | } 149 | if (fs_read(file, &ahdr, sizeof(COFF_aouthdr_t)) < 0) { 150 | ERROR("Cannot load XCOFF AOUT header...\n"); 151 | return -1; 152 | } 153 | if (ahdr.magic != AOUT_MAGIC) { 154 | ERROR("Invalid AOUT optional header\n"); 155 | return -2; 156 | } 157 | #if 0 // XXX: buggy: this makes NetBSD fail to boot 158 | if (fhdr.f_magic == 0x01DF) { 159 | /* Load embedded file */ 160 | return _bootfile_load(file, dest, entry, end, loffset + 161 | sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t) + 162 | (fhdr.f_nscns * sizeof(COFF_scnhdr_t)), 163 | -1); 164 | } 165 | #endif 166 | *entry = (void *)ahdr.entry + 0xC; 167 | last = NULL; 168 | first = last - 4; 169 | offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t); 170 | DPRINTF("XCOFF file with %d sections entry:%p\n", fhdr.f_nscns, *entry); 171 | for (i = 0; i < fhdr.f_nscns; i++) { 172 | DPRINTF("Read next header (%0x)\n", offset); 173 | file_seek(file, offset + loffset); 174 | if (fs_read(file, &shdr, sizeof(COFF_scnhdr_t)) < 0) { 175 | ERROR("Cannot load section header %d...\n", i); 176 | return -1; 177 | } 178 | if (strcmp(shdr.s_name, ".text") == 0 || 179 | strcmp(shdr.s_name, ".data") == 0) { 180 | if ((void *)shdr.s_vaddr < first) 181 | first = (void *)shdr.s_vaddr; 182 | if ((void *)shdr.s_vaddr > last) 183 | last = (void *)shdr.s_vaddr; 184 | DPRINTF("Load '%s' section from %0x %0x to %0x (%0x)\n", 185 | shdr.s_name, offset, shdr.s_scnptr, 186 | shdr.s_vaddr, shdr.s_size); 187 | #if 0 188 | if (shdr.s_scnptr + shdr.s_size > fs_inode_get_size(file)) { 189 | ERROR("Section %d data offset > file size\n", i); 190 | return -1; 191 | } 192 | #endif 193 | file_seek(file, shdr.s_scnptr + loffset); 194 | set_loadinfo((void *)first, last - first); 195 | if (fs_read(file, (void *)shdr.s_vaddr, shdr.s_size) < 0) { 196 | ERROR("Cannot load section %d...\n", i); 197 | return -1; 198 | } 199 | } else if (strcmp(shdr.s_name, ".bss") == 0) { 200 | if ((void *)shdr.s_vaddr < first) 201 | first = (void *)shdr.s_vaddr; 202 | if ((void *)shdr.s_vaddr > last) 203 | last = (void *)shdr.s_vaddr; 204 | DPRINTF("Erase '%s' section at %0x size: %0x\n", 205 | shdr.s_name, shdr.s_vaddr, shdr.s_size); 206 | memset((void *)shdr.s_vaddr, 0, shdr.s_size); 207 | } else { 208 | DPRINTF("Skip '%s' section\n", shdr.s_name); 209 | } 210 | offset += sizeof(COFF_scnhdr_t); 211 | } 212 | *dest = first; 213 | *end = last; 214 | 215 | return 0; 216 | } 217 | -------------------------------------------------------------------------------- /src/libfs/ext2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS ext2 file system management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include "bios.h" 24 | #include "libfs.h" 25 | 26 | /* ext2 filesystem */ 27 | int fs_ext2_probe (unused part_t *part, unused uint32_t *size, 28 | unused fs_ops_t **fs_ops, unused unsigned char **name, 29 | unused void **private) 30 | { 31 | return -1; 32 | } 33 | -------------------------------------------------------------------------------- /src/libfs/isofs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS ISO file system management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include "bios.h" 24 | #include "libfs.h" 25 | 26 | /* ISOFS filesystem */ 27 | int fs_isofs_probe (unused part_t *part, unused uint32_t *size, 28 | unused fs_ops_t **fs_ops, unused unsigned char **name, 29 | unused void **private) 30 | { 31 | return -1; 32 | } 33 | -------------------------------------------------------------------------------- /src/libfs/libfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS: file system library definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined(__OHW_LIBFS_H__) 23 | #define __OHW_LIBFS_H__ 24 | 25 | //#define DEBUG_FS 1 26 | #define FS_SPECIAL "" 27 | 28 | static inline int is_special_file (const unsigned char *name) 29 | { 30 | int splen = strlen(FS_SPECIAL); 31 | 32 | return name[0] == '\0' && memcmp(name + 1, FS_SPECIAL, splen) == 0 && 33 | name[splen + 1] == '\0'; 34 | } 35 | 36 | #if defined (DEBUG_FS) 37 | #define FS_DPRINTF(fmt, args...) \ 38 | do { dprintf("%s: " fmt, __func__ , ##args); } while (0) 39 | #else 40 | #define FS_DPRINTF(fmt, args...) \ 41 | do { } while (0) 42 | #endif 43 | #define FS_ERROR(fmt, args...) \ 44 | do { printf("ERROR in %s: " fmt, __func__ , ##args); } while (0) 45 | 46 | typedef struct fs_ops_t { 47 | inode_t *(*get_inode)(inode_t *parent, const unsigned char *name); 48 | void (*put_inode)(inode_t *inode); 49 | uint32_t (*map_bloc)(inode_t *inode, uint32_t bloc); 50 | inode_t *(*get_special_inode)(fs_t *fs, int type); 51 | } fs_ops_t; 52 | 53 | #define MAXNAME_LEN 1024 54 | 55 | struct fs_t { 56 | int type; 57 | part_t *part; 58 | inode_t *root; 59 | fs_ops_t *fs_ops; 60 | uint32_t size; 61 | unsigned char *name; 62 | inode_t *bootfile; 63 | inode_t *bootdir; 64 | void *private; 65 | }; 66 | 67 | struct dir_t { 68 | inode_t *inode; 69 | dirent_t *cur; 70 | int pos; 71 | }; 72 | 73 | /* All internals use inodes */ 74 | struct inode_t { 75 | fs_t *fs; 76 | /* parent inode */ 77 | inode_t *parent; 78 | /* Next inode at the same level */ 79 | inode_t *next; 80 | /* First child inode */ 81 | inode_t *child; 82 | /* Private data */ 83 | int refcount; 84 | uint32_t flags; 85 | unsigned char *name; 86 | int nb_blocs; 87 | pos_t *blocs; 88 | pos_t size; 89 | void *private; 90 | uint32_t vbloc; 91 | uint32_t vpos; 92 | }; 93 | 94 | /* Low-level helpers */ 95 | enum { 96 | FILE_UNKNOWN = -1, 97 | FILE_ROOT = 0, 98 | FILE_BOOT, 99 | FILE_BOOTDIR, 100 | }; 101 | 102 | void fs_cache_add_inode (inode_t *parent, inode_t *inode); 103 | 104 | int fs_raw_probe (part_t *part, uint32_t *size, 105 | fs_ops_t **fs_ops, unsigned char **name, 106 | void **private); 107 | int fs_ext2_probe (part_t *part, uint32_t *size, 108 | fs_ops_t **fs_ops, unsigned char **name, 109 | void **private); 110 | int fs_isofs_probe (part_t *part, uint32_t *size, 111 | fs_ops_t **fs_ops, unsigned char **name, 112 | void **private); 113 | int fs_hfs_probe (part_t *part, uint32_t *size, 114 | fs_ops_t **fs_ops, unsigned char **name, 115 | void **private); 116 | int fs_raw_set_bootfile (part_t *part, 117 | uint32_t start_bloc, uint32_t start_offset, 118 | uint32_t size_bloc, uint32_t size_offset); 119 | 120 | enum { 121 | FS_TYPE_UNKNOWN = -1, 122 | FS_TYPE_RAW = 0, 123 | FS_TYPE_EXT2, 124 | FS_TYPE_ISOFS, 125 | FS_TYPE_HFS, 126 | FS_TYPE_HFSP, 127 | }; 128 | 129 | #endif /* !defined(__OHW_LIBFS_H__) */ 130 | -------------------------------------------------------------------------------- /src/libfs/raw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS raw file system management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "../libpart/libpart.h" 26 | #include "libfs.h" 27 | 28 | /* Raw filesystem (ie no filesystem) */ 29 | static inode_t *fs_raw_get_inode (inode_t *parent, const unsigned char *name) 30 | { 31 | inode_t *new; 32 | fs_t *fs; 33 | int flags; 34 | 35 | if (parent != NULL) { 36 | return NULL; 37 | } 38 | /* Open root inode */ 39 | flags = INODE_TYPE_DIR; 40 | fs = NULL; 41 | new = malloc(sizeof(inode_t)); 42 | memset(new, 0, sizeof(inode_t)); 43 | new->flags = flags; 44 | new->name = strdup(name); 45 | 46 | return new; 47 | } 48 | 49 | static void fs_raw_put_inode (inode_t *inode) 50 | { 51 | free(inode); 52 | } 53 | 54 | static uint32_t fs_raw_map_bloc (unused inode_t *inode, uint32_t bloc) 55 | { 56 | if (inode != NULL 57 | /* XXX: can't figure out why I did this... */ 58 | /* && inode == inode->fs->bootfile*/ 59 | ) 60 | bloc += inode->blocs[0].bloc; 61 | 62 | return bloc; 63 | } 64 | 65 | static inode_t *fs_raw_get_special_inode (fs_t *fs, int type) 66 | { 67 | const unsigned char *name; 68 | inode_t *new, *parent, **inp; 69 | int flags; 70 | 71 | new = NULL; 72 | name = NULL; 73 | parent = NULL; 74 | inp = NULL; 75 | flags = 0; 76 | switch (type) { 77 | case FILE_ROOT: 78 | if (fs->root != NULL) { 79 | new = fs->root; 80 | } else { 81 | flags = INODE_TYPE_DIR; 82 | parent = NULL; 83 | name = NULL; 84 | inp = &fs->root; 85 | } 86 | break; 87 | case FILE_BOOT: 88 | if (fs->bootfile != NULL) { 89 | dprintf("bootfile already exists\n"); 90 | new = fs->bootfile; 91 | } else { 92 | new = part_private_get(fs_part(fs)); 93 | if (fs->bootdir == NULL) { 94 | dprintf("Get boot directory\n"); 95 | fs->bootdir = fs_raw_get_special_inode(fs, FILE_BOOTDIR); 96 | } 97 | parent = fs->bootdir; 98 | if (new != NULL) { 99 | dprintf("Fix bootfile\n"); 100 | new->parent = parent; 101 | new->fs = fs; 102 | } else { 103 | dprintf("New bootfile\n"); 104 | flags = INODE_TYPE_FILE | INODE_FLAG_EXEC | INODE_FLAG_BOOT; 105 | name = "ofwboot"; 106 | inp = &fs->bootfile; 107 | } 108 | } 109 | break; 110 | case FILE_BOOTDIR: 111 | if (fs->bootdir != NULL) { 112 | new = fs->bootdir; 113 | } else { 114 | flags = INODE_TYPE_DIR; 115 | parent = fs->root; 116 | name = "boot"; 117 | inp = &fs->bootdir; 118 | } 119 | break; 120 | default: 121 | return NULL; 122 | } 123 | if (new == NULL) { 124 | new = malloc(sizeof(inode_t)); 125 | memset(new, 0, sizeof(inode_t)); 126 | new->flags = flags; 127 | new->parent = parent; 128 | if (name != NULL) 129 | new->name = strdup(name); 130 | new->fs = fs; 131 | *inp = new; 132 | } 133 | 134 | return new; 135 | } 136 | 137 | static fs_ops_t fs_ops_raw = { 138 | &fs_raw_get_inode, 139 | &fs_raw_put_inode, 140 | &fs_raw_map_bloc, 141 | &fs_raw_get_special_inode, 142 | }; 143 | 144 | int fs_raw_set_bootfile (part_t *part, 145 | uint32_t start_bloc, uint32_t start_offset, 146 | uint32_t size_bloc, uint32_t size_offset) 147 | { 148 | inode_t *new; 149 | 150 | new = malloc(sizeof(inode_t)); 151 | if (new == NULL) 152 | return -1; 153 | DPRINTF("%s: pos %d %d size %d %d\n", __func__, start_bloc, start_offset, 154 | size_bloc, size_offset); 155 | memset(new, 0, sizeof(inode_t)); 156 | new->flags = INODE_TYPE_FILE | INODE_FLAG_EXEC | INODE_FLAG_BOOT; 157 | new->name = "ofwboot"; 158 | new->blocs[0].bloc = start_bloc; 159 | new->blocs[0].offset = start_offset; 160 | new->size.bloc = size_bloc; 161 | new->size.offset = size_offset; 162 | new->nb_blocs = size_bloc; 163 | part_private_set(part, new); 164 | 165 | return 0; 166 | } 167 | 168 | int fs_raw_probe (part_t *part, uint32_t *size, 169 | fs_ops_t **fs_ops, unsigned char **name, 170 | unused void **private) 171 | { 172 | DPRINTF("%s: %p map_bloc %p\n", __func__, &fs_ops_raw, &fs_raw_map_bloc); 173 | *fs_ops = &fs_ops_raw; 174 | *name = "Raw FS"; 175 | *size = part_size(part); 176 | 177 | return FS_TYPE_RAW; 178 | } 179 | -------------------------------------------------------------------------------- /src/libpart/apple.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS Apple partition type management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "libpart.h" 26 | 27 | /* Apple partitions handler */ 28 | #define HFS_BLOCSIZE (512) 29 | 30 | typedef struct Mac_head_t Mac_head_t; 31 | struct Mac_head_t { 32 | /* 0x000 */ 33 | uint8_t signature[2]; 34 | uint16_t bloc_size; 35 | uint32_t bloc_count; 36 | /* 0x008 */ 37 | uint16_t dev_type; 38 | uint16_t dev_ID; 39 | uint32_t data; 40 | /* 0x010 */ 41 | uint16_t driver_cnt; 42 | uint8_t pad[428]; 43 | /* 0x01BE */ 44 | uint8_t part_table[0x40]; 45 | /* 0x1FE */ 46 | uint8_t magic[2]; 47 | /* 0x0200 */ 48 | } __attribute__ ((packed)); 49 | 50 | typedef struct Mac_driver_entry_t Mac_driver_entry_t; 51 | struct Mac_driver_entry_t { 52 | uint32_t start; 53 | uint16_t size; 54 | uint16_t type; 55 | } __attribute__ ((packed)); 56 | 57 | typedef enum Mac_partflags_t Mac_partflags_t; 58 | enum Mac_partflags_t { 59 | MACPART_SPEC2 = 0x0100, 60 | MACPART_SPEC1 = 0x0080, 61 | MACPART_PIC = 0x0040, 62 | MACPART_WRITABLE = 0x0020, 63 | MACPART_READABLE = 0x0010, 64 | MACPART_BOOTABLE = 0x0008, 65 | MACPART_INUSE = 0x0004, 66 | MACPART_ALLOCATED = 0x0002, 67 | MACPART_VALID = 0x0001, 68 | }; 69 | 70 | #define MAC_BOOTABLE_PART (MACPART_VALID | MACPART_INUSE | MACPART_BOOTABLE) 71 | 72 | typedef struct Mac_partmap_t Mac_partmap_t; 73 | struct Mac_partmap_t { 74 | /* 0x000 */ 75 | uint8_t signature[2]; 76 | uint8_t res0[2]; 77 | uint32_t map_cnt; 78 | /* 0x008 */ 79 | uint32_t start_bloc; 80 | uint32_t bloc_cnt; 81 | /* 0x010 */ 82 | uint8_t name[32]; 83 | /* 0x030 */ 84 | uint8_t type[32]; 85 | /* 0x050 */ 86 | uint32_t data_start; 87 | uint32_t data_cnt; 88 | /* 0x058 */ 89 | uint32_t flags; 90 | uint32_t boot_start; 91 | /* 0x060 */ 92 | uint32_t boot_size; 93 | uint32_t boot_load; 94 | /* 0x068 */ 95 | uint32_t boot_load2; 96 | uint32_t boot_entry; 97 | /* 0x070 */ 98 | uint32_t boot_entry2; 99 | uint32_t boot_csum; 100 | /* 0x078 */ 101 | uint8_t CPU[16]; 102 | /* 0x088 */ 103 | uint8_t boot_args[0x80]; 104 | /* 0x108 */ 105 | uint8_t pad0[0xC8]; 106 | /* 0x1D4 */ 107 | uint16_t ntype; 108 | uint8_t ff[2]; 109 | /* 0x1D8 */ 110 | uint8_t pad1[0x24]; 111 | /* 0x1FC */ 112 | uint8_t mark[4]; 113 | /* 0x200 */ 114 | } __attribute__ ((packed)); 115 | 116 | int fs_raw_set_bootfile (part_t *part, 117 | uint32_t start_bloc, uint32_t start_offset, 118 | uint32_t size_bloc, uint32_t size_offset); 119 | 120 | part_t *Apple_probe_partitions (bloc_device_t *bd) 121 | { 122 | unsigned char tmp[33], *name; 123 | Mac_head_t *head; 124 | Mac_partmap_t *partmap; 125 | part_t *part, *boot_part; 126 | unsigned char *type; 127 | uint8_t *buffer; 128 | uint32_t pos, bloc, start, count; 129 | uint32_t bloc_size, flags; 130 | int map_count, i, n, len; 131 | 132 | part = NULL; 133 | boot_part = NULL; 134 | n = 1; 135 | buffer = malloc(HFS_BLOCSIZE); 136 | /* Read first sector */ 137 | bd_seek(bd, 0, 0); 138 | if (bd_read(bd, buffer, HFS_BLOCSIZE) < 0) { 139 | ERROR("Unable to read boot sector from boot device. Aborting...\n"); 140 | goto error; 141 | } 142 | head = (Mac_head_t *)buffer; 143 | if (head->signature[0] != 'E' || head->signature[1] != 'R') { 144 | // MSG("\rNo Apple boot bloc signature...\n"); 145 | goto error; 146 | } 147 | MSG("\rFound Apple partition map...\n"); 148 | bloc = 0; 149 | bloc_size = bd_seclen(bd); 150 | map_count = 1; 151 | #if 0 152 | if (head->magic[0] == 0x55 && head->magic[1] == 0xAA) { 153 | /* PREP boot image ! Must parse it as MS-DOS boot bloc */ 154 | ERROR("%s PREP head magic\n", __func__); 155 | goto error; 156 | } 157 | #endif 158 | /* Partition table starts in sector 1 */ 159 | for (i = 1; i < (map_count + 1); i++) { 160 | bloc = (i * HFS_BLOCSIZE) / bloc_size; 161 | pos = (i * HFS_BLOCSIZE) % bloc_size; 162 | DPRINTF("Check part %d of %d (%d %d %d)\n", 163 | i, map_count, bloc, pos, bloc_size); 164 | bd_seek(bd, bloc, pos); 165 | if (bd_read(bd, buffer, HFS_BLOCSIZE) < 0) { 166 | ERROR("%s sector_read failed (%d)\n", __func__, i); 167 | goto error; 168 | } 169 | partmap = (Mac_partmap_t *)buffer; 170 | if (partmap->signature[0] != 'P' || partmap->signature[1] != 'M' ) { 171 | ERROR("%s bad partition signature (%c %c)\n", 172 | __func__, partmap->signature[0], partmap->signature[1]); 173 | goto error; 174 | } 175 | /* We found at least one Apple partition map, 176 | * so we won't have to try to parse with other partition mappings. 177 | */ 178 | for (type = partmap->type; (type - partmap->type) < 32; type++) { 179 | if (*type != '\0') 180 | break; 181 | } 182 | if (partmap->name[0] == '\0') { 183 | sprintf(tmp, "part%d", i); 184 | name = tmp; 185 | } else { 186 | name = partmap->name; 187 | } 188 | /* Regular Apple partition */ 189 | part = malloc(sizeof(part_t)); 190 | if (part == NULL) { 191 | ERROR("%s: can't allocate partition\n", __func__); 192 | return NULL; 193 | } 194 | memset(part, 0, sizeof(part_t)); 195 | part->start = partmap->start_bloc; 196 | part->size = partmap->bloc_cnt; 197 | part_set_blocsize(bd, part, HFS_BLOCSIZE); 198 | len = 32 - (type - partmap->type); 199 | if (len == 0) { 200 | /* Place holder. Skip it */ 201 | DPRINTF("%s placeholder part\t%d\n", __func__, i); 202 | part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY; 203 | part_register(bd, part, name, i); 204 | } else if (strncmp("Apple_Void", type, 32) == 0) { 205 | /* Void partition. Skip it */ 206 | DPRINTF("%s Void part\t%d [%s]\n", __func__, i, type); 207 | part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY; 208 | part_register(bd, part, name, i); 209 | } else if (strncmp("Apple_Free", type, 32) == 0) { 210 | /* Free space. Skip it */ 211 | DPRINTF("%s Free part (%d)\n", __func__, i); 212 | part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY; 213 | part_register(bd, part, name, i); 214 | } else if (strncmp("Apple_partition_map", type, 32) == 0 || 215 | strncmp("Apple_Partition_Map", type, 32) == 0 216 | #if 0 // Is this really used or is it just a mistake ? 217 | || strncmp("Apple_patition_map", type, 32) == 0 218 | #endif 219 | ) { 220 | DPRINTF("%s Partition map\t%d [%s]\n", __func__, i, type); 221 | /* We are in the partition map descriptor */ 222 | if (i == 1) { 223 | /* Get the real map blocs count */ 224 | map_count = partmap->map_cnt; 225 | DPRINTF("%s: map_count: %d\n", __func__, map_count); 226 | } else { 227 | /* Don't about about secondary partition map 228 | * Seems to be used, at least on CDROMs, to describe 229 | * the same partition map with bloc_size = 2048 230 | */ 231 | } 232 | part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY; 233 | part_register(bd, part, name, i); 234 | } else if (strncmp("Apple_Driver", type, 32) == 0 || 235 | strncmp("Apple_Driver43", type, 32) == 0 || 236 | strncmp("Apple_Driver43_CD", type, 32) == 0 || 237 | strncmp("Apple_Driver_ATA", type, 32) == 0 || 238 | strncmp("Apple_Driver_ATAPI", type, 32) == 0 || 239 | strncmp("Apple_FWDriver", type, 32) == 0 || 240 | strncmp("Apple_Driver_IOKit", type, 32) == 0) { 241 | /* Drivers. don't care for now */ 242 | DPRINTF("%s Drivers part\t%d [%s]\n", __func__, i, type); 243 | part->flags = PART_TYPE_APPLE | PART_FLAG_DRIVER; 244 | part_register(bd, part, name, i); 245 | } else if (strncmp("Apple_Patches", type, 32) == 0) { 246 | /* Patches: don't care for now */ 247 | part->flags = PART_TYPE_APPLE | PART_FLAG_PATCH; 248 | part_register(bd, part, name, i); 249 | DPRINTF("%s Patches part\t%d [%s]\n", __func__, i, type); 250 | } else if (strncmp("Apple_HFS", type, 32) == 0 || 251 | strncmp("Apple_MFS", type, 32) == 0 || 252 | strncmp("Apple_UFS", type, 32) == 0 || 253 | strncmp("Apple_PRODOS", type, 32) == 0 || 254 | strncmp("Apple_UNIX_SVR2", type, 32) == 0 || 255 | strncmp("Linux", type, 32) == 0 || 256 | strncmp("NetBSD/macppc", type, 32) == 0 || 257 | strncmp("Apple_boot", type, 32) == 0 || 258 | strncmp("Apple_bootstrap", type, 32) == 0 || 259 | strncmp("Apple_Bootstrap", type, 32) == 0) { 260 | DPRINTF("%s Fs part\t%d [%s]\n", __func__, i, type); 261 | /* Filesystems / boot partitions */ 262 | flags = partmap->flags; 263 | start = partmap->start_bloc * HFS_BLOCSIZE; 264 | count = partmap->bloc_cnt * HFS_BLOCSIZE; 265 | if (partmap->boot_size == 0 || partmap->boot_load == 0) { 266 | printf("Not a bootable partition %d %d (%p %p)\n", 267 | partmap->boot_size, partmap->boot_load, 268 | boot_part, part); 269 | part->flags = PART_TYPE_APPLE | PART_FLAG_FS; 270 | } else { 271 | part->boot_start.bloc = partmap->boot_start; 272 | part->boot_start.offset = 0; 273 | part->boot_size.bloc = partmap->boot_size / HFS_BLOCSIZE; 274 | #if 0 275 | printf("%0x %0x %0x\n", partmap->boot_size, HFS_BLOCSIZE, 276 | part->boot_size.bloc); 277 | #endif 278 | part->boot_size.offset = (partmap->boot_size) % HFS_BLOCSIZE; 279 | part->boot_load = partmap->boot_load; 280 | part->boot_entry = partmap->boot_entry; 281 | fs_raw_set_bootfile(part, part->boot_start.bloc, 282 | part->boot_start.offset, 283 | part->boot_size.bloc, 284 | part->boot_size.offset); 285 | boot_part = part; 286 | part->flags = PART_TYPE_APPLE | PART_FLAG_FS | PART_FLAG_BOOT; 287 | } 288 | printf("Partition: %d '%s' '%s' st %0x size %0x", 289 | i, name, type, partmap->start_bloc, partmap->bloc_cnt); 290 | #ifndef DEBUG 291 | printf("\n"); 292 | #endif 293 | DPRINTF(" - %0x %0x %p %p\n", 294 | partmap->boot_start, partmap->boot_size, part, part->fs); 295 | DPRINTF(" boot %0x %0x load %0x entry %0x\n", 296 | part->boot_start.bloc, part->boot_size.bloc, 297 | part->boot_load, part->boot_entry); 298 | DPRINTF(" load %0x entry %0x %0x\n", 299 | partmap->boot_load2, partmap->boot_entry2, HFS_BLOCSIZE); 300 | part_register(bd, part, name, i); 301 | } else { 302 | memcpy(tmp, type, 32); 303 | tmp[32] = '\0'; 304 | ERROR("Unknown partition type [%s]\n", tmp); 305 | part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY; 306 | part_register(bd, part, name, i); 307 | } 308 | } 309 | error: 310 | free(buffer); 311 | 312 | return boot_part; 313 | 314 | } 315 | -------------------------------------------------------------------------------- /src/libpart/core.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS partitions management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "libpart.h" 26 | 27 | /* Bootable partitions detection and management */ 28 | part_t *part_open (bloc_device_t *bd, 29 | uint32_t start, uint32_t size, uint32_t spb) 30 | { 31 | part_t *part; 32 | 33 | if (bd_seek(bd, (start + size) * spb, 0) < 0) 34 | return NULL; 35 | part = malloc(sizeof(part_t)); 36 | if (part == NULL) 37 | return NULL; 38 | part->bd = bd; 39 | part->start = start; 40 | part->size = size; 41 | part->spb = spb; 42 | 43 | return part; 44 | } 45 | 46 | int part_seek (part_t *part, uint32_t bloc, uint32_t pos) 47 | { 48 | if (bloc > part->size) { 49 | ERROR("bloc: %d part size: %d %p\n", bloc, part->size, part); 50 | return -1; 51 | } 52 | bloc += part->start; 53 | if (part->spb != 0) { 54 | bloc *= part->spb; 55 | pos = pos % part->bloc_size; 56 | } else { 57 | pos += (bloc % part->bps) * part->bloc_size; 58 | bloc /= part->bps; 59 | } 60 | 61 | return bd_seek(part->bd, bloc, pos); 62 | } 63 | 64 | int part_read (part_t *part, void *buffer, int len) 65 | { 66 | return bd_read(part->bd, buffer, len); 67 | } 68 | 69 | int part_write (part_t *part, const void *buffer, int len) 70 | { 71 | return bd_write(part->bd, buffer, len); 72 | } 73 | 74 | void part_close (part_t *part) 75 | { 76 | part->size = 0; 77 | } 78 | 79 | uint32_t part_blocsize (part_t *part) 80 | { 81 | return part->bloc_size; 82 | } 83 | 84 | uint32_t part_flags (part_t *part) 85 | { 86 | return part->flags; 87 | } 88 | 89 | uint32_t part_size (part_t *part) 90 | { 91 | return part->size; 92 | } 93 | 94 | fs_t *part_fs (part_t *part) 95 | { 96 | return part->fs; 97 | } 98 | 99 | void part_private_set (part_t *part, void *private) 100 | { 101 | part->private = private; 102 | } 103 | 104 | void *part_private_get (part_t *part) 105 | { 106 | return part->private; 107 | } 108 | 109 | void part_set_blocsize (bloc_device_t *bd, part_t *part, uint32_t blocsize) 110 | { 111 | uint32_t seclen; 112 | 113 | part->bloc_size = blocsize; 114 | seclen = bd_seclen(bd); 115 | if (blocsize < seclen) { 116 | part->spb = 0; 117 | part->bps = bd_seclen(bd) / part->bloc_size; 118 | DPRINTF("%d part blocs in one sector (%d %d)\n", part->bps, 119 | part->bloc_size, bd_seclen(bd)); 120 | } else { 121 | part->spb = part->bloc_size / bd_seclen(bd); 122 | part->bps = 0; 123 | DPRINTF("%d sectors in one part bloc (%d %d)\n", part->spb, 124 | part->bloc_size, bd_seclen(bd)); 125 | } 126 | } 127 | 128 | int part_register (bloc_device_t *bd, part_t *partition, 129 | const unsigned char *name, int partnum) 130 | { 131 | part_t **cur; 132 | 133 | DPRINTF("Register partition '%s'\n", name); 134 | partition->bd = bd; 135 | partition->next = NULL; 136 | partition->name = strdup(name); 137 | partition->partnum = partnum; 138 | for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next) 139 | continue; 140 | *cur = partition; 141 | 142 | return 0; 143 | } 144 | 145 | part_t *part_get (bloc_device_t *bd, int partnum) 146 | { 147 | part_t **listp, *cur; 148 | 149 | listp = _bd_parts(bd); 150 | 151 | for (cur = *listp; cur != NULL; cur = cur->next) { 152 | if (cur->partnum == partnum) 153 | break; 154 | } 155 | 156 | return cur; 157 | } 158 | 159 | part_t *part_get_raw (bloc_device_t *bd) 160 | { 161 | part_t *part; 162 | uint32_t seclen; 163 | 164 | part = malloc(sizeof(part_t)); 165 | part->start = 0; 166 | seclen = bd_seclen(bd); 167 | part->size = bd_maxbloc(bd); 168 | if (seclen > 512) { 169 | part->size *= seclen / 512; 170 | } else { 171 | part->size *= 512 / seclen; 172 | } 173 | part->boot_start.bloc = 0; 174 | part->boot_start.offset = 0; 175 | part->boot_size.bloc = part->size; 176 | part->boot_size.offset = 0; 177 | part->boot_load = 0; 178 | part->boot_entry = 0; 179 | part_set_blocsize(bd, part, 512); 180 | part->bd = bd; 181 | part->flags = PART_TYPE_RAW | PART_FLAG_BOOT; 182 | part_register(bd, part, "Raw", 0); 183 | 184 | return part; 185 | } 186 | 187 | bloc_device_t *part_get_bd (part_t *part) 188 | { 189 | return part->bd; 190 | } 191 | 192 | part_t *part_probe (bloc_device_t *bd, int set_raw) 193 | { 194 | part_t *part0 = NULL, *boot_part, **cur; 195 | 196 | /* Try to find a valid boot partition */ 197 | boot_part = Apple_probe_partitions(bd); 198 | if (boot_part == NULL) { 199 | boot_part = isofs_probe_partitions(bd); 200 | if (boot_part == NULL && arch == ARCH_PREP) 201 | boot_part = PREP_find_partition(bd); 202 | if (boot_part == NULL && set_raw != 0) { 203 | dprintf("Use bloc device as raw partition\n"); 204 | } 205 | } 206 | if (_bd_parts(bd) == NULL) { 207 | /* Register the 0 partition: raw partition containing the whole disk */ 208 | part0 = part_get_raw(bd); 209 | } 210 | /* Probe filesystem on each found partition */ 211 | for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next) { 212 | const unsigned char *map, *type; 213 | switch ((*cur)->flags & 0x0F) { 214 | case PART_TYPE_PREP: 215 | map = "PREP"; 216 | break; 217 | case PART_TYPE_APPLE: 218 | map = "Apple"; 219 | break; 220 | case PART_TYPE_ISO9660: 221 | map = "ISO9660"; 222 | break; 223 | default: 224 | map = "Raw"; 225 | break; 226 | } 227 | switch ((*cur)->flags & 0xF0) { 228 | case PART_FLAG_DUMMY: 229 | type = "dummy"; 230 | break; 231 | case PART_FLAG_DRIVER: 232 | type = "driver"; 233 | break; 234 | case PART_FLAG_PATCH: 235 | type = "patches"; 236 | break; 237 | case PART_FLAG_FS: 238 | type = "filesystem"; 239 | break; 240 | default: 241 | type = "unknown"; 242 | break; 243 | } 244 | dprintf("Probe filesystem on %s %s partition '%s' %s %p\n", 245 | type, map, (*cur)->name, 246 | ((*cur)->flags) & PART_FLAG_BOOT ? "(bootable)" : "", *cur); 247 | if (((*cur)->flags) & PART_FLAG_FS) { 248 | if (((*cur)->flags) & PART_FLAG_BOOT) 249 | (*cur)->fs = fs_probe(*cur, 1); 250 | else 251 | (*cur)->fs = fs_probe(*cur, 0); 252 | } else if (((*cur)->flags) & PART_TYPE_RAW) { 253 | (*cur)->fs = fs_probe(*cur, 2); 254 | } else { 255 | (*cur)->fs = fs_probe(*cur, 2); 256 | } 257 | fs_get_bootfile((*cur)->fs); 258 | if (((*cur)->flags) & PART_FLAG_BOOT) { 259 | dprintf("Partition is bootable (%d)\n", (*cur)->partnum); 260 | bd_set_boot_part(bd, *cur, (*cur)->partnum); 261 | if (boot_part == NULL) 262 | boot_part = *cur; 263 | } 264 | } 265 | dprintf("Boot partition: %p %p %p %p\n", boot_part, boot_part->fs, 266 | part_fs(boot_part), part0); 267 | 268 | return boot_part; 269 | } 270 | 271 | int part_set_boot_file (part_t *part, uint32_t start, uint32_t offset, 272 | uint32_t size) 273 | { 274 | part->boot_start.bloc = start; 275 | part->boot_start.offset = offset; 276 | part->boot_size.bloc = size; 277 | part->boot_size.offset = 0; 278 | part->boot_load = 0; 279 | part->boot_entry = 0; 280 | part->flags |= PART_FLAG_BOOT; 281 | 282 | return 0; 283 | } 284 | 285 | unsigned int part_get_entry (part_t *part) 286 | { 287 | return part->boot_entry; 288 | } 289 | -------------------------------------------------------------------------------- /src/libpart/isofs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS ISOFS partition type management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "libpart.h" 26 | 27 | /* ISO FS partitions handlers */ 28 | #define ISOFS_BLOCSIZE (2048) 29 | 30 | /* Generic ISO fs descriptor */ 31 | typedef struct isofs_desc_t isofs_desc_t; 32 | struct isofs_desc_t { 33 | uint8_t type; 34 | uint8_t ID[5]; 35 | uint8_t version; 36 | uint8_t data[2041]; 37 | } __attribute__ ((packed)); 38 | 39 | typedef struct iso_primary_desc_t iso_primary_desc_t; 40 | struct iso_primary_desc_t { 41 | uint8_t type; 42 | uint8_t ID[5]; 43 | uint8_t version; 44 | uint8_t pad0; 45 | uint8_t system_id[32]; 46 | uint8_t volume_id[32]; 47 | uint8_t pad1[8]; 48 | uint32_t volume_size; 49 | } __attribute__ ((packed)); 50 | 51 | /* The only descriptor we're interrested in here 52 | * is El-torito boot descriptor 53 | */ 54 | typedef struct isofs_bootdesc_t isofs_bootdesc_t; 55 | struct isofs_bootdesc_t { 56 | uint8_t type; 57 | uint8_t ID[5]; 58 | uint8_t version; 59 | uint8_t sys_ID[32]; 60 | uint8_t pad[32]; 61 | uint32_t catalog; 62 | uint8_t data[1973]; 63 | } __attribute__ ((packed)); 64 | 65 | #define ISO_BOOTABLE 0x88 66 | enum { 67 | ISOBOOT_IX86 = 0, 68 | ISOBOOT_PPC = 1, 69 | ISOBOOT_MAC = 2, 70 | }; 71 | 72 | enum { 73 | ISOMEDIA_NOEMUL = 0, 74 | ISOMEDIA_FL12 = 1, 75 | ISOMEDIA_FL144 = 2, 76 | ISOMEDIA_FL288 = 3, 77 | ISOMEDIA_HD = 4, 78 | }; 79 | 80 | typedef struct isofs_validdesc_t isofs_validdesc_t; 81 | struct isofs_validdesc_t { 82 | uint8_t ID; 83 | uint8_t arch; 84 | uint8_t pad[2]; 85 | uint8_t name[24]; 86 | uint8_t csum[2]; 87 | uint16_t key; 88 | } __attribute__ ((packed)); 89 | 90 | typedef struct isofs_bootcat_t isofs_bootcat_t; 91 | struct isofs_bootcat_t { 92 | uint8_t bootable; 93 | uint8_t media; 94 | uint8_t segment[2]; 95 | uint8_t sys_type; 96 | uint8_t pad; 97 | uint16_t nsect; 98 | uint32_t offset; 99 | uint8_t data[20]; 100 | } __attribute__ ((packed)); 101 | 102 | part_t *isofs_probe_partitions (bloc_device_t *bd) 103 | { 104 | unsigned char name[32]; 105 | void *buffer; 106 | union { 107 | isofs_desc_t desc; 108 | isofs_bootdesc_t bootdesc; 109 | iso_primary_desc_t primdesc; 110 | } *desc; 111 | isofs_validdesc_t *valid; 112 | isofs_bootcat_t *bootcat; 113 | part_t *part; 114 | uint32_t boot_desc; 115 | uint32_t nsect, bloc, offset, length; 116 | int i, end_reached; 117 | 118 | part = NULL; 119 | buffer = malloc(ISOFS_BLOCSIZE); 120 | end_reached = 0; 121 | desc = buffer; 122 | boot_desc = -1; 123 | /* The descriptors start at offset 0x8000 */ 124 | for (bloc = 0x8000 / ISOFS_BLOCSIZE; end_reached == 0; bloc++) { 125 | bd_seek(bd, bloc, 0); 126 | if (bd_read(bd, buffer, ISOFS_BLOCSIZE) < 0) { 127 | ERROR("%s bloc_read %d failed\n", __func__, bloc); 128 | goto error; 129 | } 130 | if (strncmp("CD001", desc->desc.ID, 5) != 0) { 131 | // MSG("\rNo ISO9660 signature\n"); 132 | goto error; 133 | } 134 | /* We found at least one valid descriptor */ 135 | switch (desc->desc.type) { 136 | case 0x00: 137 | /* El-torito descriptor, great ! */ 138 | DPRINTF("El-torito descriptor: %08x %d\n", desc->bootdesc.catalog, 139 | (char *)&desc->bootdesc.catalog - (char *)desc); 140 | boot_desc = get_le32(&desc->bootdesc.catalog); 141 | break; 142 | case 0x01: 143 | /* ISOFS primary descriptor */ 144 | DPRINTF("ISOFS primary descriptor (%d %d)\n", 145 | get_le32(&desc->primdesc.volume_size) * 2048, 146 | get_le32(&desc->primdesc.volume_size)); 147 | break; 148 | case 0x02: 149 | /* ISOFS suplementary descriptor */ 150 | DPRINTF("ISOFS suplementary descriptor\n"); 151 | break; 152 | case 0xFF: 153 | /* End of descriptor list */ 154 | DPRINTF("End of descriptor list\n"); 155 | end_reached = 1; 156 | break; 157 | } 158 | } 159 | if (boot_desc != (uint32_t)(-1)) { 160 | /* Find the validation descriptor */ 161 | bd_seek(bd, boot_desc, 0); 162 | for (i = 0; i < (ISOFS_BLOCSIZE / 64); i++) { 163 | DPRINTF("ISO catalog...\n"); 164 | bd_read(bd, buffer, 64); 165 | valid = buffer; 166 | #if 1 167 | if (valid->ID != 0x01 || get_le16(&valid->key) != 0xAA55) { 168 | ERROR("ISO catalog with invalid ID/key: %x %x\n", 169 | valid->ID, valid->key); 170 | continue; 171 | } 172 | #endif 173 | #if 0 174 | #if defined (__i386__) 175 | if (valid->arch != ISOBOOT_IX86) { 176 | ERROR("ISO catalog not for x86: %d\n", valid->arch); 177 | continue; 178 | } 179 | #elif defined (__powerpc__) || defined (_ARCH_PPC) 180 | if (valid->arch != ISOBOOT_PPC && valid->arch != ISOBOOT_MAC) { 181 | ERROR("ISO catalog not for PPC: %d\n", valid->arch); 182 | continue; 183 | } 184 | #else 185 | ERROR("Unknown host architecture !\n"); 186 | continue; 187 | #endif 188 | #endif 189 | bootcat = (void *)(valid + 1); 190 | if (bootcat->bootable != ISO_BOOTABLE) { 191 | ERROR("Non bootable ISO catalog\n"); 192 | continue; 193 | } 194 | nsect = get_le16(&bootcat->nsect); 195 | switch (bootcat->media) { 196 | case ISOMEDIA_NOEMUL: 197 | length = nsect * ISOFS_BLOCSIZE; 198 | dprintf("No emulation\n"); 199 | break; 200 | case ISOMEDIA_FL12: 201 | length = 1200 * 1024; 202 | dprintf("1.2 MB floppy\n"); 203 | break; 204 | case ISOMEDIA_FL144: 205 | length = 1440 * 1024; 206 | dprintf("1.44 MB floppy\n"); 207 | break; 208 | case ISOMEDIA_FL288: 209 | length = 2880 * 1024; 210 | dprintf("2.88 MB floppy\n"); 211 | break; 212 | case ISOMEDIA_HD: 213 | length = nsect * ISOFS_BLOCSIZE; 214 | dprintf("HD image\n"); 215 | break; 216 | default: 217 | ERROR("Unknown media type: %d\n", bootcat->media); 218 | continue; 219 | } 220 | offset = get_le32(&bootcat->offset); 221 | /* Register boot disc */ 222 | part = malloc(sizeof(part_t)); 223 | part->bd = bd; 224 | part_set_blocsize(bd, part, ISOFS_BLOCSIZE); 225 | part->start = offset; 226 | part->size = (length + ISOFS_BLOCSIZE - 1) / ISOFS_BLOCSIZE; 227 | part->boot_start.bloc = 0; 228 | part->boot_start.offset = 0; 229 | part->boot_size.bloc = length / ISOFS_BLOCSIZE; 230 | part->boot_size.offset = length % ISOFS_BLOCSIZE; 231 | part->boot_load = 0; 232 | part->boot_entry = 0; 233 | if (valid->name[0] == '\0') { 234 | strcpy(name, "ISOFS"); 235 | } else { 236 | memcpy(name, valid->name, sizeof(valid->name)); 237 | name[sizeof(valid->name)] = '\0'; 238 | } 239 | printf("Partition '%s': %p st %0x size %0x %d\n", 240 | name, part, offset, length, bootcat->media); 241 | printf(" boot %0x %0x load %0x entry %0x\n", 242 | part->boot_start.bloc, part->boot_size.bloc, 243 | part->boot_load, part->boot_entry); 244 | part->flags = PART_TYPE_ISO9660 | PART_FLAG_BOOT; 245 | part_register(bd, part, name, i + 1); 246 | fs_raw_set_bootfile(part, part->boot_start.bloc, 247 | part->boot_start.offset, 248 | part->boot_size.bloc, 249 | part->boot_size.offset); 250 | break; 251 | } 252 | } 253 | error: 254 | free(buffer); 255 | 256 | return part; 257 | } 258 | -------------------------------------------------------------------------------- /src/libpart/libpart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS partitions management definitions 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #if !defined (__OHW_LIBPART_H__) 23 | #define __OHW_LIBPART_H__ 24 | 25 | /* LBA for IDE is 48 bits long. 26 | * For now, I'll use 32 bits to store bloc nr 27 | * and 32 bits to store offsets in blocs and will only handle LBA 28. 28 | * So, I'll be affected with the well known 128 GB disk barrier bug... 29 | */ 30 | 31 | struct part_t { 32 | bloc_device_t *bd; 33 | int partnum; 34 | uint32_t start; /* Partition first bloc */ 35 | uint32_t size; /* Partition size, in blocs */ 36 | uint32_t spb; 37 | uint32_t bps; 38 | uint32_t flags; 39 | 40 | uint32_t bloc_size; /* Bloc size (may be != bd->seclen) */ 41 | /* XXX: broken: to be reworked */ 42 | pos_t boot_start; /* Boot program start bloc & offset */ 43 | pos_t boot_size; /* Boot program size */ 44 | uint32_t boot_load; /* Boot program address load */ 45 | uint32_t boot_entry; /* Boot program entry point */ 46 | 47 | unsigned char *name; 48 | inode_t *boot_file; 49 | fs_t *fs; 50 | 51 | void *private; 52 | 53 | part_t *next; 54 | part_t *bnext; 55 | }; 56 | 57 | int part_register (bloc_device_t *bd, part_t *partition, 58 | const unsigned char *name, int partnum); 59 | void part_set_blocsize (bloc_device_t *bd, part_t *part, uint32_t blocsize); 60 | void part_private_set (part_t *part, void *private); 61 | void *part_private_get (part_t *part); 62 | 63 | part_t *PREP_find_partition (bloc_device_t *bd); 64 | part_t *Apple_probe_partitions (bloc_device_t *bd); 65 | part_t *isofs_probe_partitions (bloc_device_t *bd); 66 | 67 | #endif /* !defined (__OHW_LIBPART_H__) */ 68 | -------------------------------------------------------------------------------- /src/libpart/prep.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware PREP BIOS partition type management 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | #include "libpart.h" 26 | 27 | /* PREP image management */ 28 | typedef struct MSDOS_part_t MSDOS_part_t; 29 | struct MSDOS_part_t { 30 | uint8_t boot_ind; 31 | uint8_t start_head; 32 | uint8_t start_sect; 33 | uint8_t start_cyl; 34 | uint8_t sys_ind; 35 | uint8_t end_head; 36 | uint8_t end_sect; 37 | uint8_t end_cyl; 38 | uint32_t LBA_start; 39 | uint32_t LBA_end; 40 | } __attribute__ ((packed)); 41 | 42 | part_t *PREP_find_partition (bloc_device_t *bd) 43 | { 44 | MSDOS_part_t *p; 45 | part_t *part; 46 | uint8_t *buffer; 47 | uint32_t boot_offset, boot_size; 48 | int i; 49 | 50 | part = NULL; 51 | buffer = malloc(0x200); 52 | bd_seek(bd, 0, 0); 53 | if (bd_read(bd, buffer, 0x200) < 0) { 54 | ERROR("Unable to read boot sector from boot device. Aborting...\n"); 55 | goto error; 56 | } 57 | if (buffer[0x1FE] != 0x55 || buffer[0x1FF] != 0xAA) { 58 | ERROR("No MSDOS signature (%x %x %x %x)\n", 59 | buffer[0x000], buffer[0x001], buffer[0x1FE], buffer[0x1FF]); 60 | goto error; 61 | } 62 | for (i = 0; i < 4; i++) { 63 | p = (void *)(&buffer[0x1BE + (0x10 * i)]); 64 | DPRINTF("partition %d: %x is %sbootable - ", i, p->boot_ind, 65 | (p->boot_ind & 0x80) ? "" : "not "); 66 | DPRINTF("start %0x end %0x type %x\n", 67 | get_le32(&p->LBA_start), get_le32(&p->LBA_end), p->sys_ind); 68 | #if 0 69 | if (p->boot_ind != 0x80) 70 | continue; 71 | #endif 72 | switch (p->sys_ind) { 73 | case 0x07: /* HPFS/NTFS */ 74 | goto register_nonboot; 75 | case 0x08: /* AIX */ 76 | goto register_nonboot; 77 | case 0x09: /* AIX bootable */ 78 | /* Not supported by now */ 79 | break; 80 | case 0x0A: /* OS/2 boot manager */ 81 | /* Not supported by now */ 82 | break; 83 | case 0x41: /* PREP boot */ 84 | part = malloc(sizeof(part_t)); 85 | memset(part, 0, sizeof(part_t)); 86 | part->bd = bd; 87 | part_set_blocsize(bd, part, 0x200); 88 | /* Convert start and size into LBA */ 89 | if ((p->start_head != 0 || p->start_cyl != 0 || 90 | p->start_sect != 0) && p->LBA_start == 0) { 91 | DPRINTF("start: use CHS\n"); 92 | part->start = bd_CHS2sect(bd, p->start_cyl, 93 | p->start_head, 94 | p->start_sect); 95 | } else { 96 | DPRINTF("start: use LBA\n"); 97 | part->start = get_le32(&p->LBA_start); 98 | } 99 | if ((p->end_head != 0 || p->end_cyl != 0 || 100 | p->end_sect != 0) && p->LBA_end == 0) { 101 | DPRINTF("end: use CHS\n"); 102 | part->size = bd_CHS2sect(bd, p->end_cyl, 103 | p->end_head, p->end_sect); 104 | } else { 105 | DPRINTF("end: use LBA\n"); 106 | part->size = get_le32(&p->LBA_end); 107 | } 108 | /* XXX: seems that some (AIX !) 109 | * code the size here instead of partition end 110 | */ 111 | if (part->size > part->start) 112 | part->size -= part->start; 113 | DPRINTF("LBA: start %0x size: %0x\n", part->start, part->size); 114 | /* Now, find and check boot record */ 115 | part_seek(part, 0, 0); 116 | if (bd_read(bd, buffer, part->bloc_size) < 0) { 117 | ERROR("%s sector_read failed (%d)\n", __func__, i); 118 | freep(&part); 119 | goto error; 120 | } 121 | #if 0 122 | if (buffer[0x1FE] != 0x55 || buffer[0x1FF] != 0xAA) { 123 | ERROR("No MSDOS signature on PREP boot record\n"); 124 | freep(&part); 125 | goto error; 126 | } 127 | #endif 128 | boot_offset = get_le32(buffer); 129 | boot_size = get_le32(buffer + 4); 130 | if ((boot_offset & 3) || /*(boot_size & 3) ||*/ 131 | boot_offset == 0 || boot_size == 0) { 132 | DPRINTF("Suspicious PREP boot parameters: %08x %08x %08x %08x\n", 133 | part->start, part->start * 0x200, boot_offset, boot_size); 134 | #if 0 135 | freep(&part); 136 | goto error; 137 | #else 138 | /* IBM boot blocs respect the norm better than others... */ 139 | part->start++; 140 | part_seek(part, 0, 0); 141 | if (bd_read(bd, buffer, part->bloc_size) < 0) { 142 | ERROR("%s sector_read failed (%d)\n", __func__, i); 143 | freep(&part); 144 | goto error; 145 | } 146 | boot_offset = get_le32(buffer); 147 | boot_size = get_le32(buffer + 4); 148 | #endif 149 | } 150 | DPRINTF("PREP boot parameters: %08x %08x %08x %08x\n", 151 | part->start, part->start * 0x200, boot_offset, boot_size); 152 | if (boot_size > (part->size * part->bloc_size)) { 153 | ERROR("PREP boot image greater than boot partition: %0x %0x\n", 154 | boot_size, part->size * part->bloc_size); 155 | #if 0 156 | freep(&part); 157 | goto error; 158 | #endif 159 | } 160 | part->boot_start.bloc = 0; 161 | part->boot_start.offset = 0; 162 | part->boot_size.bloc = boot_size / part->bloc_size; 163 | part->boot_size.offset = boot_size % part->bloc_size; 164 | part->boot_load = 0; 165 | part->boot_entry = boot_offset - part->bloc_size; 166 | part->flags = PART_TYPE_PREP | PART_FLAG_BOOT; 167 | part_register(bd, part, "PREP boot", i); 168 | fs_raw_set_bootfile(part, part->boot_start.bloc, 169 | part->boot_start.offset, 170 | part->boot_size.bloc, 171 | part->boot_size.offset); 172 | break; 173 | case 0x63: /* GNU Hurd */ 174 | goto register_nonboot; 175 | case 0x83: /* Linux */ 176 | goto register_nonboot; 177 | case 86 ... 87: /* NFTS volume set */ 178 | /* Not supported by now */ 179 | break; 180 | case 0x8E: /* Linux LVM */ 181 | /* Not supported by now */ 182 | break; 183 | case 0x96: /* AIX seems to use this to identify ISO 9660 'partitions' */ 184 | break; 185 | case 0xA5: /* FreeBSD */ 186 | goto register_nonboot; 187 | case 0xA6: /* OpenBSD */ 188 | goto register_nonboot; 189 | case 0xA7: /* NeXTSTEP */ 190 | goto register_nonboot; 191 | case 0xA8: /* Darwin UFS */ 192 | goto register_nonboot; 193 | case 0xA9: /* NetBSD */ 194 | goto register_nonboot; 195 | case 0xAB: /* Darwin boot */ 196 | /* Not supported by now */ 197 | break; 198 | case 0xBE: /* Solaris boot */ 199 | /* Not supported by now */ 200 | break; 201 | case 0xEB: /* BeOS fs */ 202 | goto register_nonboot; 203 | case 0xFD: /* Linux RAID */ 204 | /* Not supported by now */ 205 | break; 206 | default: 207 | break; 208 | register_nonboot: 209 | break; 210 | } 211 | } 212 | error: 213 | free(buffer); 214 | 215 | return part; 216 | } 217 | -------------------------------------------------------------------------------- /src/main.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Open Hack'Ware BIOS main. 3 | * 4 | * Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr) 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License V2 8 | * as published by the Free Software Foundation 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | OUTPUT_ARCH(powerpc:common) 21 | 22 | MEMORY 23 | { 24 | start (rwx) : ORIGIN = 0x05800000, LENGTH = 0x00000400 25 | bios (rwx) : ORIGIN = 0x05800400, LENGTH = 0x0007FC00 26 | ram (rw) : ORIGIN = 0x06000000, LENGTH = 0x00200000 27 | } 28 | 29 | SECTIONS 30 | { 31 | .start : { *(.start) } > start 32 | . = ALIGN(4) ; 33 | .text : { *(.text*) } > bios 34 | . = ALIGN(4) ; 35 | .OpenFirmware : { *(.OpenFirmware) } > bios 36 | . = ALIGN(4) ; 37 | _data_start = . ; 38 | .data : { *(.data) } > bios 39 | _data_end = . ; 40 | . = ALIGN(4) ; 41 | _OF_vars_start = . ; 42 | .OpenFirmware_vars : { *(.OpenFirmware_vars) } > bios 43 | _OF_vars_end = . ; 44 | . = ALIGN(4) ; 45 | _sdata_start = . ; 46 | .sdata : { *(.sdata) } > bios 47 | . = ALIGN(4) ; 48 | .sdata2 : { *(.sdata2) } > bios 49 | _sdata_end = . ; 50 | . = ALIGN(4) ; 51 | _ro_start = . ; 52 | .rodata : { *(.rodata*) } > bios 53 | _ro_end = . ; 54 | . = ALIGN(4) ; 55 | _RTAS_start = .; 56 | .RTAS : { *(.RTAS) } > bios 57 | _RTAS_end = .; 58 | . = ALIGN(4) ; 59 | _RTAS_data_start = .; 60 | .RTAS_vars : { *(.RTAS_vars) } > bios 61 | . = ALIGN(4) ; 62 | _RTAS_data_end = .; 63 | _bss_start = . ; 64 | .sbss : { 65 | *(.sbss) *(.scommon) 66 | } > bios 67 | . = ALIGN(4) ; 68 | .bss : { *(.bss) *(COMMON) } > bios 69 | _bss_end = . ; 70 | . = ALIGN(4) ; 71 | _ram_start = . ; 72 | .ram : { 73 | *(.ram) 74 | } > ram 75 | /DISCARD/ : { *(.stab) } 76 | /DISCARD/ : { *(.stabstr) } 77 | /DISCARD/ : { *(.comment) } 78 | /DISCARD/ : { *(.note) } 79 | } 80 | -------------------------------------------------------------------------------- /src/mm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Open Hack'Ware BIOS memory management. 3 | * 4 | * Copyright (c) 2004-2005 Jocelyn Mayer 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License V2 8 | * as published by the Free Software Foundation 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include 21 | #include "bios.h" 22 | 23 | #if 0 24 | static uint8_t *page_bitmap; 25 | static uint32_t memory_size; 26 | 27 | static void mark_page_in_use (uint32_t page_nb) 28 | { 29 | uint32_t offset, bit; 30 | 31 | offset = page_nb >> 3; 32 | bit = page_nb & 7; 33 | page_bitmap[offset] |= 1 << bit; 34 | } 35 | 36 | static void mark_page_free (uint32_t page_nb) 37 | { 38 | uint32_t offset, bit; 39 | 40 | offset = page_nb >> 3; 41 | bit = page_nb & 7; 42 | page_bitmap[offset] &= ~(1 << bit); 43 | } 44 | 45 | static int is_page_in_use (uint32_t page_nb) 46 | { 47 | uint32_t offset, bit; 48 | 49 | offset = page_nb >> 3; 50 | bit = page_nb & 7; 51 | 52 | return (page_bitmap[offset] & (~(1 << bit))) != 0; 53 | } 54 | 55 | void mm_init (uint32_t memsize) 56 | { 57 | uint32_t page_start, page_ram_start, page, ram_start; 58 | uint32_t nb_pages, bitmap_size; 59 | 60 | /* Init bitmap */ 61 | ram_start = (uint32_t)(&_ram_start); 62 | ram_start = (ram_start + (1 << 12) - 1) & ~((1 << 12) - 1); 63 | page_bitmap = (void *)ram_start; 64 | nb_pages = (memsize + (1 << 12) - 1) >> 12; 65 | bitmap_size = (nb_pages + 7) >> 3; 66 | /* First mark all pages as free */ 67 | memset(page_bitmap, 0, bitmap_size); 68 | /* Mark all pages used by the BIOS as used (code + data + bitmap) */ 69 | page_start = (uint32_t)(0x05800000) >> 12; /* TO FIX */ 70 | ram_start += bitmap_size; 71 | ram_start = (ram_start + (1 << 12) - 1) & ~((1 << 12) - 1); 72 | page_ram_start = ram_start >> 12; 73 | for (page = page_start; page < page_ram_start; page++) 74 | mark_page_in_use(page); 75 | memory_size = memsize; 76 | } 77 | 78 | void *page_get (int nb_pages) 79 | { 80 | uint32_t page_start, page_end, page; 81 | int nb; 82 | 83 | page_start = (uint32_t)(0x05800000) >> 12; /* TO FIX */ 84 | page_end = memory_size >> 12; 85 | for (page = page_start; page < page_end; ) { 86 | /* Skip all full "blocs" */ 87 | for (; page < page_end; page += 8) { 88 | if (page_bitmap[page >> 3] != 0xFF) 89 | break; 90 | } 91 | for (nb = 0; page < page_end; page++) { 92 | if (!is_page_in_use(page)) { 93 | nb++; 94 | if (nb == nb_pages) { 95 | /* Found ! */ 96 | for (; nb >= 0; nb--, page--) 97 | mark_page_in_use(page); 98 | 99 | return (void *)(page << 12); 100 | } 101 | } 102 | } 103 | } 104 | 105 | return NULL; 106 | } 107 | 108 | void page_put (void *addr, int nb_pages) 109 | { 110 | uint32_t page_start, page_end, page; 111 | 112 | page_start = (uint32_t)addr >> 12; 113 | page_end = page_start + nb_pages; 114 | for (page = page_start; page < page_end; page++) { 115 | if (!is_page_in_use(page)) 116 | printf("ERROR: page %u has already been freed !\n", page); 117 | mark_page_free(page); 118 | } 119 | } 120 | #else 121 | static uint8_t *page_alloc; 122 | 123 | void mm_init (unused uint32_t memsize) 124 | { 125 | uint32_t ram_start; 126 | ram_start = (uint32_t)(&_ram_start); 127 | ram_start = (ram_start + (1 << 12) - 1) & ~((1 << 12) - 1); 128 | page_alloc = (void *)ram_start; 129 | } 130 | 131 | void *page_get (unused int nb_pages) 132 | { 133 | void *ret; 134 | 135 | ret = page_alloc; 136 | page_alloc += nb_pages << 12; 137 | memset(ret, 0, nb_pages << 12); 138 | 139 | return ret; 140 | } 141 | 142 | void page_put (unused void *addr, unused int nb_pages) 143 | { 144 | } 145 | #endif 146 | -------------------------------------------------------------------------------- /src/nvram.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Open Hack'Ware BIOS NVRAM management routines. 5 | * 6 | * Copyright (c) 2004-2005 Jocelyn Mayer 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License V2 10 | * as published by the Free Software Foundation 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include "bios.h" 25 | 26 | #define NVRAM_MAX_SIZE 0x2000 27 | #define NVRAM_IO_BASE 0x0074 28 | 29 | struct nvram_t { 30 | uint16_t io_base; 31 | uint16_t size; 32 | }; 33 | 34 | /* NVRAM access */ 35 | static void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value) 36 | { 37 | NVRAM_write(nvram, addr, value); 38 | } 39 | 40 | static uint8_t NVRAM_get_byte (nvram_t *nvram, uint16_t addr) 41 | { 42 | return NVRAM_read(nvram, addr); 43 | } 44 | 45 | static void NVRAM_set_word (nvram_t *nvram, uint16_t addr, uint16_t value) 46 | { 47 | NVRAM_write(nvram, addr, value >> 8); 48 | NVRAM_write(nvram, addr + 1, value); 49 | } 50 | 51 | static uint16_t NVRAM_get_word (nvram_t *nvram, uint16_t addr) 52 | { 53 | uint16_t tmp; 54 | 55 | tmp = NVRAM_read(nvram, addr) << 8; 56 | tmp |= NVRAM_read(nvram, addr + 1); 57 | 58 | return tmp; 59 | } 60 | 61 | static void NVRAM_set_lword (nvram_t *nvram, uint16_t addr, uint32_t value) 62 | { 63 | NVRAM_write(nvram, addr, value >> 24); 64 | NVRAM_write(nvram, addr + 1, value >> 16); 65 | NVRAM_write(nvram, addr + 2, value >> 8); 66 | NVRAM_write(nvram, addr + 3, value); 67 | } 68 | 69 | static uint32_t NVRAM_get_lword (nvram_t *nvram, uint16_t addr) 70 | { 71 | uint32_t tmp; 72 | 73 | tmp = NVRAM_read(nvram, addr) << 24; 74 | tmp |= NVRAM_read(nvram, addr + 1) << 16; 75 | tmp |= NVRAM_read(nvram, addr + 2) << 8; 76 | tmp |= NVRAM_read(nvram, addr + 3); 77 | 78 | return tmp; 79 | } 80 | 81 | static void NVRAM_set_string (nvram_t *nvram, uint32_t addr, 82 | const unsigned char *str, uint32_t max) 83 | { 84 | uint32_t i; 85 | 86 | for (i = 0; i < max && str[i] != '\0'; i++) { 87 | NVRAM_write(nvram, addr + i, str[i]); 88 | } 89 | NVRAM_write(nvram, addr + i, '\0'); 90 | } 91 | 92 | static int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, 93 | uint16_t addr, int max) 94 | { 95 | int i; 96 | 97 | memset(dst, 0, max); 98 | for (i = 0; i < max; i++) { 99 | dst[i] = NVRAM_get_byte(nvram, addr + i); 100 | if (dst[i] == '\0') 101 | break; 102 | } 103 | 104 | return i; 105 | } 106 | 107 | static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value) 108 | { 109 | uint16_t tmp; 110 | uint16_t pd, pd1, pd2; 111 | 112 | tmp = prev >> 8; 113 | pd = prev ^ value; 114 | pd1 = pd & 0x000F; 115 | pd2 = ((pd >> 4) & 0x000F) ^ pd1; 116 | tmp ^= (pd1 << 3) | (pd1 << 8); 117 | tmp ^= pd2 | (pd2 << 7) | (pd2 << 12); 118 | 119 | return tmp; 120 | } 121 | 122 | static uint16_t NVRAM_compute_crc (nvram_t *nvram, 123 | uint32_t start, uint32_t count) 124 | { 125 | uint32_t i; 126 | uint16_t crc = 0xFFFF; 127 | int odd; 128 | 129 | odd = count & 1; 130 | count &= ~1; 131 | for (i = 0; i != count; i++) { 132 | crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i)); 133 | } 134 | if (odd) { 135 | crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8); 136 | } 137 | 138 | return crc; 139 | } 140 | 141 | /* Format NVRAM for PREP target */ 142 | static int NVRAM_prep_format (nvram_t *nvram) 143 | { 144 | #define NVRAM_PREP_OSAREA_SIZE 512 145 | #define NVRAM_PREP_CONFSIZE 1024 146 | uint16_t crc; 147 | 148 | /* NVRAM header */ 149 | /* 0x00: NVRAM size in kB */ 150 | NVRAM_set_word(nvram, 0x00, nvram->size >> 10); 151 | /* 0x02: NVRAM version */ 152 | NVRAM_set_byte(nvram, 0x02, 0x01); 153 | /* 0x03: NVRAM revision */ 154 | NVRAM_set_byte(nvram, 0x03, 0x01); 155 | /* 0x08: last OS */ 156 | NVRAM_set_byte(nvram, 0x08, 0x00); /* Unknown */ 157 | /* 0x09: endian */ 158 | NVRAM_set_byte(nvram, 0x09, 'B'); /* Big-endian */ 159 | /* 0x0A: OSArea usage */ 160 | NVRAM_set_byte(nvram, 0x0A, 0x00); /* Empty */ 161 | /* 0x0B: PM mode */ 162 | NVRAM_set_byte(nvram, 0x0B, 0x00); /* Normal */ 163 | /* Restart block description record */ 164 | /* 0x0C: restart block version */ 165 | NVRAM_set_word(nvram, 0x0C, 0x01); 166 | /* 0x0E: restart block revision */ 167 | NVRAM_set_word(nvram, 0x0E, 0x01); 168 | /* 0x20: restart address */ 169 | NVRAM_set_lword(nvram, 0x20, 0x00); 170 | /* 0x24: save area address */ 171 | NVRAM_set_lword(nvram, 0x24, 0x00); 172 | /* 0x28: save area length */ 173 | NVRAM_set_lword(nvram, 0x28, 0x00); 174 | /* 0x1C: checksum of restart block */ 175 | crc = NVRAM_compute_crc(nvram, 0x0C, 32); 176 | NVRAM_set_word(nvram, 0x1C, crc); 177 | 178 | /* Security section */ 179 | /* Set all to zero */ 180 | /* 0xC4: pointer to global environment area */ 181 | NVRAM_set_lword(nvram, 0xC4, 0x0100); 182 | /* 0xC8: size of global environment area */ 183 | NVRAM_set_lword(nvram, 0xC8, nvram->size - NVRAM_PREP_OSAREA_SIZE - 184 | NVRAM_PREP_CONFSIZE - 0x0100); 185 | /* 0xD4: pointer to configuration area */ 186 | NVRAM_set_lword(nvram, 0xD4, nvram->size - NVRAM_PREP_CONFSIZE); 187 | /* 0xD8: size of configuration area */ 188 | NVRAM_set_lword(nvram, 0xD8, NVRAM_PREP_CONFSIZE); 189 | /* 0xE8: pointer to OS specific area */ 190 | NVRAM_set_lword(nvram, 0xE8, nvram->size - NVRAM_PREP_CONFSIZE 191 | - NVRAM_PREP_OSAREA_SIZE); 192 | /* 0xD8: size of OS specific area */ 193 | NVRAM_set_lword(nvram, 0xEC, NVRAM_PREP_OSAREA_SIZE); 194 | 195 | /* Configuration area */ 196 | 197 | /* 0x04: checksum 0 => OS area */ 198 | crc = NVRAM_compute_crc(nvram, 0x00, nvram->size - NVRAM_PREP_CONFSIZE - 199 | NVRAM_PREP_OSAREA_SIZE); 200 | NVRAM_set_word(nvram, 0x04, crc); 201 | /* 0x06: checksum of config area */ 202 | crc = NVRAM_compute_crc(nvram, nvram->size - NVRAM_PREP_CONFSIZE, 203 | NVRAM_PREP_CONFSIZE); 204 | NVRAM_set_word(nvram, 0x06, crc); 205 | 206 | return 0; 207 | } 208 | 209 | static uint8_t NVRAM_chrp_chksum (nvram_t *nvram, uint16_t pos) 210 | { 211 | uint16_t sum, end; 212 | 213 | end = pos + 0x10; 214 | sum = NVRAM_get_byte(nvram, pos); 215 | for (pos += 2; pos < end; pos++) { 216 | sum += NVRAM_get_byte(nvram, pos); 217 | } 218 | while (sum > 0xFF) { 219 | sum = (sum & 0xFF) + (sum >> 8); 220 | } 221 | 222 | return sum; 223 | } 224 | 225 | static int NVRAM_chrp_format (unused nvram_t *nvram) 226 | { 227 | uint8_t chksum; 228 | 229 | /* Mark NVRAM as free */ 230 | NVRAM_set_byte(nvram, 0x00, 0x5A); 231 | NVRAM_set_byte(nvram, 0x01, 0x00); 232 | NVRAM_set_word(nvram, 0x02, 0x2000); 233 | NVRAM_set_string(nvram, 0x04, "wwwwwwwwwwww", 12); 234 | chksum = NVRAM_chrp_chksum(nvram, 0x00); 235 | NVRAM_set_byte(nvram, 0x01, chksum); 236 | 237 | return 0; 238 | } 239 | 240 | #if 0 241 | static uint16_t NVRAM_mac99_chksum (nvram_t *nvram, 242 | uint16_t start, uint16_t len) 243 | int cnt; 244 | u32 low, high; 245 | 246 | buffer += CORE99_ADLER_START; 247 | low = 1; 248 | high = 0; 249 | for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) { 250 | if ((cnt % 5000) == 0) { 251 | high %= 65521UL; 252 | high %= 65521UL; 253 | } 254 | low += buffer[cnt]; 255 | high += low; 256 | } 257 | low %= 65521UL; 258 | high %= 65521UL; 259 | 260 | return (high << 16) | low; 261 | { 262 | uint16_t pos; 263 | uint8_t tmp, sum; 264 | 265 | sum = 0; 266 | for (pos = start; pos < (start + len); pos++) { 267 | tmp = sum + NVRAM_get_byte(nvram, pos); 268 | if (tmp < sum) 269 | tmp++; 270 | sum = tmp; 271 | } 272 | 273 | return sum; 274 | } 275 | #endif 276 | 277 | static int NVRAM_mac99_format (nvram_t *nvram) 278 | { 279 | uint8_t chksum; 280 | 281 | /* Mark NVRAM as free */ 282 | NVRAM_set_byte(nvram, 0x00, 0x5A); 283 | NVRAM_set_byte(nvram, 0x01, 0x00); 284 | NVRAM_set_word(nvram, 0x02, 0x2000); 285 | NVRAM_set_string(nvram, 0x04, "wwwwwwwwwwww", 12); 286 | chksum = NVRAM_chrp_chksum(nvram, 0x00); 287 | NVRAM_set_byte(nvram, 0x01, chksum); 288 | 289 | return 0; 290 | } 291 | 292 | static int NVRAM_pop_format (unused nvram_t *nvram) 293 | { 294 | /* TODO */ 295 | return -1; 296 | } 297 | 298 | /* Interface */ 299 | uint8_t NVRAM_read (nvram_t *nvram, uint32_t addr) 300 | { 301 | outb(nvram->io_base + 0x00, addr); 302 | outb(nvram->io_base + 0x01, addr >> 8); 303 | 304 | return inb(NVRAM_IO_BASE + 0x03); 305 | } 306 | 307 | void NVRAM_write (nvram_t *nvram, uint32_t addr, uint8_t value) 308 | { 309 | outb(nvram->io_base + 0x00, addr); 310 | outb(nvram->io_base + 0x01, addr >> 8); 311 | outb(nvram->io_base + 0x03, value); 312 | } 313 | 314 | uint16_t NVRAM_get_size (nvram_t *nvram) 315 | { 316 | return nvram->size; 317 | } 318 | 319 | int NVRAM_format (nvram_t *nvram) 320 | { 321 | int ret; 322 | 323 | { 324 | uint16_t pos; 325 | 326 | for (pos = 0; pos < nvram->size; pos += 4) 327 | NVRAM_set_lword(nvram, pos, 0); 328 | } 329 | switch (arch) { 330 | case ARCH_PREP: 331 | ret = NVRAM_prep_format(nvram); 332 | break; 333 | case ARCH_CHRP: 334 | ret = NVRAM_chrp_format(nvram); 335 | break; 336 | case ARCH_MAC99: 337 | case ARCH_HEATHROW: /* XXX: may be incorrect */ 338 | ret = NVRAM_mac99_format(nvram); 339 | break; 340 | case ARCH_POP: 341 | ret = NVRAM_pop_format(nvram); 342 | break; 343 | default: 344 | ret = -1; 345 | break; 346 | } 347 | 348 | return ret; 349 | } 350 | 351 | /* HACK... */ 352 | extern int vga_width, vga_height, vga_depth; 353 | 354 | static nvram_t global_nvram; 355 | 356 | nvram_t *NVRAM_get_config (uint32_t *RAM_size, int *boot_device, 357 | void **boot_image, uint32_t *boot_size, 358 | void **cmdline, uint32_t *cmdline_size, 359 | void **ramdisk, uint32_t *ramdisk_size) 360 | { 361 | unsigned char sign[16]; 362 | nvram_t *nvram; 363 | uint32_t lword; 364 | uint16_t NVRAM_size, crc; 365 | uint8_t byte; 366 | 367 | #if 0 368 | nvram = malloc(sizeof(nvram_t)); 369 | if (nvram == NULL) 370 | return NULL; 371 | #else 372 | nvram = &global_nvram; 373 | #endif 374 | nvram->io_base = NVRAM_IO_BASE; 375 | /* Pre-initialised NVRAM is not supported any more */ 376 | if (NVRAM_get_string(nvram, sign, 0x00, 0x10) <= 0 || 377 | strcmp(sign, "QEMU_BIOS") != 0) { 378 | ERROR("Wrong NVRAM signature %s\n", sign); 379 | return NULL; 380 | } 381 | /* Check structure version */ 382 | lword = NVRAM_get_lword(nvram, 0x10); 383 | if (lword != 0x00000002) { 384 | ERROR("Wrong NVRAM structure version: %0x\n", lword); 385 | return NULL; 386 | } 387 | /* Check CRC */ 388 | crc = NVRAM_compute_crc(nvram, 0x00, 0xF8); 389 | if (NVRAM_get_word(nvram, 0xFC) != crc) { 390 | ERROR("Invalid NVRAM structure CRC: %0x <=> %0x\n", crc, 391 | NVRAM_get_word(nvram, 0xFC)); 392 | return NULL; 393 | } 394 | NVRAM_size = NVRAM_get_word(nvram, 0x14); 395 | if ((NVRAM_size & 0x100) != 0x00 || NVRAM_size < 0x400 || 396 | NVRAM_size > 0x2000) { 397 | ERROR("Invalid NVRAM size: %d\n", NVRAM_size); 398 | return NULL; 399 | } 400 | nvram->size = NVRAM_size; 401 | if (NVRAM_get_string(nvram, sign, 0x20, 0x10) < 0) { 402 | ERROR("Unable to get architecture from NVRAM\n"); 403 | return NULL; 404 | } 405 | if (strcmp(sign, "PREP") == 0) { 406 | arch = ARCH_PREP; 407 | } else if (strcmp(sign, "CHRP") == 0) { 408 | arch = ARCH_CHRP; 409 | } else if (strcmp(sign, "MAC99") == 0) { 410 | arch = ARCH_MAC99; 411 | } else if (strcmp(sign, "POP") == 0) { 412 | arch = ARCH_POP; 413 | } else if (strcmp(sign, "HEATHROW") == 0) { 414 | arch = ARCH_HEATHROW; 415 | } else { 416 | ERROR("Unknown PPC architecture: '%s'\n", sign); 417 | return NULL; 418 | } 419 | lword = NVRAM_get_lword(nvram, 0x30); 420 | *RAM_size = lword; 421 | byte = NVRAM_get_byte(nvram, 0x34); 422 | *boot_device = byte; 423 | /* Preloaded boot image */ 424 | lword = NVRAM_get_lword(nvram, 0x38); 425 | *boot_image = (void *)lword; 426 | lword = NVRAM_get_lword(nvram, 0x3C); 427 | *boot_size = lword; 428 | /* Preloaded cmdline */ 429 | lword = NVRAM_get_lword(nvram, 0x40); 430 | *cmdline = (void *)lword; 431 | lword = NVRAM_get_lword(nvram, 0x44); 432 | *cmdline_size = lword; 433 | /* Preloaded RAM disk */ 434 | lword = NVRAM_get_lword(nvram, 0x48); 435 | *ramdisk = (void *)lword; 436 | lword = NVRAM_get_lword(nvram, 0x4C); 437 | *ramdisk_size = lword; 438 | /* Preloaded NVRAM image */ 439 | lword = NVRAM_get_lword(nvram, 0x50); 440 | /* Display init geometry */ 441 | lword = NVRAM_get_word(nvram, 0x54); 442 | vga_width = lword; 443 | lword = NVRAM_get_word(nvram, 0x56); 444 | vga_height = lword; 445 | lword = NVRAM_get_word(nvram, 0x58); 446 | vga_depth = lword; 447 | /* TODO: write it into NVRAM */ 448 | 449 | return nvram; 450 | } 451 | -------------------------------------------------------------------------------- /src/vectors.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * Second stage boot-loader and exception vectors for Open Hack'Ware 5 | * linker script 6 | * 7 | * Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr) 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License V2 11 | * as published by the Free Software Foundation 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | OUTPUT_ARCH(powerpc:common) 24 | 25 | MEMORY 26 | { 27 | text (rx) : ORIGIN = 0x00000000, LENGTH = 0x3000 28 | rodata (r) : ORIGIN = 0x00003000, LENGTH = 0x0C00 29 | data (rw) : ORIGIN = 0x00003C00, LENGTH = 0x0200 30 | } 31 | 32 | SECTIONS 33 | { 34 | .text : { *(.text) } > text 35 | .rodata : { *(.rodata) } > rodata 36 | .data : { *(.data) } > data 37 | /DISCARD/ : { *(.bss) } 38 | /DISCARD/ : { *(.sbss) } 39 | /DISCARD/ : { *(.sdata) } 40 | /DISCARD/ : { *(.sdata2) } 41 | /DISCARD/ : { *(.stab) } 42 | /DISCARD/ : { *(.stabstr) } 43 | /DISCARD/ : { *(.comment) } 44 | /DISCARD/ : { *(.note) } 45 | } 46 | -------------------------------------------------------------------------------- /src/vga.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004-2005 Fabrice Bellard 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License V2 6 | * as published by the Free Software Foundation 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | */ 17 | 18 | #include 19 | #include "bios.h" 20 | 21 | /* VGA init. We use the Bochs VESA VBE extensions */ 22 | #define VBE_DISPI_INDEX_ID 0x0 23 | #define VBE_DISPI_INDEX_XRES 0x1 24 | #define VBE_DISPI_INDEX_YRES 0x2 25 | #define VBE_DISPI_INDEX_BPP 0x3 26 | #define VBE_DISPI_INDEX_ENABLE 0x4 27 | #define VBE_DISPI_INDEX_BANK 0x5 28 | #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 29 | #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 30 | #define VBE_DISPI_INDEX_X_OFFSET 0x8 31 | #define VBE_DISPI_INDEX_Y_OFFSET 0x9 32 | #define VBE_DISPI_INDEX_NB 0xa 33 | 34 | #define VBE_DISPI_ID0 0xB0C0 35 | #define VBE_DISPI_ID1 0xB0C1 36 | #define VBE_DISPI_ID2 0xB0C2 37 | 38 | #define VBE_DISPI_DISABLED 0x00 39 | #define VBE_DISPI_ENABLED 0x01 40 | #define VBE_DISPI_LFB_ENABLED 0x40 41 | #define VBE_DISPI_NOCLEARMEM 0x80 42 | 43 | #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 44 | 45 | static void vga_text_init(void); 46 | 47 | unsigned long vga_fb_phys_addr; 48 | int vga_fb_width; 49 | int vga_fb_height; 50 | int vga_fb_linesize; 51 | int vga_fb_bpp; 52 | int vga_fb_depth; 53 | uint8_t rgb_to_index[256]; 54 | 55 | static void vbe_outw(int index, int val) 56 | { 57 | outw(0x1ce, index); 58 | outw(0x1d0, val); 59 | } 60 | 61 | /* init VGA in standard state for PREP boot */ 62 | void vga_prep_init(void) 63 | { 64 | outb(0x3c0, 0x00); /* set blanking */ 65 | vbe_outw(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); 66 | } 67 | 68 | /* build standard RGB palette */ 69 | void vga_build_rgb_palette(void) 70 | { 71 | static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff }; 72 | int i, r, g, b; 73 | 74 | i = 0; 75 | for(r = 0; r < 6; r++) { 76 | for(g = 0; g < 6; g++) { 77 | for(b = 0; b < 6; b++) { 78 | vga_set_palette(i, RGB(pal_value[r], pal_value[g], 79 | pal_value[b])); 80 | i++; 81 | } 82 | } 83 | } 84 | for(i = 0; i < 256; i++) { 85 | rgb_to_index[i] = ((i * 5) + 128) / 255; 86 | } 87 | } 88 | 89 | void vga_set_address (uint32_t address) 90 | { 91 | vga_fb_phys_addr = address; 92 | } 93 | 94 | /* depth = 8, 15, 16 or 32 */ 95 | void vga_set_mode(int width, int height, int depth) 96 | { 97 | vbe_outw(VBE_DISPI_INDEX_XRES, width); 98 | vbe_outw(VBE_DISPI_INDEX_YRES, height); 99 | vbe_outw(VBE_DISPI_INDEX_BPP, depth); 100 | vbe_outw(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED); 101 | outb(0x3c0, 0x20); /* disable blanking */ 102 | 103 | if (vga_fb_phys_addr == 0x00000000) 104 | vga_fb_phys_addr = VBE_DISPI_LFB_PHYSICAL_ADDRESS; 105 | vga_fb_width = width; 106 | vga_fb_height = height; 107 | vga_fb_depth = depth; 108 | vga_fb_bpp = (depth + 7) >> 3; 109 | vga_fb_linesize = width * vga_fb_bpp; 110 | 111 | if (depth == 8) 112 | vga_build_rgb_palette(); 113 | vga_text_init(); 114 | } 115 | 116 | /* for depth = 8 mode, set a hardware palette entry */ 117 | void vga_set_palette(int i, unsigned int rgba) 118 | { 119 | unsigned int r, g, b; 120 | 121 | r = (rgba >> 16) & 0xff; 122 | g = (rgba >> 8) & 0xff; 123 | b = (rgba) & 0xff; 124 | outb(0x3c8, i); 125 | outb(0x3c9, r >> 2); 126 | outb(0x3c9, g >> 2); 127 | outb(0x3c9, b >> 2); 128 | } 129 | 130 | /* convert a RGBA color to a color index usable in graphic primitives */ 131 | unsigned int vga_get_color(unsigned int rgba) 132 | { 133 | unsigned int r, g, b, color; 134 | 135 | switch(vga_fb_depth) { 136 | case 8: 137 | r = (rgba >> 16) & 0xff; 138 | g = (rgba >> 8) & 0xff; 139 | b = (rgba) & 0xff; 140 | color = (rgb_to_index[r] * 6 * 6) + 141 | (rgb_to_index[g] * 6) + 142 | (rgb_to_index[b]); 143 | break; 144 | case 15: 145 | r = (rgba >> 16) & 0xff; 146 | g = (rgba >> 8) & 0xff; 147 | b = (rgba) & 0xff; 148 | color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); 149 | break; 150 | case 16: 151 | r = (rgba >> 16) & 0xff; 152 | g = (rgba >> 8) & 0xff; 153 | b = (rgba) & 0xff; 154 | color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); 155 | break; 156 | case 32: 157 | default: 158 | color = rgba; 159 | break; 160 | } 161 | return color; 162 | } 163 | 164 | void vga_draw_buf (const void *buf, int buf_linesize, 165 | int posx, int posy, int width, int height) 166 | { 167 | const uint8_t *s; 168 | uint8_t *d; 169 | int y, wb; 170 | 171 | s = buf; 172 | d = (uint8_t *)vga_fb_phys_addr + 173 | vga_fb_linesize * posy + vga_fb_bpp * posx; 174 | wb = width * vga_fb_bpp; 175 | for (y = 0; y < height; y++) { 176 | memcpy(d, s, wb); 177 | s += buf_linesize; 178 | d += vga_fb_linesize; 179 | } 180 | } 181 | 182 | void vga_fill_rect (int posx, int posy, int width, int height, uint32_t color) 183 | { 184 | uint8_t *d, *d1; 185 | int x, y; 186 | 187 | d1 = (uint8_t *)vga_fb_phys_addr + 188 | vga_fb_linesize * posy + vga_fb_bpp * posx; 189 | for (y = 0; y < height; y++) { 190 | d = d1; 191 | switch(vga_fb_bpp) { 192 | case 1: 193 | for (x = 0; x < width; x++) { 194 | *((uint8_t *)d) = color; 195 | d++; 196 | } 197 | break; 198 | case 2: 199 | for (x = 0; x < width; x++) { 200 | *((uint16_t *)d) = color; 201 | d += 2; 202 | } 203 | break; 204 | case 4: 205 | for (x = 0; x < width; x++) { 206 | *((uint32_t *)d) = color; 207 | d += 4; 208 | } 209 | break; 210 | } 211 | d1 += vga_fb_linesize; 212 | } 213 | } 214 | 215 | /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */ 216 | void vga_bitblt(int xs, int ys, int xd, int yd, int w, int h) 217 | { 218 | const uint8_t *s; 219 | uint8_t *d; 220 | int wb, y; 221 | 222 | wb = w * vga_fb_bpp; 223 | if (yd <= ys) { 224 | s = (uint8_t *)vga_fb_phys_addr + 225 | vga_fb_linesize * ys + vga_fb_bpp * xs; 226 | d = (uint8_t *)vga_fb_phys_addr + 227 | vga_fb_linesize * yd + vga_fb_bpp * xd; 228 | for (y = 0; y < h; y++) { 229 | memmove(d, s, wb); 230 | d += vga_fb_linesize; 231 | s += vga_fb_linesize; 232 | } 233 | } else { 234 | s = (uint8_t *)vga_fb_phys_addr + 235 | vga_fb_linesize * (ys + h - 1) + vga_fb_bpp * xs; 236 | d = (uint8_t *)vga_fb_phys_addr + 237 | vga_fb_linesize * (yd + h - 1) + vga_fb_bpp * xd; 238 | for (y = 0; y < h; y++) { 239 | memmove(d, s, wb); 240 | d -= vga_fb_linesize; 241 | s -= vga_fb_linesize; 242 | } 243 | } 244 | } 245 | 246 | /***********************************************************/ 247 | /* basic char display */ 248 | 249 | #define FONT_HEIGHT 16 250 | #define FONT_WIDTH 8 251 | 252 | #include "vgafont.h" 253 | 254 | #define cbswap_32(__x) \ 255 | ((uint32_t)( \ 256 | (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ 257 | (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ 258 | (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ 259 | (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) 260 | 261 | /* XXX: endianness */ 262 | #if 0 263 | #define PAT(x) cbswap_32(x) 264 | #else 265 | #define PAT(x) x 266 | #endif 267 | 268 | static const uint32_t dmask16[16] = { 269 | PAT(0x00000000), 270 | PAT(0x000000ff), 271 | PAT(0x0000ff00), 272 | PAT(0x0000ffff), 273 | PAT(0x00ff0000), 274 | PAT(0x00ff00ff), 275 | PAT(0x00ffff00), 276 | PAT(0x00ffffff), 277 | PAT(0xff000000), 278 | PAT(0xff0000ff), 279 | PAT(0xff00ff00), 280 | PAT(0xff00ffff), 281 | PAT(0xffff0000), 282 | PAT(0xffff00ff), 283 | PAT(0xffffff00), 284 | PAT(0xffffffff), 285 | }; 286 | 287 | static const uint32_t dmask4[4] = { 288 | PAT(0x00000000), 289 | PAT(0x0000ffff), 290 | PAT(0xffff0000), 291 | PAT(0xffffffff), 292 | }; 293 | 294 | int text_width, text_height, text_fgcol, text_bgcol, text_x, text_y; 295 | 296 | static void vga_text_init(void) 297 | { 298 | text_width = vga_fb_width / FONT_WIDTH; 299 | text_height = vga_fb_height / FONT_HEIGHT; 300 | text_x = 0; 301 | text_y = 0; 302 | vga_text_set_fgcol(RGB(0xff, 0xff, 0xff)); 303 | vga_text_set_bgcol(RGB(0x00, 0x00, 0x00)); 304 | } 305 | 306 | static inline unsigned int col_expand(unsigned int col) 307 | { 308 | switch(vga_fb_bpp) { 309 | case 1: 310 | col |= col << 8; 311 | col |= col << 16; 312 | break; 313 | case 2: 314 | col |= col << 16; 315 | break; 316 | default: 317 | text_fgcol = 0xffffff; 318 | break; 319 | } 320 | 321 | return col; 322 | } 323 | 324 | void vga_text_set_fgcol(unsigned int rgba) 325 | { 326 | text_fgcol = col_expand(vga_get_color(rgba)); 327 | } 328 | 329 | void vga_text_set_bgcol(unsigned int rgba) 330 | { 331 | text_bgcol = col_expand(vga_get_color(rgba)); 332 | } 333 | 334 | void vga_putcharxy(int x, int y, int ch, 335 | unsigned int fgcol, unsigned int bgcol) 336 | { 337 | uint8_t *d; 338 | const uint8_t *font_ptr; 339 | unsigned int font_data, linesize, xorcol; 340 | int i; 341 | 342 | d = (uint8_t *)vga_fb_phys_addr + 343 | vga_fb_linesize * y * FONT_HEIGHT + vga_fb_bpp * x * FONT_WIDTH; 344 | linesize = vga_fb_linesize; 345 | font_ptr = vgafont16 + FONT_HEIGHT * ch; 346 | xorcol = bgcol ^ fgcol; 347 | switch(vga_fb_depth) { 348 | case 8: 349 | for(i = 0; i < FONT_HEIGHT; i++) { 350 | font_data = *font_ptr++; 351 | ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; 352 | ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; 353 | d += linesize; 354 | } 355 | break; 356 | case 16: 357 | case 15: 358 | for(i = 0; i < FONT_HEIGHT; i++) { 359 | font_data = *font_ptr++; 360 | ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; 361 | ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; 362 | ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; 363 | ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; 364 | d += linesize; 365 | } 366 | break; 367 | case 32: 368 | for(i = 0; i < FONT_HEIGHT; i++) { 369 | font_data = *font_ptr++; 370 | ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; 371 | ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; 372 | ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; 373 | ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; 374 | ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; 375 | ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; 376 | ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; 377 | ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; 378 | d += linesize; 379 | } 380 | break; 381 | } 382 | } 383 | 384 | static void vga_put_lf(void) 385 | { 386 | text_x = 0; 387 | text_y++; 388 | if (text_y >= text_height) { 389 | text_y = text_height - 1; 390 | vga_bitblt(0, FONT_HEIGHT, 0, 0, 391 | text_width * FONT_WIDTH, 392 | (text_height - 1) * FONT_HEIGHT); 393 | vga_fill_rect(0, (text_height - 1) * FONT_HEIGHT, 394 | text_width * FONT_WIDTH, FONT_HEIGHT, text_bgcol); 395 | } 396 | } 397 | 398 | void vga_putchar(int ch) 399 | { 400 | if (ch == '\r') { 401 | text_x = 0; 402 | } else if (ch == '\n') { 403 | vga_put_lf(); 404 | } else if (ch == '\b') { 405 | if (text_x == 0) { 406 | if (text_y != 0) { 407 | text_x = text_width; 408 | text_y--; 409 | goto eat_char; 410 | } 411 | } else { 412 | eat_char: 413 | vga_putcharxy(--text_x, text_y, ' ', text_fgcol, text_bgcol); 414 | } 415 | } else { 416 | vga_putcharxy(text_x, text_y, ch, text_fgcol, text_bgcol); 417 | text_x++; 418 | if (text_x >= text_width) 419 | vga_put_lf(); 420 | } 421 | } 422 | 423 | void vga_puts(const char *s) 424 | { 425 | while (*s) { 426 | vga_putchar(*(uint8_t *)s); 427 | s++; 428 | } 429 | } 430 | --------------------------------------------------------------------------------