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

Reply via email to