This is as far as I was able to get to booting OpenBSD/macppc under qemu. Posting in the hopes that it will be useful to someone, or motivate someone who understands PCI better than I do to give me a nudge in the right direction.
- Take the OpenHack'Ware 0.4.1 tarball. - Apply the patch from qemu/pc-bios/ohw.diff. - Apply the patch attached to this message. - Unpack a zlib 1.2.3 tarball and rename it to src/libz in OHW. - Get a powerpc-linux cross compiler. - Build OHW by 'make CROSS_COMPILE=powerpc-linux-'. - Point qemu at the build copy with an appropriate -L option. - Boot qemu like this: ./obj/ppc-softmmu/qemu-system-ppc -hda openbsd.img -cdrom cd40.iso \ -L OpenHackWare-release-0.4 -boot d -M mac99 You can get cd40.iso off of ftp.openbsd.org. I added zlib support, because the OpenBSD boot image is compressed ELF. It's not pretty, but that part works fine. I also made it work with my 4.1-based compiler, fixed a cosmetic bug in printf, and provided /memory/available since OpenBSD relies on it. Right now it hangs initializing ADB. The Cuda starts starts out at 0x80896000, then moves to 0x80816000 at some point during PCI initialization. OpenBSD stalls trying to get a response from it at the first address when qemu thinks it's at the second address. I don't know where it's supposed to be, but I would guess this is a problem in the emulation of the PCI controller. The console is a bit messed up too. -M g3bw: Seems to be the same. The console doesn't stop updating earlier in the boot, so something is a tiny bit happier, but cuda still gets stuck. -M prep: doesn't check for ADB, so doesn't hang there. Crashes later. Not sure where, GDB couldn't backtrace far enough. -- Daniel Jacobowitz CodeSourcery
diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/Makefile OpenHackWare-release-0.4/Makefile --- orig/OpenHackWare-release-0.4/Makefile 2005-03-31 02:23:33.000000000 -0500 +++ OpenHackWare-release-0.4/Makefile 2007-03-11 00:13:36.000000000 -0500 @@ -44,6 +44,7 @@ DISTDIR:= . SRCDIR:= src CC_BASE:= $(shell $(CC) -print-search-dirs | grep install | sed -e 's/.*\ //') +CC_BASE:= $(shell $(CC) -print-file-name=include | sed -e 's,/include$$,,') CFLAGS= -Wall -W -Werror -O2 -g -fno-builtin -fno-common -nostdinc -mregnames CFLAGS+= -DBUILD_DATE=$(BUILD_DATE) -DBUILD_TIME=$(BUILD_TIME) CFLAGS+= -I$(SRCDIR)/ -I$(SRCDIR)/libc/include -I$(CC_BASE)/include @@ -97,6 +98,9 @@ main.out_OBJS+= $(addprefix $(OBJDIR)/, # libexec objects libexec_OBJS:= core.o elf.o xcoff.o macho.o chrp.o prep.o pef.o main.out_OBJS+= $(addprefix $(OBJDIR)/exec_, $(libexec_OBJS)) +# libz objects +libz_OBJS:= inflate.o adler32.o crc32.o inftrees.o inffast.o zutil.o +main.out_OBJS+= $(addprefix $(OBJDIR)/z_, $(libz_OBJS)) # libfs objects libfs_OBJS:= core.o raw.o ext2.o isofs.o hfs.o main.out_OBJS+= $(addprefix $(OBJDIR)/fs_, $(libfs_OBJS)) @@ -207,6 +211,11 @@ $(OBJDIR)/exec_%.o: $(SRCDIR)/libexec/%. @$(DEBUG) "CFLAGS = $(CFLAGS)" $(CC) -c $(CFLAGS) -o $@ $< +# libz objects +$(OBJDIR)/z_%.o: $(SRCDIR)/libz/%.c + @$(DEBUG) "CFLAGS = $(CFLAGS)" + $(CC) -c $(CFLAGS) -DZ_PREFIX -o $@ $< + # libfs objects $(OBJDIR)/fs_%.o: $(SRCDIR)/libfs/%.c @$(DEBUG) "CFLAGS = $(CFLAGS)" diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/bios.h OpenHackWare-release-0.4/src/bios.h --- orig/OpenHackWare-release-0.4/src/bios.h 2007-03-11 17:57:00.000000000 -0400 +++ OpenHackWare-release-0.4/src/bios.h 2007-03-09 10:54:00.000000000 -0500 @@ -22,7 +22,7 @@ #define __BIOS_H__ #define USE_OPENFIRMWARE -//#define DEBUG_BIOS 1 +#define DEBUG_BIOS 1 #define BIOS_VERSION "0.4.1" diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/libc/include/limits.h OpenHackWare-release-0.4/src/libc/include/limits.h --- orig/OpenHackWare-release-0.4/src/libc/include/limits.h 1969-12-31 19:00:00.000000000 -0500 +++ OpenHackWare-release-0.4/src/libc/include/limits.h 2007-03-10 23:48:30.000000000 -0500 @@ -0,0 +1 @@ +/* empty for now? */ diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/libc/src/format.c OpenHackWare-release-0.4/src/libc/src/format.c --- orig/OpenHackWare-release-0.4/src/libc/src/format.c 2005-03-31 02:23:33.000000000 -0500 +++ OpenHackWare-release-0.4/src/libc/src/format.c 2007-03-11 10:48:34.000000000 -0400 @@ -187,7 +187,7 @@ static size_t outhex (outf_t outf, void } } if (fill > 0) - fill -= pos - 7; + fill -= 7 - pos; for (; fill != 0 && pos != (size_t)-1; fill--) { buffer[pos--] = '0'; } diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/libexec/chrp.c OpenHackWare-release-0.4/src/libexec/chrp.c --- orig/OpenHackWare-release-0.4/src/libexec/chrp.c 2005-03-31 02:23:33.000000000 -0500 +++ OpenHackWare-release-0.4/src/libexec/chrp.c 2007-03-09 10:54:54.000000000 -0500 @@ -169,7 +169,7 @@ int exec_load_chrp (inode_t *file, void case CHRP_TAG_BOOT_SCRIPT: /* Here is the interresting part... */ crc = crc32(0, tag->data, tag->dlen); -#if 0 +#if 1 DPRINTF("Forth script: %08x\n%s\n", crc, (char *)tag->data); #endif @@ -207,6 +207,8 @@ int exec_load_chrp (inode_t *file, void /* OpenBSD 3.5 */ case 0x3b7ea9e1: /* OpenBSD 3.6 */ + case 0xd67495a2: + /* OpenBSD 4.0 */ script_type = CHRP_SCRIPT_LOAD_BOOT; goto do_script; case 0xB7981DBC: diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/libexec/core.c OpenHackWare-release-0.4/src/libexec/core.c --- orig/OpenHackWare-release-0.4/src/libexec/core.c 2005-03-31 02:23:33.000000000 -0500 +++ OpenHackWare-release-0.4/src/libexec/core.c 2007-03-11 10:34:11.000000000 -0400 @@ -43,6 +43,7 @@ uint32_t file_seek (inode_t *file, uint3 enum { FILE_TYPE_ELF = 0, + FILE_TYPE_ZELF, FILE_TYPE_XCOFF, FILE_TYPE_MACHO, FILE_TYPE_PEF, @@ -73,6 +74,9 @@ int _bootfile_load (inode_t *file, void case FILE_TYPE_ELF: do_load = &exec_load_elf; break; + case FILE_TYPE_ZELF: + do_load = &exec_load_zelf; + break; case FILE_TYPE_XCOFF: do_load = &exec_load_xcoff; break; diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/libexec/elf.c OpenHackWare-release-0.4/src/libexec/elf.c --- orig/OpenHackWare-release-0.4/src/libexec/elf.c 2005-03-31 02:23:33.000000000 -0500 +++ OpenHackWare-release-0.4/src/libexec/elf.c 2007-03-11 10:58:53.000000000 -0400 @@ -23,6 +23,8 @@ #include <stdio.h> #include "bios.h" #include "exec.h" +#define Z_PREFIX +#include "libz/zlib.h" uint32_t fs_inode_get_size (inode_t *inode); @@ -237,3 +239,173 @@ int exec_load_elf (inode_t *file, void * return 0; } + +int exec_load_zelf (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset) +{ + Elf32_Ehdr_t ehdr; + Elf32_Phdr_t phdr; + void *address, *first, *last; + uint32_t offset, fsize, msize, toffset, poffset, remaining, tbytes; + int i, ret; + unsigned char zbuf[4096], buf[4096], tbuf[4096]; + z_stream zs; + + file_seek(file, loffset); + memset(&zs, 0, sizeof(zs)); + zs.avail_in = fs_read(file, zbuf, sizeof(zbuf)); + if ((unsigned long) zs.avail_in > sizeof(zbuf)) { + ERROR("Cannot load first bloc of file...\n"); + return -1; + } + DPRINTF("Check compression of %d bytes\n", zs.avail_in); + DPRINTF("Bytes %02x %02x %02x %02x\n", zbuf[0], zbuf[1], zbuf[2], zbuf[3]); + zs.next_in = zbuf; + zs.next_out = buf; + zs.avail_out = 4096; + if (inflateInit2(&zs, 15 + 16) != Z_OK) { + DPRINTF("Not a compressed file init: %s\n", zs.msg ? zs.msg : "unknown"); + inflateEnd(&zs); + return -2; + } + ret = inflate(&zs, Z_SYNC_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { + DPRINTF("Not a compressed file inflate: %s\n", zs.msg ? zs.msg : "unknown"); + inflateEnd(&zs); + return -2; + } + DPRINTF("Check ELF file\n"); + /* Check ident */ + memcpy(&ehdr, buf, sizeof(Elf32_Ehdr_t)); + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || + ehdr.e_ident[EI_MAG1] != ELFMAG1 || + ehdr.e_ident[EI_MAG2] != ELFMAG2 || + ehdr.e_ident[EI_MAG3] != ELFMAG3) { + DPRINTF("Not an ELF file %0x\n", *(uint32_t *)ehdr.e_ident); + inflateEnd(&zs); + return -2; + } + if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { + ERROR("Not a 32 bits ELF file\n"); + inflateEnd(&zs); + return -2; + } + if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB) { + ERROR("Not a big-endian ELF file\n"); + inflateEnd(&zs); + return -2; + } + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT /*|| + ehdr->e_version != EV_CURRENT*/) { + ERROR("Invalid ELF executable version %d %08x\n", + ehdr.e_ident[EI_VERSION], ehdr.e_version); + inflateEnd(&zs); + return -2; + } + if (ehdr.e_type != ET_EXEC) { + ERROR("Not an executable ELF file\n"); + inflateEnd(&zs); + return -2; + } + if (ehdr.e_machine != EM_PPC) { + ERROR("Not a PPC ELF executable\n"); + inflateEnd(&zs); + return -2; + } + /* All right, seems to be a regular ELF program for PPC */ + *entry = (void *)ehdr.e_entry; + DPRINTF("ELF file found entry = %p\n", *entry); + last = NULL; + first = last - 4; + fsize = msize = 0; + offset = ehdr.e_phoff; + toffset = 0; + memcpy(tbuf, buf, sizeof(tbuf)); + tbytes = zs.total_out; + for (i = 0; i < ehdr.e_phnum; i++) { + DPRINTF("Load program header %d from %08x\n", i, offset); + if (offset + sizeof(Elf32_Phdr_t) > sizeof(buf)) { + ERROR("Program header out of range at %d\n", offset); + inflateEnd(&zs); + return -1; + } + memcpy (&phdr, buf + offset, sizeof(Elf32_Phdr_t)); + DPRINTF("Load program header %d %08x %08x %08x %08x\n", i, + phdr.p_offset, phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz); + /* As we won't remap memory, load it at it's virtual address (!) */ + address = (void *)phdr.p_vaddr; + if (address < first) + first = address; + fsize = phdr.p_filesz; + msize = phdr.p_memsz; + if (address + msize > last) + last = address + msize; + if (phdr.p_offset < toffset) { + ERROR("Program header %d went backwards\n", i); + inflateEnd(&zs); + return -1; + } + poffset = phdr.p_offset; + remaining = fsize; + while (remaining > 0) { + if (poffset >= toffset && poffset < toffset + tbytes) { + /* Consume everything in the output buffer. */ + uint32_t bytes = tbytes + toffset - poffset; + if (bytes > remaining) + bytes = remaining; + + DPRINTF("Copying %d bytes from %08x to %08x\n", bytes, + poffset - toffset, address + poffset - phdr.p_offset); + memcpy (address + poffset - phdr.p_offset, + tbuf + poffset - toffset, bytes); + remaining -= bytes; + poffset += bytes; + if (remaining == 0) + break; + } + + if (zs.avail_in == 0) { + /* Refill input. */ + DPRINTF("Refilling, already read %d\n", zs.total_in); + file_seek(file, loffset + zs.total_in); + zs.avail_in = fs_read(file, zbuf, sizeof(zbuf)); + DPRINTF("Refilling input, got %d bytes\r\n", zs.avail_in); + DPRINTF("Bytes %02x %02x %02x %02x\n", zbuf[0], zbuf[1], zbuf[2], zbuf[3]); + if ((unsigned long) zs.avail_in > sizeof(zbuf)) { + ERROR("Cannot load ELF program %d...\n", i); + inflateEnd(&zs); + return -1; + } + zs.next_in = zbuf; + } + + /* Refill output. */ + toffset += tbytes; + zs.next_out = tbuf; + zs.avail_out = sizeof(tbuf); + ret = inflate(&zs, Z_SYNC_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { + ERROR("Failed inflate: %s\n", zs.msg ? zs.msg : "unknown"); + inflateEnd(&zs); + return -1; + } + tbytes = sizeof(tbuf) - zs.avail_out; + } + + set_loadinfo((void *)first, last - first); + if (msize > fsize) { + memset(address + fsize, 0, msize - fsize); + } + offset += ehdr.e_phentsize; + } + inflateEnd(&zs); + + *dest = (void *)first; + *end = (void *)last; + DPRINTF("ELF file loaded at %p => %p fsize %08x msize %08x " + "(%08x %08x)\n", *dest, *entry, fsize, msize, + *(uint32_t *)entry, *((uint32_t *)entry + 1)); + inflateEnd(&zs); + + return 0; +} diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/libexec/exec.h OpenHackWare-release-0.4/src/libexec/exec.h --- orig/OpenHackWare-release-0.4/src/libexec/exec.h 2005-03-31 02:23:33.000000000 -0500 +++ OpenHackWare-release-0.4/src/libexec/exec.h 2007-03-11 10:12:53.000000000 -0400 @@ -26,6 +26,8 @@ int _bootfile_load (inode_t *file, void uint32_t loffset, int type); int exec_load_elf (inode_t *file, void **dest, void **entry, void **end, uint32_t loffset); +int exec_load_zelf (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset); int exec_load_xcoff (inode_t *file, void **dest, void **entry, void **end, uint32_t loffset); int exec_load_macho (inode_t *file, void **dest, void **entry, void **end, diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/main.ld OpenHackWare-release-0.4/src/main.ld --- orig/OpenHackWare-release-0.4/src/main.ld 2005-03-31 02:23:33.000000000 -0500 +++ OpenHackWare-release-0.4/src/main.ld 2007-03-09 10:49:59.000000000 -0500 @@ -49,7 +49,7 @@ SECTIONS _sdata_end = . ; . = ALIGN(4) ; _ro_start = . ; - .rodata : { *(.rodata) } > bios + .rodata : { *(.rodata*) } > bios _ro_end = . ; . = ALIGN(4) ; _RTAS_start = .; diff -N -x libz -x video.x -x ppc_rom.bin -x .objs -urp orig/OpenHackWare-release-0.4/src/of.c OpenHackWare-release-0.4/src/of.c --- orig/OpenHackWare-release-0.4/src/of.c 2007-03-11 17:57:00.000000000 -0400 +++ OpenHackWare-release-0.4/src/of.c 2007-03-11 12:23:55.000000000 -0400 @@ -1970,10 +1970,11 @@ int OF_register_memory (uint32_t memsize regs[3].address = 0x00000000; regs[3].size = 0x00000000; OF_property_new(OF_env, mem, "reg", regs, 4 * sizeof(OF_regprop_t)); -#if 0 #if 1 - regs[0].address = 0x00000000; - regs[0].size = 0x05800000; +#if 1 + /* Remove 0x3000 for the interrupt table. */ + regs[0].address = 0x00003000; + regs[0].size = 0x05800000 - 0x3000; regs[1].address = 0x06000000; regs[1].size = memsize - 0x06000000; regs[2].address = 0x00000000; @@ -3101,8 +3102,8 @@ static void OF_serial_write (OF_env_t *O /* XXX: should use directly the serial port * and have another console package. */ - console_write(str, len); - pushd(OF_env, 0); + len = console_write(str, len); + pushd(OF_env, len); } static void OF_serial_read (OF_env_t *OF_env)
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel