aboutsummaryrefslogtreecommitdiffstats
path: root/pc-bios
diff options
context:
space:
mode:
authorUpstream <upstream-import@none>1970-01-12 13:46:40 +0000
committerUpstream <upstream-import@none>1970-01-12 13:46:40 +0000
commit413f05aaf54fa08c0ae7e997327a4f4a473c0a8d (patch)
tree642d637ab01ee6c54ca27d1fa96cf92a32df8053 /pc-bios
downloadexternal_qemu-413f05aaf54fa08c0ae7e997327a4f4a473c0a8d.zip
external_qemu-413f05aaf54fa08c0ae7e997327a4f4a473c0a8d.tar.gz
external_qemu-413f05aaf54fa08c0ae7e997327a4f4a473c0a8d.tar.bz2
external/qemu 0.8.2
Diffstat (limited to 'pc-bios')
-rw-r--r--pc-bios/Makefile24
-rw-r--r--pc-bios/README16
-rw-r--r--pc-bios/bios.binbin0 -> 65536 bytes
-rw-r--r--pc-bios/bios.diff270
-rw-r--r--pc-bios/linux_boot.S29
-rw-r--r--pc-bios/linux_boot.binbin0 -> 512 bytes
-rw-r--r--pc-bios/ohw.diff1843
-rw-r--r--pc-bios/openbios-sparc32bin0 -> 506966 bytes
-rw-r--r--pc-bios/ppc_rom.binbin0 -> 524288 bytes
-rw-r--r--pc-bios/vgabios-cirrus.binbin0 -> 35328 bytes
-rw-r--r--pc-bios/vgabios.binbin0 -> 37888 bytes
-rw-r--r--pc-bios/vgabios.diff896
-rw-r--r--pc-bios/video.xbin0 -> 12192 bytes
13 files changed, 3078 insertions, 0 deletions
diff --git a/pc-bios/Makefile b/pc-bios/Makefile
new file mode 100644
index 0000000..7ae0ff0
--- /dev/null
+++ b/pc-bios/Makefile
@@ -0,0 +1,24 @@
+#
+# NOTE: only compilable with x86 cross compile tools
+#
+include ../config-host.mak
+
+DEFINES=
+
+TARGETS=
+ifeq ($(ARCH),i386)
+TARGETS+=linux_boot.bin
+endif
+
+all: $(TARGETS)
+
+linux_boot.bin: linux_boot.o
+ ld --oformat binary -Ttext 0 -o $@ $<
+ chmod a-x $@
+
+%.o: %.S
+ $(CC) $(DEFINES) -c -o $@ $<
+
+clean:
+ rm -f $(TARGETS) *.o *~
+
diff --git a/pc-bios/README b/pc-bios/README
new file mode 100644
index 0000000..fc85eb4
--- /dev/null
+++ b/pc-bios/README
@@ -0,0 +1,16 @@
+- The PC BIOS comes from the Bochs project
+ (http://bochs.sourceforge.net/). A patch from bios.diff was applied.
+
+- The VGA BIOS and the Cirrus VGA BIOS come from the LGPL VGA bios
+ project (http://www.nongnu.org/vgabios/).
+
+- The PowerPC Open Hack'Ware Open Firmware Compatible BIOS is
+ available at http://perso.magic.fr/l_indien/OpenHackWare/index.htm.
+
+- video.x is a PowerMac NDRV compatible driver for a VGA frame
+ buffer. It comes from the Mac-on-Linux project
+ (http://www.maconlinux.org/).
+
+- OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
+ firmware implementation. The goal is to implement a 100% IEEE
+ 1275-1994 (referred to as Open Firmware) compliant firmware.
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
new file mode 100644
index 0000000..64be517
--- /dev/null
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/pc-bios/bios.diff b/pc-bios/bios.diff
new file mode 100644
index 0000000..e875927
--- /dev/null
+++ b/pc-bios/bios.diff
@@ -0,0 +1,270 @@
+Index: apmbios.S
+===================================================================
+RCS file: /cvsroot/bochs/bochs/bios/apmbios.S,v
+retrieving revision 1.4
+diff -u -w -r1.4 apmbios.S
+--- apmbios.S 26 Dec 2005 10:35:51 -0000 1.4
++++ apmbios.S 3 May 2006 21:22:46 -0000
+@@ -225,6 +225,7 @@
+ APMSYM(05):
+ cmp al, #0x05
+ jne APMSYM(07)
++ sti
+ hlt
+ jmp APMSYM(ok)
+
+Index: rombios.c
+===================================================================
+RCS file: /cvsroot/bochs/bochs/bios/rombios.c,v
+retrieving revision 1.160
+diff -u -w -r1.160 rombios.c
+--- rombios.c 25 Jan 2006 17:51:49 -0000 1.160
++++ rombios.c 3 May 2006 21:22:48 -0000
+@@ -1816,6 +1816,7 @@
+ {
+ printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
+ BIOS_BUILD_DATE, bios_cvs_version_string);
++#if 0
+ printf(
+ #ifdef BX_APM
+ "apmbios "
+@@ -1827,6 +1828,9 @@
+ "eltorito "
+ #endif
+ "\n\n");
++#else
++ printf("apmbios pcibios eltorito \n\n");
++#endif
+ }
+
+ //--------------------------------------------------------------------------
+@@ -3999,6 +4003,29 @@
+ }
+ #endif
+
++
++void set_e820_range(ES, DI, start, end, type)
++ Bit16u ES;
++ Bit16u DI;
++ Bit32u start;
++ Bit32u end;
++ Bit16u type;
++{
++ write_word(ES, DI, start);
++ write_word(ES, DI+2, start >> 16);
++ write_word(ES, DI+4, 0x00);
++ write_word(ES, DI+6, 0x00);
++
++ end -= start;
++ write_word(ES, DI+8, end);
++ write_word(ES, DI+10, end >> 16);
++ write_word(ES, DI+12, 0x0000);
++ write_word(ES, DI+14, 0x0000);
++
++ write_word(ES, DI+16, type);
++ write_word(ES, DI+18, 0x0);
++}
++
+ void
+ int15_function32(regs, ES, DS, FLAGS)
+ pushad_regs_t regs; // REGS pushed via pushad
+@@ -4063,19 +4090,8 @@
+ switch(regs.u.r16.bx)
+ {
+ case 0:
+- write_word(ES, regs.u.r16.di, 0x00);
+- write_word(ES, regs.u.r16.di+2, 0x00);
+- write_word(ES, regs.u.r16.di+4, 0x00);
+- write_word(ES, regs.u.r16.di+6, 0x00);
+-
+- write_word(ES, regs.u.r16.di+8, 0xFC00);
+- write_word(ES, regs.u.r16.di+10, 0x0009);
+- write_word(ES, regs.u.r16.di+12, 0x0000);
+- write_word(ES, regs.u.r16.di+14, 0x0000);
+-
+- write_word(ES, regs.u.r16.di+16, 0x1);
+- write_word(ES, regs.u.r16.di+18, 0x0);
+-
++ set_e820_range(ES, regs.u.r16.di,
++ 0x0000000L, 0x0009fc00L, 1);
+ regs.u.r32.ebx = 1;
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+@@ -4083,6 +4099,24 @@
+ return;
+ break;
+ case 1:
++ set_e820_range(ES, regs.u.r16.di,
++ 0x0009fc00L, 0x000a0000L, 2);
++ regs.u.r32.ebx = 2;
++ regs.u.r32.eax = 0x534D4150;
++ regs.u.r32.ecx = 0x14;
++ CLEAR_CF();
++ return;
++ break;
++ case 2:
++ set_e820_range(ES, regs.u.r16.di,
++ 0x000e8000L, 0x00100000L, 2);
++ regs.u.r32.ebx = 3;
++ regs.u.r32.eax = 0x534D4150;
++ regs.u.r32.ecx = 0x14;
++ CLEAR_CF();
++ return;
++ break;
++ case 3:
+ extended_memory_size = inb_cmos(0x35);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x34);
+@@ -4092,9 +4126,9 @@
+ extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
+ }
+ extended_memory_size *= 1024;
+- extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off
++ extended_memory_size += (16L * 1024 * 1024);
+
+- if(extended_memory_size <= 15728640)
++ if(extended_memory_size <= (16L * 1024 * 1024))
+ {
+ extended_memory_size = inb_cmos(0x31);
+ extended_memory_size <<= 8;
+@@ -4102,28 +4136,23 @@
+ extended_memory_size *= 1024;
+ }
+
+- write_word(ES, regs.u.r16.di, 0x0000);
+- write_word(ES, regs.u.r16.di+2, 0x0010);
+- write_word(ES, regs.u.r16.di+4, 0x0000);
+- write_word(ES, regs.u.r16.di+6, 0x0000);
+-
+- write_word(ES, regs.u.r16.di+8, extended_memory_size);
+- extended_memory_size >>= 16;
+- write_word(ES, regs.u.r16.di+10, extended_memory_size);
+- extended_memory_size >>= 16;
+- write_word(ES, regs.u.r16.di+12, extended_memory_size);
+- extended_memory_size >>= 16;
+- write_word(ES, regs.u.r16.di+14, extended_memory_size);
+-
+- write_word(ES, regs.u.r16.di+16, 0x1);
+- write_word(ES, regs.u.r16.di+18, 0x0);
+-
+- regs.u.r32.ebx = 0;
++ set_e820_range(ES, regs.u.r16.di,
++ 0x00100000L, extended_memory_size, 1);
++ regs.u.r32.ebx = 4;
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
+ return;
+ break;
++ case 4:
++ /* 256KB BIOS area at the end of 4 GB */
++ set_e820_range(ES, regs.u.r16.di,
++ 0xfffc0000L, 0x00000000L, 2);
++ regs.u.r32.ebx = 0;
++ regs.u.r32.eax = 0x534D4150;
++ regs.u.r32.ecx = 0x14;
++ CLEAR_CF();
++ return;
+ default: /* AX=E820, DX=534D4150, BX unrecognized */
+ goto int15_unimplemented;
+ break;
+@@ -8713,6 +8742,7 @@
+ mov al, #0x80
+ bios32_end:
+ popf
++ and dword ptr[esp+4],0xfffffffc ;; reset CS.RPL for kqemu
+ retf
+
+ .align 16
+@@ -8823,17 +8853,17 @@
+ pci_pro_fail:
+ pop edi
+ pop esi
+- sti
+ popf
+ stc
++ and dword ptr[esp+4],0xfffffffc ;; reset CS.RPL for kqemu
+ retf
+ pci_pro_ok:
+ xor ah, ah
+ pop edi
+ pop esi
+- sti
+ popf
+ clc
++ and dword ptr[esp+4],0xfffffffc ;; reset CS.RPL for kqemu
+ retf
+
+ pci_pro_select_reg:
+@@ -8971,7 +9001,7 @@
+ jmp pci_real_ok
+ pci_real_f0d: ;; write configuration dword
+ cmp al, #0x0d
+- jne pci_real_unknown
++ jne pci_real_f0e
+ call pci_real_select_reg
+ push dx
+ mov dx, #0x0cfc
+@@ -8979,6 +9009,46 @@
+ out dx, eax
+ pop dx
+ jmp pci_real_ok
++pci_real_f0e: ;; get irq routing options
++ cmp al, #0x0e
++ jne pci_real_unknown
++ SEG ES
++ cmp word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
++ jb pci_real_too_small
++ SEG ES
++ mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
++ pushf
++ push ds
++ push es
++ push cx
++ push si
++ push di
++ cld
++ mov si, #pci_routing_table_structure_start
++ push cs
++ pop ds
++ SEG ES
++ mov cx, [di+2]
++ SEG ES
++ mov es, [di+4]
++ mov di, cx
++ mov cx, #pci_routing_table_structure_end - pci_routing_table_structure_start
++ rep
++ movsb
++ pop di
++ pop si
++ pop cx
++ pop es
++ pop ds
++ popf
++ mov bx, #(1 << 9) | (1 << 11) ;; irq 9 and 11 are used
++ jmp pci_real_ok
++pci_real_too_small:
++ SEG ES
++ mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
++ mov ah, #0x89
++ jmp pci_real_fail
++
+ pci_real_unknown:
+ mov ah, #0x81
+ pci_real_fail:
+@@ -9019,6 +9089,7 @@
+ dw 0,0 ;; Miniport data
+ db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved
+ db 0x07 ;; checksum
++pci_routing_table_structure_start:
+ ;; first slot entry PCI-to-ISA (embedded)
+ db 0 ;; pci bus number
+ db 0x08 ;; pci device number (bit 7-3)
+@@ -9097,6 +9168,7 @@
+ dw 0xdef8 ;; IRQ bitmap INTD#
+ db 5 ;; physical slot (0 = embedded)
+ db 0 ;; reserved
++pci_routing_table_structure_end:
+
+ pci_irq_list:
+ db 11, 10, 9, 5;
diff --git a/pc-bios/linux_boot.S b/pc-bios/linux_boot.S
new file mode 100644
index 0000000..22fcd4b
--- /dev/null
+++ b/pc-bios/linux_boot.S
@@ -0,0 +1,29 @@
+/*
+ * QEMU Boot sector to launch a preloaded Linux kernel
+ * Copyright (c) 2004 Fabrice Bellard
+ */
+
+#define LOAD_SEG 0x9000
+
+.code16
+.text
+ .globl _start
+
+_start:
+ cli
+ cld
+ mov $LOAD_SEG, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+ mov $0x8ffe, %sp
+ ljmp $LOAD_SEG + 0x20, $0
+
+1:
+ .fill 510 - (1b - _start), 1, 0
+
+ /* boot sector signature */
+ .byte 0x55
+ .byte 0xaa
diff --git a/pc-bios/linux_boot.bin b/pc-bios/linux_boot.bin
new file mode 100644
index 0000000..80f7b5f
--- /dev/null
+++ b/pc-bios/linux_boot.bin
Binary files differ
diff --git a/pc-bios/ohw.diff b/pc-bios/ohw.diff
new file mode 100644
index 0000000..4fb5422
--- /dev/null
+++ b/pc-bios/ohw.diff
@@ -0,0 +1,1843 @@
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/bios.h OpenHackWare-release-0.4/src/bios.h
+--- OpenHackWare-release-0.4.org/src/bios.h 2005-04-06 23:20:22.000000000 +0200
++++ OpenHackWare-release-0.4/src/bios.h 2005-07-07 01:10:20.000000000 +0200
+@@ -64,6 +64,7 @@
+ ARCH_CHRP,
+ ARCH_MAC99,
+ ARCH_POP,
++ ARCH_HEATHROW,
+ };
+
+ /* Hardware definition(s) */
+@@ -174,6 +175,7 @@
+ int bd_ioctl (bloc_device_t *bd, int func, void *args);
+ uint32_t bd_seclen (bloc_device_t *bd);
+ void bd_close (bloc_device_t *bd);
++void bd_reset_all(void);
+ uint32_t bd_seclen (bloc_device_t *bd);
+ uint32_t bd_maxbloc (bloc_device_t *bd);
+ void bd_sect2CHS (bloc_device_t *bd, uint32_t secnum,
+@@ -183,12 +185,12 @@
+ part_t *bd_probe (int boot_device);
+ bloc_device_t *bd_get (int device);
+ void bd_put (bloc_device_t *bd);
+-void bd_set_boot_part (bloc_device_t *bd, part_t *partition);
++void bd_set_boot_part (bloc_device_t *bd, part_t *partition, int partnum);
+ part_t **_bd_parts (bloc_device_t *bd);
+
+ void ide_pci_pc_register (uint32_t io_base0, uint32_t io_base1,
+ uint32_t io_base2, uint32_t io_base3,
+- void *OF_private);
++ void *OF_private0, void *OF_private1);
+ void ide_pci_pmac_register (uint32_t io_base0, uint32_t io_base1,
+ void *OF_private);
+
+@@ -399,17 +401,23 @@
+ uint16_t min_grant, uint16_t max_latency);
+ void OF_finalize_pci_host (void *dev, int first_bus, int nb_busses);
+ void OF_finalize_pci_device (void *dev, uint8_t bus, uint8_t devfn,
+- uint32_t *regions, uint32_t *sizes);
++ uint32_t *regions, uint32_t *sizes,
++ int irq_line);
+ void OF_finalize_pci_macio (void *dev, uint32_t base_address, uint32_t size,
+ void *private_data);
++void OF_finalize_pci_ide (void *dev,
++ uint32_t io_base0, uint32_t io_base1,
++ uint32_t io_base2, uint32_t io_base3);
+ int OF_register_bus (const unsigned char *name, uint32_t address,
+ const unsigned char *type);
+ int OF_register_serial (const unsigned char *bus, const unsigned char *name,
+ uint32_t io_base, int irq);
+ int OF_register_stdio (const unsigned char *dev_in,
+ const unsigned char *dev_out);
+-void OF_vga_register (const unsigned char *name, uint32_t address,
+- int width, int height, int depth);
++void OF_vga_register (const unsigned char *name, unused uint32_t address,
++ int width, int height, int depth,
++ unsigned long vga_bios_addr,
++ unsigned long vga_bios_size);
+ void *OF_blockdev_register (void *parent, void *private,
+ const unsigned char *type,
+ const unsigned char *name, int devnum,
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/bloc.c OpenHackWare-release-0.4/src/bloc.c
+--- OpenHackWare-release-0.4.org/src/bloc.c 2005-04-06 23:21:00.000000000 +0200
++++ OpenHackWare-release-0.4/src/bloc.c 2005-07-08 00:28:26.000000000 +0200
+@@ -55,6 +55,7 @@
+ /* Partitions */
+ part_t *parts, *bparts;
+ part_t *boot_part;
++ int bpartnum;
+ /* Chain */
+ bloc_device_t *next;
+ };
+@@ -66,6 +67,7 @@
+
+ static int ide_initialize (bloc_device_t *bd, int device);
+ static int ide_read_sector (bloc_device_t *bd, void *buffer, int secnum);
++static int ide_reset (bloc_device_t *bd);
+
+ static int mem_initialize (bloc_device_t *bd, int device);
+ static int mem_read_sector (bloc_device_t *bd, void *buffer, int secnum);
+@@ -212,6 +214,17 @@
+ {
+ }
+
++void bd_reset_all(void)
++{
++ bloc_device_t *bd;
++ for (bd = bd_list; bd != NULL; bd = bd->next) {
++ if (bd->init == &ide_initialize) {
++ /* reset IDE drive because Darwin wants all IDE devices to be reset */
++ ide_reset(bd);
++ }
++ }
++}
++
+ uint32_t bd_seclen (bloc_device_t *bd)
+ {
+ return bd->seclen;
+@@ -223,10 +236,12 @@
+ }
+
+ /* XXX: to be suppressed */
+-void bd_set_boot_part (bloc_device_t *bd, part_t *partition)
++void bd_set_boot_part (bloc_device_t *bd, part_t *partition, int partnum)
+ {
++ dprintf("%s: part %p (%p) %d\n", __func__, partition, bd->boot_part, partnum);
+ if (bd->boot_part == NULL) {
+ bd->boot_part = partition;
++ bd->bpartnum = partnum;
+ }
+ }
+
+@@ -240,6 +255,13 @@
+ return &bd->bparts;
+ }
+
++void bd_set_boot_device (bloc_device_t *bd)
++{
++#if defined (USE_OPENFIRMWARE)
++ OF_blockdev_set_boot_device(bd->OF_private, bd->bpartnum, "\\\\ofwboot");
++#endif
++}
++
+ part_t *bd_probe (int boot_device)
+ {
+ char devices[] = { /*'a', 'b',*/ 'c', 'd', 'e', 'f', 'm', '\0', };
+@@ -272,9 +294,7 @@
+ tmp = part_probe(bd, force_raw);
+ if (boot_device == bd->device) {
+ boot_part = tmp;
+-#if defined (USE_OPENFIRMWARE)
+- OF_blockdev_set_boot_device(bd->OF_private, 2, "\\\\ofwboot");
+-#endif
++ bd_set_boot_device(bd);
+ }
+ }
+
+@@ -717,34 +737,29 @@
+ /* IDE PCI access for pc */
+ static uint8_t ide_pci_port_read (bloc_device_t *bd, int port)
+ {
+- eieio();
+-
+- return *(uint8_t *)(bd->io_base + port);
++ uint8_t value;
++ value = inb(bd->io_base + port);
++ return value;
+ }
+
+ static void ide_pci_port_write (bloc_device_t *bd, int port, uint8_t value)
+ {
+- *(uint8_t *)(bd->io_base + port) = value;
+- eieio();
++ outb(bd->io_base + port, value);
+ }
+
+ static uint32_t ide_pci_data_readl (bloc_device_t *bd)
+ {
+- eieio();
+-
+- return *((uint32_t *)bd->io_base);
++ return inl(bd->io_base);
+ }
+
+ static void ide_pci_data_writel (bloc_device_t *bd, uint32_t val)
+ {
+- *(uint32_t *)(bd->io_base) = val;
+- eieio();
++ outl(bd->io_base, val);
+ }
+
+ static void ide_pci_control_write (bloc_device_t *bd, uint32_t val)
+ {
+- *((uint8_t *)bd->tmp) = val;
+- eieio();
++ outb(bd->tmp + 2, val);
+ }
+
+ static ide_ops_t ide_pci_pc_ops = {
+@@ -761,7 +776,7 @@
+
+ void ide_pci_pc_register (uint32_t io_base0, uint32_t io_base1,
+ uint32_t io_base2, uint32_t io_base3,
+- unused void *OF_private)
++ void *OF_private0, void *OF_private1)
+ {
+ if (ide_pci_ops == NULL) {
+ ide_pci_ops = malloc(sizeof(ide_ops_t));
+@@ -770,19 +785,19 @@
+ memcpy(ide_pci_ops, &ide_pci_pc_ops, sizeof(ide_ops_t));
+ }
+ if ((io_base0 != 0 || io_base1 != 0) &&
+- ide_pci_ops->base[0] == 0 && ide_pci_ops->base[1] == 0) {
++ ide_pci_ops->base[0] == 0 && ide_pci_ops->base[2] == 0) {
+ ide_pci_ops->base[0] = io_base0;
+- ide_pci_ops->base[1] = io_base1;
++ ide_pci_ops->base[2] = io_base1;
+ #ifdef USE_OPENFIRMWARE
+- ide_pci_ops->OF_private[0] = OF_private;
++ ide_pci_ops->OF_private[0] = OF_private0;
+ #endif
+ }
+ if ((io_base2 != 0 || io_base3 != 0) &&
+- ide_pci_ops->base[2] == 0 && ide_pci_ops->base[3] == 0) {
+- ide_pci_ops->base[2] = io_base2;
++ ide_pci_ops->base[1] == 0 && ide_pci_ops->base[3] == 0) {
++ ide_pci_ops->base[1] = io_base2;
+ ide_pci_ops->base[3] = io_base3;
+ #ifdef USE_OPENFIRMWARE
+- ide_pci_ops->OF_private[1] = OF_private;
++ ide_pci_ops->OF_private[1] = OF_private1;
+ #endif
+ }
+ }
+@@ -935,6 +950,8 @@
+ }
+
+ static void atapi_pad_req (void *buffer, int len);
++static void atapi_make_req (bloc_device_t *bd, uint32_t *buffer,
++ int maxlen);
+ static int atapi_read_sector (bloc_device_t *bd, void *buffer, int secnum);
+
+ static int ide_initialize (bloc_device_t *bd, int device)
+@@ -1035,9 +1052,7 @@
+ DPRINTF("INQUIRY\n");
+ len = spc_inquiry_req(&atapi_buffer, 36);
+ atapi_pad_req(&atapi_buffer, len);
+- ide_port_write(bd, 0x07, 0xA0);
+- for (i = 0; i < 3; i++)
+- ide_data_writel(bd, ldswap32(&atapi_buffer[i]));
++ atapi_make_req(bd, atapi_buffer, 36);
+ status = ide_port_read(bd, 0x07);
+ if (status != 0x48) {
+ ERROR("ATAPI INQUIRY : status %0x != 0x48\n", status);
+@@ -1053,9 +1068,7 @@
+ DPRINTF("READ_CAPACITY\n");
+ len = mmc_read_capacity_req(&atapi_buffer);
+ atapi_pad_req(&atapi_buffer, len);
+- ide_port_write(bd, 0x07, 0xA0);
+- for (i = 0; i < 3; i++)
+- ide_data_writel(bd, ldswap32(&atapi_buffer[i]));
++ atapi_make_req(bd, atapi_buffer, 8);
+ status = ide_port_read(bd, 0x07);
+ if (status != 0x48) {
+ ERROR("ATAPI READ_CAPACITY : status %0x != 0x48\n", status);
+@@ -1105,6 +1118,22 @@
+ memset(p + len, 0, 12 - len);
+ }
+
++static void atapi_make_req (bloc_device_t *bd, uint32_t *buffer,
++ int maxlen)
++{
++ int i;
++ /* select drive */
++ if (bd->drv == 0)
++ ide_port_write(bd, 0x06, 0x40);
++ else
++ ide_port_write(bd, 0x06, 0x50);
++ ide_port_write(bd, 0x04, maxlen & 0xff);
++ ide_port_write(bd, 0x05, (maxlen >> 8) & 0xff);
++ ide_port_write(bd, 0x07, 0xA0);
++ for (i = 0; i < 3; i++)
++ ide_data_writel(bd, ldswap32(&buffer[i]));
++}
++
+ static int atapi_read_sector (bloc_device_t *bd, void *buffer, int secnum)
+ {
+ uint32_t atapi_buffer[4];
+@@ -1112,16 +1141,9 @@
+ uint32_t status, value;
+ int i, len;
+
+- /* select drive */
+- if (bd->drv == 0)
+- ide_port_write(bd, 0x06, 0x40);
+- else
+- ide_port_write(bd, 0x06, 0x50);
+ len = mmc_read12_req(atapi_buffer, secnum, 1);
+ atapi_pad_req(&atapi_buffer, len);
+- ide_port_write(bd, 0x07, 0xA0);
+- for (i = 0; i < 3; i++)
+- ide_data_writel(bd, ldswap32(&atapi_buffer[i]));
++ atapi_make_req(bd, atapi_buffer, bd->seclen);
+ status = ide_port_read(bd, 0x07);
+ if (status != 0x48) {
+ ERROR("ATAPI READ12 : status %0x != 0x48\n", status);
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/apple.c OpenHackWare-release-0.4/src/libpart/apple.c
+--- OpenHackWare-release-0.4.org/src/libpart/apple.c 2005-03-31 09:23:33.000000000 +0200
++++ OpenHackWare-release-0.4/src/libpart/apple.c 2005-07-03 16:17:41.000000000 +0200
+@@ -199,14 +199,18 @@
+ if (len == 0) {
+ /* Place holder. Skip it */
+ DPRINTF("%s placeholder part\t%d\n", __func__, i);
++ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
++ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_Void", type, 32) == 0) {
+ /* Void partition. Skip it */
+ DPRINTF("%s Void part\t%d [%s]\n", __func__, i, type);
++ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
++ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_Free", type, 32) == 0) {
+ /* Free space. Skip it */
+ DPRINTF("%s Free part (%d)\n", __func__, i);
+ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+- part_register(bd, part, name);
++ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_partition_map", type, 32) == 0 ||
+ strncmp("Apple_Partition_Map", type, 32) == 0
+ #if 0 // Is this really used or is it just a mistake ?
+@@ -226,7 +230,7 @@
+ */
+ }
+ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+- part_register(bd, part, name);
++ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_Driver", type, 32) == 0 ||
+ strncmp("Apple_Driver43", type, 32) == 0 ||
+ strncmp("Apple_Driver43_CD", type, 32) == 0 ||
+@@ -236,8 +240,12 @@
+ strncmp("Apple_Driver_IOKit", type, 32) == 0) {
+ /* Drivers. don't care for now */
+ DPRINTF("%s Drivers part\t%d [%s]\n", __func__, i, type);
++ part->flags = PART_TYPE_APPLE | PART_FLAG_DRIVER;
++ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_Patches", type, 32) == 0) {
+ /* Patches: don't care for now */
++ part->flags = PART_TYPE_APPLE | PART_FLAG_PATCH;
++ part_register(bd, part, name, i);
+ DPRINTF("%s Patches part\t%d [%s]\n", __func__, i, type);
+ } else if (strncmp("Apple_HFS", type, 32) == 0 ||
+ strncmp("Apple_MFS", type, 32) == 0 ||
+@@ -256,9 +264,8 @@
+ count = partmap->bloc_cnt * HFS_BLOCSIZE;
+ if (partmap->boot_size == 0 || partmap->boot_load == 0) {
+ printf("Not a bootable partition %d %d (%p %p)\n",
+- partmap->boot_size, partmap->boot_load,boot_part, part);
+- if (boot_part == NULL)
+- boot_part = part;
++ partmap->boot_size, partmap->boot_load,
++ boot_part, part);
+ part->flags = PART_TYPE_APPLE | PART_FLAG_FS;
+ } else {
+ part->boot_start.bloc = partmap->boot_start;
+@@ -278,8 +285,8 @@
+ boot_part = part;
+ part->flags = PART_TYPE_APPLE | PART_FLAG_FS | PART_FLAG_BOOT;
+ }
+- printf("Partition: %d %s st %0x size %0x",
+- i, name, partmap->start_bloc, partmap->bloc_cnt);
++ printf("Partition: %d '%s' '%s' st %0x size %0x",
++ i, name, type, partmap->start_bloc, partmap->bloc_cnt);
+ #ifndef DEBUG
+ printf("\n");
+ #endif
+@@ -290,11 +297,13 @@
+ part->boot_load, part->boot_entry);
+ DPRINTF(" load %0x entry %0x %0x\n",
+ partmap->boot_load2, partmap->boot_entry2, HFS_BLOCSIZE);
+- part_register(bd, part, name);
++ part_register(bd, part, name, i);
+ } else {
+ memcpy(tmp, type, 32);
+ tmp[32] = '\0';
+ ERROR("Unknown partition type [%s]\n", tmp);
++ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
++ part_register(bd, part, name, i);
+ }
+ }
+ error:
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/core.c OpenHackWare-release-0.4/src/libpart/core.c
+--- OpenHackWare-release-0.4.org/src/libpart/core.c 2005-03-31 09:23:33.000000000 +0200
++++ OpenHackWare-release-0.4/src/libpart/core.c 2005-07-03 16:17:41.000000000 +0200
+@@ -126,7 +126,7 @@
+ }
+
+ int part_register (bloc_device_t *bd, part_t *partition,
+- const unsigned char *name)
++ const unsigned char *name, int partnum)
+ {
+ part_t **cur;
+
+@@ -134,6 +134,7 @@
+ partition->bd = bd;
+ partition->next = NULL;
+ partition->name = strdup(name);
++ partition->partnum = partnum;
+ for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next)
+ continue;
+ *cur = partition;
+@@ -141,29 +142,15 @@
+ return 0;
+ }
+
+-static inline int set_boot_part (bloc_device_t *bd, int partnum)
+-{
+- part_t *cur;
+-
+- cur = part_get(bd, partnum);
+- if (cur == NULL)
+- return -1;
+- bd_set_boot_part(bd, cur);
+-
+- return 0;
+-}
+-
+ part_t *part_get (bloc_device_t *bd, int partnum)
+ {
+ part_t **listp, *cur;
+- int i;
+
+ listp = _bd_parts(bd);
+- cur = *listp;
+- for (i = 0; i != partnum; i++) {
+- if (cur == NULL)
++
++ for (cur = *listp; cur != NULL; cur = cur->next) {
++ if (cur->partnum == partnum)
+ break;
+- cur = cur->next;
+ }
+
+ return cur;
+@@ -192,17 +179,20 @@
+ part_set_blocsize(bd, part, 512);
+ part->bd = bd;
+ part->flags = PART_TYPE_RAW | PART_FLAG_BOOT;
+- part_register(bd, part, "Raw");
++ part_register(bd, part, "Raw", 0);
+
+ return part;
+ }
+
++bloc_device_t *part_get_bd (part_t *part)
++{
++ return part->bd;
++}
++
+ part_t *part_probe (bloc_device_t *bd, int set_raw)
+ {
+- part_t *part0, *boot_part, **cur;
++ part_t *part0 = NULL, *boot_part, **cur;
+
+- /* Register the 0 partition: raw partition containing the whole disk */
+- part0 = part_get_raw(bd);
+ /* Try to find a valid boot partition */
+ boot_part = Apple_probe_partitions(bd);
+ if (boot_part == NULL) {
+@@ -210,10 +200,13 @@
+ if (boot_part == NULL && arch == ARCH_PREP)
+ boot_part = PREP_find_partition(bd);
+ if (boot_part == NULL && set_raw != 0) {
+- boot_part = part0;
+- set_boot_part(bd, 0);
++ dprintf("Use bloc device as raw partition\n");
+ }
+ }
++ if (_bd_parts(bd) == NULL) {
++ /* Register the 0 partition: raw partition containing the whole disk */
++ part0 = part_get_raw(bd);
++ }
+ /* Probe filesystem on each found partition */
+ for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next) {
+ const unsigned char *map, *type;
+@@ -248,23 +241,28 @@
+ type = "unknown";
+ break;
+ }
+- DPRINTF("Probe filesystem on %s %s partition '%s' %s\n",
++ dprintf("Probe filesystem on %s %s partition '%s' %s %p\n",
+ type, map, (*cur)->name,
+- ((*cur)->flags) & PART_FLAG_BOOT ? "(bootable)" : "");
++ ((*cur)->flags) & PART_FLAG_BOOT ? "(bootable)" : "", *cur);
+ if (((*cur)->flags) & PART_FLAG_FS) {
+ if (((*cur)->flags) & PART_FLAG_BOOT)
+ (*cur)->fs = fs_probe(*cur, 1);
+ else
+ (*cur)->fs = fs_probe(*cur, 0);
++ } else if (((*cur)->flags) & PART_TYPE_RAW) {
++ (*cur)->fs = fs_probe(*cur, 2);
+ } else {
+ (*cur)->fs = fs_probe(*cur, 2);
+ }
+- if (((*cur)->flags) & PART_FLAG_BOOT) {
+- bd_set_boot_part(bd, *cur);
+ fs_get_bootfile((*cur)->fs);
++ if (((*cur)->flags) & PART_FLAG_BOOT) {
++ dprintf("Partition is bootable (%d)\n", (*cur)->partnum);
++ bd_set_boot_part(bd, *cur, (*cur)->partnum);
++ if (boot_part == NULL)
++ boot_part = *cur;
+ }
+ }
+- DPRINTF("Boot partition: %p %p %p %p\n", boot_part, boot_part->fs,
++ dprintf("Boot partition: %p %p %p %p\n", boot_part, boot_part->fs,
+ part_fs(boot_part), part0);
+
+ return boot_part;
+@@ -279,6 +277,7 @@
+ part->boot_size.offset = 0;
+ part->boot_load = 0;
+ part->boot_entry = 0;
++ part->flags |= PART_FLAG_BOOT;
+
+ return 0;
+ }
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/isofs.c OpenHackWare-release-0.4/src/libpart/isofs.c
+--- OpenHackWare-release-0.4.org/src/libpart/isofs.c 2005-03-31 09:23:33.000000000 +0200
++++ OpenHackWare-release-0.4/src/libpart/isofs.c 2005-07-03 16:17:41.000000000 +0200
+@@ -242,7 +242,7 @@
+ part->boot_start.bloc, part->boot_size.bloc,
+ part->boot_load, part->boot_entry);
+ part->flags = PART_TYPE_ISO9660 | PART_FLAG_BOOT;
+- part_register(bd, part, name);
++ part_register(bd, part, name, i + 1);
+ fs_raw_set_bootfile(part, part->boot_start.bloc,
+ part->boot_start.offset,
+ part->boot_size.bloc,
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/libpart.h OpenHackWare-release-0.4/src/libpart/libpart.h
+--- OpenHackWare-release-0.4.org/src/libpart/libpart.h 2005-03-31 09:23:33.000000000 +0200
++++ OpenHackWare-release-0.4/src/libpart/libpart.h 2005-07-03 16:17:41.000000000 +0200
+@@ -30,6 +30,7 @@
+
+ struct part_t {
+ bloc_device_t *bd;
++ int partnum;
+ uint32_t start; /* Partition first bloc */
+ uint32_t size; /* Partition size, in blocs */
+ uint32_t spb;
+@@ -54,7 +55,7 @@
+ };
+
+ int part_register (bloc_device_t *bd, part_t *partition,
+- const unsigned char *name);
++ const unsigned char *name, int partnum);
+ void part_set_blocsize (bloc_device_t *bd, part_t *part, uint32_t blocsize);
+ void part_private_set (part_t *part, void *private);
+ void *part_private_get (part_t *part);
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/libpart/prep.c OpenHackWare-release-0.4/src/libpart/prep.c
+--- OpenHackWare-release-0.4.org/src/libpart/prep.c 2005-03-31 09:23:33.000000000 +0200
++++ OpenHackWare-release-0.4/src/libpart/prep.c 2005-07-03 16:17:41.000000000 +0200
+@@ -164,7 +164,7 @@
+ part->boot_load = 0;
+ part->boot_entry = boot_offset - part->bloc_size;
+ part->flags = PART_TYPE_PREP | PART_FLAG_BOOT;
+- part_register(bd, part, "PREP boot");
++ part_register(bd, part, "PREP boot", i);
+ fs_raw_set_bootfile(part, part->boot_start.bloc,
+ part->boot_start.offset,
+ part->boot_size.bloc,
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/main.c OpenHackWare-release-0.4/src/main.c
+--- OpenHackWare-release-0.4.org/src/main.c 2005-03-31 09:23:33.000000000 +0200
++++ OpenHackWare-release-0.4/src/main.c 2005-06-07 23:48:39.000000000 +0200
+@@ -364,20 +364,24 @@
+ void *load_base, *load_entry, *last_alloc, *load_end;
+ uint32_t memsize, boot_image_size, cmdline_size, ramdisk_size;
+ uint32_t boot_base, boot_nb;
+- int boot_device;
++ int boot_device, i;
++ static const uint32_t isa_base_tab[3] = {
++ 0x80000000, /* PREP */
++ 0xFE000000, /* Grackle (Heathrow) */
++ 0xF2000000, /* UniNorth (Mac99) */
++ };
+
+ /* Retrieve NVRAM configuration */
+- nvram_retry:
++ for(i = 0; i < 3; i++) {
++ isa_io_base = isa_base_tab[i];
+ nvram = NVRAM_get_config(&memsize, &boot_device,
+ &boot_image, &boot_image_size,
+ &cmdline, &cmdline_size,
+ &ramdisk, &ramdisk_size);
+- if (nvram == NULL) {
+- /* Retry with another isa_io_base */
+- if (isa_io_base == 0x80000000) {
+- isa_io_base = 0xF2000000;
+- goto nvram_retry;
++ if (nvram)
++ break;
+ }
++ if (i == 3) {
+ ERROR("Unable to load configuration from NVRAM. Aborting...\n");
+ return -1;
+ }
+@@ -402,7 +406,7 @@
+ cpu_name = CPU_get_name(pvr);
+ OF_register_cpu(cpu_name, 0, pvr,
+ 200 * 1000 * 1000, 200 * 1000 * 1000,
+- 100 * 1000 * 1000, 10 * 1000 * 1000,
++ 100 * 1000 * 1000, 100 * 1000 * 1000,
+ 0x0092);
+ }
+ OF_register_memory(memsize, 512 * 1024 /* TOFIX */);
+@@ -433,9 +437,12 @@
+ vga_puts(copyright);
+ vga_puts("\n");
+
++#if 0
+ /* QEMU is quite incoherent: d is cdrom, not second drive */
++ /* XXX: should probe CD-ROM position */
+ if (boot_device == 'd')
+ boot_device = 'e';
++#endif
+ /* Open boot device */
+ boot_part = bd_probe(boot_device);
+ if (boot_device == 'm') {
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/nvram.c OpenHackWare-release-0.4/src/nvram.c
+--- OpenHackWare-release-0.4.org/src/nvram.c 2005-03-31 09:23:33.000000000 +0200
++++ OpenHackWare-release-0.4/src/nvram.c 2005-06-04 23:44:03.000000000 +0200
+@@ -334,6 +334,7 @@
+ ret = NVRAM_chrp_format(nvram);
+ break;
+ case ARCH_MAC99:
++ case ARCH_HEATHROW: /* XXX: may be incorrect */
+ ret = NVRAM_mac99_format(nvram);
+ break;
+ case ARCH_POP:
+@@ -409,13 +410,12 @@
+ arch = ARCH_MAC99;
+ } else if (strcmp(sign, "POP") == 0) {
+ arch = ARCH_POP;
++ } else if (strcmp(sign, "HEATHROW") == 0) {
++ arch = ARCH_HEATHROW;
+ } else {
+ ERROR("Unknown PPC architecture: '%s'\n", sign);
+ return NULL;
+ }
+- /* HACK */
+- if (arch == ARCH_CHRP)
+- arch = ARCH_MAC99;
+ lword = NVRAM_get_lword(nvram, 0x30);
+ *RAM_size = lword;
+ byte = NVRAM_get_byte(nvram, 0x34);
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/of.c OpenHackWare-release-0.4/src/of.c
+--- OpenHackWare-release-0.4.org/src/of.c 2005-04-06 23:17:26.000000000 +0200
++++ OpenHackWare-release-0.4/src/of.c 2005-07-07 23:30:08.000000000 +0200
+@@ -489,7 +489,7 @@
+ ERROR("%s can't alloc new node '%s' name\n", __func__, name);
+ return NULL;
+ }
+- new->prop_address = OF_prop_int_new(env, new, "address", address);
++ new->prop_address = OF_prop_int_new(env, new, "unit-address", address);
+ if (new->prop_address == NULL) {
+ free(new->prop_name->value);
+ free(new->prop_name);
+@@ -1017,6 +1017,33 @@
+ string, strlen(string) + 1);
+ }
+
++/* convert '\1' char to '\0' */
++static OF_prop_t *OF_prop_string_new1 (OF_env_t *env, OF_node_t *node,
++ const unsigned char *name,
++ const unsigned char *string)
++{
++ int len, i;
++ OF_prop_t *ret;
++ unsigned char *str;
++
++ if (strchr(string, '\1') == NULL) {
++ return OF_prop_string_new(env, node, name, string);
++ } else {
++ len = strlen(string) + 1;
++ str = malloc(len);
++ if (!str)
++ return NULL;
++ memcpy(str, string, len);
++ for(i = 0; i < len; i++)
++ if (str[i] == '\1')
++ str[i] = '\0';
++ ret = OF_property_new(env, node, name,
++ str, len);
++ free(str);
++ return ret;
++ }
++}
++
+ __attribute__ (( section (".OpenFirmware") ))
+ static OF_prop_t *OF_prop_int_new (OF_env_t *env, OF_node_t *node,
+ const unsigned char *name, uint32_t value)
+@@ -1421,15 +1448,12 @@
+ __attribute__ (( section (".OpenFirmware") ))
+ int OF_init (void)
+ {
+- const unsigned char compat_str[] =
+ #if 0
+ "PowerMac3,1\0MacRISC\0Power Macintosh\0";
+ "PowerMac1,2\0MacRISC\0Power Macintosh\0";
+ "AAPL,PowerMac G3\0PowerMac G3\0MacRISC\0Power Macintosh\0";
+ "AAPL,PowerMac3,0\0MacRISC\0Power Macintosh\0";
+ "AAPL,Gossamer\0MacRISC\0Power Macintosh\0";
+-#else
+- "AAPL,PowerMac G3\0PowerMac G3\0MacRISC\0Power Macintosh\0";
+ #endif
+ OF_env_t *OF_env;
+ OF_node_t *als, *opt, *chs, *pks;
+@@ -1455,15 +1479,21 @@
+ return -1;
+ }
+ OF_prop_string_new(OF_env, OF_node_root, "device_type", "bootrom");
+-#if 0
+- OF_prop_string_new(OF_env, OF_node_root,
+- "model", "PPC Open Hack'Ware " BIOS_VERSION);
+-#else
++ if (arch == ARCH_HEATHROW) {
++ const unsigned char compat_str[] =
++ "PowerMac1,1\0MacRISC\0Power Macintosh";
++ OF_property_new(OF_env, OF_node_root, "compatible",
++ compat_str, sizeof(compat_str));
+ OF_prop_string_new(OF_env, OF_node_root,
+- "model", compat_str);
+-#endif
++ "model", "Power Macintosh");
++ } else {
++ const unsigned char compat_str[] =
++ "PowerMac3,1\0MacRISC\0Power Macintosh";
+ OF_property_new(OF_env, OF_node_root, "compatible",
+ compat_str, sizeof(compat_str));
++ OF_prop_string_new(OF_env, OF_node_root,
++ "model", "PowerMac3,1");
++ }
+ #if 0
+ OF_prop_string_new(OF_env, OF_node_root, "copyright", copyright);
+ #else
+@@ -1561,14 +1591,15 @@
+ range.size = 0x00800000;
+ OF_property_new(OF_env, rom, "ranges", &range, sizeof(OF_range_t));
+ OF_prop_int_new(OF_env, rom, "#address-cells", 1);
++
+ /* "/rom/boot-rom@fff00000" node */
+- brom = OF_node_new(OF_env, OF_node_root, "boot-rom", 0xfff00000);
++ brom = OF_node_new(OF_env, rom, "boot-rom", 0xfff00000);
+ if (brom == NULL) {
+ ERROR("Cannot create 'boot-rom'\n");
+ return -1;
+ }
+ regs.address = 0xFFF00000;
+- regs.size = 0x00010000;
++ regs.size = 0x00100000;
+ OF_property_new(OF_env, brom, "reg", &regs, sizeof(OF_regprop_t));
+ OF_prop_string_new(OF_env, brom, "write-characteristic", "flash");
+ OF_prop_string_new(OF_env, brom, "BootROM-build-date",
+@@ -1577,7 +1608,7 @@
+ OF_prop_string_new(OF_env, brom, "copyright", copyright);
+ OF_prop_string_new(OF_env, brom, "model", BIOS_str);
+ OF_prop_int_new(OF_env, brom, "result", 0);
+-#if 0
++#if 1
+ {
+ /* Hack taken 'as-is' from PearPC */
+ unsigned char info[] = {
+@@ -1596,7 +1627,9 @@
+ OF_node_put(OF_env, brom);
+ OF_node_put(OF_env, rom);
+ }
++#if 0
+ /* From here, hardcoded hacks to get a Mac-like machine */
++ /* XXX: Core99 does not seem to like this NVRAM tree */
+ /* "/nvram@fff04000" node */
+ {
+ OF_regprop_t regs;
+@@ -1617,6 +1650,7 @@
+ OF_prop_int_new(OF_env, chs, "nvram", OF_pack_handle(OF_env, nvr));
+ OF_node_put(OF_env, nvr);
+ }
++#endif
+ /* "/pseudo-hid" : hid emulation as Apple does */
+ {
+ OF_node_t *hid;
+@@ -1663,7 +1697,27 @@
+ }
+ OF_node_put(OF_env, hid);
+ }
++ if (arch == ARCH_MAC99) {
++ OF_node_t *unin;
++ OF_regprop_t regs;
+
++ unin = OF_node_new(OF_env, OF_node_root,
++ "uni-n", 0xf8000000);
++ if (unin == NULL) {
++ ERROR("Cannot create 'uni-n'\n");
++ return -1;
++ }
++ OF_prop_string_new(OF_env, unin, "device-type", "memory-controller");
++ OF_prop_string_new(OF_env, unin, "model", "AAPL,UniNorth");
++ OF_prop_string_new(OF_env, unin, "compatible", "uni-north");
++ regs.address = 0xf8000000;
++ regs.size = 0x01000000;
++ OF_property_new(OF_env, unin, "reg", &regs, sizeof(regs));
++ OF_prop_int_new(OF_env, unin, "#address-cells", 1);
++ OF_prop_int_new(OF_env, unin, "#size-cells", 1);
++ OF_prop_int_new(OF_env, unin, "device-rev", 3);
++ OF_node_put(OF_env, unin);
++ }
+
+ #if 1 /* This is mandatory for claim to work
+ * but I don't know where it should really be (in cpu ?)
+@@ -1693,7 +1747,9 @@
+
+ /* "/options/boot-args" node */
+ {
+- const unsigned char *args = "-v rootdev cdrom";
++ // const unsigned char *args = "-v rootdev cdrom";
++ //const unsigned char *args = "-v io=0xffffffff";
++ const unsigned char *args = "-v";
+ /* Ask MacOS X to print debug messages */
+ // OF_prop_string_new(OF_env, chs, "machargs", args);
+ // OF_prop_string_new(OF_env, opt, "boot-command", args);
+@@ -2013,17 +2069,17 @@
+ OF_prop_int_new(OF_env, node, "min-grant", min_grant);
+ OF_prop_int_new(OF_env, node, "max-latency", max_latency);
+ if (dev->type != NULL)
+- OF_prop_string_new(OF_env, node, "device_type", dev->type);
++ OF_prop_string_new1(OF_env, node, "device_type", dev->type);
+ if (dev->compat != NULL)
+- OF_prop_string_new(OF_env, node, "compatible", dev->compat);
++ OF_prop_string_new1(OF_env, node, "compatible", dev->compat);
+ if (dev->model != NULL)
+- OF_prop_string_new(OF_env, node, "model", dev->model);
++ OF_prop_string_new1(OF_env, node, "model", dev->model);
+ if (dev->acells != 0)
+ OF_prop_int_new(OF_env, node, "#address-cells", dev->acells);
+ if (dev->scells != 0)
+- OF_prop_int_new(OF_env, node, "#interrupt-cells", dev->acells);
++ OF_prop_int_new(OF_env, node, "#size-cells", dev->scells);
+ if (dev->icells != 0)
+- OF_prop_int_new(OF_env, node, "#size-cells", dev->acells);
++ OF_prop_int_new(OF_env, node, "#interrupt-cells", dev->icells);
+ dprintf("Done %p %p\n", parent, node);
+
+ return node;
+@@ -2040,8 +2096,9 @@
+ OF_env_t *OF_env;
+ pci_range_t ranges[3];
+ OF_regprop_t regs[1];
+- OF_node_t *pci_host;
++ OF_node_t *pci_host, *als;
+ int nranges;
++ unsigned char buffer[OF_NAMELEN_MAX];
+
+ OF_env = OF_env_main;
+ dprintf("register PCI host '%s' '%s' '%s' '%s'\n",
+@@ -2052,6 +2109,17 @@
+ ERROR("Cannot create pci host\n");
+ return NULL;
+ }
++
++ als = OF_node_get(OF_env, "aliases");
++ if (als == NULL) {
++ ERROR("Cannot get 'aliases'\n");
++ return NULL;
++ }
++ sprintf(buffer, "/%s", dev->name);
++ OF_prop_string_set(OF_env, als, "pci", buffer);
++ OF_node_put(OF_env, als);
++
++
+ regs[0].address = cfg_base;
+ regs[0].size = cfg_len;
+ OF_property_new(OF_env, pci_host, "reg", regs, sizeof(OF_regprop_t));
+@@ -2136,6 +2204,11 @@
+ return pci_dev;
+ }
+
++/* XXX: suppress that, used for interrupt map init */
++OF_node_t *pci_host_node;
++uint32_t pci_host_interrupt_map[7 * 32];
++int pci_host_interrupt_map_len = 0;
++
+ void OF_finalize_pci_host (void *dev, int first_bus, int nb_busses)
+ {
+ OF_env_t *OF_env;
+@@ -2145,10 +2218,12 @@
+ regs[0].address = first_bus;
+ regs[0].size = nb_busses;
+ OF_property_new(OF_env, dev, "bus-range", regs, sizeof(OF_regprop_t));
++ pci_host_node = dev;
+ }
+
+ void OF_finalize_pci_device (void *dev, uint8_t bus, uint8_t devfn,
+- uint32_t *regions, uint32_t *sizes)
++ uint32_t *regions, uint32_t *sizes,
++ int irq_line)
+ {
+ OF_env_t *OF_env;
+ pci_reg_prop_t pregs[6], rregs[6];
+@@ -2156,6 +2231,7 @@
+ int i, j, k;
+
+ OF_env = OF_env_main;
++ /* XXX: only useful for VGA card in fact */
+ if (regions[0] != 0x00000000)
+ OF_prop_int_set(OF_env, dev, "address", regions[0] & ~0x0000000F);
+ for (i = 0, j = 0, k = 0; i < 6; i++) {
+@@ -2222,7 +2298,22 @@
+ } else {
+ OF_property_new(OF_env, dev, "assigned-addresses", NULL, 0);
+ }
+-#if 0
++ if (irq_line >= 0) {
++ int i;
++ OF_prop_int_new(OF_env, dev, "interrupts", 1);
++ i = pci_host_interrupt_map_len;
++ pci_host_interrupt_map[i++] = (devfn << 8) & 0xf800;
++ pci_host_interrupt_map[i++] = 0;
++ pci_host_interrupt_map[i++] = 0;
++ pci_host_interrupt_map[i++] = 0;
++ pci_host_interrupt_map[i++] = 0; /* pic handle will be patched later */
++ pci_host_interrupt_map[i++] = irq_line;
++ if (arch != ARCH_HEATHROW) {
++ pci_host_interrupt_map[i++] = 1;
++ }
++ pci_host_interrupt_map_len = i;
++ }
++#if 1
+ {
+ OF_prop_t *prop_name = ((OF_node_t *)dev)->prop_name;
+
+@@ -2390,6 +2481,54 @@
+ return 0;
+ }
+
++static void keylargo_ata(OF_node_t *mio, uint32_t base_address,
++ uint32_t base, int irq1, int irq2,
++ uint16_t pic_phandle)
++{
++ OF_env_t *OF_env = OF_env_main;
++ OF_node_t *ata;
++ OF_regprop_t regs[2];
++
++ ata = OF_node_new(OF_env, mio, "ata-4", base);
++ if (ata == NULL) {
++ ERROR("Cannot create 'ata-4'\n");
++ return;
++ }
++ OF_prop_string_new(OF_env, ata, "device_type", "ata");
++#if 1
++ OF_prop_string_new(OF_env, ata, "compatible", "key2largo-ata");
++ OF_prop_string_new(OF_env, ata, "model", "ata-4");
++ OF_prop_string_new(OF_env, ata, "cable-type", "80-conductor");
++#else
++ OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
++ OF_prop_string_new(OF_env, ata, "model", "ata-4");
++#endif
++ OF_prop_int_new(OF_env, ata, "#address-cells", 1);
++ OF_prop_int_new(OF_env, ata, "#size-cells", 0);
++ regs[0].address = base;
++ regs[0].size = 0x00001000;
++#if 0 // HACK: Don't set up DMA registers
++ regs[1].address = 0x00008A00;
++ regs[1].size = 0x00001000;
++ OF_property_new(OF_env, ata, "reg",
++ regs, 2 * sizeof(OF_regprop_t));
++#else
++ OF_property_new(OF_env, ata, "reg",
++ regs, sizeof(OF_regprop_t));
++#endif
++ OF_prop_int_new(OF_env, ata, "interrupt-parent", pic_phandle);
++ regs[0].address = irq1;
++ regs[0].size = 0x00000001;
++ regs[1].address = irq2;
++ regs[1].size = 0x00000000;
++ OF_property_new(OF_env, ata, "interrupts",
++ regs, 2 * sizeof(OF_regprop_t));
++ if (base == 0x1f000)
++ ide_pci_pmac_register(base_address + base, 0x00000000, ata);
++ else
++ ide_pci_pmac_register(0x00000000, base_address + base, ata);
++}
++
+ void OF_finalize_pci_macio (void *dev, uint32_t base_address, uint32_t size,
+ void *private_data)
+ {
+@@ -2398,6 +2537,8 @@
+ pci_reg_prop_t pregs[2];
+ OF_node_t *mio, *chs, *als;
+ uint16_t pic_phandle;
++ int rec_len;
++ OF_prop_t *mio_reg;
+
+ OF_DPRINTF("mac-io: %p\n", dev);
+ OF_env = OF_env_main;
+@@ -2416,10 +2557,14 @@
+ mio = dev;
+ mio->private_data = private_data;
+ pregs[0].addr.hi = 0x00000000;
+- pregs[0].addr.mid = 0x82013810;
++ pregs[0].addr.mid = 0x00000000;
+ pregs[0].addr.lo = 0x00000000;
+ pregs[0].size_hi = base_address;
+ pregs[0].size_lo = size;
++ mio_reg = OF_property_get(OF_env, mio, "reg");
++ if (mio_reg && mio_reg->vlen >= 5 * 4) {
++ pregs[0].addr.mid = ((pci_reg_prop_t *)mio_reg->value)->addr.hi;
++ }
+ OF_property_new(OF_env, mio, "ranges",
+ &pregs, sizeof(pci_reg_prop_t));
+ #if 0
+@@ -2431,8 +2576,32 @@
+ OF_property_new(OF_env, mio, "assigned-addresses",
+ &pregs, sizeof(pci_reg_prop_t));
+ #endif
++
++ if (arch == ARCH_HEATHROW) {
++ /* Heathrow PIC */
++ OF_regprop_t regs;
++ OF_node_t *mpic;
++ const char compat_str[] = "heathrow\0mac-risc";
++
++ mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x10);
++ if (mpic == NULL) {
++ ERROR("Cannot create 'mpic'\n");
++ goto out;
++ }
++ OF_prop_string_new(OF_env, mpic, "device_type", "interrupt-controller");
++ OF_property_new(OF_env, mpic, "compatible", compat_str, sizeof(compat_str));
++ OF_prop_int_new(OF_env, mpic, "#interrupt-cells", 1);
++ regs.address = 0x10;
++ regs.size = 0x20;
++ OF_property_new(OF_env, mpic, "reg",
++ &regs, sizeof(regs));
++ OF_property_new(OF_env, mpic, "interrupt-controller", NULL, 0);
++ pic_phandle = OF_pack_handle(OF_env, mpic);
++ OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
++ OF_node_put(OF_env, mpic);
++ rec_len = 6;
++ } else {
+ /* OpenPIC */
+- {
+ OF_regprop_t regs[4];
+ OF_node_t *mpic;
+ mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x40000);
+@@ -2455,8 +2624,37 @@
+ pic_phandle = OF_pack_handle(OF_env, mpic);
+ OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
+ OF_node_put(OF_env, mpic);
++ rec_len = 7;
+ }
+-#if 1
++
++ /* patch pci host table */
++ /* XXX: do it after the PCI init */
++ {
++ int i;
++ uint32_t tab[4];
++
++ for(i = 0; i < pci_host_interrupt_map_len; i += rec_len)
++ pci_host_interrupt_map[i + 4] = pic_phandle;
++#if 0
++ dprintf("interrupt-map:\n");
++ for(i = 0; i < pci_host_interrupt_map_len; i++) {
++ dprintf(" %08x", pci_host_interrupt_map[i]);
++ if ((i % rec_len) == (rec_len - 1))
++ dprintf("\n");
++ }
++ dprintf("\n");
++#endif
++ OF_property_new(OF_env, pci_host_node, "interrupt-map",
++ pci_host_interrupt_map,
++ pci_host_interrupt_map_len * sizeof(uint32_t));
++ tab[0] = 0xf800;
++ tab[1] = 0;
++ tab[2] = 0;
++ tab[3] = 0;
++ OF_property_new(OF_env, pci_host_node, "interrupt-map-mask",
++ tab, 4 * sizeof(uint32_t));
++ }
++#if 0
+ /* escc is usefull to get MacOS X debug messages */
+ {
+ OF_regprop_t regs[8];
+@@ -2645,85 +2843,12 @@
+ OF_node_put(OF_env, scc);
+ }
+ #endif
+- /* IDE controller */
+- {
+- OF_node_t *ata;
+- OF_regprop_t regs[2];
+- ata = OF_node_new(OF_env, mio, "ata-4", 0x1f000);
+- if (ata == NULL) {
+- ERROR("Cannot create 'ata-4'\n");
+- goto out;
+- }
+- OF_prop_string_new(OF_env, ata, "device_type", "ata");
+-#if 1
+- OF_prop_string_new(OF_env, ata, "compatible", "keylargo-ata");
+- OF_prop_string_new(OF_env, ata, "model", "ata-4");
+-#else
+- OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
+- OF_prop_string_new(OF_env, ata, "model", "ata-4");
+-#endif
+- OF_prop_int_new(OF_env, ata, "#address-cells", 1);
+- OF_prop_int_new(OF_env, ata, "#size-cells", 0);
+- regs[0].address = 0x0001F000;
+- regs[0].size = 0x00001000;
+-#if 0 // HACK: Don't set up DMA registers
+- regs[1].address = 0x00008A00;
+- regs[1].size = 0x00001000;
+- OF_property_new(OF_env, ata, "reg",
+- regs, 2 * sizeof(OF_regprop_t));
+-#else
+- OF_property_new(OF_env, ata, "reg",
+- regs, sizeof(OF_regprop_t));
+-#endif
+- OF_prop_int_new(OF_env, ata, "interrupt-parent", pic_phandle);
+- regs[0].address = 0x00000013;
+- regs[0].size = 0x00000001;
+- regs[1].address = 0x0000000B;
+- regs[1].size = 0x00000000;
+- OF_property_new(OF_env, ata, "interrupts",
+- regs, 2 * sizeof(OF_regprop_t));
+- ide_pci_pmac_register(base_address + 0x1f000, 0x00000000, ata);
+-
+- }
+- {
+- OF_node_t *ata;
+- OF_regprop_t regs[2];
+- ata = OF_node_new(OF_env, mio, "ata-4", 0x20000);
+- if (ata == NULL) {
+- ERROR("Cannot create 'ata-4'\n");
+- goto out;
+- }
+- OF_prop_string_new(OF_env, ata, "device_type", "ata");
+-#if 1
+- OF_prop_string_new(OF_env, ata, "compatible", "keylargo-ata");
+- OF_prop_string_new(OF_env, ata, "model", "ata-4");
+-#else
+- OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
+- OF_prop_string_new(OF_env, ata, "model", "ata-4");
+-#endif
+- OF_prop_int_new(OF_env, ata, "#address-cells", 1);
+- OF_prop_int_new(OF_env, ata, "#size-cells", 0);
+- regs[0].address = 0x00020000;
+- regs[0].size = 0x00001000;
+-#if 0 // HACK: Don't set up DMA registers
+- regs[1].address = 0x00008A00;
+- regs[1].size = 0x00001000;
+- OF_property_new(OF_env, ata, "reg",
+- regs, 2 * sizeof(OF_regprop_t));
+-#else
+- OF_property_new(OF_env, ata, "reg",
+- regs, sizeof(OF_regprop_t));
+-#endif
+- OF_prop_int_new(OF_env, ata, "interrupt-parent", pic_phandle);
+- regs[0].address = 0x00000014;
+- regs[0].size = 0x00000001;
+- regs[1].address = 0x0000000B;
+- regs[1].size = 0x00000000;
+- OF_property_new(OF_env, ata, "interrupts",
+- regs, 2 * sizeof(OF_regprop_t));
+- ide_pci_pmac_register(0x00000000, base_address + 0x20000, ata);
+-
++ /* Keylargo IDE controller: need some work (DMA problem ?) */
++ if (arch == ARCH_MAC99) {
++ keylargo_ata(mio, base_address, 0x1f000, 0x13, 0xb, pic_phandle);
++ keylargo_ata(mio, base_address, 0x20000, 0x14, 0xb, pic_phandle);
+ }
++#if 0
+ /* Timer */
+ {
+ OF_node_t *tmr;
+@@ -2746,10 +2871,11 @@
+ regs, sizeof(OF_regprop_t));
+ OF_node_put(OF_env, tmr);
+ }
++#endif
+ /* VIA-PMU */
+ {
+ /* Controls adb, RTC and power-mgt (forget it !) */
+- OF_node_t *via, *adb, *rtc;
++ OF_node_t *via, *adb;
+ OF_regprop_t regs[1];
+ #if 0 // THIS IS A HACK AND IS COMPLETELY ABSURD !
+ // (but needed has Qemu doesn't emulate via-pmu).
+@@ -2773,14 +2899,21 @@
+ regs[0].size = 0x00002000;
+ OF_property_new(OF_env, via, "reg", regs, sizeof(OF_regprop_t));
+ OF_prop_int_new(OF_env, via, "interrupt-parent", pic_phandle);
++ if (arch == ARCH_HEATHROW) {
++ OF_prop_int_new(OF_env, via, "interrupts", 0x12);
++ } else {
+ regs[0].address = 0x00000019;
+ regs[0].size = 0x00000001;
+ OF_property_new(OF_env, via, "interrupts",
+ regs, sizeof(OF_regprop_t));
++ }
++ /* force usage of OF bus speeds */
++ OF_prop_int_new(OF_env, via, "BusSpeedCorrect", 1);
+ #if 0
+ OF_prop_int_new(OF_env, via, "pmu-version", 0x00D0740C);
+ #endif
+-#if 1
++ {
++ OF_node_t *kbd, *mouse;
+ /* ADB pseudo-device */
+ adb = OF_node_new(OF_env, via, "adb", OF_ADDRESS_NONE);
+ if (adb == NULL) {
+@@ -2797,9 +2930,26 @@
+ OF_prop_int_new(OF_env, adb, "#size-cells", 0);
+ OF_pack_get_path(OF_env, tmp, 512, adb);
+ OF_prop_string_new(OF_env, als, "adb", tmp);
+- /* XXX: add "keyboard@2" and "mouse@3" */
+- OF_node_put(OF_env, adb);
+-#endif
++
++ kbd = OF_node_new(OF_env, adb, "keyboard", 2);
++ if (kbd == NULL) {
++ ERROR("Cannot create 'kbd'\n");
++ goto out;
++ }
++ OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
++ OF_prop_int_new(OF_env, kbd, "reg", 2);
++
++ mouse = OF_node_new(OF_env, adb, "mouse", 3);
++ if (mouse == NULL) {
++ ERROR("Cannot create 'mouse'\n");
++ goto out;
++ }
++ OF_prop_string_new(OF_env, mouse, "device_type", "mouse");
++ OF_prop_int_new(OF_env, mouse, "reg", 3);
++ OF_prop_int_new(OF_env, mouse, "#buttons", 3);
++ }
++ {
++ OF_node_t *rtc;
+
+ rtc = OF_node_new(OF_env, via, "rtc", OF_ADDRESS_NONE);
+ if (rtc == NULL) {
+@@ -2813,14 +2963,68 @@
+ OF_prop_string_new(OF_env, rtc, "compatible", "rtc");
+ #endif
+ OF_node_put(OF_env, rtc);
+- OF_node_put(OF_env, via);
+ }
++ // OF_node_put(OF_env, via);
++ }
++ {
++ OF_node_t *pmgt;
++ pmgt = OF_node_new(OF_env, mio, "power-mgt", OF_ADDRESS_NONE);
++ OF_prop_string_new(OF_env, pmgt, "device_type", "power-mgt");
++ OF_prop_string_new(OF_env, pmgt, "compatible", "cuda");
++ OF_prop_string_new(OF_env, pmgt, "mgt-kind", "min-consumption-pwm-led");
++ OF_node_put(OF_env, pmgt);
++ }
++
++ if (arch == ARCH_HEATHROW) {
++ /* NVRAM */
++ OF_node_t *nvr;
++ OF_regprop_t regs;
++ nvr = OF_node_new(OF_env, mio, "nvram", 0x60000);
++ OF_prop_string_new(OF_env, nvr, "device_type", "nvram");
++ regs.address = 0x60000;
++ regs.size = 0x00020000;
++ OF_property_new(OF_env, nvr, "reg", &regs, sizeof(regs));
++ OF_prop_int_new(OF_env, nvr, "#bytes", 0x2000);
++ OF_node_put(OF_env, nvr);
++ }
++
+ out:
+ // OF_node_put(OF_env, mio);
+ OF_node_put(OF_env, chs);
+ OF_node_put(OF_env, als);
+ }
+
++void OF_finalize_pci_ide (void *dev,
++ uint32_t io_base0, uint32_t io_base1,
++ uint32_t io_base2, uint32_t io_base3)
++{
++ OF_env_t *OF_env = OF_env_main;
++ OF_node_t *pci_ata = dev;
++ OF_node_t *ata, *atas[2];
++ int i;
++
++ OF_prop_int_new(OF_env, pci_ata, "#address-cells", 1);
++ OF_prop_int_new(OF_env, pci_ata, "#size-cells", 0);
++
++ /* XXX: Darwin handles only one device */
++ for(i = 0; i < 1; i++) {
++ ata = OF_node_new(OF_env, pci_ata, "ata-4", i);
++ if (ata == NULL) {
++ ERROR("Cannot create 'ata-4'\n");
++ return;
++ }
++ OF_prop_string_new(OF_env, ata, "device_type", "ata");
++ OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
++ OF_prop_string_new(OF_env, ata, "model", "ata-4");
++ OF_prop_int_new(OF_env, ata, "#address-cells", 1);
++ OF_prop_int_new(OF_env, ata, "#size-cells", 0);
++ OF_prop_int_new(OF_env, ata, "reg", i);
++ atas[i] = ata;
++ }
++ ide_pci_pc_register(io_base0, io_base1, io_base2, io_base3,
++ atas[0], atas[1]);
++}
++
+ /*****************************************************************************/
+ /* Fake package */
+ static void OF_method_fake (OF_env_t *OF_env)
+@@ -2862,11 +3066,11 @@
+ /* As we get a 1:1 mapping, do nothing */
+ ihandle = popd(OF_env);
+ args = (void *)popd(OF_env);
+- address = popd(OF_env);
+- virt = popd(OF_env);
+- size = popd(OF_env);
+ popd(OF_env);
+- OF_DPRINTF("Translate address %0x %0x %0x %0x\n", ihandle, address,
++ size = popd(OF_env);
++ virt = popd(OF_env);
++ address = popd(OF_env);
++ OF_DPRINTF("Map %0x %0x %0x %0x\n", ihandle, address,
+ virt, size);
+ pushd(OF_env, 0);
+ }
+@@ -3270,7 +3474,7 @@
+ OF_prop_string_new(OF_env, dsk, "device_type", "block");
+ OF_prop_string_new(OF_env, dsk, "category", type);
+ OF_prop_int_new(OF_env, dsk, "device_id", devnum);
+- OF_prop_int_new(OF_env, dsk, "reg", 0);
++ OF_prop_int_new(OF_env, dsk, "reg", devnum);
+ OF_method_new(OF_env, dsk, "open", &OF_blockdev_open);
+ OF_method_new(OF_env, dsk, "seek", &OF_blockdev_seek);
+ OF_method_new(OF_env, dsk, "read", &OF_blockdev_read);
+@@ -3432,7 +3636,8 @@
+ }
+
+ void OF_vga_register (const unsigned char *name, unused uint32_t address,
+- int width, int height, int depth)
++ int width, int height, int depth,
++ unsigned long vga_bios_addr, unsigned long vga_bios_size)
+ {
+ OF_env_t *OF_env;
+ unsigned char tmp[OF_NAMELEN_MAX];
+@@ -3504,6 +3709,18 @@
+ OF_prop_string_new(OF_env, als, "display", tmp);
+ OF_node_put(OF_env, als);
+ /* XXX: may also need read-rectangle */
++
++ if (vga_bios_size >= 8) {
++ const uint8_t *p;
++ int size;
++ /* check the QEMU VGA BIOS header */
++ p = (const uint8_t *)vga_bios_addr;
++ if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') {
++ size = *(uint32_t *)(p + 4);
++ OF_property_new(OF_env, disp, "driver,AAPL,MacOS,PowerPC",
++ p + 8, size);
++ }
++ }
+ out:
+ OF_node_put(OF_env, disp);
+ }
+@@ -4451,7 +4668,10 @@
+ break;
+ case 0x233441d3: /* MacOS X 10.2 and OpenDarwin 1.41 */
+ /* Create "memory-map" pseudo device */
+- popd(OF_env);
++ {
++ OF_node_t *map;
++ uint32_t phandle;
++
+ /* Find "/packages" */
+ chs = OF_pack_find_by_name(OF_env, OF_node_root, "/chosen");
+ if (chs == NULL) {
+@@ -4459,10 +4679,6 @@
+ ERROR("Cannot get '/chosen'\n");
+ break;
+ }
+- {
+-#if 1
+- OF_node_t *map;
+- uint32_t phandle;
+ map = OF_node_new(OF_env, chs, "memory-map", OF_ADDRESS_NONE);
+ if (map == NULL) {
+ pushd(OF_env, -1);
+@@ -4473,11 +4689,8 @@
+ OF_node_put(OF_env, map);
+ OF_node_put(OF_env, chs);
+ pushd(OF_env, phandle);
+- }
+-#else
+- pushd(OF_env, 0);
+-#endif
+ pushd(OF_env, 0);
++ }
+ break;
+ case 0x32a2d18e: /* MacOS X 10.2 and OpenDarwin 6.02 */
+ /* Return screen ihandle */
+@@ -4540,9 +4753,10 @@
+ case 0x4ad41f2d:
+ /* Yaboot: wait 10 ms: sure ! */
+ break;
++
+ default:
+ /* ERROR */
+- printf("Script:\n%s\n", FString);
++ printf("Script: len=%d\n%s\n", (int)strlen(FString), FString);
+ printf("Call %0x NOT IMPLEMENTED !\n", crc);
+ bug();
+ break;
+@@ -4581,6 +4795,7 @@
+ {
+ OF_CHECK_NBARGS(OF_env, 0);
+ /* Should free all OF resources */
++ bd_reset_all();
+ #if defined (DEBUG_BIOS)
+ {
+ uint16_t loglevel = 0x02 | 0x10 | 0x80;
+diff -wruN --exclude '*~' --exclude '*.o' --exclude '*.bin' --exclude '*.out' --exclude mkdiff OpenHackWare-release-0.4.org/src/pci.c OpenHackWare-release-0.4/src/pci.c
+--- OpenHackWare-release-0.4.org/src/pci.c 2005-03-31 09:23:33.000000000 +0200
++++ OpenHackWare-release-0.4/src/pci.c 2005-07-07 23:27:37.000000000 +0200
+@@ -99,8 +99,8 @@
+ uint16_t min_grant;
+ uint16_t max_latency;
+ uint8_t irq_line;
+- uint32_t regions[6];
+- uint32_t sizes[6];
++ uint32_t regions[7]; /* the region 6 is the PCI ROM */
++ uint32_t sizes[7];
+ pci_device_t *next;
+ };
+
+@@ -158,6 +158,7 @@
+
+ /* IRQ numbers assigned to PCI IRQs */
+ static uint8_t prep_pci_irqs[4] = { 9, 11, 9, 11 };
++static uint8_t heathrow_pci_irqs[4] = { 0x15, 0x16, 0x17, 0x18 };
+ static uint8_t pmac_pci_irqs[4] = { 8, 9, 10, 11 };
+
+ /* PREP PCI host */
+@@ -399,6 +400,79 @@
+ &uninorth_config_readl, &uninorth_config_writel,
+ };
+
++/* Grackle PCI host */
++
++static uint32_t grackle_cfg_address (pci_bridge_t *bridge,
++ uint8_t bus, uint8_t devfn,
++ uint8_t offset)
++{
++ uint32_t addr;
++ addr = 0x80000000 | (bus << 16) | (devfn << 8) | (offset & 0xfc);
++ stswap32((uint32_t *)bridge->cfg_addr, addr);
++ return bridge->cfg_data + (offset & 3);
++}
++
++static uint8_t grackle_config_readb (pci_bridge_t *bridge,
++ uint8_t bus, uint8_t devfn,
++ uint8_t offset)
++{
++ uint32_t addr;
++ addr = grackle_cfg_address(bridge, bus, devfn, offset);
++ return *((uint8_t *)addr);
++}
++
++static void grackle_config_writeb (pci_bridge_t *bridge,
++ uint8_t bus, uint8_t devfn,
++ uint8_t offset, uint8_t val)
++{
++ uint32_t addr;
++ addr = grackle_cfg_address(bridge, bus, devfn, offset);
++ *((uint8_t *)addr) = val;
++}
++
++static uint16_t grackle_config_readw (pci_bridge_t *bridge,
++ uint8_t bus, uint8_t devfn,
++ uint8_t offset)
++{
++ uint32_t addr;
++ addr = grackle_cfg_address(bridge, bus, devfn, offset);
++ return ldswap16((uint16_t *)addr);
++}
++
++static void grackle_config_writew (pci_bridge_t *bridge,
++ uint8_t bus, uint8_t devfn,
++ uint8_t offset, uint16_t val)
++{
++ uint32_t addr;
++ addr = grackle_cfg_address(bridge, bus, devfn, offset);
++ stswap16((uint16_t *)addr, val);
++}
++
++static uint32_t grackle_config_readl (pci_bridge_t *bridge,
++ uint8_t bus, uint8_t devfn,
++ uint8_t offset)
++{
++ uint32_t addr;
++ addr = grackle_cfg_address(bridge, bus, devfn, offset);
++ return ldswap32((uint32_t *)addr);
++}
++
++static void grackle_config_writel (pci_bridge_t *bridge,
++ uint8_t bus, uint8_t devfn,
++ uint8_t offset, uint32_t val)
++{
++ uint32_t addr;
++
++ addr = grackle_cfg_address(bridge, bus, devfn, offset);
++ stswap32((uint32_t *)addr, val);
++}
++
++static pci_ops_t grackle_pci_ops = {
++ &grackle_config_readb, &grackle_config_writeb,
++ &grackle_config_readw, &grackle_config_writew,
++ &grackle_config_readl, &grackle_config_writel,
++};
++
+ static inline uint8_t pci_config_readb (pci_bridge_t *bridge,
+ uint8_t bus, uint8_t devfn,
+ uint8_t offset)
+@@ -466,12 +540,22 @@
+ },
+ };
+
++static int ide_config_cb2 (pci_device_t *device)
++{
++ OF_finalize_pci_ide(device->common.OF_private,
++ device->regions[0] & ~0x0000000F,
++ device->regions[1] & ~0x0000000F,
++ device->regions[2] & ~0x0000000F,
++ device->regions[3] & ~0x0000000F);
++ return 0;
++}
++
+ static pci_dev_t ide_devices[] = {
+ {
+- 0x8086, 0x0100,
+- NULL, "Qemu IDE", "Qemu IDE", "ide",
++ 0x1095, 0x0646, /* CMD646 IDE controller */
++ "pci-ide", "pci-ata", NULL, NULL,
+ 0, 0, 0,
+- NULL, NULL,
++ ide_config_cb2, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+@@ -481,7 +565,9 @@
+ },
+ };
+
+-static int ide_config_cb (pci_device_t *device)
++#if 0
++/* should base it on PCI ID, not on arch */
++static int ide_config_cb (unused pci_device_t *device)
+ {
+ printf("Register IDE controller\n");
+ switch (arch) {
+@@ -491,14 +577,8 @@
+ device->common.OF_private);
+ break;
+ default:
+- ide_pci_pc_register(device->regions[0] & ~0x0000000F,
+- device->regions[1] & ~0x0000000F,
+- device->regions[2] & ~0x0000000F,
+- device->regions[3] & ~0x0000000F,
+- device->common.OF_private);
+ break;
+ }
+-
+ return 0;
+ }
+
+@@ -512,16 +592,12 @@
+ device->common.OF_private);
+ break;
+ default:
+- ide_pci_pc_register(device->regions[0] & ~0x0000000F,
+- device->regions[1] & ~0x0000000F,
+- device->regions[2] & ~0x0000000F,
+- device->regions[3] & ~0x0000000F,
+- device->common.OF_private);
+ break;
+ }
+
+ return 0;
+ }
++#endif
+
+ static pci_subclass_t mass_subclass[] = {
+ {
+@@ -530,7 +606,7 @@
+ },
+ {
+ 0x01, "IDE controller", "ide", ide_devices, NULL,
+- &ide_config_cb, NULL,
++ NULL, NULL,
+ },
+ {
+ 0x02, "Floppy disk controller", NULL, NULL, NULL,
+@@ -546,7 +622,7 @@
+ },
+ {
+ 0x05, "ATA controller", "ata", NULL, NULL,
+- &ata_config_cb, NULL,
++ NULL, NULL,
+ },
+ {
+ 0x80, "misc mass-storage controller", NULL, NULL, NULL,
+@@ -646,7 +722,9 @@
+ /* VGA 640x480x16 */
+ OF_vga_register(device->common.device->name,
+ device->regions[0] & ~0x0000000F,
+- vga_width, vga_height, vga_depth);
++ vga_width, vga_height, vga_depth,
++ device->regions[6] & ~0x0000000F,
++ device->sizes[6]);
+ }
+ vga_console_register();
+
+@@ -750,6 +828,13 @@
+ NULL, &PREP_pci_ops,
+ };
+
++pci_dev_t grackle_fake_bridge = {
++ 0xFFFF, 0xFFFF,
++ "pci", "pci-bridge", "DEC,21154", "DEC,21154.pci-bridge",
++ -1, -1, -1,
++ NULL, &grackle_pci_ops,
++};
++
+ static pci_dev_t hbrg_devices[] = {
+ {
+ 0x106B, 0x0020, NULL,
+@@ -758,8 +843,8 @@
+ NULL, &uninorth_agp_fake_bridge,
+ },
+ {
+- 0x106B, 0x001F,
+- NULL, "pci", "AAPL,UniNorth", "uni-north",
++ 0x106B, 0x001F, NULL,
++ "pci", "AAPL,UniNorth", "uni-north",
+ 3, 2, 1,
+ NULL, &uninorth_fake_bridge,
+ },
+@@ -770,10 +855,10 @@
+ NULL, &uninorth_fake_bridge,
+ },
+ {
+- 0x1011, 0x0026, NULL,
+- "pci-bridge", NULL, NULL,
++ 0x1057, 0x0002, "pci",
++ "pci", "MOT,MPC106", "grackle",
+ 3, 2, 1,
+- NULL, &PREP_pci_ops,
++ NULL, &grackle_fake_bridge,
+ },
+ {
+ 0x1057, 0x4801, NULL,
+@@ -1443,7 +1528,14 @@
+ }
+
+ static const pci_dev_t misc_pci[] = {
+- /* Apple Mac-io controller */
++ /* Paddington Mac I/O */
++ {
++ 0x106B, 0x0017,
++ "mac-io", "mac-io", "AAPL,343S1211", "paddington\1heathrow",
++ 1, 1, 1,
++ &macio_config_cb, NULL,
++ },
++ /* KeyLargo Mac I/O */
+ {
+ 0x106B, 0x0022,
+ "mac-io", "mac-io", "AAPL,Keylargo", "Keylargo",
+@@ -1599,7 +1691,7 @@
+ uint8_t min_grant, uint8_t max_latency,
+ int irq_line)
+ {
+- uint32_t cmd;
++ uint32_t cmd, addr;
+ int i;
+
+ device->min_grant = min_grant;
+@@ -1611,22 +1703,28 @@
+ printf("MAP PCI device %d:%d to IRQ %d\n",
+ device->bus, device->devfn, irq_line);
+ }
+- for (i = 0; i < 6; i++) {
++ for (i = 0; i < 7; i++) {
+ if ((device->regions[i] & ~0xF) != 0x00000000 &&
+ (device->regions[i] & ~0xF) != 0xFFFFFFF0) {
+ printf("Map PCI device %d:%d %d to %0x %0x (%s)\n",
+ device->bus, device->devfn, i,
+ device->regions[i], device->sizes[i],
+- device->regions[i] & 0x00000001 ? "I/O" : "memory");
++ (device->regions[i] & 0x00000001) && i != 6 ? "I/O" :
++ "memory");
++ if (i != 6) {
+ cmd = pci_config_readl(bridge, device->bus, device->devfn, 0x04);
+ if (device->regions[i] & 0x00000001)
+ cmd |= 0x00000001;
+ else
+ cmd |= 0x00000002;
+ pci_config_writel(bridge, device->bus, device->devfn, 0x04, cmd);
++ }
++ if (i == 6)
++ addr = 0x30; /* PCI ROM */
++ else
++ addr = 0x10 + (i * sizeof(uint32_t));
+ pci_config_writel(bridge, device->bus, device->devfn,
+- 0x10 + (i * sizeof(uint32_t)),
+- device->regions[i]);
++ addr, device->regions[i]);
+ }
+ }
+ }
+@@ -1900,7 +1998,7 @@
+ goto out;
+ }
+ ret = (pci_u_t *)newd;
+- max_areas = 6;
++ max_areas = 7;
+ /* register PCI device in OF tree */
+ if (bridge->dev.common.type == PCI_FAKE_BRIDGE) {
+ newd->common.OF_private =
+@@ -1927,6 +2025,9 @@
+ /* Handle 64 bits memory mapping */
+ continue;
+ }
++ if (i == 6)
++ addr = 0x30; /* PCI ROM */
++ else
+ addr = 0x10 + (i * sizeof(uint32_t));
+ /* Get region size
+ * Note: we assume it's always a power of 2
+@@ -1935,7 +2036,7 @@
+ smask = pci_config_readl(bridge, bus, devfn, addr);
+ if (smask == 0x00000000 || smask == 0xFFFFFFFF)
+ continue;
+- if (smask & 0x00000001) {
++ if ((smask & 0x00000001) != 0 && i != 6) {
+ /* I/O space */
+ base = io_base;
+ /* Align to a minimum of 256 bytes (arbitrary) */
+@@ -1947,6 +2048,8 @@
+ /* Align to a minimum of 64 kB (arbitrary) */
+ min_align = 1 << 16;
+ amask = 0x0000000F;
++ if (i == 6)
++ smask |= 1; /* PCI ROM enable */
+ }
+ omask = smask & amask;
+ smask &= ~amask;
+@@ -1980,7 +2083,10 @@
+ if (irq_pin > 0) {
+ /* assign the IRQ */
+ irq_pin = ((devfn >> 3) + irq_pin - 1) & 3;
+- if (arch == ARCH_PREP) {
++ /* XXX: should base it on the PCI bridge type, not the arch */
++ switch(arch) {
++ case ARCH_PREP:
++ {
+ int elcr_port, val;
+ irq_line = prep_pci_irqs[irq_pin];
+ /* set the IRQ to level-sensitive */
+@@ -1988,14 +2094,22 @@
+ val = inb(elcr_port);
+ val |= 1 << (irq_line & 7);
+ outb(elcr_port, val);
+- } else {
++ }
++ break;
++ case ARCH_MAC99:
+ irq_line = pmac_pci_irqs[irq_pin];
++ break;
++ case ARCH_HEATHROW:
++ irq_line = heathrow_pci_irqs[irq_pin];
++ break;
++ default:
++ break;
+ }
+ }
+ update_device:
+ pci_update_device(bridge, newd, min_grant, max_latency, irq_line);
+ OF_finalize_pci_device(newd->common.OF_private, bus, devfn,
+- newd->regions, newd->sizes);
++ newd->regions, newd->sizes, irq_line);
+ /* Call special inits if needed */
+ if (dev->config_cb != NULL)
+ (*dev->config_cb)(newd);
+@@ -2049,6 +2163,32 @@
+ case ARCH_CHRP:
+ /* TODO */
+ break;
++ case ARCH_HEATHROW:
++ dev = pci_find_device(0x06, 0x00, 0xFF, checkv, checkp);
++ if (dev == NULL)
++ return -1;
++ fake_host = pci_add_host(hostp, dev,
++ (0x06 << 24) | (0x00 << 16) | (0xFF << 8));
++ if (fake_host == NULL)
++ return -1;
++ fake_host->dev.common.type = PCI_FAKE_HOST;
++ dev = &grackle_fake_bridge;
++ if (dev == NULL)
++ goto free_fake_host;
++ fake_bridge = pci_add_bridge(fake_host, 0, 0, dev,
++ (0x06 << 24) | (0x04 << 16) | (0xFF << 8),
++ cfg_base, cfg_len,
++ cfg_base + 0x7ec00000,
++ cfg_base + 0x7ee00000,
++ mem_base, mem_len,
++ io_base, io_len,
++ rbase, rlen,
++ 0,
++ &grackle_pci_ops);
++ if (fake_bridge == NULL)
++ goto free_fake_host;
++ fake_bridge->dev.common.type = PCI_FAKE_BRIDGE;
++ break;
+ case ARCH_MAC99:
+ dev = pci_find_device(0x06, 0x00, 0xFF, checkv, checkp);
+ if (dev == NULL)
+@@ -2167,6 +2307,30 @@
+ case ARCH_CHRP:
+ /* TODO */
+ break;
++ case ARCH_HEATHROW:
++ cfg_base = 0x80000000;
++ cfg_len = 0x7f000000;
++ mem_base = 0x80000000;
++ mem_len = 0x01000000;
++ io_base = 0xfe000000;
++ io_len = 0x00800000;
++#if 1
++ rbase = 0xfd000000;
++ rlen = 0x01000000;
++#else
++ rbase = 0x00000000;
++ rlen = 0x01000000;
++#endif
++ if (pci_check_host(&pci_main, cfg_base, cfg_len,
++ mem_base, mem_len, io_base, io_len, rbase, rlen,
++ 0x1057, 0x0002) == 0) {
++ isa_io_base = io_base;
++ busnum++;
++ }
++ for (curh = pci_main; curh->next != NULL; curh = curh->next)
++ continue;
++ pci_check_devices(curh);
++ break;
+ case ARCH_MAC99:
+ /* We are supposed to have 3 host bridges:
+ * - the uninorth AGP bridge at 0xF0000000
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
new file mode 100644
index 0000000..7a729aa
--- /dev/null
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/ppc_rom.bin b/pc-bios/ppc_rom.bin
new file mode 100644
index 0000000..f7cd8a8
--- /dev/null
+++ b/pc-bios/ppc_rom.bin
Binary files differ
diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin
new file mode 100644
index 0000000..34f9a9f
--- /dev/null
+++ b/pc-bios/vgabios-cirrus.bin
Binary files differ
diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin
new file mode 100644
index 0000000..17cb63f
--- /dev/null
+++ b/pc-bios/vgabios.bin
Binary files differ
diff --git a/pc-bios/vgabios.diff b/pc-bios/vgabios.diff
new file mode 100644
index 0000000..661c032
--- /dev/null
+++ b/pc-bios/vgabios.diff
@@ -0,0 +1,896 @@
+Index: Makefile
+===================================================================
+RCS file: /sources/vgabios/vgabios/Makefile,v
+retrieving revision 1.17
+diff -u -w -r1.17 Makefile
+--- Makefile 6 Mar 2005 13:06:47 -0000 1.17
++++ Makefile 14 Jun 2006 00:51:06 -0000
+@@ -22,7 +22,7 @@
+ cirrus-bios: vgabios-cirrus.bin vgabios-cirrus.debug.bin
+
+ clean:
+- /bin/rm -f biossums *.o *.s *.ld86 \
++ /bin/rm -f biossums vbetables-gen vbetables.h *.o *.s *.ld86 \
+ temp.awk.* vgabios*.orig _vgabios_* _vgabios-debug_* core vgabios*.bin vgabios*.txt $(RELEASE).bin *.bak
+
+ dist-clean: clean
+@@ -79,3 +79,9 @@
+
+ biossums: biossums.c
+ $(CC) -o biossums biossums.c
++
++vbetables-gen: vbetables-gen.c
++ $(CC) -o vbetables-gen vbetables-gen.c
++
++vbetables.h: vbetables-gen
++ ./vbetables-gen > $@
+Index: clext.c
+===================================================================
+RCS file: /sources/vgabios/vgabios/clext.c,v
+retrieving revision 1.10
+diff -u -w -r1.10 clext.c
+--- clext.c 25 Mar 2006 10:19:15 -0000 1.10
++++ clext.c 14 Jun 2006 00:51:06 -0000
+@@ -544,6 +544,13 @@
+ cirrus_set_video_mode_extended:
+ call cirrus_switch_mode
+ pop ax ;; mode
++ test al, #0x80
++ jnz cirrus_set_video_mode_extended_1
++ push ax
++ mov ax, #0xffff ; set to 0xff to keep win 2K happy
++ call cirrus_clear_vram
++ pop ax
++cirrus_set_video_mode_extended_1:
+ and al, #0x7f
+
+ push ds
+@@ -1011,6 +1018,13 @@
+ jnz cirrus_vesa_02h_3
+ call cirrus_enable_16k_granularity
+ cirrus_vesa_02h_3:
++ test bx, #0x8000 ;; no clear
++ jnz cirrus_vesa_02h_4
++ push ax
++ xor ax,ax
++ call cirrus_clear_vram
++ pop ax
++cirrus_vesa_02h_4:
+ pop ax
+ push ds
+ #ifdef CIRRUS_VESA3_PMINFO
+@@ -1479,6 +1493,38 @@
+ pop bx
+ ret
+
++cirrus_clear_vram:
++ pusha
++ push es
++ mov si, ax
++
++ call cirrus_enable_16k_granularity
++ call cirrus_extbios_85h
++ shl al, #2
++ mov bl, al
++ xor ah,ah
++cirrus_clear_vram_1:
++ mov al, #0x09
++ mov dx, #0x3ce
++ out dx, ax
++ push ax
++ mov cx, #0xa000
++ mov es, cx
++ xor di, di
++ mov ax, si
++ mov cx, #8192
++ cld
++ rep
++ stosw
++ pop ax
++ inc ah
++ cmp ah, bl
++ jne cirrus_clear_vram_1
++
++ pop es
++ popa
++ ret
++
+ cirrus_extbios_handlers:
+ ;; 80h
+ dw cirrus_extbios_80h
+Index: vbe.c
+===================================================================
+RCS file: /sources/vgabios/vgabios/vbe.c,v
+retrieving revision 1.48
+diff -u -w -r1.48 vbe.c
+--- vbe.c 26 Dec 2005 19:50:26 -0000 1.48
++++ vbe.c 14 Jun 2006 00:51:07 -0000
+@@ -118,21 +118,114 @@
+ .word VBE_VESA_MODE_END_OF_LIST
+ #endif
+
++ .align 2
+ vesa_pm_start:
+ dw vesa_pm_set_window - vesa_pm_start
+- dw vesa_pm_set_display_strt - vesa_pm_start
++ dw vesa_pm_set_display_start - vesa_pm_start
+ dw vesa_pm_unimplemented - vesa_pm_start
+- dw 0
++ dw vesa_pm_io_ports_table - vesa_pm_start
++vesa_pm_io_ports_table:
++ dw VBE_DISPI_IOPORT_INDEX
++ dw VBE_DISPI_IOPORT_INDEX + 1
++ dw VBE_DISPI_IOPORT_DATA
++ dw VBE_DISPI_IOPORT_DATA + 1
++ dw 0xffff
++ dw 0xffff
+
+ USE32
+ vesa_pm_set_window:
+- mov ax, #0x4f05
+- int #0x10
++ cmp bx, #0x00
++ je vesa_pm_set_display_window1
++ mov ax, #0x0100
++ ret
++vesa_pm_set_display_window1:
++ mov ax, dx
++ push dx
++ push ax
++ mov dx, # VBE_DISPI_IOPORT_INDEX
++ mov ax, # VBE_DISPI_INDEX_BANK
++ out dx, ax
++ pop ax
++ mov dx, # VBE_DISPI_IOPORT_DATA
++ out dx, ax
++ pop dx
++ mov ax, #0x004f
+ ret
+
+ vesa_pm_set_display_start:
+- mov ax, #0x4f07
+- int #0x10
++ cmp bl, #0x80
++ je vesa_pm_set_display_start1
++ cmp bl, #0x00
++ je vesa_pm_set_display_start1
++ mov ax, #0x0100
++ ret
++vesa_pm_set_display_start1:
++; convert offset to (X, Y) coordinate
++; (would be simpler to change Bochs VBE API...)
++ push eax
++ push ecx
++ push edx
++ push esi
++ push edi
++ shl edx, #16
++ and ecx, #0xffff
++ or ecx, edx
++ shl ecx, #2
++ mov eax, ecx
++
++ push eax
++ mov dx, # VBE_DISPI_IOPORT_INDEX
++ mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
++ out dx, ax
++ mov dx, # VBE_DISPI_IOPORT_DATA
++ in ax, dx
++ movzx ecx, ax
++
++ mov dx, # VBE_DISPI_IOPORT_INDEX
++ mov ax, # VBE_DISPI_INDEX_BPP
++ out dx, ax
++ mov dx, # VBE_DISPI_IOPORT_DATA
++ in ax, dx
++ movzx esi, ax
++ pop eax
++
++ add esi, #7
++ shr esi, #3
++ imul ecx, esi
++ xor edx, edx
++ div ecx
++ mov edi, eax
++ mov eax, edx
++ xor edx, edx
++ div esi
++
++ push dx
++ push ax
++ mov dx, # VBE_DISPI_IOPORT_INDEX
++ mov ax, # VBE_DISPI_INDEX_X_OFFSET
++ out dx, ax
++ pop ax
++ mov dx, # VBE_DISPI_IOPORT_DATA
++ out dx, ax
++ pop dx
++
++ mov ax, di
++ push dx
++ push ax
++ mov dx, # VBE_DISPI_IOPORT_INDEX
++ mov ax, # VBE_DISPI_INDEX_Y_OFFSET
++ out dx, ax
++ pop ax
++ mov dx, # VBE_DISPI_IOPORT_DATA
++ out dx, ax
++ pop dx
++
++ pop edi
++ pop esi
++ pop edx
++ pop ecx
++ pop eax
++ mov ax, #0x004f
+ ret
+
+ vesa_pm_unimplemented:
+@@ -835,6 +928,64 @@
+ ASM_END
+
+
++Bit16u vbe_biosfn_read_video_state_size()
++{
++ return 9 * 2;
++}
++
++void vbe_biosfn_save_video_state(ES, BX)
++ Bit16u ES; Bit16u BX;
++{
++ Bit16u enable, i;
++
++ outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
++ enable = inw(VBE_DISPI_IOPORT_DATA);
++ write_word(ES, BX, enable);
++ BX += 2;
++ if (!(enable & VBE_DISPI_ENABLED))
++ return;
++ for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
++ if (i != VBE_DISPI_INDEX_ENABLE) {
++ outw(VBE_DISPI_IOPORT_INDEX, i);
++ write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
++ BX += 2;
++ }
++ }
++}
++
++
++void vbe_biosfn_restore_video_state(ES, BX)
++ Bit16u ES; Bit16u BX;
++{
++ Bit16u enable, i;
++
++ enable = read_word(ES, BX);
++ BX += 2;
++
++ if (!(enable & VBE_DISPI_ENABLED)) {
++ outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
++ outw(VBE_DISPI_IOPORT_DATA, enable);
++ } else {
++ outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
++ outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
++ BX += 2;
++ outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
++ outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
++ BX += 2;
++ outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
++ outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
++ BX += 2;
++ outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
++ outw(VBE_DISPI_IOPORT_DATA, enable);
++
++ for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
++ outw(VBE_DISPI_IOPORT_INDEX, i);
++ outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
++ BX += 2;
++ }
++ }
++}
++
+ /** Function 04h - Save/Restore State
+ *
+ * Input:
+@@ -849,10 +1000,48 @@
+ * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
+ *
+ */
+-void vbe_biosfn_save_restore_state(AX, DL, CX, ES, BX)
++void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
++Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
+ {
+-}
++ Bit16u ss=get_SS();
++ Bit16u result, val;
+
++ result = 0x4f;
++ switch(GET_DL()) {
++ case 0x00:
++ val = biosfn_read_video_state_size2(CX);
++#ifdef DEBUG
++ printf("VGA state size=%x\n", val);
++#endif
++ if (CX & 8)
++ val += vbe_biosfn_read_video_state_size();
++ write_word(ss, BX, val);
++ break;
++ case 0x01:
++ val = read_word(ss, BX);
++ val = biosfn_save_video_state(CX, ES, val);
++#ifdef DEBUG
++ printf("VGA save_state offset=%x\n", val);
++#endif
++ if (CX & 8)
++ vbe_biosfn_save_video_state(ES, val);
++ break;
++ case 0x02:
++ val = read_word(ss, BX);
++ val = biosfn_restore_video_state(CX, ES, val);
++#ifdef DEBUG
++ printf("VGA restore_state offset=%x\n", val);
++#endif
++ if (CX & 8)
++ vbe_biosfn_restore_video_state(ES, val);
++ break;
++ default:
++ // function failed
++ result = 0x100;
++ break;
++ }
++ write_word(ss, AX, result);
++}
+
+ /** Function 05h - Display Window Control
+ *
+@@ -1090,7 +1279,7 @@
+ */
+ ASM_START
+ vbe_biosfn_return_protected_mode_interface:
+- test bx, bx
++ test bl, bl
+ jnz _fail
+ mov di, #0xc000
+ mov es, di
+Index: vbe.h
+===================================================================
+RCS file: /sources/vgabios/vgabios/vbe.h,v
+retrieving revision 1.24
+diff -u -w -r1.24 vbe.h
+--- vbe.h 9 May 2004 20:31:31 -0000 1.24
++++ vbe.h 14 Jun 2006 00:51:07 -0000
+@@ -14,7 +14,7 @@
+ void vbe_biosfn_return_controller_information(AX, ES, DI);
+ void vbe_biosfn_return_mode_information(AX, CX, ES, DI);
+ void vbe_biosfn_set_mode(AX, BX, ES, DI);
+-void vbe_biosfn_save_restore_state(AX, DL, CX, ES, BX);
++void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX);
+ void vbe_biosfn_set_get_palette_data(AX);
+ void vbe_biosfn_return_protected_mode_interface(AX);
+
+@@ -151,6 +151,12 @@
+ Bit8u Reserved[189];
+ } ModeInfoBlock;
+
++typedef struct ModeInfoListItem
++{
++ Bit16u mode;
++ ModeInfoBlockCompact info;
++} ModeInfoListItem;
++
+ // VBE Return Status Info
+ // AL
+ #define VBE_RETURN_STATUS_SUPPORTED 0x4F
+@@ -193,6 +199,10 @@
+ #define VBE_VESA_MODE_1280X1024X1555 0x119
+ #define VBE_VESA_MODE_1280X1024X565 0x11A
+ #define VBE_VESA_MODE_1280X1024X888 0x11B
++#define VBE_VESA_MODE_1600X1200X8 0x11C
++#define VBE_VESA_MODE_1600X1200X1555 0x11D
++#define VBE_VESA_MODE_1600X1200X565 0x11E
++#define VBE_VESA_MODE_1600X1200X888 0x11F
+
+ // BOCHS/PLEX86 'own' mode numbers
+ #define VBE_OWN_MODE_320X200X8888 0x140
+@@ -202,6 +212,12 @@
+ #define VBE_OWN_MODE_1024X768X8888 0x144
+ #define VBE_OWN_MODE_1280X1024X8888 0x145
+ #define VBE_OWN_MODE_320X200X8 0x146
++#define VBE_OWN_MODE_1600X1200X8888 0x147
++#define VBE_OWN_MODE_1152X864X8 0x148
++#define VBE_OWN_MODE_1152X864X1555 0x149
++#define VBE_OWN_MODE_1152X864X565 0x14a
++#define VBE_OWN_MODE_1152X864X888 0x14b
++#define VBE_OWN_MODE_1152X864X8888 0x14c
+
+ #define VBE_VESA_MODE_END_OF_LIST 0xFFFF
+
+@@ -259,7 +275,7 @@
+ // like 0xE0000000
+
+
+- #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 4
++ #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 8
+
+ #define VBE_DISPI_BANK_ADDRESS 0xA0000
+ #define VBE_DISPI_BANK_SIZE_KB 64
+Index: vgabios.c
+===================================================================
+RCS file: /sources/vgabios/vgabios/vgabios.c,v
+retrieving revision 1.64
+diff -u -w -r1.64 vgabios.c
+--- vgabios.c 25 Mar 2006 10:19:16 -0000 1.64
++++ vgabios.c 14 Jun 2006 00:51:07 -0000
+@@ -109,8 +109,8 @@
+ static void biosfn_write_string();
+ static void biosfn_read_state_info();
+ static void biosfn_read_video_state_size();
+-static void biosfn_save_video_state();
+-static void biosfn_restore_video_state();
++static Bit16u biosfn_save_video_state();
++static Bit16u biosfn_restore_video_state();
+ extern Bit8u video_save_pointer_table[];
+
+ // This is for compiling with gcc2 and gcc3
+@@ -748,12 +748,7 @@
+ vbe_biosfn_set_mode(&AX,BX,ES,DI);
+ break;
+ case 0x04:
+- //FIXME
+-#ifdef DEBUG
+- unimplemented();
+-#endif
+- // function failed
+- AX=0x100;
++ vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
+ break;
+ case 0x09:
+ //FIXME
+@@ -3138,23 +3133,215 @@
+ }
+
+ // --------------------------------------------------------------------------------------------
+-static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
++// --------------------------------------------------------------------------------------------
++static Bit16u biosfn_read_video_state_size2 (CX)
++ Bit16u CX;
+ {
+-#ifdef DEBUG
+- unimplemented();
+-#endif
++ Bit16u size;
++ size = 0;
++ if (CX & 1) {
++ size += 0x46;
++ }
++ if (CX & 2) {
++ size += (5 + 8 + 5) * 2 + 6;
++ }
++ if (CX & 4) {
++ size += 3 + 256 * 3 + 1;
+ }
+-static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
++ return size;
++}
++
++static void biosfn_read_video_state_size (CX, BX)
++ Bit16u CX; Bit16u *BX;
+ {
+-#ifdef DEBUG
+- unimplemented();
+-#endif
++ Bit16u ss=get_SS();
++ write_word(ss, BX, biosfn_read_video_state_size2(CX));
+ }
+-static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
++
++static Bit16u biosfn_save_video_state (CX,ES,BX)
++ Bit16u CX;Bit16u ES;Bit16u BX;
+ {
+-#ifdef DEBUG
+- unimplemented();
+-#endif
++ Bit16u i, v, crtc_addr, ar_index;
++
++ crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
++ if (CX & 1) {
++ write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
++ write_byte(ES, BX, inb(crtc_addr)); BX++;
++ write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
++ inb(VGAREG_ACTL_RESET);
++ ar_index = inb(VGAREG_ACTL_ADDRESS);
++ write_byte(ES, BX, ar_index); BX++;
++ write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
++
++ for(i=1;i<=4;i++){
++ outb(VGAREG_SEQU_ADDRESS, i);
++ write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
++ }
++ outb(VGAREG_SEQU_ADDRESS, 0);
++ write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
++
++ for(i=0;i<=0x18;i++) {
++ outb(crtc_addr,i);
++ write_byte(ES, BX, inb(crtc_addr+1)); BX++;
++ }
++
++ for(i=0;i<=0x13;i++) {
++ inb(VGAREG_ACTL_RESET);
++ outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
++ write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
++ }
++ inb(VGAREG_ACTL_RESET);
++
++ for(i=0;i<=8;i++) {
++ outb(VGAREG_GRDC_ADDRESS,i);
++ write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
++ }
++
++ write_word(ES, BX, crtc_addr); BX+= 2;
++
++ /* XXX: read plane latches */
++ write_byte(ES, BX, 0); BX++;
++ write_byte(ES, BX, 0); BX++;
++ write_byte(ES, BX, 0); BX++;
++ write_byte(ES, BX, 0); BX++;
++ }
++ if (CX & 2) {
++ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
++ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
++ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
++ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
++ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
++ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
++ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
++ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
++ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
++ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
++ for(i=0;i<8;i++) {
++ write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
++ BX += 2;
++ }
++ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
++ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
++ /* current font */
++ write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
++ write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
++ write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
++ write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
++ }
++ if (CX & 4) {
++ /* XXX: check this */
++ write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
++ write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
++ write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
++ // Set the whole dac always, from 0
++ outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
++ for(i=0;i<256*3;i++) {
++ write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
++ }
++ write_byte(ES, BX, 0); BX++; /* color select register */
++ }
++ return BX;
++}
++
++static Bit16u biosfn_restore_video_state (CX,ES,BX)
++ Bit16u CX;Bit16u ES;Bit16u BX;
++{
++ Bit16u i, crtc_addr, v, addr1, ar_index;
++
++ if (CX & 1) {
++ // Reset Attribute Ctl flip-flop
++ inb(VGAREG_ACTL_RESET);
++
++ crtc_addr = read_word(ES, BX + 0x40);
++ addr1 = BX;
++ BX += 5;
++
++ for(i=1;i<=4;i++){
++ outb(VGAREG_SEQU_ADDRESS, i);
++ outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
++ }
++ outb(VGAREG_SEQU_ADDRESS, 0);
++ outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
++
++ // Disable CRTC write protection
++ outw(crtc_addr,0x0011);
++ // Set CRTC regs
++ for(i=0;i<=0x18;i++) {
++ if (i != 0x11) {
++ outb(crtc_addr,i);
++ outb(crtc_addr+1, read_byte(ES, BX));
++ }
++ BX++;
++ }
++ // select crtc base address
++ v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
++ if (crtc_addr = 0x3d4)
++ v |= 0x01;
++ outb(VGAREG_WRITE_MISC_OUTPUT, v);
++
++ // enable write protection if needed
++ outb(crtc_addr, 0x11);
++ outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
++
++ // Set Attribute Ctl
++ ar_index = read_byte(ES, addr1 + 0x03);
++ inb(VGAREG_ACTL_RESET);
++ for(i=0;i<=0x13;i++) {
++ outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
++ outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
++ }
++ outb(VGAREG_ACTL_ADDRESS, ar_index);
++ inb(VGAREG_ACTL_RESET);
++
++ for(i=0;i<=8;i++) {
++ outb(VGAREG_GRDC_ADDRESS,i);
++ outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
++ }
++ BX += 2; /* crtc_addr */
++ BX += 4; /* plane latches */
++
++ outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
++ outb(crtc_addr, read_byte(ES, addr1)); addr1++;
++ outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
++ addr1++;
++ outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
++ }
++ if (CX & 2) {
++ write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
++ write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
++ write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
++ write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
++ write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
++ write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
++ write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
++ write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
++ write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
++ write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
++ for(i=0;i<8;i++) {
++ write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
++ BX += 2;
++ }
++ write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
++ write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
++ /* current font */
++ write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
++ write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
++ write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
++ write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
++ }
++ if (CX & 4) {
++ BX++;
++ v = read_byte(ES, BX); BX++;
++ outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
++ // Set the whole dac always, from 0
++ outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
++ for(i=0;i<256*3;i++) {
++ outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
++ }
++ BX++;
++ outb(VGAREG_DAC_WRITE_ADDRESS, v);
++ }
++ return BX;
+ }
+
+ // ============================================================================================
+diff -u -w vbetables-gen.c
+--- vbetables-gen.c 1970-01-01 01:00:00.000000000 +0100
++++ vbetables-gen.c 2006-06-14 00:52:18.000000000 +0200
+@@ -0,0 +1,217 @@
++/* Generate the VGABIOS VBE Tables */
++#include <stdlib.h>
++#include <stdio.h>
++
++typedef struct {
++ int width;
++ int height;
++ int depth;
++ int mode;
++} ModeInfo;
++
++ModeInfo modes[] = {
++ /* standard VESA modes */
++{ 640, 400, 8 , 0x100},
++{ 640, 480, 8 , 0x101},
++{ 800, 600, 4 , 0x102},
++{ 800, 600, 8 , 0x103},
++ //{ 1024, 768, 4 , 0x104},
++{ 1024, 768, 8 , 0x105},
++ //{ 1280, 1024, 4 , 0x106},
++{ 1280, 1024, 8 , 0x107},
++{ 320, 200, 15 , 0x10D},
++{ 320, 200, 16 , 0x10E},
++{ 320, 200, 24 , 0x10F},
++{ 640, 480, 15 , 0x110},
++{ 640, 480, 16 , 0x111},
++{ 640, 480, 24 , 0x112},
++{ 800, 600, 15 , 0x113},
++{ 800, 600, 16 , 0x114},
++{ 800, 600, 24 , 0x115},
++{ 1024, 768, 15 , 0x116},
++{ 1024, 768, 16 , 0x117},
++{ 1024, 768, 24 , 0x118},
++{ 1280, 1024, 15 , 0x119},
++{ 1280, 1024, 16 , 0x11A},
++{ 1280, 1024, 24 , 0x11B},
++{ 1600, 1200, 8 , 0x11C},
++{ 1600, 1200, 15 , 0x11D},
++{ 1600, 1200, 16 , 0x11E},
++{ 1600, 1200, 24 , 0x11F},
++
++ /* BOCHS/PLE, 86 'own' mode numbers */
++{ 320, 200, 32 , 0x140},
++{ 640, 400, 32 , 0x141},
++{ 640, 480, 32 , 0x142},
++{ 800, 600, 32 , 0x143},
++{ 1024, 768, 32 , 0x144},
++{ 1280, 1024, 32 , 0x145},
++{ 320, 200, 8 , 0x146},
++{ 1600, 1200, 32 , 0x147},
++{ 1152, 864, 8 , 0x148},
++{ 1152, 864, 15 , 0x149},
++{ 1152, 864, 16 , 0x14a},
++{ 1152, 864, 24 , 0x14b},
++{ 1152, 864, 32 , 0x14c},
++{ 0, },
++};
++
++int main(int argc, char **argv)
++{
++ const ModeInfo *pm;
++ int pitch, r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos;
++ const char *str;
++
++ printf("/* THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT */\n");
++ printf("static ModeInfoListItem mode_info_list[]=\n");
++ printf("{\n");
++ for(pm = modes; pm->mode != 0; pm++) {
++ printf("{ 0x%04x, /* %dx%dx%d */\n",
++ pm->mode, pm->width, pm->height, pm->depth);
++ printf("{ /*Bit16u ModeAttributes*/ %s,\n",
++ "VBE_MODE_ATTRIBUTE_SUPPORTED | "
++ "VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | "
++ "VBE_MODE_ATTRIBUTE_COLOR_MODE | "
++ "VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE | "
++ "VBE_MODE_ATTRIBUTE_GRAPHICS_MODE");
++
++ printf("/*Bit8u WinAAttributes*/ %s,\n",
++ "VBE_WINDOW_ATTRIBUTE_RELOCATABLE | "
++ "VBE_WINDOW_ATTRIBUTE_READABLE | "
++ "VBE_WINDOW_ATTRIBUTE_WRITEABLE");
++
++ printf("/*Bit8u WinBAttributes*/ %d,\n", 0);
++
++ printf("/*Bit16u WinGranularity*/ %s,\n", "VBE_DISPI_BANK_SIZE_KB");
++
++ printf("/*Bit16u WinSize*/ %s,\n", "VBE_DISPI_BANK_SIZE_KB");
++
++ printf("/*Bit16u WinASegment*/ %s,\n", "VGAMEM_GRAPH");
++
++ printf("/*Bit16u WinBSegment*/ 0x%04x,\n", 0);
++
++ printf("/*Bit32u WinFuncPtr*/ %d,\n", 0);
++
++ if (pm->depth == 4)
++ pitch = (pm->width + 7) / 8;
++ else
++ pitch = pm->width * ((pm->depth + 7) / 8);
++ printf("/*Bit16u BytesPerScanLine*/ %d,\n", pitch);
++
++ // Mandatory information for VBE 1.2 and above
++ printf("/*Bit16u XResolution*/ %d,\n", pm->width);
++ printf("/*Bit16u YResolution*/ %d,\n", pm->height);
++ printf("/*Bit8u XCharSize*/ %d,\n", 8);
++ printf("/*Bit8u YCharSize*/ %d,\n", 16);
++ if (pm->depth == 4) {
++ printf("/*Bit8u NumberOfPlanes*/ %d,\n", 4);
++ printf("/*Bit8u BitsPerPixel*/ %d,\n", pm->depth);
++ } else {
++ printf("/*Bit8u NumberOfPlanes*/ %d,\n", 1);
++ printf("/*Bit8u BitsPerPixel*/ %d,\n", pm->depth);
++ }
++ printf("/*Bit8u NumberOfBanks*/ %d,\n",
++ (pm->height * pitch + 65535) / 65536);
++
++ if (pm->depth == 4)
++ str = "VBE_MEMORYMODEL_PLANAR";
++ else if (pm->depth == 8)
++ str = "VBE_MEMORYMODEL_PACKED_PIXEL";
++ else
++ str = "VBE_MEMORYMODEL_DIRECT_COLOR";
++ printf("/*Bit8u MemoryModel*/ %s,\n", str);
++ printf("/*Bit8u BankSize*/ %d,\n", 0);
++ /* XXX: check */
++ printf("/*Bit8u NumberOfImagePages*/ %d,\n", 0);
++ printf("/*Bit8u Reserved_page*/ %d,\n", 0);
++
++ // Direct Color fields (required for direct/6 and YUV/7 memory models)
++ switch(pm->depth) {
++ case 15:
++ r_size = 5;
++ r_pos = 10;
++ g_size = 5;
++ g_pos = 5;
++ b_size = 5;
++ b_pos = 0;
++ a_size = 1;
++ a_pos = 15;
++ break;
++ case 16:
++ r_size = 5;
++ r_pos = 11;
++ g_size = 6;
++ g_pos = 5;
++ b_size = 5;
++ b_pos = 0;
++ a_size = 0;
++ a_pos = 0;
++ break;
++ case 24:
++ r_size = 8;
++ r_pos = 16;
++ g_size = 8;
++ g_pos = 8;
++ b_size = 8;
++ b_pos = 0;
++ a_size = 0;
++ a_pos = 0;
++ break;
++ case 32:
++ r_size = 8;
++ r_pos = 16;
++ g_size = 8;
++ g_pos = 8;
++ b_size = 8;
++ b_pos = 0;
++ a_size = 8;
++ a_pos = 24;
++ break;
++ default:
++ r_size = 0;
++ r_pos = 0;
++ g_size = 0;
++ g_pos = 0;
++ b_size = 0;
++ b_pos = 0;
++ a_size = 0;
++ a_pos = 0;
++ break;
++ }
++
++ printf("/*Bit8u RedMaskSize*/ %d,\n", r_size);
++ printf("/*Bit8u RedFieldPosition*/ %d,\n", r_pos);
++ printf("/*Bit8u GreenMaskSize*/ %d,\n", g_size);
++ printf("/*Bit8u GreenFieldPosition*/ %d,\n", g_pos);
++ printf("/*Bit8u BlueMaskSize*/ %d,\n", b_size);
++ printf("/*Bit8u BlueFieldPosition*/ %d,\n", b_pos);
++ printf("/*Bit8u RsvdMaskSize*/ %d,\n", a_size);
++ printf("/*Bit8u RsvdFieldPosition*/ %d,\n", a_pos);
++ printf("/*Bit8u DirectColorModeInfo*/ %d,\n", 0);
++
++// Mandatory information for VBE 2.0 and above
++ printf("/*Bit32u PhysBasePtr*/ %s,\n",
++ "VBE_DISPI_LFB_PHYSICAL_ADDRESS");
++ printf("/*Bit32u OffScreenMemOffset*/ %d,\n", 0);
++ printf("/*Bit16u OffScreenMemSize*/ %d,\n", 0);
++ // Mandatory information for VBE 3.0 and above
++ printf("/*Bit16u LinBytesPerScanLine*/ %d,\n", pitch);
++ printf("/*Bit8u BnkNumberOfPages*/ %d,\n", 0);
++ printf("/*Bit8u LinNumberOfPages*/ %d,\n", 0);
++ printf("/*Bit8u LinRedMaskSize*/ %d,\n", r_size);
++ printf("/*Bit8u LinRedFieldPosition*/ %d,\n", r_pos);
++ printf("/*Bit8u LinGreenMaskSize*/ %d,\n", g_size);
++ printf("/*Bit8u LinGreenFieldPosition*/ %d,\n", g_pos);
++ printf("/*Bit8u LinBlueMaskSize*/ %d,\n", b_size);
++ printf("/*Bit8u LinBlueFieldPosition*/ %d,\n", b_pos);
++ printf("/*Bit8u LinRsvdMaskSize*/ %d,\n", a_size);
++ printf("/*Bit8u LinRsvdFieldPosition*/ %d,\n", a_pos);
++ printf("/*Bit32u MaxPixelClock*/ %d,\n", 0);
++ printf("} },\n");
++ }
++ printf("{ VBE_VESA_MODE_END_OF_LIST,\n");
++ printf("{ 0,\n");
++ printf("} },\n");
++ printf("};\n");
++ return 0;
++}
diff --git a/pc-bios/video.x b/pc-bios/video.x
new file mode 100644
index 0000000..761aa0c
--- /dev/null
+++ b/pc-bios/video.x
Binary files differ