aboutsummaryrefslogtreecommitdiffstats
path: root/roms/openbios
diff options
context:
space:
mode:
authorfishsoupisgood <github@madingley.org>2019-04-29 01:17:54 +0100
committerfishsoupisgood <github@madingley.org>2019-05-27 03:43:43 +0100
commit3f2546b2ef55b661fd8dd69682b38992225e86f6 (patch)
tree65ca85f13617aee1dce474596800950f266a456c /roms/openbios
downloadqemu-master.tar.gz
qemu-master.tar.bz2
qemu-master.zip
Initial import of qemu-2.4.1HEADmaster
Diffstat (limited to 'roms/openbios')
-rw-r--r--roms/openbios/.gitignore3
-rw-r--r--roms/openbios/COPYING341
-rw-r--r--roms/openbios/Documentation/ChangeLog.arch1895
-rw-r--r--roms/openbios/Documentation/README.debugger50
-rw-r--r--roms/openbios/Documentation/TODO.sparc64
-rw-r--r--roms/openbios/Documentation/kernel/AUTHORS6
-rw-r--r--roms/openbios/Documentation/kernel/COPYING358
-rw-r--r--roms/openbios/Documentation/kernel/Changelog.stepan300
-rw-r--r--roms/openbios/Documentation/kernel/TODO11
-rw-r--r--roms/openbios/Documentation/kernel/dictformat.txt8
-rw-r--r--roms/openbios/Documentation/kernel/glossary.txt14
-rw-r--r--roms/openbios/Documentation/kernel/initializers.txt24
-rw-r--r--roms/openbios/Makefile51
-rw-r--r--roms/openbios/Makefile.target86
-rw-r--r--roms/openbios/README132
-rw-r--r--roms/openbios/VERSION1
-rw-r--r--roms/openbios/arch/amd64/Kconfig48
-rw-r--r--roms/openbios/arch/amd64/boot.c41
-rw-r--r--roms/openbios/arch/amd64/build.xml6
-rw-r--r--roms/openbios/arch/amd64/builtin.c25
-rw-r--r--roms/openbios/arch/amd64/console.c417
-rw-r--r--roms/openbios/arch/amd64/context.c124
-rw-r--r--roms/openbios/arch/amd64/context.h48
-rw-r--r--roms/openbios/arch/amd64/defconfig65
-rw-r--r--roms/openbios/arch/amd64/init.fs83
-rw-r--r--roms/openbios/arch/amd64/ldscript73
-rw-r--r--roms/openbios/arch/amd64/lib.c56
-rw-r--r--roms/openbios/arch/amd64/linux_load.c647
-rw-r--r--roms/openbios/arch/amd64/multiboot.c125
-rw-r--r--roms/openbios/arch/amd64/multiboot.h96
-rw-r--r--roms/openbios/arch/amd64/openbios.c108
-rw-r--r--roms/openbios/arch/amd64/openbios.h29
-rw-r--r--roms/openbios/arch/amd64/plainboot.c21
-rw-r--r--roms/openbios/arch/amd64/relocate.h1
-rw-r--r--roms/openbios/arch/amd64/segment.c134
-rw-r--r--roms/openbios/arch/amd64/segment.h30
-rw-r--r--roms/openbios/arch/amd64/switch.S116
-rw-r--r--roms/openbios/arch/amd64/sys_info.c58
-rw-r--r--roms/openbios/arch/build.xml10
-rw-r--r--roms/openbios/arch/ia64/Kconfig22
-rw-r--r--roms/openbios/arch/ia64/build.xml5
-rw-r--r--roms/openbios/arch/ia64/defconfig65
-rw-r--r--roms/openbios/arch/ia64/init.fs76
-rw-r--r--roms/openbios/arch/ppc/Kconfig48
-rw-r--r--roms/openbios/arch/ppc/Makefile79
-rw-r--r--roms/openbios/arch/ppc/Makefile.asm32
-rw-r--r--roms/openbios/arch/ppc/briq/briq.c194
-rw-r--r--roms/openbios/arch/ppc/briq/briq.fs115
-rw-r--r--roms/openbios/arch/ppc/briq/briq.h24
-rw-r--r--roms/openbios/arch/ppc/briq/init.c130
-rw-r--r--roms/openbios/arch/ppc/briq/kernel.c16
-rw-r--r--roms/openbios/arch/ppc/briq/main.c145
-rw-r--r--roms/openbios/arch/ppc/briq/methods.c333
-rw-r--r--roms/openbios/arch/ppc/briq/tree.c23
-rw-r--r--roms/openbios/arch/ppc/briq/tree.fs305
-rw-r--r--roms/openbios/arch/ppc/briq/vfd.c42
-rw-r--r--roms/openbios/arch/ppc/build.xml211
-rw-r--r--roms/openbios/arch/ppc/defconfig48
-rw-r--r--roms/openbios/arch/ppc/kernel.c99
-rw-r--r--roms/openbios/arch/ppc/kernel.h41
-rw-r--r--roms/openbios/arch/ppc/misc.S74
-rw-r--r--roms/openbios/arch/ppc/mmutypes.h76
-rw-r--r--roms/openbios/arch/ppc/mol/console.c30
-rw-r--r--roms/openbios/arch/ppc/mol/init.c119
-rw-r--r--roms/openbios/arch/ppc/mol/kernel.c16
-rw-r--r--roms/openbios/arch/ppc/mol/main.c370
-rw-r--r--roms/openbios/arch/ppc/mol/methods.c470
-rw-r--r--roms/openbios/arch/ppc/mol/mol.c165
-rw-r--r--roms/openbios/arch/ppc/mol/mol.fs107
-rw-r--r--roms/openbios/arch/ppc/mol/mol.h44
-rw-r--r--roms/openbios/arch/ppc/mol/osi-blk.c119
-rw-r--r--roms/openbios/arch/ppc/mol/osi-scsi.c271
-rw-r--r--roms/openbios/arch/ppc/mol/prom.c175
-rw-r--r--roms/openbios/arch/ppc/mol/prom.h47
-rw-r--r--roms/openbios/arch/ppc/mol/pseudodisk.c178
-rw-r--r--roms/openbios/arch/ppc/mol/tree.c165
-rw-r--r--roms/openbios/arch/ppc/mol/tree.fs103
-rw-r--r--roms/openbios/arch/ppc/ofmem.c308
-rw-r--r--roms/openbios/arch/ppc/osi.h170
-rw-r--r--roms/openbios/arch/ppc/osi_calls.h454
-rw-r--r--roms/openbios/arch/ppc/pearpc/console.c43
-rw-r--r--roms/openbios/arch/ppc/pearpc/init.c136
-rw-r--r--roms/openbios/arch/ppc/pearpc/kernel.c16
-rw-r--r--roms/openbios/arch/ppc/pearpc/main.c145
-rw-r--r--roms/openbios/arch/ppc/pearpc/methods.c329
-rw-r--r--roms/openbios/arch/ppc/pearpc/pearpc.c206
-rw-r--r--roms/openbios/arch/ppc/pearpc/pearpc.fs116
-rw-r--r--roms/openbios/arch/ppc/pearpc/pearpc.h26
-rw-r--r--roms/openbios/arch/ppc/pearpc/tree.c23
-rw-r--r--roms/openbios/arch/ppc/pearpc/tree.fs305
-rw-r--r--roms/openbios/arch/ppc/pearpc/vfd.c42
-rw-r--r--roms/openbios/arch/ppc/ppc.fs68
-rw-r--r--roms/openbios/arch/ppc/qemu/console.c88
-rw-r--r--roms/openbios/arch/ppc/qemu/init.c951
-rw-r--r--roms/openbios/arch/ppc/qemu/kernel.c115
-rw-r--r--roms/openbios/arch/ppc/qemu/kernel.h42
-rw-r--r--roms/openbios/arch/ppc/qemu/ldscript68
-rw-r--r--roms/openbios/arch/ppc/qemu/main.c85
-rw-r--r--roms/openbios/arch/ppc/qemu/methods.c327
-rw-r--r--roms/openbios/arch/ppc/qemu/mmutypes.h97
-rw-r--r--roms/openbios/arch/ppc/qemu/ofmem.c563
-rw-r--r--roms/openbios/arch/ppc/qemu/qemu.c106
-rw-r--r--roms/openbios/arch/ppc/qemu/qemu.fs95
-rw-r--r--roms/openbios/arch/ppc/qemu/qemu.h24
-rw-r--r--roms/openbios/arch/ppc/qemu/start.S729
-rw-r--r--roms/openbios/arch/ppc/qemu/tree.fs71
-rw-r--r--roms/openbios/arch/ppc/qemu/vfd.c42
-rw-r--r--roms/openbios/arch/ppc/start.S335
-rw-r--r--roms/openbios/arch/ppc/timebase.S33
-rw-r--r--roms/openbios/arch/ppc64/qemu/ldscript85
-rw-r--r--roms/openbios/arch/sparc32/boot.c261
-rw-r--r--roms/openbios/arch/sparc32/boot.h41
-rw-r--r--roms/openbios/arch/sparc32/build.xml74
-rw-r--r--roms/openbios/arch/sparc32/builtin.c33
-rw-r--r--roms/openbios/arch/sparc32/call-romvec.S94
-rw-r--r--roms/openbios/arch/sparc32/console.c62
-rw-r--r--roms/openbios/arch/sparc32/context.c113
-rw-r--r--roms/openbios/arch/sparc32/context.h31
-rw-r--r--roms/openbios/arch/sparc32/crs.h0
-rw-r--r--roms/openbios/arch/sparc32/entry.S532
-rw-r--r--roms/openbios/arch/sparc32/init.fs83
-rw-r--r--roms/openbios/arch/sparc32/ldscript73
-rw-r--r--roms/openbios/arch/sparc32/lib.c397
-rw-r--r--roms/openbios/arch/sparc32/linux_load.c648
-rw-r--r--roms/openbios/arch/sparc32/multiboot.c125
-rw-r--r--roms/openbios/arch/sparc32/multiboot.h96
-rw-r--r--roms/openbios/arch/sparc32/ofmem_sparc32.c253
-rw-r--r--roms/openbios/arch/sparc32/openbios.c1005
-rw-r--r--roms/openbios/arch/sparc32/openbios.h28
-rw-r--r--roms/openbios/arch/sparc32/openprom.h260
-rw-r--r--roms/openbios/arch/sparc32/pgtsrmmu.h223
-rw-r--r--roms/openbios/arch/sparc32/plainboot.c21
-rw-r--r--roms/openbios/arch/sparc32/psr.h88
-rw-r--r--roms/openbios/arch/sparc32/romvec.c524
-rw-r--r--roms/openbios/arch/sparc32/romvec.h79
-rw-r--r--roms/openbios/arch/sparc32/switch.S154
-rw-r--r--roms/openbios/arch/sparc32/sys_info.c58
-rw-r--r--roms/openbios/arch/sparc32/tree.fs114
-rw-r--r--roms/openbios/arch/sparc32/udiv.S357
-rw-r--r--roms/openbios/arch/sparc32/vectors.S254
-rw-r--r--roms/openbios/arch/sparc32/wof.S133
-rw-r--r--roms/openbios/arch/sparc32/wuf.S154
-rw-r--r--roms/openbios/arch/sparc64/boot.c130
-rw-r--r--roms/openbios/arch/sparc64/boot.h35
-rw-r--r--roms/openbios/arch/sparc64/build.xml72
-rw-r--r--roms/openbios/arch/sparc64/builtin.c33
-rw-r--r--roms/openbios/arch/sparc64/call-client.S236
-rw-r--r--roms/openbios/arch/sparc64/console.c68
-rw-r--r--roms/openbios/arch/sparc64/const.h19
-rw-r--r--roms/openbios/arch/sparc64/context.c129
-rw-r--r--roms/openbios/arch/sparc64/context.h33
-rw-r--r--roms/openbios/arch/sparc64/entry.S287
-rw-r--r--roms/openbios/arch/sparc64/init.fs61
-rw-r--r--roms/openbios/arch/sparc64/ldscript67
-rw-r--r--roms/openbios/arch/sparc64/lib.c508
-rw-r--r--roms/openbios/arch/sparc64/linux_load.c653
-rw-r--r--roms/openbios/arch/sparc64/lsu.h20
-rw-r--r--roms/openbios/arch/sparc64/multiboot.c125
-rw-r--r--roms/openbios/arch/sparc64/multiboot.h96
-rw-r--r--roms/openbios/arch/sparc64/ofmem_sparc64.c381
-rw-r--r--roms/openbios/arch/sparc64/openbios.c664
-rw-r--r--roms/openbios/arch/sparc64/openbios.h27
-rw-r--r--roms/openbios/arch/sparc64/openprom.h281
-rw-r--r--roms/openbios/arch/sparc64/plainboot.c21
-rw-r--r--roms/openbios/arch/sparc64/pstate.h90
-rw-r--r--roms/openbios/arch/sparc64/spitfire.h510
-rw-r--r--roms/openbios/arch/sparc64/switch.S124
-rw-r--r--roms/openbios/arch/sparc64/sys_info.c59
-rw-r--r--roms/openbios/arch/sparc64/tree.fs49
-rw-r--r--roms/openbios/arch/sparc64/vectors.S765
-rw-r--r--roms/openbios/arch/unix/Kconfig18
-rw-r--r--roms/openbios/arch/unix/Makefile29
-rw-r--r--roms/openbios/arch/unix/blk.c115
-rw-r--r--roms/openbios/arch/unix/blk.h8
-rw-r--r--roms/openbios/arch/unix/boot.c84
-rw-r--r--roms/openbios/arch/unix/build.xml23
-rw-r--r--roms/openbios/arch/unix/gui_qt/Makefile42
-rw-r--r--roms/openbios/arch/unix/gui_qt/gui-qt.cpp128
-rw-r--r--roms/openbios/arch/unix/gui_qt/gui-qt.h44
-rw-r--r--roms/openbios/arch/unix/gui_qt/gui-qt.pro18
-rw-r--r--roms/openbios/arch/unix/gui_qt/logo.xpm132
-rw-r--r--roms/openbios/arch/unix/gui_qt/qt-main.cpp97
-rw-r--r--roms/openbios/arch/unix/plugins.c197
-rw-r--r--roms/openbios/arch/unix/plugins/Kconfig16
-rw-r--r--roms/openbios/arch/unix/plugins/Makefile13
-rw-r--r--roms/openbios/arch/unix/plugins/Rules.plugin15
-rw-r--r--roms/openbios/arch/unix/plugins/loader.c209
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_pci/Makefile7
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_pci/Makefile.old21
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_pci/plugin_pci.c221
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_qt/Makefile37
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_qt/logo.xpm132
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_qt/pciconfig.h42
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.cpp128
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.h44
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.pro18
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_qt/qt_main.cpp102
-rw-r--r--roms/openbios/arch/unix/plugins/plugin_qt/qt_rom.fs85
-rw-r--r--roms/openbios/arch/unix/tree.fs116
-rw-r--r--roms/openbios/arch/unix/unix.c611
-rw-r--r--roms/openbios/arch/x86/Kconfig47
-rw-r--r--roms/openbios/arch/x86/boot.c74
-rw-r--r--roms/openbios/arch/x86/boot.h18
-rw-r--r--roms/openbios/arch/x86/build.xml86
-rw-r--r--roms/openbios/arch/x86/builtin.c32
-rw-r--r--roms/openbios/arch/x86/console.c418
-rw-r--r--roms/openbios/arch/x86/context.c130
-rw-r--r--roms/openbios/arch/x86/context.h48
-rw-r--r--roms/openbios/arch/x86/defconfig65
-rw-r--r--roms/openbios/arch/x86/entry.S315
-rw-r--r--roms/openbios/arch/x86/exception.c92
-rw-r--r--roms/openbios/arch/x86/init.fs84
-rw-r--r--roms/openbios/arch/x86/ldscript73
-rw-r--r--roms/openbios/arch/x86/lib.c56
-rw-r--r--roms/openbios/arch/x86/linux_load.c671
-rw-r--r--roms/openbios/arch/x86/multiboot.c127
-rw-r--r--roms/openbios/arch/x86/multiboot.h96
-rw-r--r--roms/openbios/arch/x86/openbios.c134
-rw-r--r--roms/openbios/arch/x86/openbios.h32
-rw-r--r--roms/openbios/arch/x86/plainboot.c21
-rw-r--r--roms/openbios/arch/x86/relocate.h1
-rw-r--r--roms/openbios/arch/x86/segment.c133
-rw-r--r--roms/openbios/arch/x86/segment.h30
-rw-r--r--roms/openbios/arch/x86/sys_info.c57
-rw-r--r--roms/openbios/arch/x86/xbox/console.c23
-rw-r--r--roms/openbios/arch/x86/xbox/methods.c102
-rw-r--r--roms/openbios/build.xml14
-rw-r--r--roms/openbios/config/examples/amd64_config.xml61
-rw-r--r--roms/openbios/config/examples/ppc64_config.xml77
-rw-r--r--roms/openbios/config/examples/ppc_config.xml85
-rw-r--r--roms/openbios/config/examples/sparc32_config.xml74
-rw-r--r--roms/openbios/config/examples/sparc64_config.xml74
-rw-r--r--roms/openbios/config/examples/x86_config.xml63
-rwxr-xr-xroms/openbios/config/scripts/reldir10
-rwxr-xr-xroms/openbios/config/scripts/switch-arch427
-rw-r--r--roms/openbios/config/xml/config-c.xsl57
-rw-r--r--roms/openbios/config/xml/config-forth.xsl41
-rw-r--r--roms/openbios/config/xml/dictionary.xsl195
-rw-r--r--roms/openbios/config/xml/fcode.xsl48
-rw-r--r--roms/openbios/config/xml/makefile.xsl20
-rw-r--r--roms/openbios/config/xml/object.xsl327
-rw-r--r--roms/openbios/config/xml/rules.xml34
-rw-r--r--roms/openbios/config/xml/util.xsl80
-rw-r--r--roms/openbios/config/xml/xinclude.xsl43
-rw-r--r--roms/openbios/drivers/Kconfig59
-rw-r--r--roms/openbios/drivers/adb_bus.c257
-rw-r--r--roms/openbios/drivers/adb_bus.h104
-rw-r--r--roms/openbios/drivers/adb_kbd.c595
-rw-r--r--roms/openbios/drivers/adb_kbd.h22
-rw-r--r--roms/openbios/drivers/adb_mouse.c67
-rw-r--r--roms/openbios/drivers/adb_mouse.h22
-rw-r--r--roms/openbios/drivers/build.xml41
-rw-r--r--roms/openbios/drivers/cgthree.fs197
-rw-r--r--roms/openbios/drivers/cuda.c424
-rw-r--r--roms/openbios/drivers/cuda.h17
-rw-r--r--roms/openbios/drivers/escc.c476
-rw-r--r--roms/openbios/drivers/escc.h9
-rw-r--r--roms/openbios/drivers/esp.c598
-rw-r--r--roms/openbios/drivers/esp.fs18
-rw-r--r--roms/openbios/drivers/esp.h269
-rw-r--r--roms/openbios/drivers/floppy.c1179
-rw-r--r--roms/openbios/drivers/floppy.h9
-rw-r--r--roms/openbios/drivers/fw_cfg.c76
-rw-r--r--roms/openbios/drivers/hdreg.h289
-rw-r--r--roms/openbios/drivers/ide.c1685
-rw-r--r--roms/openbios/drivers/ide.h213
-rw-r--r--roms/openbios/drivers/iommu.c207
-rw-r--r--roms/openbios/drivers/iommu.h102
-rw-r--r--roms/openbios/drivers/kbd.c116
-rw-r--r--roms/openbios/drivers/kbd.h108
-rw-r--r--roms/openbios/drivers/macio.c281
-rw-r--r--roms/openbios/drivers/macio.h5
-rw-r--r--roms/openbios/drivers/obio.c525
-rw-r--r--roms/openbios/drivers/obio.h165
-rw-r--r--roms/openbios/drivers/pc_kbd.c236
-rw-r--r--roms/openbios/drivers/pc_serial.c208
-rw-r--r--roms/openbios/drivers/pci.c1569
-rw-r--r--roms/openbios/drivers/pci.fs92
-rw-r--r--roms/openbios/drivers/pci.h87
-rw-r--r--roms/openbios/drivers/pci_database.c1275
-rw-r--r--roms/openbios/drivers/pci_database.h57
-rw-r--r--roms/openbios/drivers/sbus.c523
-rw-r--r--roms/openbios/drivers/sbus.fs94
-rw-r--r--roms/openbios/drivers/scsi.h262
-rw-r--r--roms/openbios/drivers/tcx.fs280
-rw-r--r--roms/openbios/drivers/timer.c100
-rw-r--r--roms/openbios/drivers/timer.h62
-rw-r--r--roms/openbios/drivers/usb.c587
-rw-r--r--roms/openbios/drivers/usb.h357
-rw-r--r--roms/openbios/drivers/usbhid.c579
-rw-r--r--roms/openbios/drivers/usbohci.c926
-rw-r--r--roms/openbios/drivers/usbohci.h45
-rw-r--r--roms/openbios/drivers/usbohci_private.h270
-rw-r--r--roms/openbios/drivers/usbohci_rh.c212
-rw-r--r--roms/openbios/drivers/vga.fs204
-rw-r--r--roms/openbios/drivers/vga.h231
-rw-r--r--roms/openbios/drivers/vga_load_regs.c496
-rw-r--r--roms/openbios/drivers/vga_set_mode.c148
-rw-r--r--roms/openbios/forth/Kconfig9
-rw-r--r--roms/openbios/forth/admin/README3
-rw-r--r--roms/openbios/forth/admin/banner.fs49
-rw-r--r--roms/openbios/forth/admin/build.xml25
-rw-r--r--roms/openbios/forth/admin/callback.fs10
-rw-r--r--roms/openbios/forth/admin/devices.fs515
-rw-r--r--roms/openbios/forth/admin/help.fs51
-rw-r--r--roms/openbios/forth/admin/iocontrol.fs168
-rw-r--r--roms/openbios/forth/admin/nvram.fs385
-rw-r--r--roms/openbios/forth/admin/reset.fs12
-rw-r--r--roms/openbios/forth/admin/script.fs16
-rw-r--r--roms/openbios/forth/admin/security.fs10
-rw-r--r--roms/openbios/forth/admin/selftest.fs49
-rw-r--r--roms/openbios/forth/admin/userboot.fs29
-rw-r--r--roms/openbios/forth/bootstrap/bootstrap.fs1590
-rw-r--r--roms/openbios/forth/bootstrap/build.xml16
-rw-r--r--roms/openbios/forth/bootstrap/builtin.fs28
-rw-r--r--roms/openbios/forth/bootstrap/hayes.fs1064
-rw-r--r--roms/openbios/forth/bootstrap/interpreter.fs175
-rw-r--r--roms/openbios/forth/bootstrap/memory.fs216
-rw-r--r--roms/openbios/forth/bootstrap/start.fs69
-rw-r--r--roms/openbios/forth/build.xml13
-rw-r--r--roms/openbios/forth/debugging/build.xml18
-rw-r--r--roms/openbios/forth/debugging/client.fs299
-rw-r--r--roms/openbios/forth/debugging/fcode.fs14
-rw-r--r--roms/openbios/forth/debugging/firmware.fs90
-rw-r--r--roms/openbios/forth/debugging/see.fs114
-rw-r--r--roms/openbios/forth/device/README.device22
-rw-r--r--roms/openbios/forth/device/build.xml31
-rw-r--r--roms/openbios/forth/device/builtin.fs30
-rw-r--r--roms/openbios/forth/device/device.fs202
-rw-r--r--roms/openbios/forth/device/display.fs421
-rw-r--r--roms/openbios/forth/device/extra.fs103
-rw-r--r--roms/openbios/forth/device/fcode.fs573
-rw-r--r--roms/openbios/forth/device/feval.fs100
-rw-r--r--roms/openbios/forth/device/font.fs17
-rw-r--r--roms/openbios/forth/device/logo.fs98
-rw-r--r--roms/openbios/forth/device/missing38
-rw-r--r--roms/openbios/forth/device/other.fs233
-rw-r--r--roms/openbios/forth/device/package.fs287
-rw-r--r--roms/openbios/forth/device/pathres.fs522
-rw-r--r--roms/openbios/forth/device/preof.fs49
-rw-r--r--roms/openbios/forth/device/property.fs335
-rw-r--r--roms/openbios/forth/device/romfont.binbin0 -> 4096 bytes
-rw-r--r--roms/openbios/forth/device/structures.fs54
-rw-r--r--roms/openbios/forth/device/table.fs462
-rw-r--r--roms/openbios/forth/device/terminal.fs302
-rw-r--r--roms/openbios/forth/device/tree.fs59
-rw-r--r--roms/openbios/forth/lib/64bit.fs128
-rw-r--r--roms/openbios/forth/lib/build.xml22
-rw-r--r--roms/openbios/forth/lib/creation.fs52
-rw-r--r--roms/openbios/forth/lib/lists.fs26
-rw-r--r--roms/openbios/forth/lib/locals.fs197
-rw-r--r--roms/openbios/forth/lib/preinclude.fs11
-rw-r--r--roms/openbios/forth/lib/preprocessor.fs76
-rw-r--r--roms/openbios/forth/lib/split.fs49
-rw-r--r--roms/openbios/forth/lib/string.fs127
-rw-r--r--roms/openbios/forth/lib/vocabulary.fs153
-rw-r--r--roms/openbios/forth/packages/Kconfig16
-rw-r--r--roms/openbios/forth/packages/README11
-rw-r--r--roms/openbios/forth/packages/build.xml19
-rw-r--r--roms/openbios/forth/packages/deblocker.fs63
-rw-r--r--roms/openbios/forth/packages/disklabel.fs22
-rw-r--r--roms/openbios/forth/packages/obp-tftp.fs22
-rw-r--r--roms/openbios/forth/packages/packages.fs17
-rw-r--r--roms/openbios/forth/packages/terminal-emulator.fs23
-rw-r--r--roms/openbios/forth/system/build.xml16
-rw-r--r--roms/openbios/forth/system/ciface.fs363
-rw-r--r--roms/openbios/forth/system/main.fs60
-rw-r--r--roms/openbios/forth/testsuite/README8
-rw-r--r--roms/openbios/forth/testsuite/build.xml16
-rw-r--r--roms/openbios/forth/testsuite/fract.fs35
-rw-r--r--roms/openbios/forth/testsuite/framebuffer-test.fs10
-rw-r--r--roms/openbios/forth/testsuite/memory-testsuite.fs106
-rw-r--r--roms/openbios/forth/testsuite/splitfunc-testsuite.fs38
-rw-r--r--roms/openbios/forth/util/apic.fs62
-rw-r--r--roms/openbios/forth/util/build.xml19
-rw-r--r--roms/openbios/forth/util/pci.fs92
-rw-r--r--roms/openbios/forth/util/util.fs95
-rw-r--r--roms/openbios/fs/build.xml14
-rw-r--r--roms/openbios/fs/ext2/build.xml14
-rw-r--r--roms/openbios/fs/ext2/ext2.h33
-rw-r--r--roms/openbios/fs/ext2/ext2_close.c18
-rw-r--r--roms/openbios/fs/ext2/ext2_closedir.c18
-rw-r--r--roms/openbios/fs/ext2/ext2_fs.c309
-rw-r--r--roms/openbios/fs/ext2/ext2_fs.h534
-rw-r--r--roms/openbios/fs/ext2/ext2_lseek.c38
-rw-r--r--roms/openbios/fs/ext2/ext2_mount.c62
-rw-r--r--roms/openbios/fs/ext2/ext2_open.c65
-rw-r--r--roms/openbios/fs/ext2/ext2_opendir.c49
-rw-r--r--roms/openbios/fs/ext2/ext2_read.c23
-rw-r--r--roms/openbios/fs/ext2/ext2_readdir.c25
-rw-r--r--roms/openbios/fs/ext2/ext2_utils.c332
-rw-r--r--roms/openbios/fs/ext2/ext2_utils.h54
-rw-r--r--roms/openbios/fs/ext2/libext2.h25
-rw-r--r--roms/openbios/fs/grubfs/Kconfig83
-rw-r--r--roms/openbios/fs/grubfs/build.xml17
-rw-r--r--roms/openbios/fs/grubfs/debug.h1
-rw-r--r--roms/openbios/fs/grubfs/defs.h86
-rw-r--r--roms/openbios/fs/grubfs/dir.h141
-rw-r--r--roms/openbios/fs/grubfs/disk_inode.h110
-rw-r--r--roms/openbios/fs/grubfs/disk_inode_ffs.h101
-rw-r--r--roms/openbios/fs/grubfs/fat.h99
-rw-r--r--roms/openbios/fs/grubfs/filesys.h303
-rw-r--r--roms/openbios/fs/grubfs/fs.h457
-rw-r--r--roms/openbios/fs/grubfs/fsys_affs.c712
-rw-r--r--roms/openbios/fs/grubfs/fsys_ext2fs.c794
-rw-r--r--roms/openbios/fs/grubfs/fsys_fat.c477
-rw-r--r--roms/openbios/fs/grubfs/fsys_ffs.c311
-rw-r--r--roms/openbios/fs/grubfs/fsys_iso9660.c342
-rw-r--r--roms/openbios/fs/grubfs/fsys_jfs.c404
-rw-r--r--roms/openbios/fs/grubfs/fsys_minix.c535
-rw-r--r--roms/openbios/fs/grubfs/fsys_ntfs.c1255
-rw-r--r--roms/openbios/fs/grubfs/fsys_reiserfs.c1220
-rw-r--r--roms/openbios/fs/grubfs/fsys_ufs.c391
-rw-r--r--roms/openbios/fs/grubfs/fsys_vstafs.c254
-rw-r--r--roms/openbios/fs/grubfs/fsys_xfs.c639
-rw-r--r--roms/openbios/fs/grubfs/glue.h48
-rw-r--r--roms/openbios/fs/grubfs/grubfs_fs.c398
-rw-r--r--roms/openbios/fs/grubfs/iso9660.h167
-rw-r--r--roms/openbios/fs/grubfs/jfs.h604
-rw-r--r--roms/openbios/fs/grubfs/shared.h3
-rw-r--r--roms/openbios/fs/grubfs/ufs_dinode.h191
-rw-r--r--roms/openbios/fs/grubfs/ufs_fs.h635
-rw-r--r--roms/openbios/fs/grubfs/vstafs.h89
-rw-r--r--roms/openbios/fs/grubfs/xfs.h546
-rw-r--r--roms/openbios/fs/hfs/block.c612
-rw-r--r--roms/openbios/fs/hfs/btree.c230
-rw-r--r--roms/openbios/fs/hfs/build.xml15
-rw-r--r--roms/openbios/fs/hfs/data.c476
-rw-r--r--roms/openbios/fs/hfs/file.c191
-rw-r--r--roms/openbios/fs/hfs/hfs.c747
-rw-r--r--roms/openbios/fs/hfs/hfs_fs.c593
-rw-r--r--roms/openbios/fs/hfs/include/apple.h273
-rw-r--r--roms/openbios/fs/hfs/include/block.h41
-rw-r--r--roms/openbios/fs/hfs/include/btree.h34
-rw-r--r--roms/openbios/fs/hfs/include/data.h57
-rw-r--r--roms/openbios/fs/hfs/include/file.h46
-rw-r--r--roms/openbios/fs/hfs/include/hfs.h180
-rw-r--r--roms/openbios/fs/hfs/include/libhfs.h225
-rw-r--r--roms/openbios/fs/hfs/include/low.h45
-rw-r--r--roms/openbios/fs/hfs/include/medium.h43
-rw-r--r--roms/openbios/fs/hfs/include/node.h35
-rw-r--r--roms/openbios/fs/hfs/include/record.h48
-rw-r--r--roms/openbios/fs/hfs/include/volume.h71
-rw-r--r--roms/openbios/fs/hfs/low.c157
-rw-r--r--roms/openbios/fs/hfs/medium.c84
-rw-r--r--roms/openbios/fs/hfs/node.c60
-rw-r--r--roms/openbios/fs/hfs/record.c553
-rw-r--r--roms/openbios/fs/hfs/volume.c612
-rw-r--r--roms/openbios/fs/hfs_mdb.h118
-rw-r--r--roms/openbios/fs/hfsplus/build.xml11
-rw-r--r--roms/openbios/fs/hfsplus/hfsp_blockiter.c141
-rw-r--r--roms/openbios/fs/hfsplus/hfsp_btree.c372
-rw-r--r--roms/openbios/fs/hfsplus/hfsp_fs.c632
-rw-r--r--roms/openbios/fs/hfsplus/hfsp_record.c759
-rw-r--r--roms/openbios/fs/hfsplus/hfsp_unicode.c511
-rw-r--r--roms/openbios/fs/hfsplus/hfsp_volume.c323
-rw-r--r--roms/openbios/fs/hfsplus/include/apple.h111
-rw-r--r--roms/openbios/fs/hfsplus/include/blockiter.h59
-rw-r--r--roms/openbios/fs/hfsplus/include/btree.h50
-rw-r--r--roms/openbios/fs/hfsplus/include/hfs.h32
-rw-r--r--roms/openbios/fs/hfsplus/include/hfsp.h305
-rw-r--r--roms/openbios/fs/hfsplus/include/hfstime.h34
-rw-r--r--roms/openbios/fs/hfsplus/include/libhfsp.h201
-rw-r--r--roms/openbios/fs/hfsplus/include/record.h80
-rw-r--r--roms/openbios/fs/hfsplus/include/swab.h64
-rw-r--r--roms/openbios/fs/hfsplus/include/unicode.h28
-rw-r--r--roms/openbios/fs/hfsplus/include/volume.h87
-rw-r--r--roms/openbios/fs/hfsplus/libhfsp.c29
-rw-r--r--roms/openbios/fs/ioglue.c92
-rw-r--r--roms/openbios/fs/iso9660/build.xml13
-rw-r--r--roms/openbios/fs/iso9660/iso9660.h58
-rw-r--r--roms/openbios/fs/iso9660/iso9660_close.c15
-rw-r--r--roms/openbios/fs/iso9660/iso9660_closedir.c19
-rw-r--r--roms/openbios/fs/iso9660/iso9660_fs.c263
-rw-r--r--roms/openbios/fs/iso9660/iso9660_fs.h161
-rw-r--r--roms/openbios/fs/iso9660/iso9660_lseek.c37
-rw-r--r--roms/openbios/fs/iso9660/iso9660_mount.c210
-rw-r--r--roms/openbios/fs/iso9660/iso9660_open.c39
-rw-r--r--roms/openbios/fs/iso9660/iso9660_opendir.c133
-rw-r--r--roms/openbios/fs/iso9660/iso9660_read.c74
-rw-r--r--roms/openbios/fs/iso9660/iso9660_readdir.c50
-rw-r--r--roms/openbios/fs/iso9660/libiso9660.h27
-rw-r--r--roms/openbios/fs/os.h57
-rw-r--r--roms/openbios/include/arch/amd64/elf.h6
-rw-r--r--roms/openbios/include/arch/amd64/io.h71
-rw-r--r--roms/openbios/include/arch/amd64/pci.h66
-rw-r--r--roms/openbios/include/arch/amd64/types.h67
-rw-r--r--roms/openbios/include/arch/common/a.out.h271
-rw-r--r--roms/openbios/include/arch/common/elf.h227
-rw-r--r--roms/openbios/include/arch/common/elf_boot.h105
-rw-r--r--roms/openbios/include/arch/common/fw_cfg.h90
-rw-r--r--roms/openbios/include/arch/common/nvram.h24
-rw-r--r--roms/openbios/include/arch/common/xcoff.h98
-rw-r--r--roms/openbios/include/arch/ia64/elf.h5
-rw-r--r--roms/openbios/include/arch/ia64/io.h59
-rw-r--r--roms/openbios/include/arch/ia64/types.h60
-rw-r--r--roms/openbios/include/arch/ppc/asmdefs.h151
-rw-r--r--roms/openbios/include/arch/ppc/elf.h5
-rw-r--r--roms/openbios/include/arch/ppc/io.h208
-rw-r--r--roms/openbios/include/arch/ppc/pci.h69
-rw-r--r--roms/openbios/include/arch/ppc/processor.h467
-rw-r--r--roms/openbios/include/arch/ppc/types.h104
-rw-r--r--roms/openbios/include/arch/sparc32/a.out.h98
-rw-r--r--roms/openbios/include/arch/sparc32/asi.h111
-rw-r--r--roms/openbios/include/arch/sparc32/crs.h14
-rw-r--r--roms/openbios/include/arch/sparc32/dma.h213
-rw-r--r--roms/openbios/include/arch/sparc32/elf.h5
-rw-r--r--roms/openbios/include/arch/sparc32/io.h201
-rw-r--r--roms/openbios/include/arch/sparc32/ofmem_sparc32.h31
-rw-r--r--roms/openbios/include/arch/sparc32/types.h93
-rw-r--r--roms/openbios/include/arch/sparc64/a.out.h108
-rw-r--r--roms/openbios/include/arch/sparc64/asi.h145
-rw-r--r--roms/openbios/include/arch/sparc64/elf.h5
-rw-r--r--roms/openbios/include/arch/sparc64/io.h209
-rw-r--r--roms/openbios/include/arch/sparc64/ofmem_sparc64.h50
-rw-r--r--roms/openbios/include/arch/sparc64/pci.h67
-rw-r--r--roms/openbios/include/arch/sparc64/types.h102
-rw-r--r--roms/openbios/include/arch/unix/plugin_pci.h25
-rw-r--r--roms/openbios/include/arch/unix/plugins.h31
-rw-r--r--roms/openbios/include/arch/x86/elf.h5
-rw-r--r--roms/openbios/include/arch/x86/io.h74
-rw-r--r--roms/openbios/include/arch/x86/pci.h66
-rw-r--r--roms/openbios/include/arch/x86/types.h69
-rw-r--r--roms/openbios/include/config.h68
-rw-r--r--roms/openbios/include/drivers/drivers.h132
-rw-r--r--roms/openbios/include/drivers/pci.h217
-rw-r--r--roms/openbios/include/drivers/usb.h8
-rw-r--r--roms/openbios/include/drivers/vga.h20
-rw-r--r--roms/openbios/include/fs/fs.h100
-rw-r--r--roms/openbios/include/kernel/kernel.h58
-rw-r--r--roms/openbios/include/kernel/stack.h117
-rw-r--r--roms/openbios/include/libc/byteorder.h61
-rw-r--r--roms/openbios/include/libc/diskio.h33
-rw-r--r--roms/openbios/include/libc/stdlib.h26
-rw-r--r--roms/openbios/include/libc/string.h105
-rw-r--r--roms/openbios/include/libc/vsprintf.h35
-rw-r--r--roms/openbios/include/libopenbios/aout_load.h27
-rw-r--r--roms/openbios/include/libopenbios/bindings.h156
-rw-r--r--roms/openbios/include/libopenbios/bootcode_load.h22
-rw-r--r--roms/openbios/include/libopenbios/bootinfo_load.h26
-rw-r--r--roms/openbios/include/libopenbios/console.h25
-rw-r--r--roms/openbios/include/libopenbios/elf_load.h31
-rw-r--r--roms/openbios/include/libopenbios/fcode_load.h24
-rw-r--r--roms/openbios/include/libopenbios/fontdata.h28
-rw-r--r--roms/openbios/include/libopenbios/forth_load.h24
-rw-r--r--roms/openbios/include/libopenbios/initprogram.h22
-rw-r--r--roms/openbios/include/libopenbios/ipchecksum.h7
-rw-r--r--roms/openbios/include/libopenbios/load.h22
-rw-r--r--roms/openbios/include/libopenbios/of.h22
-rw-r--r--roms/openbios/include/libopenbios/ofmem.h145
-rw-r--r--roms/openbios/include/libopenbios/openbios.h22
-rw-r--r--roms/openbios/include/libopenbios/sys_info.h38
-rw-r--r--roms/openbios/include/libopenbios/video.h36
-rw-r--r--roms/openbios/include/libopenbios/xcoff_load.h27
-rw-r--r--roms/openbios/include/mconfig.h70
-rw-r--r--roms/openbios/include/packages/nvram.h24
-rw-r--r--roms/openbios/include/packages/video.h7
-rw-r--r--roms/openbios/include/sysinclude.h20
-rw-r--r--roms/openbios/kernel/Kconfig88
-rw-r--r--roms/openbios/kernel/README93
-rw-r--r--roms/openbios/kernel/bootstrap.c1322
-rw-r--r--roms/openbios/kernel/build.xml16
-rw-r--r--roms/openbios/kernel/cross.h124
-rw-r--r--roms/openbios/kernel/dict.c320
-rw-r--r--roms/openbios/kernel/forth.c1966
-rw-r--r--roms/openbios/kernel/include/dict.h59
-rw-r--r--roms/openbios/kernel/stack.c46
-rw-r--r--roms/openbios/libc/build.xml12
-rw-r--r--roms/openbios/libc/ctype.c34
-rw-r--r--roms/openbios/libc/diskio.c248
-rw-r--r--roms/openbios/libc/extra.c49
-rw-r--r--roms/openbios/libc/misc.c144
-rw-r--r--roms/openbios/libc/string.c387
-rw-r--r--roms/openbios/libc/vsprintf.c448
-rw-r--r--roms/openbios/libgcc/__divdi3.c26
-rw-r--r--roms/openbios/libgcc/__divti3.c26
-rw-r--r--roms/openbios/libgcc/__lshrdi3.c59
-rw-r--r--roms/openbios/libgcc/__negti2.c53
-rw-r--r--roms/openbios/libgcc/__udivdi3.c10
-rw-r--r--roms/openbios/libgcc/__udivmoddi4.c31
-rw-r--r--roms/openbios/libgcc/__udivmodti4.c31
-rw-r--r--roms/openbios/libgcc/__udivti3.c10
-rw-r--r--roms/openbios/libgcc/__umoddi3.c13
-rw-r--r--roms/openbios/libgcc/__umodti3.c13
-rw-r--r--roms/openbios/libgcc/ashldi3.c59
-rw-r--r--roms/openbios/libgcc/ashrdi3.c60
-rw-r--r--roms/openbios/libgcc/build.xml24
-rw-r--r--roms/openbios/libgcc/crtsavres.S401
-rw-r--r--roms/openbios/libgcc/libgcc.h45
-rw-r--r--roms/openbios/libgcc/multi3.c83
-rw-r--r--roms/openbios/libopenbios/Kconfig97
-rw-r--r--roms/openbios/libopenbios/aout_load.c176
-rw-r--r--roms/openbios/libopenbios/bindings.c524
-rw-r--r--roms/openbios/libopenbios/bootcode_load.c99
-rw-r--r--roms/openbios/libopenbios/bootinfo_load.c263
-rw-r--r--roms/openbios/libopenbios/build.xml31
-rw-r--r--roms/openbios/libopenbios/clib.fs36
-rw-r--r--roms/openbios/libopenbios/client.c367
-rw-r--r--roms/openbios/libopenbios/console.c68
-rw-r--r--roms/openbios/libopenbios/elf_info.c151
-rw-r--r--roms/openbios/libopenbios/elf_load.c537
-rw-r--r--roms/openbios/libopenbios/fcode_load.c109
-rw-r--r--roms/openbios/libopenbios/font_8x16.c4622
-rw-r--r--roms/openbios/libopenbios/font_8x8.c2571
-rw-r--r--roms/openbios/libopenbios/forth_load.c88
-rw-r--r--roms/openbios/libopenbios/helpers.fs35
-rw-r--r--roms/openbios/libopenbios/init.c27
-rw-r--r--roms/openbios/libopenbios/initprogram.c85
-rw-r--r--roms/openbios/libopenbios/ipchecksum.c55
-rw-r--r--roms/openbios/libopenbios/linuxbios.h181
-rw-r--r--roms/openbios/libopenbios/linuxbios_info.c130
-rw-r--r--roms/openbios/libopenbios/load.c122
-rw-r--r--roms/openbios/libopenbios/ofmem_common.c990
-rw-r--r--roms/openbios/libopenbios/video_common.c258
-rw-r--r--roms/openbios/libopenbios/xcoff_load.c147
-rw-r--r--roms/openbios/packages/bootinfo-loader.c29
-rw-r--r--roms/openbios/packages/build.xml23
-rw-r--r--roms/openbios/packages/cmdline.c415
-rw-r--r--roms/openbios/packages/cmdline.fs41
-rw-r--r--roms/openbios/packages/deblocker.c221
-rw-r--r--roms/openbios/packages/disk-label.c245
-rw-r--r--roms/openbios/packages/disk-label.fs102
-rw-r--r--roms/openbios/packages/elf-loader.c31
-rw-r--r--roms/openbios/packages/init.c67
-rw-r--r--roms/openbios/packages/mac-parts.c447
-rw-r--r--roms/openbios/packages/mac-parts.h88
-rw-r--r--roms/openbios/packages/molvideo.c124
-rw-r--r--roms/openbios/packages/nvram.c308
-rw-r--r--roms/openbios/packages/packages.h36
-rw-r--r--roms/openbios/packages/pc-parts.c393
-rw-r--r--roms/openbios/packages/sun-parts.c343
-rw-r--r--roms/openbios/packages/xcoff-loader.c31
-rw-r--r--roms/openbios/utils/README52
-rw-r--r--roms/openbios/utils/devbios/COPYING353
-rw-r--r--roms/openbios/utils/devbios/CREDITS4
-rw-r--r--roms/openbios/utils/devbios/ChangeLog295
-rw-r--r--roms/openbios/utils/devbios/Makefile22
-rw-r--r--roms/openbios/utils/devbios/Makefile.2481
-rw-r--r--roms/openbios/utils/devbios/README.bios256
-rw-r--r--roms/openbios/utils/devbios/ToDo33
-rw-r--r--roms/openbios/utils/devbios/bios.h38
-rw-r--r--roms/openbios/utils/devbios/bios_core.c198
-rw-r--r--roms/openbios/utils/devbios/comp.c47
-rw-r--r--roms/openbios/utils/devbios/filesystem.c300
-rw-r--r--roms/openbios/utils/devbios/flashchips.c313
-rw-r--r--roms/openbios/utils/devbios/flashchips.h81
-rw-r--r--roms/openbios/utils/devbios/pcisets.c630
-rw-r--r--roms/openbios/utils/devbios/pcisets.h45
-rw-r--r--roms/openbios/utils/devbios/procfs.c162
-rw-r--r--roms/openbios/utils/devbios/programming.c539
-rw-r--r--roms/openbios/utils/devbios/programming.h73
-rw-r--r--roms/openbios/utils/dist/debian/changelog6
-rw-r--r--roms/openbios/utils/dist/debian/control16
-rw-r--r--roms/openbios/utils/dist/debian/packages45
-rwxr-xr-xroms/openbios/utils/dist/debian/rules189
-rw-r--r--roms/openbios/utils/dist/openbios.spec61
-rw-r--r--roms/openbios/utils/iso/README5
-rw-r--r--roms/openbios/utils/iso/boot/grub/README1
-rw-r--r--roms/openbios/utils/iso/boot/grub/menu.lst7
-rw-r--r--roms/openbios/utils/iso/boot/grub/stage2_eltoritobin0 -> 100682 bytes
-rw-r--r--roms/openbios/utils/ofclient/Makefile14
-rw-r--r--roms/openbios/utils/ofclient/README4
-rw-r--r--roms/openbios/utils/ofclient/endian.h18
-rw-r--r--roms/openbios/utils/ofclient/of1275.c451
-rw-r--r--roms/openbios/utils/ofclient/of1275.h437
-rw-r--r--roms/openbios/utils/ofclient/of1275_io.c51
-rw-r--r--roms/openbios/utils/ofclient/ofclient.c9
667 files changed, 119030 insertions, 0 deletions
diff --git a/roms/openbios/.gitignore b/roms/openbios/.gitignore
new file mode 100644
index 00000000..38e6dd89
--- /dev/null
+++ b/roms/openbios/.gitignore
@@ -0,0 +1,3 @@
+obj-*
+.stgit-*
+config-host.mak
diff --git a/roms/openbios/COPYING b/roms/openbios/COPYING
new file mode 100644
index 00000000..8a6932a7
--- /dev/null
+++ b/roms/openbios/COPYING
@@ -0,0 +1,341 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/roms/openbios/Documentation/ChangeLog.arch b/roms/openbios/Documentation/ChangeLog.arch
new file mode 100644
index 00000000..8213b28b
--- /dev/null
+++ b/roms/openbios/Documentation/ChangeLog.arch
@@ -0,0 +1,1895 @@
+# do not edit -- automatically generated by arch changelog
+# arch-tag: automatic-ChangeLog--stepan@openbios.org--devel/openbios--main--1.0
+#
+
+2006-04-26 11:52:05 GMT Stefan Reinauer <stepan@openbios.org> patch-26
+
+ Summary:
+ small gcc4 changes
+ Revision:
+ openbios--main--1.0--patch-26
+
+ lvalue stuff
+
+
+ modified files:
+ Documentation/ChangeLog.arch config/examples/x86_config.xml
+ kernel/bootstrap.c kernel/dict.c
+
+
+2006-02-22 17:01:41 GMT Stefan Reinauer <stepan@openbios.org> patch-25
+
+ Summary:
+ make romheaders work on non linux systems
+ Revision:
+ openbios--main--1.0--patch-25
+
+ removes endian dependency and some signed/unsigned comparisons
+
+
+
+ modified files:
+ Documentation/ChangeLog.arch utils/romheaders/Makefile
+ utils/romheaders/romheaders.c
+
+
+2005-10-15 16:01:47 GMT Stefan Reinauer <stepan@openbios.org> patch-24
+
+ Summary:
+ toke fix: hex string handling
+ Revision:
+ openbios--main--1.0--patch-24
+
+ This revision fixes a bug in toke when creating hex definitions within strings.
+ It also contains a little documentation update.
+
+
+ removed files:
+ toke/.arch-ids/TODO.id toke/TODO
+
+ modified files:
+ Documentation/ChangeLog.arch toke/ChangeLog toke/README
+ toke/scanner.c toke/toke.c
+
+
+2005-10-05 18:26:56 GMT Stefan Reinauer <stepan@openbios.org> patch-23
+
+ Summary:
+ address change, second attempt
+ Revision:
+ openbios--main--1.0--patch-23
+
+ The correct address of FSF is:
+
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+
+ modified files:
+ COPYING Documentation/ChangeLog.arch
+ Documentation/kernel/COPYING drivers/adb.c drivers/adb.h
+ drivers/kbd.c drivers/kbd.h fs/grubfs/jfs.h fs/grubfs/xfs.h
+ toke/COPYING toke/Makefile toke/dictionary.c toke/dictionary.h
+ toke/emit.c toke/emit.h toke/macros.c toke/scanner.c
+ toke/stack.c toke/stack.h toke/stream.c toke/stream.h
+ toke/toke.c toke/toke.h utils/detok/COPYING
+ utils/detok/Makefile utils/detok/decode.c utils/detok/detok.c
+ utils/detok/detok.h utils/detok/dictionary.c
+ utils/detok/stream.c utils/detok/stream.h
+ utils/devbios/COPYING utils/devbios/bios.h
+ utils/devbios/bios_core.c utils/devbios/filesystem.c
+ utils/devbios/flashchips.c utils/devbios/flashchips.h
+ utils/devbios/pcisets.c utils/devbios/pcisets.h
+ utils/devbios/procfs.c utils/devbios/programming.c
+ utils/devbios/programming.h utils/fccc/COPYING
+ utils/romheaders/Makefile
+
+
+2005-10-05 17:44:01 GMT Stefan Reinauer <stepan@openbios.org> patch-22
+
+ Summary:
+ Update FSF address all over the tree
+ Revision:
+ openbios--main--1.0--patch-22
+
+ The FSF moved to a new address this April already. The old address was
+ still in place in many files in the tree. Now we're up to date again ;)
+
+
+ modified files:
+ COPYING Documentation/ChangeLog.arch
+ Documentation/kernel/COPYING drivers/adb.c drivers/adb.h
+ drivers/kbd.c drivers/kbd.h utils/detok/COPYING
+ utils/detok/Makefile utils/detok/decode.c utils/detok/detok.c
+ utils/detok/detok.h utils/detok/dictionary.c
+ utils/detok/stream.c utils/detok/stream.h
+ utils/devbios/COPYING utils/devbios/bios.h
+ utils/devbios/bios_core.c utils/devbios/filesystem.c
+ utils/devbios/flashchips.c utils/devbios/flashchips.h
+ utils/devbios/pcisets.c utils/devbios/pcisets.h
+ utils/devbios/procfs.c utils/devbios/programming.c
+ utils/devbios/programming.h utils/fccc/COPYING
+ utils/romheaders/Makefile
+
+
+2005-10-05 17:40:18 GMT Stefan Reinauer <stepan@openbios.org> patch-21
+
+ Summary:
+ fix two bugs in toke, update FSF address
+ Revision:
+ openbios--main--1.0--patch-21
+
+ * toke: fix signed/unsigned bug
+ * toke: error if maximum word count is exceeded
+ * toke: change FSF address to 51 Franklin St, Fifth Floor, Boston, MA, 02111-1301 USA
+
+
+ modified files:
+ Documentation/ChangeLog.arch toke/COPYING toke/ChangeLog
+ toke/Makefile toke/dictionary.c toke/dictionary.h toke/emit.c
+ toke/emit.h toke/macros.c toke/scanner.c toke/stack.c
+ toke/stack.h toke/stream.c toke/stream.h toke/toke.c
+ toke/toke.h
+
+
+2005-10-02 12:18:38 GMT Stefan Reinauer <stepan@openbios.org> patch-20
+
+ Summary:
+ add preliminary floppy driver
+ Revision:
+ openbios--main--1.0--patch-20
+
+ This is a simple floppy driver, borrowed from linuxbios v1
+
+
+ new files:
+ drivers/.arch-ids/floppy.c.id drivers/.arch-ids/floppy.h.id
+ drivers/floppy.c drivers/floppy.h
+
+ modified files:
+ Documentation/ChangeLog.arch arch/x86/openbios.c
+ config/examples/x86_config.xml drivers/build.xml
+
+
+2005-09-17 15:29:08 GMT Stefan Reinauer <stepan@openbios.org> patch-19
+
+ Summary:
+ merge openbios--xml--1.0--patch-48 back into openbios--main
+ Revision:
+ openbios--main--1.0--patch-19
+
+ finally merging the xml tree back to the main tree. Some things are missing
+ like a decent config tool (Kconfig?) But well..
+
+ Patches applied:
+
+ * oxygene@openbios.org--2005/openbios--xml--1.0--base-0
+ tag of stepan@openbios.org--devel/openbios--xml--1.0--patch-29
+
+ * oxygene@openbios.org--2005/openbios--xml--1.0--patch-1
+ update openbios--xml with openbios--main
+
+ * oxygene@openbios.org--2005/openbios--xml--1.0--patch-2
+ change to word "dev"
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--base-0
+ tag of stepan@openbios.org--devel/openbios--main--1.0--patch-14
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-1
+ initial checkin
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-2
+ get briq building
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-3
+ latest changes. clean ppc building up, etc pp
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-4
+ checksum support
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-5
+ first merge of cross platform abstraction
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-6
+ more cross api changes
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-7
+ more cross api merges
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-8
+
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-9
+ toke fixes
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-10
+ fix detok, v0.6.1
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-11
+ release ready version
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-12
+ 2 flash chips supported
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-13
+ devbios: fix filesystem.c
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-14
+ fix devbios for 2.6.10.
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-15
+ small fixes for ppc and filesystems
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-16
+ cross api and other cleanups
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-17
+ activate central trampoline for bootstrapping
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-18
+ getting build process more into shape
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-19
+ cross api: 64->32bit cross compilation
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-20
+ only use cross.h during bootstrap.
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-21
+ cross api swapped endian support.
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-22
+ smaller fixes
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-23
+ fill in cylinders on non chs disks as well
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-24
+ fix NULL phandle problem
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-25
+ fix ppc dictionary cross compiling
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-26
+ small ppc pci update
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-27
+ first merge of pearpc target
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-28
+ fix pearpc nvram access
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-29
+ pearpc update
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-30
+ remove some gnuisms
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-31
+ merge from patrick, some smaller updates
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-32
+ add freebsd UFS driver (patch from Ed Schouten)
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-33
+ two more missing files for UFS support..
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-34
+ fix gnuish leftovers (&>)
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-35
+ small fix and ufs config file update
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-36
+ another one: fix build.xml for UFS
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-37
+ fix warnings in ufs driver
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-38
+ get strcpy right
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-39
+ start unifying video console code
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-40
+ first try for xbox console output
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-41
+ small preprocessor fix
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-42
+ fix -ldl issue for non-linux systems.
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-43
+ next try xbox console..
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-44
+ remove xml namespace from base tag
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-45
+ drop video.c from ppc platform specific code
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-46
+ add load address masking to boot fbsd kernels
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-47
+ add openfirmware client interface example.
+
+ * stepan@openbios.org--devel/openbios--xml--1.0--patch-48
+ lots of endian fixes
+
+
+ new files:
+ .arch-ids/build.xml.id .arch-ids/config.xml.id
+ .arch-ids/rules.xml.id arch/.arch-ids/build.xml.id
+ arch/amd64/.arch-ids/build.xml.id arch/amd64/build.xml
+ arch/build.xml arch/ia64/.arch-ids/build.xml.id
+ arch/ia64/build.xml arch/ppc/.arch-ids/build.xml.id
+ arch/ppc/build.xml arch/ppc/pearpc/.arch-ids/=id
+ arch/ppc/pearpc/.arch-ids/console.c.id
+ arch/ppc/pearpc/.arch-ids/init.c.id
+ arch/ppc/pearpc/.arch-ids/kernel.c.id
+ arch/ppc/pearpc/.arch-ids/main.c.id
+ arch/ppc/pearpc/.arch-ids/methods.c.id
+ arch/ppc/pearpc/.arch-ids/pearpc.c.id
+ arch/ppc/pearpc/.arch-ids/pearpc.fs.id
+ arch/ppc/pearpc/.arch-ids/pearpc.h.id
+ arch/ppc/pearpc/.arch-ids/tree.c.id
+ arch/ppc/pearpc/.arch-ids/tree.fs.id
+ arch/ppc/pearpc/.arch-ids/vfd.c.id arch/ppc/pearpc/console.c
+ arch/ppc/pearpc/init.c arch/ppc/pearpc/kernel.c
+ arch/ppc/pearpc/main.c arch/ppc/pearpc/methods.c
+ arch/ppc/pearpc/pearpc.c arch/ppc/pearpc/pearpc.fs
+ arch/ppc/pearpc/pearpc.h arch/ppc/pearpc/tree.c
+ arch/ppc/pearpc/tree.fs arch/ppc/pearpc/vfd.c
+ arch/unix/.arch-ids/build.xml.id arch/unix/build.xml
+ arch/x86/.arch-ids/build.xml.id arch/x86/build.xml
+ arch/x86/xbox/.arch-ids/=id
+ arch/x86/xbox/.arch-ids/console.c.id
+ arch/x86/xbox/.arch-ids/methods.c.id arch/x86/xbox/console.c
+ arch/x86/xbox/methods.c build.xml config.xml
+ config/.arch-ids/=id config/examples/.arch-ids/=id
+ config/examples/.arch-ids/amd64_config.xml.id
+ config/examples/.arch-ids/amd64_rules.xml.id
+ config/examples/.arch-ids/cross-ppc_config.xml.id
+ config/examples/.arch-ids/cross-ppc_rules.xml.id
+ config/examples/.arch-ids/x86_config.xml.id
+ config/examples/.arch-ids/x86_rules.xml.id
+ config/examples/amd64_config.xml
+ config/examples/amd64_rules.xml
+ config/examples/cross-ppc_config.xml
+ config/examples/cross-ppc_rules.xml
+ config/examples/x86_config.xml config/examples/x86_rules.xml
+ config/scripts/.arch-ids/switch-arch.id
+ config/scripts/switch-arch config/xml/.arch-ids/=id
+ config/xml/.arch-ids/config-c.xsl.id
+ config/xml/.arch-ids/config-forth.xsl.id
+ config/xml/.arch-ids/dictionary.xsl.id
+ config/xml/.arch-ids/makefile.xsl.id
+ config/xml/.arch-ids/object.xsl.id
+ config/xml/.arch-ids/util.xsl.id
+ config/xml/.arch-ids/xinclude.xsl.id config/xml/config-c.xsl
+ config/xml/config-forth.xsl config/xml/dictionary.xsl
+ config/xml/makefile.xsl config/xml/object.xsl
+ config/xml/util.xsl config/xml/xinclude.xsl
+ drivers/.arch-ids/adb.c.id drivers/.arch-ids/adb.fs.id
+ drivers/.arch-ids/adb.h.id drivers/.arch-ids/build.xml.id
+ drivers/.arch-ids/cuda.c.id drivers/.arch-ids/cuda.h.id
+ drivers/.arch-ids/kbd.c.id drivers/.arch-ids/kbd.h.id
+ drivers/adb.c drivers/adb.fs drivers/adb.h drivers/build.xml
+ drivers/cuda.c drivers/cuda.h drivers/kbd.c drivers/kbd.h
+ forth/.arch-ids/build.xml.id
+ forth/admin/.arch-ids/build.xml.id forth/admin/build.xml
+ forth/bootstrap/.arch-ids/build.xml.id
+ forth/bootstrap/build.xml forth/build.xml
+ forth/debugging/.arch-ids/build.xml.id
+ forth/debugging/build.xml forth/device/.arch-ids/build.xml.id
+ forth/device/build.xml forth/lib/.arch-ids/build.xml.id
+ forth/lib/.arch-ids/preinclude.fs.id forth/lib/build.xml
+ forth/lib/preinclude.fs forth/packages/.arch-ids/build.xml.id
+ forth/packages/build.xml forth/system/.arch-ids/build.xml.id
+ forth/system/build.xml forth/testsuite/.arch-ids/build.xml.id
+ forth/testsuite/build.xml forth/util/.arch-ids/build.xml.id
+ forth/util/build.xml fs/.arch-ids/build.xml.id fs/build.xml
+ fs/grubfs/.arch-ids/build.xml.id
+ fs/grubfs/.arch-ids/fsys_ufs.c.id
+ fs/grubfs/.arch-ids/ufs_dinode.h.id
+ fs/grubfs/.arch-ids/ufs_fs.h.id fs/grubfs/build.xml
+ fs/grubfs/fsys_ufs.c fs/grubfs/ufs_dinode.h fs/grubfs/ufs_fs.h
+ fs/hfs/.arch-ids/build.xml.id fs/hfs/build.xml
+ fs/hfsplus/.arch-ids/build.xml.id fs/hfsplus/build.xml
+ include/.arch-ids/mconfig.h.id include/mconfig.h
+ include/ppc/.arch-ids/pci.h.id include/ppc/pci.h
+ kernel/.arch-ids/build.xml.id kernel/.arch-ids/cross.h.id
+ kernel/build.xml kernel/cross.h libc/.arch-ids/build.xml.id
+ libc/build.xml modules/.arch-ids/build.xml.id
+ modules/.arch-ids/console.c.id modules/.arch-ids/video.c.id
+ modules/build.xml modules/console.c modules/video.c rules.xml
+ toke/.arch-ids/Makefile.id toke/.arch-ids/build.xml.id
+ toke/Makefile toke/build.xml utils/ofclient/.arch-ids/=id
+ utils/ofclient/.arch-ids/Makefile.id
+ utils/ofclient/.arch-ids/README.id
+ utils/ofclient/.arch-ids/endian.h.id
+ utils/ofclient/.arch-ids/of1275.c.id
+ utils/ofclient/.arch-ids/of1275.h.id
+ utils/ofclient/.arch-ids/of1275_io.c.id
+ utils/ofclient/.arch-ids/ofclient.c.id utils/ofclient/Makefile
+ utils/ofclient/README utils/ofclient/endian.h
+ utils/ofclient/of1275.c utils/ofclient/of1275.h
+ utils/ofclient/of1275_io.c utils/ofclient/ofclient.c
+
+ removed files:
+ .arch-ids/autogen.sh.id .arch-ids/configure.id
+ .arch-ids/setup_links.id arch/amd64/.arch-ids/Makefile.asm.id
+ arch/amd64/.arch-ids/Makefile.id arch/amd64/Makefile
+ arch/amd64/Makefile.asm arch/ia64/.arch-ids/Makefile.asm.id
+ arch/ia64/.arch-ids/Makefile.id arch/ia64/Makefile
+ arch/ia64/Makefile.asm arch/ppc/mol/.arch-ids/video.c.id
+ arch/ppc/mol/video.c arch/x86/.arch-ids/Makefile.asm.id
+ arch/x86/.arch-ids/Makefile.id arch/x86/Makefile
+ arch/x86/Makefile.asm autogen.sh config/.arch-ids/=id
+ config/.arch-ids/Makefile.defs.in.id
+ config/.arch-ids/Makefile.id
+ config/.arch-ids/Makefile.master.id
+ config/.arch-ids/Makefile.top.id
+ config/.arch-ids/Rules.forth.id config/.arch-ids/Rules.make.id
+ config/.arch-ids/configure.in.id config/Makefile
+ config/Makefile.defs.in config/Makefile.master
+ config/Makefile.top config/Rules.forth config/Rules.make
+ config/configure.in config/kconfig/.arch-ids/=id
+ config/kconfig/.arch-ids/Makefile.id
+ config/kconfig/.arch-ids/conf.c.id
+ config/kconfig/.arch-ids/confdata.c.id
+ config/kconfig/.arch-ids/expr.c.id
+ config/kconfig/.arch-ids/expr.h.id
+ config/kconfig/.arch-ids/lkc.h.id
+ config/kconfig/.arch-ids/lkc_proto.h.id
+ config/kconfig/.arch-ids/mconf.c.id
+ config/kconfig/.arch-ids/menu.c.id
+ config/kconfig/.arch-ids/symbol.c.id
+ config/kconfig/.arch-ids/zconf-l.l.id
+ config/kconfig/.arch-ids/zconf-y.y.id config/kconfig/Makefile
+ config/kconfig/conf.c config/kconfig/confdata.c
+ config/kconfig/expr.c config/kconfig/expr.h
+ config/kconfig/lkc.h config/kconfig/lkc_proto.h
+ config/kconfig/mconf.c config/kconfig/menu.c
+ config/kconfig/symbol.c config/kconfig/zconf-l.l
+ config/kconfig/zconf-y.y config/lxdialog/.arch-ids/=id
+ config/lxdialog/.arch-ids/Makefile.id
+ config/lxdialog/.arch-ids/checklist.c.id
+ config/lxdialog/.arch-ids/colors.h.id
+ config/lxdialog/.arch-ids/dialog.h.id
+ config/lxdialog/.arch-ids/inputbox.c.id
+ config/lxdialog/.arch-ids/lxdialog.c.id
+ config/lxdialog/.arch-ids/menubox.c.id
+ config/lxdialog/.arch-ids/msgbox.c.id
+ config/lxdialog/.arch-ids/textbox.c.id
+ config/lxdialog/.arch-ids/util.c.id
+ config/lxdialog/.arch-ids/yesno.c.id config/lxdialog/Makefile
+ config/lxdialog/checklist.c config/lxdialog/colors.h
+ config/lxdialog/dialog.h config/lxdialog/inputbox.c
+ config/lxdialog/lxdialog.c config/lxdialog/menubox.c
+ config/lxdialog/msgbox.c config/lxdialog/textbox.c
+ config/lxdialog/util.c config/lxdialog/yesno.c configure
+ drivers/.arch-ids/Makefile.id drivers/Makefile
+ forth/.arch-ids/Makefile.id forth/Makefile
+ forth/admin/.arch-ids/Makefile.id forth/admin/Makefile
+ forth/debugging/.arch-ids/Makefile.id forth/debugging/Makefile
+ forth/device/.arch-ids/Makefile.id forth/device/Makefile
+ forth/lib/.arch-ids/Makefile.id forth/lib/Makefile
+ forth/packages/.arch-ids/Makefile.id forth/packages/Makefile
+ forth/system/.arch-ids/Makefile.id forth/system/Makefile
+ forth/testsuite/.arch-ids/Makefile.id forth/testsuite/Makefile
+ forth/util/.arch-ids/Makefile.id forth/util/Makefile
+ fs/.arch-ids/Makefile.id fs/Makefile
+ fs/grubfs/.arch-ids/Makefile.id fs/grubfs/Makefile
+ fs/hfs/.arch-ids/Makefile.id fs/hfs/Makefile
+ fs/hfsplus/.arch-ids/Makefile.id fs/hfsplus/Makefile
+ kernel/.arch-ids/Makefile.id kernel/Makefile
+ libc/.arch-ids/Makefile.id libc/.arch-ids/byteorder.c.id
+ libc/Makefile libc/byteorder.c modules/.arch-ids/Makefile.id
+ modules/Makefile setup_links toke/.arch-ids/Makefile.id
+ toke/Makefile
+
+ modified files:
+ Documentation/ChangeLog.arch Makefile README
+ arch/ppc/briq/briq.c arch/ppc/briq/init.c
+ arch/ppc/briq/kernel.c arch/ppc/mol/console.c arch/ppc/ofmem.c
+ arch/unix/Makefile arch/unix/plugins/Makefile arch/unix/unix.c
+ arch/x86/elfload.c arch/x86/multiboot.c arch/x86/openbios.c
+ arch/x86/sys_info.c drivers/ide.c drivers/pci.c drivers/pci.fs
+ forth/admin/banner.fs forth/admin/devices.fs
+ forth/bootstrap/bootstrap.fs forth/device/font.fs
+ fs/grubfs/Kconfig fs/grubfs/filesys.h fs/grubfs/fsys_ext2fs.c
+ fs/grubfs/fsys_reiserfs.c fs/grubfs/fsys_xfs.c
+ fs/grubfs/grubfs_fs.c include/amd64/io.h
+ include/libc/byteorder.h include/libc/stdlib.h
+ include/openbios/stack.h include/ppc/io.h include/ppc/types.h
+ include/x86/io.h include/x86/pci.h include/x86/types.h
+ kernel/bootstrap.c kernel/dict.c kernel/forth.c
+ kernel/include/dict.h kernel/internal.c kernel/primitives.c
+ modules/bindings.c modules/pc-parts.c toke/ChangeLog
+ toke/dictionary.c toke/dictionary.h toke/emit.c toke/emit.h
+ toke/macros.c toke/scanner.c toke/stack.c toke/stack.h
+ toke/stream.c toke/stream.h toke/toke.c toke/toke.h
+ utils/README utils/devbios/filesystem.c
+ utils/devbios/flashchips.c utils/devbios/pcisets.c
+
+ renamed files:
+ arch/ppc/mol/.arch-ids/font_8x8.c.id
+ ==> modules/.arch-ids/font_8x8.c.id
+ arch/ppc/mol/font_8x8.c
+ ==> modules/font_8x8.c
+ dist/.arch-ids/=id
+ ==> utils/dist/.arch-ids/=id
+ dist/.arch-ids/openbios.spec.id
+ ==> utils/dist/.arch-ids/openbios.spec.id
+ dist/debian/.arch-ids/=id
+ ==> utils/dist/debian/.arch-ids/=id
+ dist/debian/.arch-ids/changelog.id
+ ==> utils/dist/debian/.arch-ids/changelog.id
+ dist/debian/.arch-ids/control.id
+ ==> utils/dist/debian/.arch-ids/control.id
+ dist/debian/.arch-ids/packages.id
+ ==> utils/dist/debian/.arch-ids/packages.id
+ dist/debian/.arch-ids/rules.id
+ ==> utils/dist/debian/.arch-ids/rules.id
+
+ new directories:
+ arch/ppc/pearpc arch/ppc/pearpc/.arch-ids arch/x86/xbox
+ arch/x86/xbox/.arch-ids config config/examples
+ config/examples/.arch-ids config/xml config/xml/.arch-ids
+ utils/dist/.arch-ids utils/dist/debian/.arch-ids
+ utils/ofclient utils/ofclient/.arch-ids
+
+ removed directories:
+ config config/kconfig config/kconfig/.arch-ids config/lxdialog
+ config/lxdialog/.arch-ids dist/.arch-ids dist/debian/.arch-ids
+
+ modified directories:
+ config/.arch-ids
+
+ renamed directories:
+ config/.arch-ids
+ ==> config/.arch-ids
+ config/scripts
+ ==> config/scripts
+ dist
+ ==> utils/dist
+
+ new patches:
+ oxygene@openbios.org--2005/openbios--xml--1.0--base-0
+ oxygene@openbios.org--2005/openbios--xml--1.0--patch-1
+ oxygene@openbios.org--2005/openbios--xml--1.0--patch-2
+ stepan@openbios.org--devel/openbios--xml--1.0--base-0
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-1
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-2
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-3
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-4
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-5
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-6
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-7
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-8
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-9
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-10
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-11
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-12
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-13
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-14
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-15
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-16
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-17
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-18
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-19
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-20
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-21
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-22
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-23
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-24
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-25
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-26
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-27
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-28
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-29
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-30
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-31
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-32
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-33
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-34
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-35
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-36
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-37
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-38
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-39
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-40
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-41
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-42
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-43
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-44
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-45
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-46
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-47
+ stepan@openbios.org--devel/openbios--xml--1.0--patch-48
+
+
+2005-03-10 14:46:23 GMT Stefan Reinauer <stepan@openbios.org> patch-18
+
+ Summary:
+ detok update: 0.6.1
+ Revision:
+ openbios--main--1.0--patch-18
+
+ * fix bug in output of strings. Strings were cut off when 0 bytes
+ occured, in a C manner. Now detok prints correct forth strings.
+ Thanks to Arti Itra <a.itra@ieee.org> for reporting this.
+
+ * free string after printing it.
+
+
+ modified files:
+ Documentation/ChangeLog.arch utils/detok/ChangeLog
+ utils/detok/Makefile utils/detok/README utils/detok/decode.c
+ utils/detok/detok.c utils/detok/detok.h
+ utils/detok/dictionary.c utils/detok/stream.c
+ utils/detok/stream.h
+
+
+2005-03-10 12:52:08 GMT Stefan Reinauer <stepan@openbios.org> patch-17
+
+ Summary:
+ toke update
+ Revision:
+ openbios--main--1.0--patch-17
+
+ * fix fload. Problem reported by David L. Paktor <dlpaktor@us.ibm.com>
+ * remove debug enforcement in scanner.c
+
+
+ modified files:
+ Documentation/ChangeLog.arch toke/scanner.c toke/stream.c
+
+
+2005-02-22 21:54:06 GMT Stefan Reinauer <stepan@openbios.org> patch-16
+
+ Summary:
+ fix uninitialized variable
+ Revision:
+ openbios--main--1.0--patch-16
+
+ step towards fixing devbios
+
+
+ modified files:
+ Documentation/ChangeLog.arch utils/devbios/pcisets.c
+
+
+2005-01-27 10:12:20 GMT Stefan Reinauer <stepan@openbios.org> patch-15
+
+ Summary:
+ update documentation
+ Revision:
+ openbios--main--1.0--patch-15
+
+ Documentation update (thanks to Brian Sammon)
+
+
+ modified files:
+ Documentation/ChangeLog.arch README
+
+
+2004-11-01 20:33:55 GMT Stefan Reinauer <stepan@openbios.org> patch-14
+
+ Summary:
+ add exception handling for x86
+ Revision:
+ openbios--main--1.0--patch-14
+
+ simple exception handling for x86. Safe return does not seem to work yet.
+
+
+ new files:
+ arch/x86/.arch-ids/exception.c.id arch/x86/exception.c
+
+ modified files:
+ Documentation/ChangeLog.arch arch/unix/unix.c
+ arch/x86/Makefile arch/x86/context.c arch/x86/entry.S
+
+ renamed files:
+ arch/x86/.arch-ids/switch.S.id
+ ==> arch/x86/.arch-ids/entry.S.id
+ arch/x86/switch.S
+ ==> arch/x86/entry.S
+
+
+2004-09-19 20:24:46 GMT Stefan Reinauer <stepan@openbios.org> patch-13
+
+ Summary:
+ type cleanups
+ Revision:
+ openbios--main--1.0--patch-13
+
+ applying first patch of issue 38
+
+
+
+ modified files:
+ Documentation/ChangeLog.arch kernel/bootstrap.c kernel/forth.c
+
+
+2004-09-19 15:34:22 GMT Stefan Reinauer <stepan@openbios.org> patch-12
+
+ Summary:
+ use ranlib instead of "ar s"
+ Revision:
+ openbios--main--1.0--patch-12
+
+ "ar s" is GNU specific and the documenation says it is equal to ranlib. So we
+ rather use ranlib and stay portable (ie. to Solaris9)
+
+ fixes issue 36
+
+
+ modified files:
+ Documentation/ChangeLog.arch config/Rules.make
+
+
+2004-09-19 13:38:37 GMT Stefan Reinauer <stepan@openbios.org> patch-11
+
+ Summary:
+ initialize ofmem structure properly
+ Revision:
+ openbios--main--1.0--patch-11
+
+ initialize ofmem structure with zero. The correct fix
+ would be to obtain all information from either linuxbios,
+ uboot, the hardware or a defined per-board function
+
+
+ modified files:
+ Documentation/ChangeLog.arch arch/ppc/ofmem.c
+
+
+2004-09-12 15:02:04 GMT Stefan Reinauer <stepan@openbios.org> patch-10
+
+ Summary:
+ initialize nvram structure completely
+ Revision:
+ openbios--main--1.0--patch-10
+
+ fixes issue 17. nvram structure did not get initialized completely
+
+
+ modified files:
+ Documentation/ChangeLog.arch modules/nvram.c
+
+
+2004-09-12 14:43:23 GMT Stefan Reinauer <stepan@openbios.org> patch-9
+
+ Summary:
+ fix little endian/big endian handling
+ Revision:
+ openbios--main--1.0--patch-9
+
+ this should fix issue 20. Switch all endianess handling to use
+ CONFIG_LITTLE_ENDIAN/CONFIG_BIG_ENDIAN
+
+
+
+ modified files:
+ Documentation/ChangeLog.arch fs/hfsplus/btree.c
+ include/amd64/types.h include/ia64/types.h include/ppc/types.h
+ include/x86/types.h kernel/bootstrap.c kernel/forth.c
+
+
+2004-09-12 12:29:55 GMT Stefan Reinauer <stepan@openbios.org> patch-8
+
+ Summary:
+
+ Revision:
+ openbios--main--1.0--patch-8
+
+
+
+
+ modified files:
+ Documentation/ChangeLog.arch arch/amd64/boot.c
+ arch/amd64/context.c arch/amd64/elfload.c arch/amd64/lib.c
+ arch/amd64/linux_load.c arch/amd64/multiboot.c
+ arch/amd64/segment.c arch/amd64/sys_info.c
+ arch/ppc/briq/briq.c arch/ppc/briq/init.c arch/ppc/briq/main.c
+ arch/ppc/briq/methods.c arch/ppc/kernel.c arch/ppc/mol/init.c
+ arch/ppc/mol/main.c arch/ppc/mol/methods.c arch/ppc/mol/mol.c
+ arch/ppc/mol/osi-blk.c arch/ppc/mol/osi-scsi.c
+ arch/ppc/mol/prom.c arch/ppc/mol/pseudodisk.c
+ arch/ppc/mol/tree.c arch/ppc/mol/video.c arch/ppc/ofmem.c
+ arch/unix/blk.c arch/unix/boot.c arch/unix/unix.c
+ arch/x86/boot.c arch/x86/context.c arch/x86/elfload.c
+ arch/x86/forthload.c arch/x86/lib.c arch/x86/linux_load.c
+ arch/x86/multiboot.c arch/x86/segment.c arch/x86/sys_info.c
+ drivers/ide.c drivers/pci.c fs/grubfs/grubfs_fs.c
+ fs/hfs/hfs_fs.c fs/hfsplus/hfsp_fs.c fs/ioglue.c
+ include/openbios/sysinclude.h kernel/internal.c
+ modules/bindings.c modules/client.c modules/deblocker.c
+ modules/disk-label.c modules/elfload.c modules/elfnote.c
+ modules/filesystems.c modules/linuxbios.c modules/mac-parts.c
+ modules/nvram.c modules/pc-parts.c
+
+
+2004-09-11 23:18:56 GMT Stefan Reinauer <stepan@openbios.org> patch-7
+
+ Summary:
+ get tla silent on commit
+ Revision:
+ openbios--main--1.0--patch-7
+
+ get tla silent on commit. add some files to precious
+
+
+ modified files:
+ Documentation/ChangeLog.arch {arch}/=tagging-method
+
+
+2004-09-11 22:21:05 GMT Stefan Reinauer <stepan@openbios.org> patch-6
+
+ Summary:
+ elimination of variables tramp_semis and trampoline
+ Revision:
+ openbios--main--1.0--patch-6
+
+ This fixes https://openbios.org/roundup/openbios/issue22
+
+
+ modified files:
+ Documentation/ChangeLog.arch kernel/internal.c
+
+
+2004-09-11 21:55:42 GMT Stefan Reinauer <stepan@openbios.org> patch-5
+
+ Summary:
+ initialize cache_xt and catch_xt to 0
+ Revision:
+ openbios--main--1.0--patch-5
+
+ this fixes openbios to work with compilers that do not null out uninitialized
+ variables. (fixes issues 13 and 18)
+
+
+ modified files:
+ Documentation/ChangeLog.arch include/openbios/bindings.h
+ modules/bindings.c
+
+
+2004-09-11 21:33:13 GMT Stefan Reinauer <stepan@openbios.org> patch-4
+
+ Summary:
+ IDE fix
+ Revision:
+ openbios--main--1.0--patch-4
+
+ shame, shame, shame, shame..
+ shame on me..
+
+
+ modified files:
+ Documentation/ChangeLog.arch drivers/ide.c
+
+
+2004-09-05 17:41:18 GMT Stefan Reinauer <stepan@openbios.org> patch-3
+
+ Summary:
+ fix briq build
+ Revision:
+ openbios--main--1.0--patch-3
+
+ fix build for Total Impact Briq systems. This is mostly fixing typos that I
+ introduced in Gregs recent changes.
+
+
+ modified files:
+ Documentation/ChangeLog.arch arch/ppc/Makefile
+ arch/ppc/briq/briq.h arch/ppc/briq/kernel.c drivers/Kconfig
+ drivers/ide.c drivers/ide.h drivers/timer.c drivers/timer.h
+
+
+2004-09-03 19:40:52 GMT Stefan Reinauer <stepan@openbios.org> patch-2
+
+ Summary:
+ oxygene fixed the file permissions
+ Revision:
+ openbios--main--1.0--patch-2
+
+ merged from Patricks tree
+
+ Patches applied:
+
+ * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-4
+ make all files writable, we're not using bitkeeper
+
+
+ modified files:
+ .arch-ids/COPYING.id .arch-ids/Makefile.id .arch-ids/README.id
+ .arch-ids/autogen.sh.id .arch-ids/configure.id
+ .arch-ids/setup_links.id COPYING Documentation/.arch-ids/=id
+ Documentation/ChangeLog.arch
+ Documentation/kernel/.arch-ids/=id
+ Documentation/kernel/.arch-ids/AUTHORS.id
+ Documentation/kernel/.arch-ids/COPYING.id
+ Documentation/kernel/.arch-ids/Changelog.stepan.id
+ Documentation/kernel/.arch-ids/TODO.id
+ Documentation/kernel/.arch-ids/dictformat.txt.id
+ Documentation/kernel/.arch-ids/glossary.txt.id
+ Documentation/kernel/.arch-ids/initializers.txt.id
+ Documentation/kernel/AUTHORS Documentation/kernel/COPYING
+ Documentation/kernel/Changelog.stepan
+ Documentation/kernel/TODO Documentation/kernel/dictformat.txt
+ Documentation/kernel/glossary.txt
+ Documentation/kernel/initializers.txt Makefile README
+ arch/.arch-ids/=id arch/amd64/.arch-ids/=id
+ arch/amd64/.arch-ids/Kconfig.id
+ arch/amd64/.arch-ids/Makefile.asm.id
+ arch/amd64/.arch-ids/Makefile.id
+ arch/amd64/.arch-ids/boot.c.id
+ arch/amd64/.arch-ids/builtin.c.id
+ arch/amd64/.arch-ids/console.c.id
+ arch/amd64/.arch-ids/context.c.id
+ arch/amd64/.arch-ids/context.h.id
+ arch/amd64/.arch-ids/defconfig.id
+ arch/amd64/.arch-ids/elfload.c.id
+ arch/amd64/.arch-ids/init.fs.id
+ arch/amd64/.arch-ids/ldscript.id arch/amd64/.arch-ids/lib.c.id
+ arch/amd64/.arch-ids/linux_load.c.id
+ arch/amd64/.arch-ids/loadfs.c.id
+ arch/amd64/.arch-ids/loadfs.h.id
+ arch/amd64/.arch-ids/multiboot.c.id
+ arch/amd64/.arch-ids/multiboot.h.id
+ arch/amd64/.arch-ids/openbios.c.id
+ arch/amd64/.arch-ids/openbios.h.id
+ arch/amd64/.arch-ids/plainboot.c.id
+ arch/amd64/.arch-ids/relocate.h.id
+ arch/amd64/.arch-ids/segment.c.id
+ arch/amd64/.arch-ids/segment.h.id
+ arch/amd64/.arch-ids/switch.S.id
+ arch/amd64/.arch-ids/sys_info.c.id arch/amd64/Kconfig
+ arch/amd64/Makefile arch/amd64/Makefile.asm arch/amd64/boot.c
+ arch/amd64/builtin.c arch/amd64/console.c arch/amd64/context.c
+ arch/amd64/context.h arch/amd64/defconfig arch/amd64/elfload.c
+ arch/amd64/init.fs arch/amd64/ldscript arch/amd64/lib.c
+ arch/amd64/linux_load.c arch/amd64/loadfs.c
+ arch/amd64/loadfs.h arch/amd64/multiboot.c
+ arch/amd64/multiboot.h arch/amd64/openbios.c
+ arch/amd64/openbios.h arch/amd64/plainboot.c
+ arch/amd64/relocate.h arch/amd64/segment.c
+ arch/amd64/segment.h arch/amd64/switch.S arch/amd64/sys_info.c
+ arch/ia64/.arch-ids/=id arch/ia64/.arch-ids/Kconfig.id
+ arch/ia64/.arch-ids/Makefile.asm.id
+ arch/ia64/.arch-ids/Makefile.id
+ arch/ia64/.arch-ids/defconfig.id
+ arch/ia64/.arch-ids/init.fs.id arch/ia64/Kconfig
+ arch/ia64/Makefile arch/ia64/Makefile.asm arch/ia64/defconfig
+ arch/ia64/init.fs arch/ppc/.arch-ids/=id
+ arch/ppc/.arch-ids/Kconfig.id
+ arch/ppc/.arch-ids/Makefile.asm.id
+ arch/ppc/.arch-ids/Makefile.id arch/ppc/.arch-ids/defconfig.id
+ arch/ppc/.arch-ids/kernel.c.id arch/ppc/.arch-ids/kernel.h.id
+ arch/ppc/.arch-ids/misc.S.id arch/ppc/.arch-ids/mmutypes.h.id
+ arch/ppc/.arch-ids/ofmem.c.id arch/ppc/.arch-ids/osi.h.id
+ arch/ppc/.arch-ids/osi_calls.h.id arch/ppc/.arch-ids/ppc.fs.id
+ arch/ppc/.arch-ids/start.S.id arch/ppc/.arch-ids/timebase.S.id
+ arch/ppc/Kconfig arch/ppc/Makefile arch/ppc/Makefile.asm
+ arch/ppc/briq/.arch-ids/=id arch/ppc/briq/.arch-ids/briq.c.id
+ arch/ppc/briq/.arch-ids/briq.fs.id
+ arch/ppc/briq/.arch-ids/briq.h.id
+ arch/ppc/briq/.arch-ids/init.c.id
+ arch/ppc/briq/.arch-ids/kernel.c.id
+ arch/ppc/briq/.arch-ids/main.c.id
+ arch/ppc/briq/.arch-ids/methods.c.id
+ arch/ppc/briq/.arch-ids/tree.c.id
+ arch/ppc/briq/.arch-ids/tree.fs.id
+ arch/ppc/briq/.arch-ids/vfd.c.id arch/ppc/briq/briq.c
+ arch/ppc/briq/briq.fs arch/ppc/briq/briq.h
+ arch/ppc/briq/init.c arch/ppc/briq/kernel.c
+ arch/ppc/briq/main.c arch/ppc/briq/methods.c
+ arch/ppc/briq/tree.c arch/ppc/briq/tree.fs arch/ppc/briq/vfd.c
+ arch/ppc/defconfig arch/ppc/kernel.c arch/ppc/kernel.h
+ arch/ppc/misc.S arch/ppc/mmutypes.h arch/ppc/mol/.arch-ids/=id
+ arch/ppc/mol/.arch-ids/console.c.id
+ arch/ppc/mol/.arch-ids/font_8x8.c.id
+ arch/ppc/mol/.arch-ids/init.c.id
+ arch/ppc/mol/.arch-ids/kernel.c.id
+ arch/ppc/mol/.arch-ids/main.c.id
+ arch/ppc/mol/.arch-ids/methods.c.id
+ arch/ppc/mol/.arch-ids/mol.c.id
+ arch/ppc/mol/.arch-ids/mol.fs.id
+ arch/ppc/mol/.arch-ids/mol.h.id
+ arch/ppc/mol/.arch-ids/osi-blk.c.id
+ arch/ppc/mol/.arch-ids/osi-scsi.c.id
+ arch/ppc/mol/.arch-ids/prom.c.id
+ arch/ppc/mol/.arch-ids/prom.h.id
+ arch/ppc/mol/.arch-ids/pseudodisk.c.id
+ arch/ppc/mol/.arch-ids/tree.c.id
+ arch/ppc/mol/.arch-ids/tree.fs.id
+ arch/ppc/mol/.arch-ids/video.c.id arch/ppc/mol/console.c
+ arch/ppc/mol/font_8x8.c arch/ppc/mol/init.c
+ arch/ppc/mol/kernel.c arch/ppc/mol/main.c
+ arch/ppc/mol/methods.c arch/ppc/mol/mol.c arch/ppc/mol/mol.fs
+ arch/ppc/mol/mol.h arch/ppc/mol/osi-blk.c
+ arch/ppc/mol/osi-scsi.c arch/ppc/mol/prom.c
+ arch/ppc/mol/prom.h arch/ppc/mol/pseudodisk.c
+ arch/ppc/mol/tree.c arch/ppc/mol/tree.fs arch/ppc/mol/video.c
+ arch/ppc/ofmem.c arch/ppc/osi.h arch/ppc/osi_calls.h
+ arch/ppc/ppc.fs arch/ppc/start.S arch/ppc/timebase.S
+ arch/unix/.arch-ids/=id arch/unix/.arch-ids/Kconfig.id
+ arch/unix/.arch-ids/Makefile.id arch/unix/.arch-ids/blk.c.id
+ arch/unix/.arch-ids/blk.h.id arch/unix/.arch-ids/boot.c.id
+ arch/unix/.arch-ids/plugins.c.id
+ arch/unix/.arch-ids/tree.fs.id arch/unix/.arch-ids/unix.c.id
+ arch/unix/Kconfig arch/unix/Makefile arch/unix/blk.c
+ arch/unix/blk.h arch/unix/boot.c
+ arch/unix/gui_qt/.arch-ids/=id
+ arch/unix/gui_qt/.arch-ids/Makefile.id
+ arch/unix/gui_qt/.arch-ids/gui-qt.cpp.id
+ arch/unix/gui_qt/.arch-ids/gui-qt.h.id
+ arch/unix/gui_qt/.arch-ids/gui-qt.pro.id
+ arch/unix/gui_qt/.arch-ids/logo.xpm.id
+ arch/unix/gui_qt/.arch-ids/qt-main.cpp.id
+ arch/unix/gui_qt/Makefile arch/unix/gui_qt/gui-qt.cpp
+ arch/unix/gui_qt/gui-qt.h arch/unix/gui_qt/gui-qt.pro
+ arch/unix/gui_qt/logo.xpm arch/unix/gui_qt/qt-main.cpp
+ arch/unix/plugins.c arch/unix/plugins/.arch-ids/=id
+ arch/unix/plugins/.arch-ids/Kconfig.id
+ arch/unix/plugins/.arch-ids/Makefile.id
+ arch/unix/plugins/.arch-ids/Rules.plugin.id
+ arch/unix/plugins/.arch-ids/loader.c.id
+ arch/unix/plugins/Kconfig arch/unix/plugins/Makefile
+ arch/unix/plugins/Rules.plugin arch/unix/plugins/loader.c
+ arch/unix/plugins/plugin_pci/.arch-ids/=id
+ arch/unix/plugins/plugin_pci/.arch-ids/Makefile.id
+ arch/unix/plugins/plugin_pci/.arch-ids/Makefile.old.id
+ arch/unix/plugins/plugin_pci/.arch-ids/plugin_pci.c.id
+ arch/unix/plugins/plugin_pci/Makefile
+ arch/unix/plugins/plugin_pci/Makefile.old
+ arch/unix/plugins/plugin_pci/plugin_pci.c
+ arch/unix/plugins/plugin_qt/.arch-ids/=id
+ arch/unix/plugins/plugin_qt/.arch-ids/Makefile.id
+ arch/unix/plugins/plugin_qt/.arch-ids/logo.xpm.id
+ arch/unix/plugins/plugin_qt/.arch-ids/pciconfig.h.id
+ arch/unix/plugins/plugin_qt/.arch-ids/plugin_qt.cpp.id
+ arch/unix/plugins/plugin_qt/.arch-ids/plugin_qt.h.id
+ arch/unix/plugins/plugin_qt/.arch-ids/plugin_qt.pro.id
+ arch/unix/plugins/plugin_qt/.arch-ids/qt_main.cpp.id
+ arch/unix/plugins/plugin_qt/.arch-ids/qt_rom.fs.id
+ arch/unix/plugins/plugin_qt/Makefile
+ arch/unix/plugins/plugin_qt/logo.xpm
+ arch/unix/plugins/plugin_qt/pciconfig.h
+ arch/unix/plugins/plugin_qt/plugin_qt.cpp
+ arch/unix/plugins/plugin_qt/plugin_qt.h
+ arch/unix/plugins/plugin_qt/plugin_qt.pro
+ arch/unix/plugins/plugin_qt/qt_main.cpp
+ arch/unix/plugins/plugin_qt/qt_rom.fs arch/unix/tree.fs
+ arch/unix/unix.c arch/x86/.arch-ids/=id
+ arch/x86/.arch-ids/Kconfig.id
+ arch/x86/.arch-ids/Makefile.asm.id
+ arch/x86/.arch-ids/Makefile.id arch/x86/.arch-ids/boot.c.id
+ arch/x86/.arch-ids/boot.h.id arch/x86/.arch-ids/builtin.c.id
+ arch/x86/.arch-ids/console.c.id
+ arch/x86/.arch-ids/context.c.id
+ arch/x86/.arch-ids/context.h.id
+ arch/x86/.arch-ids/defconfig.id
+ arch/x86/.arch-ids/elfload.c.id
+ arch/x86/.arch-ids/forthload.c.id
+ arch/x86/.arch-ids/init.fs.id arch/x86/.arch-ids/ldscript.id
+ arch/x86/.arch-ids/lib.c.id arch/x86/.arch-ids/linux_load.c.id
+ arch/x86/.arch-ids/loadfs.c.id arch/x86/.arch-ids/loadfs.h.id
+ arch/x86/.arch-ids/multiboot.c.id
+ arch/x86/.arch-ids/multiboot.h.id
+ arch/x86/.arch-ids/openbios.c.id
+ arch/x86/.arch-ids/openbios.h.id
+ arch/x86/.arch-ids/plainboot.c.id
+ arch/x86/.arch-ids/relocate.h.id
+ arch/x86/.arch-ids/segment.c.id
+ arch/x86/.arch-ids/segment.h.id arch/x86/.arch-ids/switch.S.id
+ arch/x86/.arch-ids/sys_info.c.id arch/x86/Kconfig
+ arch/x86/Makefile arch/x86/Makefile.asm arch/x86/boot.c
+ arch/x86/boot.h arch/x86/builtin.c arch/x86/console.c
+ arch/x86/context.c arch/x86/context.h arch/x86/defconfig
+ arch/x86/elfload.c arch/x86/forthload.c arch/x86/init.fs
+ arch/x86/ldscript arch/x86/lib.c arch/x86/linux_load.c
+ arch/x86/loadfs.c arch/x86/loadfs.h arch/x86/multiboot.c
+ arch/x86/multiboot.h arch/x86/openbios.c arch/x86/openbios.h
+ arch/x86/plainboot.c arch/x86/relocate.h arch/x86/segment.c
+ arch/x86/segment.h arch/x86/switch.S arch/x86/sys_info.c
+ autogen.sh config/.arch-ids/=id
+ config/.arch-ids/Makefile.defs.in.id
+ config/.arch-ids/Makefile.id
+ config/.arch-ids/Makefile.master.id
+ config/.arch-ids/Makefile.top.id
+ config/.arch-ids/Rules.forth.id config/.arch-ids/Rules.make.id
+ config/.arch-ids/configure.in.id config/Makefile
+ config/Makefile.defs.in config/Makefile.master
+ config/Makefile.top config/Rules.forth config/Rules.make
+ config/configure.in config/kconfig/.arch-ids/=id
+ config/kconfig/.arch-ids/Makefile.id
+ config/kconfig/.arch-ids/conf.c.id
+ config/kconfig/.arch-ids/confdata.c.id
+ config/kconfig/.arch-ids/expr.c.id
+ config/kconfig/.arch-ids/expr.h.id
+ config/kconfig/.arch-ids/lkc.h.id
+ config/kconfig/.arch-ids/lkc_proto.h.id
+ config/kconfig/.arch-ids/mconf.c.id
+ config/kconfig/.arch-ids/menu.c.id
+ config/kconfig/.arch-ids/symbol.c.id
+ config/kconfig/.arch-ids/zconf-l.l.id
+ config/kconfig/.arch-ids/zconf-y.y.id config/kconfig/Makefile
+ config/kconfig/conf.c config/kconfig/confdata.c
+ config/kconfig/expr.c config/kconfig/expr.h
+ config/kconfig/lkc.h config/kconfig/lkc_proto.h
+ config/kconfig/mconf.c config/kconfig/menu.c
+ config/kconfig/symbol.c config/kconfig/zconf-l.l
+ config/kconfig/zconf-y.y config/lxdialog/.arch-ids/=id
+ config/lxdialog/.arch-ids/Makefile.id
+ config/lxdialog/.arch-ids/checklist.c.id
+ config/lxdialog/.arch-ids/colors.h.id
+ config/lxdialog/.arch-ids/dialog.h.id
+ config/lxdialog/.arch-ids/inputbox.c.id
+ config/lxdialog/.arch-ids/lxdialog.c.id
+ config/lxdialog/.arch-ids/menubox.c.id
+ config/lxdialog/.arch-ids/msgbox.c.id
+ config/lxdialog/.arch-ids/textbox.c.id
+ config/lxdialog/.arch-ids/util.c.id
+ config/lxdialog/.arch-ids/yesno.c.id config/lxdialog/Makefile
+ config/lxdialog/checklist.c config/lxdialog/colors.h
+ config/lxdialog/dialog.h config/lxdialog/inputbox.c
+ config/lxdialog/lxdialog.c config/lxdialog/menubox.c
+ config/lxdialog/msgbox.c config/lxdialog/textbox.c
+ config/lxdialog/util.c config/lxdialog/yesno.c
+ config/scripts/.arch-ids/=id
+ config/scripts/.arch-ids/archname.id
+ config/scripts/.arch-ids/reldir.id config/scripts/archname
+ config/scripts/reldir configure dist/.arch-ids/=id
+ dist/.arch-ids/openbios.spec.id dist/debian/.arch-ids/=id
+ dist/debian/.arch-ids/changelog.id
+ dist/debian/.arch-ids/control.id
+ dist/debian/.arch-ids/packages.id
+ dist/debian/.arch-ids/rules.id dist/debian/changelog
+ dist/debian/control dist/debian/packages dist/debian/rules
+ dist/openbios.spec drivers/.arch-ids/=id
+ drivers/.arch-ids/Kconfig.id drivers/.arch-ids/Makefile.id
+ drivers/.arch-ids/hdreg.h.id drivers/.arch-ids/ide.c.id
+ drivers/.arch-ids/ide.fs.id drivers/.arch-ids/ide.h.id
+ drivers/.arch-ids/pci.c.id drivers/.arch-ids/pci.fs.id
+ drivers/.arch-ids/pci.h.id drivers/.arch-ids/timer.c.id
+ drivers/.arch-ids/timer.h.id drivers/Kconfig drivers/Makefile
+ drivers/hdreg.h drivers/ide.c drivers/ide.fs drivers/ide.h
+ drivers/pci.c drivers/pci.fs drivers/pci.h drivers/timer.c
+ drivers/timer.h forth/.arch-ids/=id forth/.arch-ids/Kconfig.id
+ forth/.arch-ids/Makefile.id forth/Kconfig forth/Makefile
+ forth/admin/.arch-ids/=id forth/admin/.arch-ids/Makefile.id
+ forth/admin/.arch-ids/README.id
+ forth/admin/.arch-ids/banner.fs.id
+ forth/admin/.arch-ids/callback.fs.id
+ forth/admin/.arch-ids/devices.fs.id
+ forth/admin/.arch-ids/help.fs.id
+ forth/admin/.arch-ids/iocontrol.fs.id
+ forth/admin/.arch-ids/nvram.fs.id
+ forth/admin/.arch-ids/reset.fs.id
+ forth/admin/.arch-ids/script.fs.id
+ forth/admin/.arch-ids/security.fs.id
+ forth/admin/.arch-ids/selftest.fs.id
+ forth/admin/.arch-ids/userboot.fs.id forth/admin/Makefile
+ forth/admin/README forth/admin/banner.fs
+ forth/admin/callback.fs forth/admin/devices.fs
+ forth/admin/help.fs forth/admin/iocontrol.fs
+ forth/admin/nvram.fs forth/admin/reset.fs
+ forth/admin/script.fs forth/admin/security.fs
+ forth/admin/selftest.fs forth/admin/userboot.fs
+ forth/bootstrap/.arch-ids/=id
+ forth/bootstrap/.arch-ids/bootstrap.fs.id
+ forth/bootstrap/.arch-ids/builtin.fs.id
+ forth/bootstrap/.arch-ids/hayes.fs.id
+ forth/bootstrap/.arch-ids/interpreter.fs.id
+ forth/bootstrap/.arch-ids/memory.fs.id
+ forth/bootstrap/.arch-ids/start.fs.id
+ forth/bootstrap/bootstrap.fs forth/bootstrap/builtin.fs
+ forth/bootstrap/hayes.fs forth/bootstrap/interpreter.fs
+ forth/bootstrap/memory.fs forth/bootstrap/start.fs
+ forth/debugging/.arch-ids/=id
+ forth/debugging/.arch-ids/Makefile.id
+ forth/debugging/.arch-ids/client.fs.id
+ forth/debugging/.arch-ids/fcode.fs.id
+ forth/debugging/.arch-ids/firmware.fs.id
+ forth/debugging/.arch-ids/see.fs.id forth/debugging/Makefile
+ forth/debugging/client.fs forth/debugging/fcode.fs
+ forth/debugging/firmware.fs forth/debugging/see.fs
+ forth/device/.arch-ids/=id forth/device/.arch-ids/Makefile.id
+ forth/device/.arch-ids/README.device.id
+ forth/device/.arch-ids/builtin.fs.id
+ forth/device/.arch-ids/device.fs.id
+ forth/device/.arch-ids/display.fs.id
+ forth/device/.arch-ids/extra.fs.id
+ forth/device/.arch-ids/fcode.fs.id
+ forth/device/.arch-ids/feval.fs.id
+ forth/device/.arch-ids/font.fs.id
+ forth/device/.arch-ids/logo.fs.id
+ forth/device/.arch-ids/missing.id
+ forth/device/.arch-ids/other.fs.id
+ forth/device/.arch-ids/package.fs.id
+ forth/device/.arch-ids/pathres.fs.id
+ forth/device/.arch-ids/preof.fs.id
+ forth/device/.arch-ids/property.fs.id
+ forth/device/.arch-ids/romfont.bin.id
+ forth/device/.arch-ids/structures.fs.id
+ forth/device/.arch-ids/table.fs.id
+ forth/device/.arch-ids/terminal.fs.id
+ forth/device/.arch-ids/tree.fs.id forth/device/Makefile
+ forth/device/README.device forth/device/builtin.fs
+ forth/device/device.fs forth/device/display.fs
+ forth/device/extra.fs forth/device/fcode.fs
+ forth/device/feval.fs forth/device/font.fs
+ forth/device/logo.fs forth/device/missing
+ forth/device/other.fs forth/device/package.fs
+ forth/device/pathres.fs forth/device/preof.fs
+ forth/device/property.fs forth/device/romfont.bin
+ forth/device/structures.fs forth/device/table.fs
+ forth/device/terminal.fs forth/device/tree.fs
+ forth/lib/.arch-ids/=id forth/lib/.arch-ids/Makefile.id
+ forth/lib/.arch-ids/creation.fs.id
+ forth/lib/.arch-ids/lists.fs.id
+ forth/lib/.arch-ids/preprocessor.fs.id
+ forth/lib/.arch-ids/split.fs.id
+ forth/lib/.arch-ids/string.fs.id
+ forth/lib/.arch-ids/vocabulary.fs.id forth/lib/Makefile
+ forth/lib/creation.fs forth/lib/lists.fs
+ forth/lib/preprocessor.fs forth/lib/split.fs
+ forth/lib/string.fs forth/lib/vocabulary.fs
+ forth/packages/.arch-ids/=id
+ forth/packages/.arch-ids/Kconfig.id
+ forth/packages/.arch-ids/Makefile.id
+ forth/packages/.arch-ids/README.id
+ forth/packages/.arch-ids/deblocker.fs.id
+ forth/packages/.arch-ids/disklabel.fs.id
+ forth/packages/.arch-ids/obp-tftp.fs.id
+ forth/packages/.arch-ids/packages.fs.id
+ forth/packages/.arch-ids/terminal-emulator.fs.id
+ forth/packages/Kconfig forth/packages/Makefile
+ forth/packages/README forth/packages/deblocker.fs
+ forth/packages/disklabel.fs forth/packages/obp-tftp.fs
+ forth/packages/packages.fs forth/packages/terminal-emulator.fs
+ forth/system/.arch-ids/=id forth/system/.arch-ids/Makefile.id
+ forth/system/.arch-ids/ciface.fs.id
+ forth/system/.arch-ids/main.fs.id forth/system/Makefile
+ forth/system/ciface.fs forth/system/main.fs
+ forth/testsuite/.arch-ids/=id
+ forth/testsuite/.arch-ids/Makefile.id
+ forth/testsuite/.arch-ids/README.id
+ forth/testsuite/.arch-ids/fract.fs.id
+ forth/testsuite/.arch-ids/framebuffer-test.fs.id
+ forth/testsuite/.arch-ids/memory-testsuite.fs.id
+ forth/testsuite/.arch-ids/splitfunc-testsuite.fs.id
+ forth/testsuite/Makefile forth/testsuite/README
+ forth/testsuite/fract.fs forth/testsuite/framebuffer-test.fs
+ forth/testsuite/memory-testsuite.fs
+ forth/testsuite/splitfunc-testsuite.fs
+ forth/util/.arch-ids/=id forth/util/.arch-ids/Makefile.id
+ forth/util/.arch-ids/apic.fs.id forth/util/.arch-ids/pci.fs.id
+ forth/util/.arch-ids/util.fs.id forth/util/Makefile
+ forth/util/apic.fs forth/util/pci.fs forth/util/util.fs
+ fs/.arch-ids/=id fs/.arch-ids/Makefile.id
+ fs/.arch-ids/hfs_mdb.h.id fs/.arch-ids/ioglue.c.id
+ fs/.arch-ids/os.h.id fs/Makefile fs/grubfs/.arch-ids/=id
+ fs/grubfs/.arch-ids/Kconfig.id fs/grubfs/.arch-ids/Makefile.id
+ fs/grubfs/.arch-ids/debug.h.id fs/grubfs/.arch-ids/defs.h.id
+ fs/grubfs/.arch-ids/dir.h.id
+ fs/grubfs/.arch-ids/disk_inode.h.id
+ fs/grubfs/.arch-ids/disk_inode_ffs.h.id
+ fs/grubfs/.arch-ids/fat.h.id fs/grubfs/.arch-ids/filesys.h.id
+ fs/grubfs/.arch-ids/fs.h.id fs/grubfs/.arch-ids/fsys_affs.c.id
+ fs/grubfs/.arch-ids/fsys_ext2fs.c.id
+ fs/grubfs/.arch-ids/fsys_fat.c.id
+ fs/grubfs/.arch-ids/fsys_ffs.c.id
+ fs/grubfs/.arch-ids/fsys_iso9660.c.id
+ fs/grubfs/.arch-ids/fsys_jfs.c.id
+ fs/grubfs/.arch-ids/fsys_minix.c.id
+ fs/grubfs/.arch-ids/fsys_ntfs.c.id
+ fs/grubfs/.arch-ids/fsys_reiserfs.c.id
+ fs/grubfs/.arch-ids/fsys_vstafs.c.id
+ fs/grubfs/.arch-ids/fsys_xfs.c.id
+ fs/grubfs/.arch-ids/glue.h.id
+ fs/grubfs/.arch-ids/grubfs_fs.c.id
+ fs/grubfs/.arch-ids/iso9660.h.id fs/grubfs/.arch-ids/jfs.h.id
+ fs/grubfs/.arch-ids/shared.h.id
+ fs/grubfs/.arch-ids/vstafs.h.id fs/grubfs/.arch-ids/xfs.h.id
+ fs/grubfs/Kconfig fs/grubfs/Makefile fs/grubfs/debug.h
+ fs/grubfs/defs.h fs/grubfs/dir.h fs/grubfs/disk_inode.h
+ fs/grubfs/disk_inode_ffs.h fs/grubfs/fat.h fs/grubfs/filesys.h
+ fs/grubfs/fs.h fs/grubfs/fsys_affs.c fs/grubfs/fsys_ext2fs.c
+ fs/grubfs/fsys_fat.c fs/grubfs/fsys_ffs.c
+ fs/grubfs/fsys_iso9660.c fs/grubfs/fsys_jfs.c
+ fs/grubfs/fsys_minix.c fs/grubfs/fsys_ntfs.c
+ fs/grubfs/fsys_reiserfs.c fs/grubfs/fsys_vstafs.c
+ fs/grubfs/fsys_xfs.c fs/grubfs/glue.h fs/grubfs/grubfs_fs.c
+ fs/grubfs/iso9660.h fs/grubfs/jfs.h fs/grubfs/shared.h
+ fs/grubfs/vstafs.h fs/grubfs/xfs.h fs/hfs/.arch-ids/=id
+ fs/hfs/.arch-ids/Makefile.id fs/hfs/.arch-ids/block.c.id
+ fs/hfs/.arch-ids/btree.c.id fs/hfs/.arch-ids/data.c.id
+ fs/hfs/.arch-ids/file.c.id fs/hfs/.arch-ids/hfs.c.id
+ fs/hfs/.arch-ids/hfs_fs.c.id fs/hfs/.arch-ids/low.c.id
+ fs/hfs/.arch-ids/medium.c.id fs/hfs/.arch-ids/node.c.id
+ fs/hfs/.arch-ids/record.c.id fs/hfs/.arch-ids/volume.c.id
+ fs/hfs/Makefile fs/hfs/block.c fs/hfs/btree.c fs/hfs/data.c
+ fs/hfs/file.c fs/hfs/hfs.c fs/hfs/hfs_fs.c
+ fs/hfs/include/.arch-ids/=id
+ fs/hfs/include/.arch-ids/apple.h.id
+ fs/hfs/include/.arch-ids/block.h.id
+ fs/hfs/include/.arch-ids/btree.h.id
+ fs/hfs/include/.arch-ids/data.h.id
+ fs/hfs/include/.arch-ids/file.h.id
+ fs/hfs/include/.arch-ids/hfs.h.id
+ fs/hfs/include/.arch-ids/libhfs.h.id
+ fs/hfs/include/.arch-ids/low.h.id
+ fs/hfs/include/.arch-ids/medium.h.id
+ fs/hfs/include/.arch-ids/node.h.id
+ fs/hfs/include/.arch-ids/record.h.id
+ fs/hfs/include/.arch-ids/volume.h.id fs/hfs/include/apple.h
+ fs/hfs/include/block.h fs/hfs/include/btree.h
+ fs/hfs/include/data.h fs/hfs/include/file.h
+ fs/hfs/include/hfs.h fs/hfs/include/libhfs.h
+ fs/hfs/include/low.h fs/hfs/include/medium.h
+ fs/hfs/include/node.h fs/hfs/include/record.h
+ fs/hfs/include/volume.h fs/hfs/low.c fs/hfs/medium.c
+ fs/hfs/node.c fs/hfs/record.c fs/hfs/volume.c fs/hfs_mdb.h
+ fs/hfsplus/.arch-ids/=id fs/hfsplus/.arch-ids/Makefile.id
+ fs/hfsplus/.arch-ids/blockiter.c.id
+ fs/hfsplus/.arch-ids/btree.c.id
+ fs/hfsplus/.arch-ids/hfsp_fs.c.id
+ fs/hfsplus/.arch-ids/libhfsp.c.id
+ fs/hfsplus/.arch-ids/record.c.id
+ fs/hfsplus/.arch-ids/unicode.c.id
+ fs/hfsplus/.arch-ids/volume.c.id fs/hfsplus/Makefile
+ fs/hfsplus/blockiter.c fs/hfsplus/btree.c fs/hfsplus/hfsp_fs.c
+ fs/hfsplus/include/.arch-ids/=id
+ fs/hfsplus/include/.arch-ids/apple.h.id
+ fs/hfsplus/include/.arch-ids/blockiter.h.id
+ fs/hfsplus/include/.arch-ids/btree.h.id
+ fs/hfsplus/include/.arch-ids/hfs.h.id
+ fs/hfsplus/include/.arch-ids/hfsp.h.id
+ fs/hfsplus/include/.arch-ids/hfstime.h.id
+ fs/hfsplus/include/.arch-ids/libhfsp.h.id
+ fs/hfsplus/include/.arch-ids/record.h.id
+ fs/hfsplus/include/.arch-ids/swab.h.id
+ fs/hfsplus/include/.arch-ids/unicode.h.id
+ fs/hfsplus/include/.arch-ids/volume.h.id
+ fs/hfsplus/include/apple.h fs/hfsplus/include/blockiter.h
+ fs/hfsplus/include/btree.h fs/hfsplus/include/hfs.h
+ fs/hfsplus/include/hfsp.h fs/hfsplus/include/hfstime.h
+ fs/hfsplus/include/libhfsp.h fs/hfsplus/include/record.h
+ fs/hfsplus/include/swab.h fs/hfsplus/include/unicode.h
+ fs/hfsplus/include/volume.h fs/hfsplus/libhfsp.c
+ fs/hfsplus/record.c fs/hfsplus/unicode.c fs/hfsplus/volume.c
+ fs/ioglue.c fs/os.h include/.arch-ids/=id
+ include/.arch-ids/elf_boot.h.id
+ include/.arch-ids/ipchecksum.h.id include/.arch-ids/ofmem.h.id
+ include/.arch-ids/sys_info.h.id include/amd64/.arch-ids/=id
+ include/amd64/.arch-ids/elf.h.id
+ include/amd64/.arch-ids/io.h.id
+ include/amd64/.arch-ids/types.h.id include/amd64/elf.h
+ include/amd64/io.h include/amd64/types.h include/elf_boot.h
+ include/ia64/.arch-ids/=id include/ia64/.arch-ids/elf.h.id
+ include/ia64/.arch-ids/io.h.id
+ include/ia64/.arch-ids/types.h.id include/ia64/elf.h
+ include/ia64/io.h include/ia64/types.h include/ipchecksum.h
+ include/libc/.arch-ids/=id
+ include/libc/.arch-ids/byteorder.h.id
+ include/libc/.arch-ids/diskio.h.id
+ include/libc/.arch-ids/stdlib.h.id
+ include/libc/.arch-ids/string.h.id
+ include/libc/.arch-ids/vsprintf.h.id include/libc/byteorder.h
+ include/libc/diskio.h include/libc/stdlib.h
+ include/libc/string.h include/libc/vsprintf.h include/ofmem.h
+ include/openbios/.arch-ids/=id
+ include/openbios/.arch-ids/asm.m4.id
+ include/openbios/.arch-ids/bindings.h.id
+ include/openbios/.arch-ids/config.h.id
+ include/openbios/.arch-ids/drivers.h.id
+ include/openbios/.arch-ids/elf.h.id
+ include/openbios/.arch-ids/elfload.h.id
+ include/openbios/.arch-ids/fs.h.id
+ include/openbios/.arch-ids/kernel.h.id
+ include/openbios/.arch-ids/nvram.h.id
+ include/openbios/.arch-ids/of.h.id
+ include/openbios/.arch-ids/stack.h.id
+ include/openbios/.arch-ids/sysinclude.h.id
+ include/openbios/asm.m4 include/openbios/bindings.h
+ include/openbios/config.h include/openbios/drivers.h
+ include/openbios/elf.h include/openbios/elfload.h
+ include/openbios/fs.h include/openbios/kernel.h
+ include/openbios/nvram.h include/openbios/of.h
+ include/openbios/stack.h include/openbios/sysinclude.h
+ include/ppc/.arch-ids/=id include/ppc/.arch-ids/asmdefs.h.id
+ include/ppc/.arch-ids/elf.h.id include/ppc/.arch-ids/io.h.id
+ include/ppc/.arch-ids/processor.h.id
+ include/ppc/.arch-ids/types.h.id include/ppc/asmdefs.h
+ include/ppc/elf.h include/ppc/io.h include/ppc/processor.h
+ include/ppc/types.h include/sys_info.h
+ include/unix/.arch-ids/=id
+ include/unix/.arch-ids/plugin_pci.h.id
+ include/unix/.arch-ids/plugins.h.id include/unix/plugin_pci.h
+ include/unix/plugins.h include/x86/.arch-ids/=id
+ include/x86/.arch-ids/elf.h.id include/x86/.arch-ids/io.h.id
+ include/x86/.arch-ids/pci.h.id
+ include/x86/.arch-ids/types.h.id include/x86/elf.h
+ include/x86/io.h include/x86/pci.h include/x86/types.h
+ kernel/.arch-ids/=id kernel/.arch-ids/Kconfig.id
+ kernel/.arch-ids/Makefile.id kernel/.arch-ids/README.id
+ kernel/.arch-ids/bootstrap.c.id kernel/.arch-ids/dict.c.id
+ kernel/.arch-ids/forth.c.id kernel/.arch-ids/internal.c.id
+ kernel/.arch-ids/primitives.c.id kernel/.arch-ids/stack.c.id
+ kernel/Kconfig kernel/Makefile kernel/README
+ kernel/bootstrap.c kernel/dict.c kernel/forth.c
+ kernel/include/.arch-ids/=id
+ kernel/include/.arch-ids/dict.h.id kernel/include/dict.h
+ kernel/internal.c kernel/primitives.c kernel/stack.c
+ libc/.arch-ids/=id libc/.arch-ids/Makefile.id
+ libc/.arch-ids/byteorder.c.id libc/.arch-ids/ctype.c.id
+ libc/.arch-ids/diskio.c.id libc/.arch-ids/extra.c.id
+ libc/.arch-ids/misc.c.id libc/.arch-ids/string.c.id
+ libc/.arch-ids/vsprintf.c.id libc/Makefile libc/byteorder.c
+ libc/ctype.c libc/diskio.c libc/extra.c libc/misc.c
+ libc/string.c libc/vsprintf.c modules/.arch-ids/=id
+ modules/.arch-ids/Kconfig.id modules/.arch-ids/Makefile.id
+ modules/.arch-ids/bindings.c.id modules/.arch-ids/clib.fs.id
+ modules/.arch-ids/client.c.id modules/.arch-ids/cmdline.c.id
+ modules/.arch-ids/deblocker.c.id
+ modules/.arch-ids/disk-label.c.id
+ modules/.arch-ids/elfload.c.id modules/.arch-ids/elfnote.c.id
+ modules/.arch-ids/filesystems.c.id
+ modules/.arch-ids/helpers.fs.id modules/.arch-ids/init.c.id
+ modules/.arch-ids/ipchecksum.c.id
+ modules/.arch-ids/linuxbios.c.id
+ modules/.arch-ids/linuxbios.h.id
+ modules/.arch-ids/mac-parts.c.id
+ modules/.arch-ids/mac-parts.h.id
+ modules/.arch-ids/modules.h.id modules/.arch-ids/nvram.c.id
+ modules/.arch-ids/pc-parts.c.id
+ modules/.arch-ids/support.fs.id modules/Kconfig
+ modules/Makefile modules/bindings.c modules/clib.fs
+ modules/client.c modules/cmdline.c modules/deblocker.c
+ modules/disk-label.c modules/elfload.c modules/elfnote.c
+ modules/filesystems.c modules/helpers.fs modules/init.c
+ modules/ipchecksum.c modules/linuxbios.c modules/linuxbios.h
+ modules/mac-parts.c modules/mac-parts.h modules/modules.h
+ modules/nvram.c modules/pc-parts.c modules/support.fs
+ setup_links toke/.arch-ids/=id toke/.arch-ids/COPYING.id
+ toke/.arch-ids/ChangeLog.id toke/.arch-ids/Makefile.id
+ toke/.arch-ids/README.id toke/.arch-ids/Rules.make.id
+ toke/.arch-ids/TODO.id toke/.arch-ids/dictionary.c.id
+ toke/.arch-ids/dictionary.h.id toke/.arch-ids/emit.c.id
+ toke/.arch-ids/emit.h.id toke/.arch-ids/macros.c.id
+ toke/.arch-ids/scanner.c.id toke/.arch-ids/stack.c.id
+ toke/.arch-ids/stack.h.id toke/.arch-ids/stream.c.id
+ toke/.arch-ids/stream.h.id toke/.arch-ids/toke.c.id
+ toke/.arch-ids/toke.h.id toke/COPYING toke/ChangeLog
+ toke/Makefile toke/README toke/Rules.make toke/TODO
+ toke/dictionary.c toke/dictionary.h toke/emit.c toke/emit.h
+ toke/examples/.arch-ids/=id toke/examples/.arch-ids/case.fs.id
+ toke/examples/.arch-ids/date.fs.id
+ toke/examples/.arch-ids/display.fs.id
+ toke/examples/.arch-ids/fcdisp.fs.id
+ toke/examples/.arch-ids/fract.fs.id
+ toke/examples/.arch-ids/pciexample.fs.id
+ toke/examples/.arch-ids/primes.fs.id
+ toke/examples/.arch-ids/simple.fs.id
+ toke/examples/.arch-ids/version1.fs.id
+ toke/examples/.arch-ids/world.fs.id toke/examples/case.fs
+ toke/examples/date.fs toke/examples/display.fs
+ toke/examples/fcdisp.fs toke/examples/fract.fs
+ toke/examples/pciexample.fs toke/examples/primes.fs
+ toke/examples/scsi-sample/.arch-ids/=id
+ toke/examples/scsi-sample/.arch-ids/README.sample.id
+ toke/examples/scsi-sample/.arch-ids/hacom.fs.id
+ toke/examples/scsi-sample/.arch-ids/overall.fs.id
+ toke/examples/scsi-sample/.arch-ids/scsicom.fs.id
+ toke/examples/scsi-sample/.arch-ids/scsidisk.fs.id
+ toke/examples/scsi-sample/.arch-ids/scsiha.fs.id
+ toke/examples/scsi-sample/.arch-ids/scsitape.fs.id
+ toke/examples/scsi-sample/README.sample
+ toke/examples/scsi-sample/hacom.fs
+ toke/examples/scsi-sample/overall.fs
+ toke/examples/scsi-sample/scsicom.fs
+ toke/examples/scsi-sample/scsidisk.fs
+ toke/examples/scsi-sample/scsiha.fs
+ toke/examples/scsi-sample/scsitape.fs toke/examples/simple.fs
+ toke/examples/version1.fs toke/examples/world.fs toke/macros.c
+ toke/scanner.c toke/stack.c toke/stack.h toke/stream.c
+ toke/stream.h toke/toke.c toke/toke.h utils/.arch-ids/=id
+ utils/.arch-ids/README.id utils/README
+ utils/detok/.arch-ids/=id utils/detok/.arch-ids/COPYING.id
+ utils/detok/.arch-ids/ChangeLog.id
+ utils/detok/.arch-ids/Makefile.id
+ utils/detok/.arch-ids/README.id
+ utils/detok/.arch-ids/Rules.make.id
+ utils/detok/.arch-ids/decode.c.id
+ utils/detok/.arch-ids/detok.c.id
+ utils/detok/.arch-ids/detok.h.id
+ utils/detok/.arch-ids/dictionary.c.id
+ utils/detok/.arch-ids/stream.c.id
+ utils/detok/.arch-ids/stream.h.id utils/detok/COPYING
+ utils/detok/ChangeLog utils/detok/Makefile utils/detok/README
+ utils/detok/Rules.make utils/detok/decode.c
+ utils/detok/detok.c utils/detok/detok.h
+ utils/detok/dictionary.c utils/detok/stream.c
+ utils/detok/stream.h utils/devbios/.arch-ids/=id
+ utils/devbios/.arch-ids/COPYING.id
+ utils/devbios/.arch-ids/CREDITS.id
+ utils/devbios/.arch-ids/ChangeLog.id
+ utils/devbios/.arch-ids/Makefile.24.id
+ utils/devbios/.arch-ids/Makefile.id
+ utils/devbios/.arch-ids/README.bios.id
+ utils/devbios/.arch-ids/ToDo.id
+ utils/devbios/.arch-ids/bios.h.id
+ utils/devbios/.arch-ids/bios_core.c.id
+ utils/devbios/.arch-ids/comp.c.id
+ utils/devbios/.arch-ids/filesystem.c.id
+ utils/devbios/.arch-ids/flashchips.c.id
+ utils/devbios/.arch-ids/flashchips.h.id
+ utils/devbios/.arch-ids/pcisets.c.id
+ utils/devbios/.arch-ids/pcisets.h.id
+ utils/devbios/.arch-ids/procfs.c.id
+ utils/devbios/.arch-ids/programming.c.id
+ utils/devbios/.arch-ids/programming.h.id utils/devbios/COPYING
+ utils/devbios/CREDITS utils/devbios/ChangeLog
+ utils/devbios/Makefile utils/devbios/Makefile.24
+ utils/devbios/README.bios utils/devbios/ToDo
+ utils/devbios/bios.h utils/devbios/bios_core.c
+ utils/devbios/comp.c utils/devbios/filesystem.c
+ utils/devbios/flashchips.c utils/devbios/flashchips.h
+ utils/devbios/pcisets.c utils/devbios/pcisets.h
+ utils/devbios/procfs.c utils/devbios/programming.c
+ utils/devbios/programming.h utils/fccc/.arch-ids/=id
+ utils/fccc/.arch-ids/COPYING.id utils/fccc/COPYING
+ utils/fccc/include/.arch-ids/=id
+ utils/fccc/include/.arch-ids/fccc-tools.h.id
+ utils/fccc/include/.arch-ids/fccc.h.id
+ utils/fccc/include/.arch-ids/linklist.h.id
+ utils/fccc/include/.arch-ids/parserfunctions.h.id
+ utils/fccc/include/.arch-ids/symboltable.h.id
+ utils/fccc/include/fccc-tools.h utils/fccc/include/fccc.h
+ utils/fccc/include/linklist.h
+ utils/fccc/include/parserfunctions.h
+ utils/fccc/include/symboltable.h utils/fccc/src/.arch-ids/=id
+ utils/fccc/src/.arch-ids/Makefile.id
+ utils/fccc/src/.arch-ids/fccc-tools.c.id
+ utils/fccc/src/.arch-ids/fccc.lex.id
+ utils/fccc/src/.arch-ids/fccc.y.id
+ utils/fccc/src/.arch-ids/linklist.c.id
+ utils/fccc/src/.arch-ids/plain_ass.c.id
+ utils/fccc/src/.arch-ids/symboltable.c.id
+ utils/fccc/src/Makefile utils/fccc/src/fccc-tools.c
+ utils/fccc/src/fccc.lex utils/fccc/src/fccc.y
+ utils/fccc/src/linklist.c utils/fccc/src/plain_ass.c
+ utils/fccc/src/symboltable.c utils/fccc/test/.arch-ids/=id
+ utils/fccc/test/.arch-ids/test1.c.id utils/fccc/test/test1.c
+ utils/romheaders/.arch-ids/=id
+ utils/romheaders/.arch-ids/Makefile.id
+ utils/romheaders/.arch-ids/romheaders.c.id
+ utils/romheaders/Makefile utils/romheaders/romheaders.c
+ {arch}/.arch-project-tree {arch}/=tagging-method
+ {arch}/openbios/openbios--main/openbios--main--1.0/stepan@openbios.org--devel/patch-log/base-0
+ {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log/base-0
+ {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log/patch-1
+ {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log/patch-2
+ {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log/patch-3
+
+ modified directories:
+ .arch-ids Documentation/.arch-ids
+ Documentation/kernel/.arch-ids arch/.arch-ids
+ arch/amd64/.arch-ids arch/ia64/.arch-ids arch/ppc/.arch-ids
+ arch/ppc/briq/.arch-ids arch/ppc/mol/.arch-ids
+ arch/unix/.arch-ids arch/unix/gui_qt/.arch-ids
+ arch/unix/plugins/.arch-ids
+ arch/unix/plugins/plugin_pci/.arch-ids
+ arch/unix/plugins/plugin_qt/.arch-ids arch/x86/.arch-ids
+ config/.arch-ids config/kconfig/.arch-ids
+ config/lxdialog/.arch-ids config/scripts/.arch-ids
+ dist/.arch-ids dist/debian/.arch-ids drivers/.arch-ids
+ forth/.arch-ids forth/admin/.arch-ids
+ forth/bootstrap/.arch-ids forth/debugging/.arch-ids
+ forth/device/.arch-ids forth/lib/.arch-ids
+ forth/packages/.arch-ids forth/system/.arch-ids
+ forth/testsuite/.arch-ids forth/util/.arch-ids fs/.arch-ids
+ fs/grubfs/.arch-ids fs/hfs/.arch-ids fs/hfs/include/.arch-ids
+ fs/hfsplus/.arch-ids fs/hfsplus/include/.arch-ids
+ include/.arch-ids include/amd64/.arch-ids
+ include/ia64/.arch-ids include/libc/.arch-ids
+ include/openbios/.arch-ids include/ppc/.arch-ids
+ include/unix/.arch-ids include/x86/.arch-ids kernel/.arch-ids
+ kernel/include/.arch-ids libc/.arch-ids modules/.arch-ids
+ toke/.arch-ids toke/examples/.arch-ids
+ toke/examples/scsi-sample/.arch-ids utils/.arch-ids
+ utils/detok/.arch-ids utils/devbios/.arch-ids
+ utils/fccc/.arch-ids utils/fccc/include/.arch-ids
+ utils/fccc/src/.arch-ids utils/fccc/test/.arch-ids
+ utils/romheaders/.arch-ids {arch} {arch}/openbios
+ {arch}/openbios/openbios--main
+ {arch}/openbios/openbios--main/openbios--main--1.0
+ {arch}/openbios/openbios--main/openbios--main--1.0/stepan@openbios.org--devel
+ {arch}/openbios/openbios--main/openbios--main--1.0/stepan@openbios.org--devel/patch-log
+ {arch}/openbios/openbios--porting
+ {arch}/openbios/openbios--porting/openbios--porting--0
+ {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004
+ {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log
+
+ new patches:
+ oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-4
+
+
+2004-09-01 19:03:41 GMT Stefan Reinauer <stepan@openbios.org> patch-1
+
+ Summary:
+
+ Revision:
+ openbios--main--1.0--patch-1
+
+
+
+ Patches applied:
+
+ * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--base-0
+ tag of stepan@openbios.org--devel/openbios--main--1.0--base-0
+
+ * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-1
+ changes to make it build on dragonflybsd
+
+ * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-2
+ no need for the uue hack anymore
+
+ * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-3
+ check for stack protector for gcc and disable if present
+
+
+ new files:
+ forth/device/.arch-ids/romfont.bin.id forth/device/romfont.bin
+
+ removed files:
+ forth/device/.arch-ids/romfont.uue.id forth/device/romfont.uue
+
+ modified files:
+ Documentation/ChangeLog.arch arch/unix/unix.c
+ arch/x86/builtin.c config/configure.in drivers/ide.h
+ forth/device/Makefile include/openbios/kernel.h
+ include/x86/types.h {arch}/=tagging-method
+
+ new patches:
+ oxygene@studentenbude.ath.cx--2004/openbios--porting--0--base-0
+ oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-1
+ oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-2
+ oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-3
+
+
+2004-08-29 13:29:22 GMT Stefan Reinauer <stepan@openbios.org> base-0
+
+ Summary:
+ initial import
+ Revision:
+ openbios--main--1.0--base-0
+
+
+ (automatically generated log message)
+
+ new files:
+ COPYING Documentation/ChangeLog.arch
+ Documentation/kernel/AUTHORS Documentation/kernel/COPYING
+ Documentation/kernel/Changelog.stepan
+ Documentation/kernel/TODO Documentation/kernel/dictformat.txt
+ Documentation/kernel/glossary.txt
+ Documentation/kernel/initializers.txt Makefile README
+ arch/amd64/Kconfig arch/amd64/Makefile arch/amd64/Makefile.asm
+ arch/amd64/boot.c arch/amd64/builtin.c arch/amd64/console.c
+ arch/amd64/context.c arch/amd64/context.h arch/amd64/defconfig
+ arch/amd64/elfload.c arch/amd64/init.fs arch/amd64/ldscript
+ arch/amd64/lib.c arch/amd64/linux_load.c arch/amd64/loadfs.c
+ arch/amd64/loadfs.h arch/amd64/multiboot.c
+ arch/amd64/multiboot.h arch/amd64/openbios.c
+ arch/amd64/openbios.h arch/amd64/plainboot.c
+ arch/amd64/relocate.h arch/amd64/segment.c
+ arch/amd64/segment.h arch/amd64/switch.S arch/amd64/sys_info.c
+ arch/ia64/Kconfig arch/ia64/Makefile arch/ia64/Makefile.asm
+ arch/ia64/defconfig arch/ia64/init.fs arch/ppc/Kconfig
+ arch/ppc/Makefile arch/ppc/Makefile.asm arch/ppc/briq/briq.c
+ arch/ppc/briq/briq.fs arch/ppc/briq/briq.h
+ arch/ppc/briq/init.c arch/ppc/briq/kernel.c
+ arch/ppc/briq/main.c arch/ppc/briq/methods.c
+ arch/ppc/briq/tree.c arch/ppc/briq/tree.fs arch/ppc/briq/vfd.c
+ arch/ppc/defconfig arch/ppc/kernel.c arch/ppc/kernel.h
+ arch/ppc/misc.S arch/ppc/mmutypes.h arch/ppc/mol/console.c
+ arch/ppc/mol/font_8x8.c arch/ppc/mol/init.c
+ arch/ppc/mol/kernel.c arch/ppc/mol/main.c
+ arch/ppc/mol/methods.c arch/ppc/mol/mol.c arch/ppc/mol/mol.fs
+ arch/ppc/mol/mol.h arch/ppc/mol/osi-blk.c
+ arch/ppc/mol/osi-scsi.c arch/ppc/mol/prom.c
+ arch/ppc/mol/prom.h arch/ppc/mol/pseudodisk.c
+ arch/ppc/mol/tree.c arch/ppc/mol/tree.fs arch/ppc/mol/video.c
+ arch/ppc/ofmem.c arch/ppc/osi.h arch/ppc/osi_calls.h
+ arch/ppc/ppc.fs arch/ppc/start.S arch/ppc/timebase.S
+ arch/unix/Kconfig arch/unix/Makefile arch/unix/blk.c
+ arch/unix/blk.h arch/unix/boot.c arch/unix/gui_qt/Makefile
+ arch/unix/gui_qt/gui-qt.cpp arch/unix/gui_qt/gui-qt.h
+ arch/unix/gui_qt/gui-qt.pro arch/unix/gui_qt/logo.xpm
+ arch/unix/gui_qt/qt-main.cpp arch/unix/plugins.c
+ arch/unix/plugins/Kconfig arch/unix/plugins/Makefile
+ arch/unix/plugins/Rules.plugin arch/unix/plugins/loader.c
+ arch/unix/plugins/plugin_pci/Makefile
+ arch/unix/plugins/plugin_pci/Makefile.old
+ arch/unix/plugins/plugin_pci/plugin_pci.c
+ arch/unix/plugins/plugin_qt/Makefile
+ arch/unix/plugins/plugin_qt/logo.xpm
+ arch/unix/plugins/plugin_qt/pciconfig.h
+ arch/unix/plugins/plugin_qt/plugin_qt.cpp
+ arch/unix/plugins/plugin_qt/plugin_qt.h
+ arch/unix/plugins/plugin_qt/plugin_qt.pro
+ arch/unix/plugins/plugin_qt/qt_main.cpp
+ arch/unix/plugins/plugin_qt/qt_rom.fs arch/unix/tree.fs
+ arch/unix/unix.c arch/x86/Kconfig arch/x86/Makefile
+ arch/x86/Makefile.asm arch/x86/boot.c arch/x86/boot.h
+ arch/x86/builtin.c arch/x86/console.c arch/x86/context.c
+ arch/x86/context.h arch/x86/defconfig arch/x86/elfload.c
+ arch/x86/forthload.c arch/x86/init.fs arch/x86/ldscript
+ arch/x86/lib.c arch/x86/linux_load.c arch/x86/loadfs.c
+ arch/x86/loadfs.h arch/x86/multiboot.c arch/x86/multiboot.h
+ arch/x86/openbios.c arch/x86/openbios.h arch/x86/plainboot.c
+ arch/x86/relocate.h arch/x86/segment.c arch/x86/segment.h
+ arch/x86/switch.S arch/x86/sys_info.c autogen.sh
+ config/Makefile config/Makefile.defs.in config/Makefile.master
+ config/Makefile.top config/Rules.forth config/Rules.make
+ config/configure.in config/kconfig/Makefile
+ config/kconfig/conf.c config/kconfig/confdata.c
+ config/kconfig/expr.c config/kconfig/expr.h
+ config/kconfig/lkc.h config/kconfig/lkc_proto.h
+ config/kconfig/mconf.c config/kconfig/menu.c
+ config/kconfig/symbol.c config/kconfig/zconf-l.l
+ config/kconfig/zconf-y.y config/lxdialog/Makefile
+ config/lxdialog/checklist.c config/lxdialog/colors.h
+ config/lxdialog/dialog.h config/lxdialog/inputbox.c
+ config/lxdialog/lxdialog.c config/lxdialog/menubox.c
+ config/lxdialog/msgbox.c config/lxdialog/textbox.c
+ config/lxdialog/util.c config/lxdialog/yesno.c
+ config/scripts/archname config/scripts/reldir configure
+ dist/debian/changelog dist/debian/control dist/debian/packages
+ dist/debian/rules dist/openbios.spec drivers/Kconfig
+ drivers/Makefile drivers/hdreg.h drivers/ide.c drivers/ide.fs
+ drivers/ide.h drivers/pci.c drivers/pci.fs drivers/pci.h
+ drivers/timer.c drivers/timer.h forth/Kconfig forth/Makefile
+ forth/admin/Makefile forth/admin/README forth/admin/banner.fs
+ forth/admin/callback.fs forth/admin/devices.fs
+ forth/admin/help.fs forth/admin/iocontrol.fs
+ forth/admin/nvram.fs forth/admin/reset.fs
+ forth/admin/script.fs forth/admin/security.fs
+ forth/admin/selftest.fs forth/admin/userboot.fs
+ forth/bootstrap/bootstrap.fs forth/bootstrap/builtin.fs
+ forth/bootstrap/hayes.fs forth/bootstrap/interpreter.fs
+ forth/bootstrap/memory.fs forth/bootstrap/start.fs
+ forth/debugging/Makefile forth/debugging/client.fs
+ forth/debugging/fcode.fs forth/debugging/firmware.fs
+ forth/debugging/see.fs forth/device/Makefile
+ forth/device/README.device forth/device/builtin.fs
+ forth/device/device.fs forth/device/display.fs
+ forth/device/extra.fs forth/device/fcode.fs
+ forth/device/feval.fs forth/device/font.fs
+ forth/device/logo.fs forth/device/missing
+ forth/device/other.fs forth/device/package.fs
+ forth/device/pathres.fs forth/device/preof.fs
+ forth/device/property.fs forth/device/romfont.uue
+ forth/device/structures.fs forth/device/table.fs
+ forth/device/terminal.fs forth/device/tree.fs
+ forth/lib/Makefile forth/lib/creation.fs forth/lib/lists.fs
+ forth/lib/preprocessor.fs forth/lib/split.fs
+ forth/lib/string.fs forth/lib/vocabulary.fs
+ forth/packages/Kconfig forth/packages/Makefile
+ forth/packages/README forth/packages/deblocker.fs
+ forth/packages/disklabel.fs forth/packages/obp-tftp.fs
+ forth/packages/packages.fs forth/packages/terminal-emulator.fs
+ forth/system/Makefile forth/system/ciface.fs
+ forth/system/main.fs forth/testsuite/Makefile
+ forth/testsuite/README forth/testsuite/fract.fs
+ forth/testsuite/framebuffer-test.fs
+ forth/testsuite/memory-testsuite.fs
+ forth/testsuite/splitfunc-testsuite.fs forth/util/Makefile
+ forth/util/apic.fs forth/util/pci.fs forth/util/util.fs
+ fs/Makefile fs/grubfs/Kconfig fs/grubfs/Makefile
+ fs/grubfs/debug.h fs/grubfs/defs.h fs/grubfs/dir.h
+ fs/grubfs/disk_inode.h fs/grubfs/disk_inode_ffs.h
+ fs/grubfs/fat.h fs/grubfs/filesys.h fs/grubfs/fs.h
+ fs/grubfs/fsys_affs.c fs/grubfs/fsys_ext2fs.c
+ fs/grubfs/fsys_fat.c fs/grubfs/fsys_ffs.c
+ fs/grubfs/fsys_iso9660.c fs/grubfs/fsys_jfs.c
+ fs/grubfs/fsys_minix.c fs/grubfs/fsys_ntfs.c
+ fs/grubfs/fsys_reiserfs.c fs/grubfs/fsys_vstafs.c
+ fs/grubfs/fsys_xfs.c fs/grubfs/glue.h fs/grubfs/grubfs_fs.c
+ fs/grubfs/iso9660.h fs/grubfs/jfs.h fs/grubfs/shared.h
+ fs/grubfs/vstafs.h fs/grubfs/xfs.h fs/hfs/Makefile
+ fs/hfs/block.c fs/hfs/btree.c fs/hfs/data.c fs/hfs/file.c
+ fs/hfs/hfs.c fs/hfs/hfs_fs.c fs/hfs/include/apple.h
+ fs/hfs/include/block.h fs/hfs/include/btree.h
+ fs/hfs/include/data.h fs/hfs/include/file.h
+ fs/hfs/include/hfs.h fs/hfs/include/libhfs.h
+ fs/hfs/include/low.h fs/hfs/include/medium.h
+ fs/hfs/include/node.h fs/hfs/include/record.h
+ fs/hfs/include/volume.h fs/hfs/low.c fs/hfs/medium.c
+ fs/hfs/node.c fs/hfs/record.c fs/hfs/volume.c fs/hfs_mdb.h
+ fs/hfsplus/Makefile fs/hfsplus/blockiter.c fs/hfsplus/btree.c
+ fs/hfsplus/hfsp_fs.c fs/hfsplus/include/apple.h
+ fs/hfsplus/include/blockiter.h fs/hfsplus/include/btree.h
+ fs/hfsplus/include/hfs.h fs/hfsplus/include/hfsp.h
+ fs/hfsplus/include/hfstime.h fs/hfsplus/include/libhfsp.h
+ fs/hfsplus/include/record.h fs/hfsplus/include/swab.h
+ fs/hfsplus/include/unicode.h fs/hfsplus/include/volume.h
+ fs/hfsplus/libhfsp.c fs/hfsplus/record.c fs/hfsplus/unicode.c
+ fs/hfsplus/volume.c fs/ioglue.c fs/os.h include/amd64/elf.h
+ include/amd64/io.h include/amd64/types.h include/elf_boot.h
+ include/ia64/elf.h include/ia64/io.h include/ia64/types.h
+ include/ipchecksum.h include/libc/byteorder.h
+ include/libc/diskio.h include/libc/stdlib.h
+ include/libc/string.h include/libc/vsprintf.h include/ofmem.h
+ include/openbios/asm.m4 include/openbios/bindings.h
+ include/openbios/config.h include/openbios/drivers.h
+ include/openbios/elf.h include/openbios/elfload.h
+ include/openbios/fs.h include/openbios/kernel.h
+ include/openbios/nvram.h include/openbios/of.h
+ include/openbios/stack.h include/openbios/sysinclude.h
+ include/ppc/asmdefs.h include/ppc/elf.h include/ppc/io.h
+ include/ppc/processor.h include/ppc/types.h include/sys_info.h
+ include/unix/plugin_pci.h include/unix/plugins.h
+ include/x86/elf.h include/x86/io.h include/x86/pci.h
+ include/x86/types.h kernel/Kconfig kernel/Makefile
+ kernel/README kernel/bootstrap.c kernel/dict.c kernel/forth.c
+ kernel/include/dict.h kernel/internal.c kernel/primitives.c
+ kernel/stack.c libc/Makefile libc/byteorder.c libc/ctype.c
+ libc/diskio.c libc/extra.c libc/misc.c libc/string.c
+ libc/vsprintf.c modules/Kconfig modules/Makefile
+ modules/bindings.c modules/clib.fs modules/client.c
+ modules/cmdline.c modules/deblocker.c modules/disk-label.c
+ modules/elfload.c modules/elfnote.c modules/filesystems.c
+ modules/helpers.fs modules/init.c modules/ipchecksum.c
+ modules/linuxbios.c modules/linuxbios.h modules/mac-parts.c
+ modules/mac-parts.h modules/modules.h modules/nvram.c
+ modules/pc-parts.c modules/support.fs setup_links toke/COPYING
+ toke/ChangeLog toke/Makefile toke/README toke/Rules.make
+ toke/TODO toke/dictionary.c toke/dictionary.h toke/emit.c
+ toke/emit.h toke/examples/case.fs toke/examples/date.fs
+ toke/examples/display.fs toke/examples/fcdisp.fs
+ toke/examples/fract.fs toke/examples/pciexample.fs
+ toke/examples/primes.fs
+ toke/examples/scsi-sample/README.sample
+ toke/examples/scsi-sample/hacom.fs
+ toke/examples/scsi-sample/overall.fs
+ toke/examples/scsi-sample/scsicom.fs
+ toke/examples/scsi-sample/scsidisk.fs
+ toke/examples/scsi-sample/scsiha.fs
+ toke/examples/scsi-sample/scsitape.fs toke/examples/simple.fs
+ toke/examples/version1.fs toke/examples/world.fs toke/macros.c
+ toke/scanner.c toke/stack.c toke/stack.h toke/stream.c
+ toke/stream.h toke/toke.c toke/toke.h utils/README
+ utils/detok/COPYING utils/detok/ChangeLog utils/detok/Makefile
+ utils/detok/README utils/detok/Rules.make utils/detok/decode.c
+ utils/detok/detok.c utils/detok/detok.h
+ utils/detok/dictionary.c utils/detok/stream.c
+ utils/detok/stream.h utils/devbios/COPYING
+ utils/devbios/CREDITS utils/devbios/ChangeLog
+ utils/devbios/Makefile utils/devbios/Makefile.24
+ utils/devbios/README.bios utils/devbios/ToDo
+ utils/devbios/bios.h utils/devbios/bios_core.c
+ utils/devbios/comp.c utils/devbios/filesystem.c
+ utils/devbios/flashchips.c utils/devbios/flashchips.h
+ utils/devbios/pcisets.c utils/devbios/pcisets.h
+ utils/devbios/procfs.c utils/devbios/programming.c
+ utils/devbios/programming.h utils/fccc/COPYING
+ utils/fccc/include/fccc-tools.h utils/fccc/include/fccc.h
+ utils/fccc/include/linklist.h
+ utils/fccc/include/parserfunctions.h
+ utils/fccc/include/symboltable.h utils/fccc/src/Makefile
+ utils/fccc/src/fccc-tools.c utils/fccc/src/fccc.lex
+ utils/fccc/src/fccc.y utils/fccc/src/linklist.c
+ utils/fccc/src/plain_ass.c utils/fccc/src/symboltable.c
+ utils/fccc/test/test1.c utils/romheaders/Makefile
+ utils/romheaders/romheaders.c
+
+
diff --git a/roms/openbios/Documentation/README.debugger b/roms/openbios/Documentation/README.debugger
new file mode 100644
index 00000000..a44f5a85
--- /dev/null
+++ b/roms/openbios/Documentation/README.debugger
@@ -0,0 +1,50 @@
+The following Forth words can be used for debugging:
+
+ debug <xt> - Mark word for debugging
+ debug-off - Unmark all words for debugging
+ resume - Return from subordinate Forth interpreter
+
+The source debugger also implements the following commands when it has been activated:
+
+ Up - Unmark current word for debugging, mark parent and continue
+ Down - Mark next word for debugging
+ Trace - Continue execution until end of word displaying
+ debug information
+ Rstack - Display contents of the Rstack
+ Forth - Launch subordinate Forth interpreter
+
+An example session:
+0 > see boot
+: boot
+ linefeed parse cr " platform-boot" $find if
+ execute then
+ 2drop cr " Booting " type type cr " ... not supported on this system." type cr
+ ;
+ ok
+0 > debug boot
+Stepper keys: <space>/<enter> Up Down Trace Rstack Forth
+ ok
+0 > boot
+: boot ( Empty )
+00000000ffe26b08: linefeed ( a )
+00000000ffe26b10: parse ( ffec6e24 0 )
+00000000ffe26b18: cr
+ ( ffec6e24 0 )
+00000000ffe26b20: (") ( ffec6e24 0 ffe26b30 d )
+00000000ffe26b40: $find ( ffec6e24 0 ffe31710 ffffffffffffffff )
+00000000ffe26b48: do?branch ( ffec6e24 0 ffe31710 )
+00000000ffe26b58: execute [sparc64] Booting file 'cdrom' with parameters ''
+Not a bootable ELF image
+Not a Linux kernel image
+Not a bootable a.out image
+Loading FCode image...
+Loaded 5936 bytes
+entry point is 0x4000
+Evaluating FCode...
+open isn't unique.
+Boot load failed.
+ ( Empty )
+00000000ffe26b60: dobranch ( Empty )
+00000000ffe26bf8: (semis)
+[ Finished boot ] ok
+0 >
diff --git a/roms/openbios/Documentation/TODO.sparc b/roms/openbios/Documentation/TODO.sparc
new file mode 100644
index 00000000..1dda96f6
--- /dev/null
+++ b/roms/openbios/Documentation/TODO.sparc
@@ -0,0 +1,64 @@
+TODO-list:
+
+Sparc common:
+- Unimplemented features/bugs:
+ - Send keycode on keypress
+ - Remove compiler warnings
+ - Clean up
+
+- Optimizations/improvements:
+ - Merge allocators (lib.c malloc, romvec opb_, iommu, OF /memory, Sparc64)
+ - Warm reset detection
+ - Boot logo
+
+Sparc32:
+- Unimplemented features/bugs:
+ - Some console escape codes (Debian 3.1R1, NetBSD)
+ - Arbitrary resolution support
+ - Add cg6, bwtwo
+ - Probe devices (like Proll?)
+ - Less fixed hardware choices, conditional HW
+ - SBus slot probing, FCode ROM support
+ - Compile for least capable CPU
+ - DBRI audio (Am7930)
+ - BPP parallel
+ - Diagnostic switch
+
+Sparc64:
+- Unimplemented features/bugs:
+ - Debug direct kernel boot
+ - Boot from drive, cdrom or floppy
+
+- Optimizations/improvements:
+ - Hypervisor
+
+Sun4:
+- Support to be added
+
+Sun4c:
+- Support to be added
+
+Sun4m:
+- Unimplemented features/bugs:
+ - JavaStation machines
+ - Realistic SMP probing
+ - SS600MP ledma -> lebuffer
+
+Sun4d:
+- Support to be added
+
+Sun4u:
+- Unimplemented features/bugs:
+ - Interrupt controller setup
+ - PCI/IOMMU support (Simba, JIO, Tomatillo, Psycho, Schizo, Safari...)
+ - SMP/CMT
+ - Happy Meal Ethernet, flash, I2C, GPIO
+ - A lot of real machine types
+
+Sun4v:
+- Support to be added
+
+Ideas:
+ - Real machine test with special entry.S
+ - Unix compile with uClibc
+ - Sparc64: Emulate hypervisor so that OpenBoot image can be used
diff --git a/roms/openbios/Documentation/kernel/AUTHORS b/roms/openbios/Documentation/kernel/AUTHORS
new file mode 100644
index 00000000..365e098d
--- /dev/null
+++ b/roms/openbios/Documentation/kernel/AUTHORS
@@ -0,0 +1,6 @@
+The OpenBIOS forth engine was written by
+
+ Patrick Mauritz <oxygene@openbios.info>
+ Stefan Reinauer <stepan@openbios.info>
+
+# tag: list of authors
diff --git a/roms/openbios/Documentation/kernel/COPYING b/roms/openbios/Documentation/kernel/COPYING
new file mode 100644
index 00000000..91f234ff
--- /dev/null
+++ b/roms/openbios/Documentation/kernel/COPYING
@@ -0,0 +1,358 @@
+All or most of the source files in this distribution refer to this
+file for copyright and warranty information. This file should be
+included whenever those files are redistributed.
+
+This software is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License, version 2, as
+published by the Free Software Foundation. This license is reproduced
+below.
+
+Please note that we explicitely do not allow applying any newer version
+of the GPL to this work. Once the FSF releases such a revision we will
+reconsider to allow it as well.
+
+----------------- verbatim license text below ---------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+# tag: General Public License text
+#
diff --git a/roms/openbios/Documentation/kernel/Changelog.stepan b/roms/openbios/Documentation/kernel/Changelog.stepan
new file mode 100644
index 00000000..1b4d5344
--- /dev/null
+++ b/roms/openbios/Documentation/kernel/Changelog.stepan
@@ -0,0 +1,300 @@
+# tag: stepan's changelog for CVS
+
+Mon Jul 14 02:16:49 CEST 2003
+ - fix segv overrun while dumping dictionary in unix.c
+ - implement first version of >number and $number
+ - add stack diagram to digit
+ - no newline after accept
+ - new version of the interpreter
+ - fix make run target
+
+Mon Jul 14 20:15:40 CEST 2003
+ - negate true value in prims
+ - get rid of primitive word bounds.
+ - get rid of some obsolete code.
+ - implement io[cwl][@!]
+ - reorganize [in|out][bwl]
+ - start adding stack diagrams to primitives.
+
+Mon Jul 14 23:57:46 CEST 2003
+ - added some more stack diagrams in forth.h
+ - move parse, parse-word, word to bootstrap.fs
+ - include memory.fs from bootstrap.fs for above.
+
+Wed Jul 16 22:57:31 CEST 2003
+ - add include guards
+ - add banner
+ - fix primitives' dependencies
+
+Sun Jul 20 03:27:40 CEST 2003
+ - remove unneeded readcell
+ - rename ' to ['] to meet specs
+
+Sun Jul 20 14:08:43 CEST 2003
+ - add rest of stack diagrams in forth.h
+ - move here and here! to forth.h (from internal.h)
+ - indent includes
+ - merge system.h into forth.h
+ - Change tag of forth.h (!) because the old one
+ did not meet the meaning of the code.
+ - update comments in primitives.c
+
+Sun Jul 27 01:53:18 CEST 2003
+ - include great new do/?do/loop/+loop
+ implementation from Patrick.
+ - include testsuite enhancement from Patrick
+ - include trampoline from Patrick (fixes execute)
+
+Sun Jul 27 21:11:50 CEST 2003
+ - update x86 console code to become when using
+ multiboot (vga/keyboard).
+ - fix exit properly
+ - revert to old case..endcase code
+ - fix >number and $number
+ - add number parsing to interpreter
+ - add simple stack checking to interpreter
+ - add 2 testcases (exit and case2)
+
+Mon Jul 28 14:49:31 CEST 2003
+ - move 7.3.7 Flag constants up in bootstrap.fs
+ - move 7.3.9.2.4 Miscellaneous dictionary down.
+ - add reveal, recursive, recurse, environment? to 7.3.9.2.4
+ - move (to) to bootstrap.fs
+
+Mon Jul 28 17:08:58 CEST 2003
+ - add stack overflow check to interpreter
+ - check parse-word result in interpreter.
+ - add ascii and char, add helper handle-lit
+
+Tue Jul 29 09:20:18 CEST 2003
+ - add s" and ."
+ - add [char] and control
+ - heavily move around words in bootstrap.fs
+ to get dependencies resolved.
+ - fix skipws crash
+ - rename query to refill
+ - interpreter reads several words in a line now
+ - interpreter stops now if error encountered in
+ currently parsed line.
+ - add forth definitions of ( and \
+ - change c parser/interpreter to handle comments
+ correctly.
+ - indent, clean up unix.c
+
+Tue Jul 29 18:13:27 CEST 2003
+ - add .( (chapter 7.3.4.4)
+ - add pack, -trailing (chapter 7.3.4.8)
+ - add d#, h#, o# (chapter 7.3.5.2)
+ - let first stack element start at 1 instead of 0
+ to have a 1 cell guard band.
+ - set SA_NODEFER flag to signal handler to ensure
+ that it is entered recursively.
+
+Tue Jul 29 19:06:18 CEST 2003
+ - more simplification for unix.c
+ - add ', ['], find
+ - fix pack, count
+ - add literal, compile, [compile], compile,
+ - fix [
+
+Wed Jul 30 01:24:24 CEST 2003
+ - add >body, body>
+ - add helpers: flags?, immediate?, compile-only?, header
+ - add :, ;, constant, value, variable, buffer:
+ - parse word's flags in interpreter to make colon
+ definitions work
+ - add "compiled" acknowledge when interpreter is in compile mode
+
+Wed Jul 30 07:27:58 CEST 2003
+ - fix flags handling in interpreter
+ - fix handle-text compile mode behaviour
+ - add defer, struct, field
+ - add behaviour, to
+ - add $create, create, does> (missing c code DODOES)
+ - add abort
+
+Thu Jul 31 07:58:35 CEST 2003
+ - fix DODOES cfa code
+ - make 2@ and 2! colon definitions instead of primitives.
+ - add word "cell"
+ - add warning message as described in 7.3.9.1 if an already
+ existing word is created
+
+Fri Aug 1 23:32:57 CEST 2003
+ - fix s" in C interpreter (compare case insensitive)
+ - fix forth source dependencies
+ - fix forth word sm/rem
+
+Sat Aug 2 13:34:43 CEST 2003
+ - add band guard around input buffer
+ - make sure that "header" pads null bytes
+ - define -1,0,1,2,3 early to safe dictionary space
+
+Sat Aug 2 16:58:31 CEST 2003
+ - use getopt/getopt_long for option parsing
+ - add include path option -I to unix
+ - don't create obsolete symlink in forth/Makefile
+ - fix recurse
+ - fix prim word /
+ - implement postpone
+ - fix 2!, ['] and '
+ - implement evaluate/eval
+
+Sun Aug 3 11:48:18 CEST 2003
+ - implement "bye" to leave the engine
+ - change initial word to "initialize" and
+ make quit restart the forth engine.
+ - fix missing ; in u.
+ - fix return value of find when handling an immediate
+ - getting rid of primitives mod, /mod and /, replacing
+ them by floored variants as IEEE 1275-1994 says.
+ - clean up primitives.
+
+Sun Aug 3 23:06:39 CEST 2003
+ - fix >body, body>
+ - make not a synonym for invert as described in IEEE 1275
+ - todigit can now switch between capital and small letters via
+ value capital-hex?
+
+Mon Aug 4 21:57:06 CEST 2003
+ - indent unix.c
+ - reimplement do, ?do, loop, +loop with prim helpers. It now
+ passes hayes' ans forth test suite.
+ - adopt unix.c and bootstrap.fs to new (?)do..(+)loop
+ - remove unneeded if around ?do..loop in ",
+ - interpreter: clear input buffer before refilling it
+ - serialize PC changes in dobranch and do?branch
+
+Thu Aug 7 19:00:43 CEST 2003
+ - add/change missing/incomplete copyright notices
+ - implement "
+
+Sun Aug 10 19:52:20 CEST 2003
+ - reimplement catch, through
+ - implement abort"
+ - rephrase endcase
+ - change interpreter to use exception words
+ - implement forget
+ - add dummy "forth"
+
+Sun Aug 10 22:12:28 CEST 2003
+ - fix "spaces"
+ - create subdir util for types.sh and new bin2hex
+ - enable forth.html again, running hayes test suite.
+ - include dictionary in char array instead of elf section
+ when building an x86 "full" image
+ - don't newline in accept.
+ - fix " compile mode behavior.
+ - move throw/catch and use it with ' and [']
+ - add :noname
+
+Thu Aug 14 23:02:15 CEST 2003
+ - fix "field"
+ - implement second stage bootstrapping
+ NOTE: changes dictionary format!
+ - drop initxt from dictionary, since we know "last" now.
+ - output dictionary can be named on command line.
+ - make segfault handler optional
+
+Mon Sep 1 19:41:23 CEST 2003
+ - move findword() et al to dict.c (needed by openbios.c due
+ to last dictionary change)
+ - fix findword() return values and optimize it slightly.
+ - indented some files.
+
+Mon Sep 8 22:43:55 CEST 2003
+ - add initial AMD64 support (cloned x86 target)
+ - get vocabulary implementation working. maybe buggy, but operable
+ - enable vocabulary support by default (vocabularies? set to true)
+ - drop duplicate "forth"
+ - fix some comments in forth files.
+
+Sun Sep 28 14:26:41 CEST 2003
+ - some documentation and comment fixes
+ - fix parameter passing for io words.
+
+Thu Oct 2 08:21:06 CEST 2003
+ - clean up lit
+ - inline some functions from internal.h (reduces size and execution
+ time)
+
+Fri Oct 3 15:20:44 CEST 2003
+ - make i and j primitives. This safes a lot of time in loops.
+ i.e. the following dummy loop executes 300% faster:
+ : fbar 1000 0 do 1000 0 do j drop i drop loop loop ;
+
+Sat Oct 11 20:18:22 CEST 2003
+ - include plugin interface for unix hosted version.
+ - add plugin_pci and plugin_qt as examples.
+ - add simple set of pci functions for testing the pci plugin
+ - add state variable "runforth" to be changed by the qt plugin
+ on exit.
+
+Sun Oct 12 14:57:54 CEST 2003
+ - move internal.h and forth.h to kernel/
+ - replace make by $(MAKE) in some places.
+
+Tue Oct 14 01:06:39 CEST 2003
+ - add (immediate) and (compile-only)
+
+Wed Oct 15 00:52:49 CEST 2003
+ - check whether dlopen() needs libdl.
+ - include BSD compile fixes from oxygene
+ - fix abort"
+
+Tue Oct 21 22:08:00 CEST 2003
+ - fix forth.html dependencies
+ - yet another indent orgy
+
+Thu Oct 30 16:10:01 CET 2003
+ - add "call" to execute native code functions
+ - plugin_qt: fix framebuffer address on 64bit systems
+ - plugin_pci: create position independent code.
+
+Wed Nov 5 08:38:18 CET 2003
+ - fix "comp" (from Samuel Rydh)
+ - include instance support (from Samuel Rydh)
+
+Sun Nov 9 15:53:33 CET 2003
+ - some changes for "see"
+ - apply more patches from Samuel.
+ - smaller, better implementation of handle-text
+
+Mon Nov 10 22:06:32 CET 2003
+ - increase max dictionary size from 64k to 128k
+ - add simple fcode to qt plugin
+ - fix handle-text (move null-align up)
+
+Tue Nov 11 22:53:27 CET 2003
+ - rename ?key to key?.
+ - clean up .s
+ - add (cr
+
+Tue Nov 17 22:42:54 CET 2003
+ - enterforth rstack fix (from Samuel)
+ - include latest version of qt interface
+ fcode driver
+ - fix "header" (from Samuel)
+
+Wed Nov 26 15:12:07 CET 2003
+ - merge patches from Samuel:
+ - add $buffer:
+ - fill all of "ib", not only 80 characters
+ - interpreted conditionals support
+ - late initializers
+
+Sun Nov 30 23:04:28 CET 2003
+ - fix bug in enterforth (non-colon words would destroy PC)
+
+Sat Dec 13 00:57:01 CET 2003
+ - add initial ppc infrastructure
+ - only search current wordlist in "header"
+ - seperate unix host binary and bootstrap interpreter.
+
+Sun Dec 14 18:13:29 CET 2003
+ - add sys-debug word and use it to stop forth interpreter
+ during bootstrap if an error occurs.
+
+Sat Mar 13 16:30:30 CET 2004
+ - fix digit problem
+
diff --git a/roms/openbios/Documentation/kernel/TODO b/roms/openbios/Documentation/kernel/TODO
new file mode 100644
index 00000000..82ebf7b3
--- /dev/null
+++ b/roms/openbios/Documentation/kernel/TODO
@@ -0,0 +1,11 @@
+TODO
+
+booting
+ * support more arches than x86+amd64
+ * compressed + rommable dictionary
+
+forth bootstrap
+ * make prompt configurable
+ * check state-variable when defining a new word.
+
+tag: TODO for the forth system
diff --git a/roms/openbios/Documentation/kernel/dictformat.txt b/roms/openbios/Documentation/kernel/dictformat.txt
new file mode 100644
index 00000000..431e2cd3
--- /dev/null
+++ b/roms/openbios/Documentation/kernel/dictformat.txt
@@ -0,0 +1,8 @@
+# tag: contains a description of the dictionary format
+
+name | length of name in bytes + 0x80 | align with 0's | flags (bit 7 set) | LFA | CFA | PFA
+
+LFA == link field address (backlink)
+CFA == code field address ("word type")
+PFA == program field address (definitions)
+
diff --git a/roms/openbios/Documentation/kernel/glossary.txt b/roms/openbios/Documentation/kernel/glossary.txt
new file mode 100644
index 00000000..74785f12
--- /dev/null
+++ b/roms/openbios/Documentation/kernel/glossary.txt
@@ -0,0 +1,14 @@
+# tag: glossary of openbios forth
+
+# dictionary
+LFA == link field address (backlink)
+CFA == code field address ("word type")
+PFA == program field address (definitions)
+
+# forth engine
+TIB == text input buffer
+
+inner interpreter: interprets dictionary, does threading
+outer interpreter: "user" interpreter, reads forth words from user.
+
+
diff --git a/roms/openbios/Documentation/kernel/initializers.txt b/roms/openbios/Documentation/kernel/initializers.txt
new file mode 100644
index 00000000..18a8e23a
--- /dev/null
+++ b/roms/openbios/Documentation/kernel/initializers.txt
@@ -0,0 +1,24 @@
+
+Initializers are called when the forth kernel is started, to do some
+initialization stuff.
+Pro: If code needs initialization you can keep this in place with the code
+and don't need to patch the kernel itself to do so.
+
+There are 2 types of initializers. "Normal" and "Late" initializers.
+
+Since initializers are only called during startup, they don't need a name.
+
+Definition:
+ initializer ( xt -- )
+ late-initializer ( xt -- )
+
+Examples:
+ :noname <definition> ; initializer
+
+ :noname
+ some-base initializations
+ ; late-initializer
+
+Late initializers are run after all ordinary initializers have
+been executed.
+
diff --git a/roms/openbios/Makefile b/roms/openbios/Makefile
new file mode 100644
index 00000000..172f4507
--- /dev/null
+++ b/roms/openbios/Makefile
@@ -0,0 +1,51 @@
+include config-host.mak
+
+all: requirements info build
+
+requirements:
+ @which xsltproc &>/dev/null || ( echo ; echo "Please install libxslt2"; \
+ echo; exit 1 )
+
+info:
+ @echo "Building OpenBIOS for $(TARGETS)"
+
+clean:
+ @echo "Cleaning up..."
+ @for dir in $(ODIRS); do \
+ $(MAKE) -C $$dir clean; \
+ done
+
+build: start-build
+ @for dir in $(ODIRS); do \
+ $(MAKE) -C $$dir > $$dir/build.log 2>&1 && echo "ok." || \
+ ( echo "error:"; tail -15 $$dir/build.log; exit 1 ) \
+ done
+
+SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGETS))
+SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory)
+
+quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
+
+build-verbose: start-build $(SUBDIR_RULES)
+
+subdir-%:
+ $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C obj-$* V="$(V)" all,)
+
+start-build:
+ @echo "Building..."
+
+run:
+ @echo "Running..."
+ @for dir in $(ODIRS); do \
+ $$dir/openbios-unix $$dir/openbios-unix.dict; \
+ done
+
+
+# The following two targets will only work on x86 so far.
+#
+$(ODIR)/openbios.iso: $(ODIR)/openbios.multiboot $(ODIR)/openbios-x86.dict
+ @mkisofs -input-charset UTF-8 -r -b boot/grub/stage2_eltorito -no-emul-boot \
+ -boot-load-size 4 -boot-info-table -o $@ utils/iso $^
+
+runiso: $(ODIR)/openbios.iso
+ qemu -cdrom $^
diff --git a/roms/openbios/Makefile.target b/roms/openbios/Makefile.target
new file mode 100644
index 00000000..a7363e66
--- /dev/null
+++ b/roms/openbios/Makefile.target
@@ -0,0 +1,86 @@
+#
+# OpenBIOS Makefile
+# (C) 2004-2009 by the OpenBIOS team
+#
+
+include config.mak
+
+ODIR := .
+HOSTCC := gcc
+
+HOSTCFLAGS+= -O2 -g -DFCOMPILER -DBOOTSTRAP $(CROSSCFLAGS)
+HOSTCFLAGS+= -Wall -Wredundant-decls -Wshadow -Wpointer-arith
+HOSTCFLAGS+= -Wstrict-prototypes -Wmissing-declarations -Wundef -Wendif-labels
+HOSTCFLAGS+= -Wstrict-aliasing -Wwrite-strings -Wmissing-prototypes -Wnested-externs
+HOSTCFLAGS+= -W
+# Flags for dependency generation
+HOSTCFLAGS+= -MMD -MP -MT $@ -MF '$(*D)/$(*F).d'
+HOSTINCLUDES := -I$(SRCDIR)/include -I$(SRCDIR)/kernel -I$(SRCDIR)/kernel/include -I$(ODIR)/target/include
+
+CC := $(TARGET)gcc
+AS := $(TARGET)as
+AR := $(TARGET)ar
+LD := $(TARGET)ld
+NM := $(TARGET)nm
+STRIP := $(TARGET)strip
+RANLIB := $(TARGET)ranlib
+
+CFLAGS+= -Os -g -DNATIVE_BITWIDTH_EQUALS_HOST_BITWIDTH -USWAP_ENDIANNESS
+CFLAGS+= -Wall -Wredundant-decls -Wshadow -Wpointer-arith
+CFLAGS+= -Wstrict-prototypes -Wmissing-declarations -Wundef -Wendif-labels
+CFLAGS+= -Wstrict-aliasing -Wwrite-strings -Wmissing-prototypes -Wnested-externs
+CFLAGS+= -Werror
+# Flags for dependency generation
+CFLAGS+= -MMD -MP -MT $@ -MF '$(*D)/$(*F).d'
+INCLUDES := -I$(SRCDIR)/include -I$(SRCDIR)/kernel/include -I$(ODIR)/target/include
+AS_FLAGS+= -g
+
+# FCode tokeniser
+TOKE := toke
+
+quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
+
+VPATH_SUFFIXES = %.c %.h %.S %.fs
+set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
+$(call set-vpath, $(SRCDIR))
+
+#
+# pre rules
+#
+
+all: versions dictionaries host-libraries target-libraries host-executables target-executables
+
+versions: $(ODIR)/target/include/openbios-version.h $(ODIR)/forth/version.fs
+
+$(ODIR)/forth/version.fs:
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+ @DATE="$(shell echo `LC_ALL=C TZ=UTC date +'%b %e %Y %H:%M'`)" ; \
+ ( echo ": builddate \" $$DATE\" ; " ; \
+ echo ": version \" $(VERSION)\" ; " ; ) \
+ > $(dir $@)/version.fs
+
+$(ODIR)/target/include/openbios-version.h:
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+ @DATE="$(shell echo `LC_ALL=C TZ=UTC date +'%b %e %Y %H:%M'`)" ; \
+ ( echo "#define OPENBIOS_BUILD_DATE \"$$DATE\"" ; \
+ echo "#define OPENBIOS_VERSION_STR \"$(VERSION)\"" ; ) \
+ > $(dir $@)/openbios-version.h
+
+info:
+ @echo "Building OpenBIOS on $(HOSTARCH) for $(ARCH)"
+
+clean:
+ @printf "Cleaning up for $(ARCH)..."
+ @rm -rf forth.dict.core forthstrap *.dict openbios-*
+ @rm -f $(ODIR)/target/include/openbios-version.h $(ODIR)/forth/version.fs
+ @find . -type f \( -name "*~" -o -name '*.o' -o -name '*.d' -o -name '*.a' \) -exec rm \{\} \;
+ @echo " ok"
+
+build-verbose: info build
+
+build: all
+
+include rules.mak
+
+# Include automatically generated dependency files
+-include $(wildcard $(ODIR)/*.d $(ODIR)/host/kernel/*.d $(ODIR)/target/*/*.d $(ODIR)/target/*/*/*.d $(ODIR)/target/*/*/*/*.d)
diff --git a/roms/openbios/README b/roms/openbios/README
new file mode 100644
index 00000000..b6a9978a
--- /dev/null
+++ b/roms/openbios/README
@@ -0,0 +1,132 @@
+Welcome to OpenBIOS
+-------------------
+
+OpenBIOS is a free, portable implementation of IEEE 1275-1994
+(Open Firmware). Find detailed information about OpenBIOS at
+http://www.openbios.org/
+
+What is OpenBIOS?
+-----------------
+
+OpenBIOS can replace your system firmware (BIOS) partly or completely. It
+can also be used as a bootloader to create an Open Firmware compatible
+interface between legacy firmware and an operating system.
+
+This is achieved by a modular concept that consists of a portable Forth
+kernel and three interfaces for user interaction, device initialization
+and client (operating system) control.
+
+While far not all possible applications of OpenBIOS are implemented yet,
+a lot of functionality is already there. OpenBIOS can be used to enhance
+LinuxBIOS (http://www.linuxbios.org), or be booted from any multiboot
+capable bootloader to bring Open Firmware to your machine. OpenBIOS can
+also be used when an operating system is already running. It provides
+the needed OpenFirmware functionality to MOL (MacOnLinux) to boot MacOS
+9 and X on PPC machines, as well as Linux (all supported platforms)
+
+OpenBIOS build options
+---------------------
+
+ config/scripts/switch-arch <platform> - build for specified platform
+ Look in config/example for
+ platforms.
+
+ make - build all configured binaries
+
+ make run - run unix example.
+
+
+How OpenBIOS works
+------------------
+
+ The OpenBIOS forth core is split into a forth kernel written in portable
+ C and a forth dictionary which operated on by the kernel.
+
+ When building the forth core, you get different versions of
+ the forth kernel:
+
+ * a unix executable program
+
+ - to execute a forth dictionary from a file. This can be used for
+ easily testing and developing OpenBIOS on a unix host.
+
+ - to create a dictionary file. Such a dictionary file sets up
+ all of the forth language. Primitives are indexed to save relocations.
+
+ The default is to create a forth dictionary forth.dict from
+ forth/start.fs. This file includes all of the basic forth language
+ constructs from forth/bootstrap.fs and starts the interpreter.
+
+ To achieve this, the hosted unix version contains a basic set of
+ forth words coded in C that allow creating a full dictionary.
+
+ * a varying number of target specific binaries. On x86 you can start
+ openbios for example from GRUB or LinuxBIOS. They are all based on
+ the same forth engine consisting of a dictionary scheduler, primitive
+ words needed to build the forth environment, 2 stacks and a simple
+ set of console functions. These binaries can not be started directly
+ in the unix host environment.
+
+Requirements
+------------
+ * gcc
+ * gnu make
+ * OpenBIOS FCode Utils
+ Download with svn co svn://openbios.org/openbios/fcode-utils
+ * grub or any other multiboot loader to run the multiboot
+ binary "openbios.multiboot" with it's module "openbios-<platform>.dict"
+ * xsltproc
+
+Building & Usage
+----------------
+
+ * make
+
+ this builds "openbios.multiboot", the standalone image and "openbios-unix",
+ the hosted image. Additionally it creates a forth dictionary
+ file from forth/start.fs. All generated files are written to
+ the absolute directory held by the variable BUILDDIR, which defaults
+ to obj-[platform]. Some compile time parameters can be tweaked in
+ include/config.h
+
+ * use "openbios-unix" to create a forth dictionary on your own:
+ $ obj-x86/openbios-unix -Iforth start.fs
+ creates the file forth.dict from forth source forth/start.fs.
+
+ * use "openbios-unix" to run a created dictionary:
+ $ obj-x86/openbios-unix obj-x86/openbios-unix.dict
+ This is useful for testing
+
+ * booting openbios
+ You can boot openbios i.e. in grub. Add the following lines to
+ your menu.lst:
+
+ title openbios
+ kernel (hd0,2)/boot/openbios.multiboot
+ module (hd0,2)/boot/openbios-x86.dict
+
+ Note: change (hd0,2) to the partition you copied the openbios image and
+ openbios-x86.dict to.
+
+ To boot OpenBIOS from LinuxBIOS/etherboot, you can either use
+ "openbios-plain.elf" or "openbios-builtin.elf":
+
+ - openbios-plain.elf is the pure kernel that loads the dictionary from a
+ hardcoded address in flash memory (0xfffe0000)
+
+ - openbios-builtin.elf also includes the dictionary directly so that it
+ can be easily used from etherboot or the LinuxBIOS builtin ELF
+ loader without taking care of the dictionary
+
+CREDITS
+-------
+OpenBIOS was developed by Stefan Reinauer, Samuel Rydh and Patrick Mauritz.
+The OpenBIOS IDE driver was written by Jens Axboe.
+For license details on this piece of software, see Documentation/COPYING.
+
+
+If you have patches, questions, comments, feel free to contact the OpenBIOS
+mailinglist.
+
+Regards,
+ the OpenBIOS team
diff --git a/roms/openbios/VERSION b/roms/openbios/VERSION
new file mode 100644
index 00000000..9459d4ba
--- /dev/null
+++ b/roms/openbios/VERSION
@@ -0,0 +1 @@
+1.1
diff --git a/roms/openbios/arch/amd64/Kconfig b/roms/openbios/arch/amd64/Kconfig
new file mode 100644
index 00000000..f1f677db
--- /dev/null
+++ b/roms/openbios/arch/amd64/Kconfig
@@ -0,0 +1,48 @@
+mainmenu "OpenBIOS Configuration"
+
+config AMD64
+ bool
+ default y
+ help
+ Building for AMD64 hardware.
+
+config LITTLE_ENDIAN
+ bool
+ default y
+ help
+ AMD64 is little endian.
+
+
+menu "Kernel binaries (AMD64)"
+
+config IMAGE_ELF
+ bool "ELF image (for LinuxBIOS)"
+ default y
+ help
+ Build a simple elf image that can be used with LinuxBIOS
+ This image will be called openbios.elf
+
+config IMAGE_ELF_EMBEDDED
+ bool "ELF image with embedded dictionary"
+ default y
+ help
+ Build an elf image with embedded dictionary. This image
+ can easily be used with etherboot.
+ The image filename is openbios.full
+
+config IMAGE_ELF_MULTIBOOT
+ bool "Multiboot image"
+ default y
+ help
+ Build a multiboot image for booting with grub
+
+endmenu
+
+menu "Build hosted UNIX Binary"
+source "arch/unix/Kconfig"
+endmenu
+
+source "kernel/Kconfig"
+source "forth/Kconfig"
+source "libopenbios/Kconfig"
+source "drivers/Kconfig"
diff --git a/roms/openbios/arch/amd64/boot.c b/roms/openbios/arch/amd64/boot.c
new file mode 100644
index 00000000..0e1fe7ef
--- /dev/null
+++ b/roms/openbios/arch/amd64/boot.c
@@ -0,0 +1,41 @@
+/*
+ *
+ */
+#undef BOOTSTRAP
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elfload.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libopenbios/sys_info.h"
+
+int elf_load(struct sys_info *, const char *filename, const char *cmdline);
+int linux_load(struct sys_info *, const char *filename, const char *cmdline);
+
+void boot(void);
+
+void boot(void)
+{
+ char *path=pop_fstr_copy(), *param;
+
+ // char *param="root=/dev/hda2 console=ttyS0,115200n8 console=tty0";
+
+ if(!path) {
+ printk("[x86] Booting default not supported.\n");
+ return;
+ }
+
+ param = strchr(path, ' ');
+ if(param) {
+ *param = '\0';
+ param++;
+ }
+
+ printk("[x86] Booting file '%s' with parameters '%s'\n",path, param);
+
+ if (elf_load(&sys_info, path, param) == LOADER_NOT_SUPPORT)
+ if (linux_load(&sys_info, path, param) == LOADER_NOT_SUPPORT)
+ printk("Unsupported image format\n");
+
+ free(path);
+}
diff --git a/roms/openbios/arch/amd64/build.xml b/roms/openbios/arch/amd64/build.xml
new file mode 100644
index 00000000..8f436d00
--- /dev/null
+++ b/roms/openbios/arch/amd64/build.xml
@@ -0,0 +1,6 @@
+<build condition="AMD64">
+ <dictionary name="openbios-amd64" init="openbios" target="forth">
+ <object source="init.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA" />
+ </dictionary>
+</build>
diff --git a/roms/openbios/arch/amd64/builtin.c b/roms/openbios/arch/amd64/builtin.c
new file mode 100644
index 00000000..93ced0ae
--- /dev/null
+++ b/roms/openbios/arch/amd64/builtin.c
@@ -0,0 +1,25 @@
+/* tag: openbios forth starter for builtin dictionary for amd64
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include <asm/types.h>
+#include "libopenbios/sys_info.h"
+
+/*
+ * wrap an array around the hex'ed dictionary file
+ */
+
+#include "static-dict.h"
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ info->dict_start=(unsigned long *)forth_dictionary;
+ info->dict_end=(unsigned long *)((ucell)forth_dictionary +
+ sizeof(forth_dictionary));
+}
diff --git a/roms/openbios/arch/amd64/console.c b/roms/openbios/arch/amd64/console.c
new file mode 100644
index 00000000..71a22b68
--- /dev/null
+++ b/roms/openbios/arch/amd64/console.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "openbios.h"
+
+#ifdef CONFIG_DEBUG_CONSOLE
+
+/* ******************************************************************
+ * serial console functions
+ * ****************************************************************** */
+
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+
+#define RBR(x) x==2?0x2f8:0x3f8
+#define THR(x) x==2?0x2f8:0x3f8
+#define IER(x) x==2?0x2f9:0x3f9
+#define IIR(x) x==2?0x2fa:0x3fa
+#define LCR(x) x==2?0x2fb:0x3fb
+#define MCR(x) x==2?0x2fc:0x3fc
+#define LSR(x) x==2?0x2fd:0x3fd
+#define MSR(x) x==2?0x2fe:0x3fe
+#define SCR(x) x==2?0x2ff:0x3ff
+#define DLL(x) x==2?0x2f8:0x3f8
+#define DLM(x) x==2?0x2f9:0x3f9
+
+static int uart_charav(int port)
+{
+ if (!port)
+ return -1;
+ return ((inb(LSR(port)) & 1) != 0);
+}
+
+static char uart_getchar(int port)
+{
+ if (!port)
+ return -1;
+ while (!uart_charav(port));
+ return ((char) inb(RBR(port)) & 0177);
+}
+
+static void uart_putchar(int port, unsigned char c)
+{
+ if (!port)
+ return;
+ if (c == '\n')
+ uart_putchar(port, '\r');
+ while (!(inb(LSR(port)) & 0x20));
+ outb(c, THR(port));
+}
+
+static void uart_init_line(int port, unsigned long baud)
+{
+ int i, baudconst;
+
+ if (!port)
+ return;
+
+ switch (baud) {
+ case 115200:
+ baudconst = 1;
+ break;
+ case 57600:
+ baudconst = 2;
+ break;
+ case 38400:
+ baudconst = 3;
+ break;
+ case 19200:
+ baudconst = 6;
+ break;
+ case 9600:
+ default:
+ baudconst = 12;
+ break;
+ }
+
+ outb(0x87, LCR(port));
+ outb(0x00, DLM(port));
+ outb(baudconst, DLL(port));
+ outb(0x07, LCR(port));
+ outb(0x0f, MCR(port));
+
+ for (i = 10; i > 0; i--) {
+ if (inb(LSR(port)) == (unsigned int) 0)
+ break;
+ inb(RBR(port));
+ }
+}
+
+int uart_init(int port, unsigned long speed)
+{
+ if (port)
+ uart_init_line(port, speed);
+ return -1;
+}
+
+static void serial_putchar(int c)
+{
+ uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff));
+}
+
+static void serial_cls(void)
+{
+ serial_putchar(27);
+ serial_putchar('[');
+ serial_putchar('H');
+ serial_putchar(27);
+ serial_putchar('[');
+ serial_putchar('J');
+}
+
+#endif
+
+/* ******************************************************************
+ * simple polling video/keyboard console functions
+ * ****************************************************************** */
+
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+
+/* raw vga text mode */
+#define COLUMNS 80 /* The number of columns. */
+#define LINES 25 /* The number of lines. */
+#define ATTRIBUTE 7 /* The attribute of an character. */
+
+#define VGA_BASE 0xB8000 /* The video memory address. */
+
+/* VGA Index and Data Registers */
+#define VGA_REG_INDEX 0x03D4 /* VGA index register */
+#define VGA_REG_DATA 0x03D5 /* VGA data register */
+
+#define VGA_IDX_CURMSL 0x09 /* cursor maximum scan line */
+#define VGA_IDX_CURSTART 0x0A /* cursor start */
+#define VGA_IDX_CUREND 0x0B /* cursor end */
+#define VGA_IDX_CURLO 0x0F /* cursor position (low 8 bits) */
+#define VGA_IDX_CURHI 0x0E /* cursor position (high 8 bits) */
+
+/* Save the X and Y position. */
+static int xpos, ypos;
+/* Point to the video memory. */
+static volatile unsigned char *video = (unsigned char *) VGA_BASE;
+
+static void video_initcursor(void)
+{
+ u8 val;
+ outb(VGA_IDX_CURMSL, VGA_REG_INDEX);
+ val = inb(VGA_REG_DATA) & 0x1f; /* maximum scan line -1 */
+
+ outb(VGA_IDX_CURSTART, VGA_REG_INDEX);
+ outb(0, VGA_REG_DATA);
+
+ outb(VGA_IDX_CUREND, VGA_REG_INDEX);
+ outb(val, VGA_REG_DATA);
+}
+
+
+
+static void video_poscursor(unsigned int x, unsigned int y)
+{
+ unsigned short pos;
+
+ /* Calculate new cursor position as a function of x and y */
+ pos = (y * COLUMNS) + x;
+
+ /* Output the new position to VGA card */
+ outb(VGA_IDX_CURLO, VGA_REG_INDEX); /* output low 8 bits */
+ outb((u8) (pos), VGA_REG_DATA);
+ outb(VGA_IDX_CURHI, VGA_REG_INDEX); /* output high 8 bits */
+ outb((u8) (pos >> 8), VGA_REG_DATA);
+
+};
+
+
+static void video_newline(void)
+{
+ xpos = 0;
+
+ if (ypos < LINES - 1) {
+ ypos++;
+ } else {
+ int i;
+ memmove((void *) video, (void *) (video + 2 * COLUMNS),
+ (LINES - 1) * COLUMNS * 2);
+
+ for (i = ((LINES - 1) * 2 * COLUMNS);
+ i < 2 * COLUMNS * LINES;) {
+ video[i++] = 0;
+ video[i++] = ATTRIBUTE;
+ }
+ }
+
+}
+
+/* Put the character C on the screen. */
+static void video_putchar(int c)
+{
+ int p=1;
+
+ if (c == '\n' || c == '\r') {
+ video_newline();
+ return;
+ }
+
+ if (c == '\b') {
+ if (xpos) xpos--;
+ c=' ';
+ p=0;
+ }
+
+
+ if (xpos >= COLUMNS)
+ video_newline();
+
+ *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
+ *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
+
+ if (p)
+ xpos++;
+
+ video_poscursor(xpos, ypos);
+}
+
+static void video_cls(void)
+{
+ int i;
+
+ for (i = 0; i < 2 * COLUMNS * LINES;) {
+ video[i++] = 0;
+ video[i++] = ATTRIBUTE;
+ }
+
+
+ xpos = 0;
+ ypos = 0;
+
+ video_initcursor();
+ video_poscursor(xpos, ypos);
+}
+
+void video_init(void)
+{
+ video=phys_to_virt((unsigned char*)VGA_BASE);
+}
+
+/*
+ * keyboard driver
+ */
+
+static char normal[] = {
+ 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
+ '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
+ 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j',
+ 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b',
+ 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f
+};
+
+static char shifted[] = {
+ 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
+ '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
+ 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J',
+ 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B',
+ 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8',
+ '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f
+};
+
+static int key_ext;
+static int key_lshift = 0, key_rshift = 0, key_caps = 0;
+
+static char last_key;
+
+static void keyboard_cmd(unsigned char cmd, unsigned char val)
+{
+ outb(cmd, 0x60);
+ /* wait until keyboard controller accepts cmds: */
+ while (inb(0x64) & 2);
+ outb(val, 0x60);
+ while (inb(0x64) & 2);
+}
+
+static char keyboard_poll(void)
+{
+ unsigned int c;
+ if (inb(0x64) & 1) {
+ c = inb(0x60);
+ switch (c) {
+ case 0xe0:
+ key_ext = 1;
+ return 0;
+ case 0x2a:
+ key_lshift = 1;
+ return 0;
+ case 0x36:
+ key_rshift = 1;
+ return 0;
+ case 0xaa:
+ key_lshift = 0;
+ return 0;
+ case 0xb6:
+ key_rshift = 0;
+ return 0;
+ case 0x3a:
+ if (key_caps) {
+ key_caps = 0;
+ keyboard_cmd(0xed, 0);
+ } else {
+ key_caps = 1;
+ keyboard_cmd(0xed, 4); /* set caps led */
+ }
+ return 0;
+ }
+
+ if (key_ext) {
+ // void printk(const char *format, ...);
+ printk("extended keycode: %x\n", c);
+
+ key_ext = 0;
+ return 0;
+ }
+
+ if (c & 0x80) /* unhandled key release */
+ return 0;
+
+ if (key_lshift || key_rshift)
+ return key_caps ? normal[c] : shifted[c];
+ else
+ return key_caps ? shifted[c] : normal[c];
+ }
+ return 0;
+}
+
+static int keyboard_dataready(void)
+{
+ if (last_key)
+ return 1;
+
+ last_key = keyboard_poll();
+
+ return (last_key != 0);
+}
+
+static unsigned char keyboard_readdata(void)
+{
+ char tmp;
+ while (!keyboard_dataready());
+ tmp = last_key;
+ last_key = 0;
+ return tmp;
+}
+#endif
+
+
+/* ******************************************************************
+ * common functions, implementing simple concurrent console
+ * ****************************************************************** */
+
+int arch_putchar(int c)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ serial_putchar(c);
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ video_putchar(c);
+#endif
+ return c;
+}
+
+int arch_availchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return 1;
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ if (keyboard_dataready())
+ return 1;
+#endif
+ return 0;
+}
+
+int arch_getchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return (uart_getchar(CONFIG_SERIAL_PORT));
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ if (keyboard_dataready())
+ return (keyboard_readdata());
+#endif
+ return 0;
+}
+
+void cls(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ serial_cls();
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ video_cls();
+#endif
+}
+
+struct _console_ops arch_console_ops = {
+ .putchar = arch_putchar,
+ .availchar = arch_availchar,
+ .getchar = arch_getchar
+};
+
+#endif // CONFIG_DEBUG_CONSOLE
diff --git a/roms/openbios/arch/amd64/context.c b/roms/openbios/arch/amd64/context.c
new file mode 100644
index 00000000..2e4df6a3
--- /dev/null
+++ b/roms/openbios/arch/amd64/context.c
@@ -0,0 +1,124 @@
+/*
+ * context switching
+ * 2003-10 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "segment.h"
+#include "context.h"
+
+#define MAIN_STACK_SIZE 16384
+#define IMAGE_STACK_SIZE 4096
+
+#define debug printk
+
+static void start_main(void); /* forward decl. */
+void __exit_context(void); /* assembly routine */
+
+/*
+ * Main context structure
+ * It is placed at the bottom of our stack, and loaded by assembly routine
+ * to start us up.
+ */
+struct context main_ctx __attribute__((section (".initctx"))) = {
+ .gdt_base = (uint64_t) gdt,
+ .gdt_limit = GDT_LIMIT,
+ .cs = FLAT_CS,
+ .ds = FLAT_DS,
+ .es = FLAT_DS,
+ .fs = FLAT_DS,
+ .gs = FLAT_DS,
+ .ss = FLAT_DS,
+ .esp = (uint32_t) ESP_LOC(&main_ctx),
+ .eip = (uint32_t) start_main,
+ .return_addr = (uint32_t) __exit_context,
+};
+
+/* This is used by assembly routine to load/store the context which
+ * it is to switch/switched. */
+struct context *__context = &main_ctx;
+
+/* Stack for loaded ELF image */
+static uint8_t image_stack[IMAGE_STACK_SIZE];
+
+/* Pointer to startup context (physical address) */
+unsigned long __boot_ctx;
+
+/*
+ * Main starter
+ * This is the C function that runs first.
+ */
+static void start_main(void)
+{
+ int retval;
+ extern int openbios(void);
+
+ /* Save startup context, so we can refer to it later.
+ * We have to keep it in physical address since we will relocate. */
+ __boot_ctx = virt_to_phys(__context);
+
+ /* Start the real fun */
+ retval = openbios();
+
+ /* Pass return value to startup context. Bootloader may see it. */
+ boot_ctx->eax = retval;
+
+ /* Returning from here should jump to __exit_context */
+ __context = boot_ctx;
+}
+
+/* Setup a new context using the given stack.
+ */
+struct context *
+init_context(uint8_t *stack, uint32_t stack_size, int num_params)
+{
+ struct context *ctx;
+
+ ctx = (struct context *)
+ (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t)));
+ memset(ctx, 0, sizeof(*ctx));
+
+ /* Fill in reasonable default for flat memory model */
+ ctx->gdt_base = virt_to_phys(gdt);
+ ctx->gdt_limit = GDT_LIMIT;
+ ctx->cs = FLAT_CS;
+ ctx->ds = FLAT_DS;
+ ctx->es = FLAT_DS;
+ ctx->fs = FLAT_DS;
+ ctx->gs = FLAT_DS;
+ ctx->ss = FLAT_DS;
+ ctx->esp = virt_to_phys(ESP_LOC(ctx));
+ ctx->return_addr = virt_to_phys(__exit_context);
+
+ return ctx;
+}
+
+/* Switch to another context. */
+struct context *switch_to(struct context *ctx)
+{
+ struct context *save, *ret;
+
+ debug("switching to new context:\n");
+ save = __context;
+ __context = ctx;
+ asm ("pushl %cs; call __switch_context");
+ ret = __context;
+ __context = save;
+ return ret;
+}
+
+/* Start ELF Boot image */
+uint32_t start_elf(uint32_t entry_point, uint32_t param)
+{
+ struct context *ctx;
+
+ ctx = init_context(image_stack, sizeof image_stack, 1);
+ ctx->eip = entry_point;
+ ctx->param[0] = param;
+ ctx->eax = 0xe1fb007;
+ ctx->ebx = param;
+
+ ctx = switch_to(ctx);
+ return ctx->eax;
+}
diff --git a/roms/openbios/arch/amd64/context.h b/roms/openbios/arch/amd64/context.h
new file mode 100644
index 00000000..4c3832ef
--- /dev/null
+++ b/roms/openbios/arch/amd64/context.h
@@ -0,0 +1,48 @@
+#ifndef AMD64_CONTEXT_H
+#define AMD64_CONTEXT_H
+
+struct context {
+ /* Stack Segment, placed here because of the alignment issue... */
+ uint16_t ss;
+ /* Used with sgdt/lgdt */
+ uint16_t gdt_limit;
+ uint64_t gdt_base;
+ /* General registers, accessed with pushal/popal */
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t esp; /* points just below eax */
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+#define ESP_LOC(ctx) (&(ctx)->gs)
+ /* Segment registers */
+ uint32_t gs;
+ uint32_t fs;
+ uint32_t es;
+ uint32_t ds;
+ /* Flags */
+ uint32_t eflags;
+ /* Code segment:offset */
+ uint32_t eip;
+ uint32_t cs;
+ /* Optional stack contents */
+ uint32_t return_addr;
+ uint32_t param[0];
+};
+
+/* Create a new context in the given stack */
+struct context *
+init_context(uint8_t *stack, uint32_t stack_size, int num_param);
+
+/* Switch context */
+struct context *switch_to(struct context *);
+
+/* Holds physical address of boot context */
+extern unsigned long __boot_ctx;
+
+/* This can always be safely used to refer to the boot context */
+#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx))
+
+#endif /* AMD64_CONTEXT_H */
diff --git a/roms/openbios/arch/amd64/defconfig b/roms/openbios/arch/amd64/defconfig
new file mode 100644
index 00000000..570a6c86
--- /dev/null
+++ b/roms/openbios/arch/amd64/defconfig
@@ -0,0 +1,65 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_AMD64=y
+CONFIG_LITTLE_ENDIAN=y
+
+#
+# Kernel binaries (AMD64)
+#
+# CONFIG_IMAGE_ELF is not set
+# CONFIG_IMAGE_ELF_EMBEDDED is not set
+# CONFIG_IMAGE_ELF_MULTIBOOT is not set
+
+#
+# Build hosted UNIX Binary
+#
+CONFIG_HOST_UNIX=y
+# CONFIG_PLUGIN_PCI is not set
+
+#
+# Kernel Debugging
+#
+# CONFIG_DEBUG is not set
+CONFIG_DEBUG_CONSOLE=y
+CONFIG_DEBUG_CONSOLE_SERIAL=y
+CONFIG_SERIAL_PORT=1
+CONFIG_SERIAL_SPEED=115200
+CONFIG_DEBUG_CONSOLE_VGA=y
+
+#
+# Module Configuration
+#
+CONFIG_CMDLINE=y
+CONFIG_DEBLOCKER=y
+
+#
+# Filesystem Configuration
+#
+CONFIG_DISK_LABEL=y
+CONFIG_PART_SUPPORT=y
+CONFIG_PC_PARTS=y
+CONFIG_FS=y
+CONFIG_GRUBFS=y
+CONFIG_FSYS_EXT2FS=y
+CONFIG_FSYS_FAT=y
+CONFIG_FSYS_JFS=y
+# CONFIG_FSYS_MINIX is not set
+CONFIG_FSYS_REISERFS=y
+CONFIG_FSYS_XFS=y
+CONFIG_FSYS_ISO9660=y
+# CONFIG_FSYS_FFS is not set
+# CONFIG_FSYS_VSTAFS is not set
+# CONFIG_DEBUG_FS is not set
+
+#
+# Miscellaneous
+#
+CONFIG_LINUXBIOS=y
+
+#
+# Drivers
+#
+CONFIG_DRIVER_PCI=y
+CONFIG_DRIVER_IDE=y
+# CONFIG_DEBUG_IDE is not set
diff --git a/roms/openbios/arch/amd64/init.fs b/roms/openbios/arch/amd64/init.fs
new file mode 100644
index 00000000..fda3acdc
--- /dev/null
+++ b/roms/openbios/arch/amd64/init.fs
@@ -0,0 +1,83 @@
+include config.fs
+
+:noname
+ ." Type 'help' for detailed information" cr
+ \ ." boot secondary slave cdrom: " cr
+ \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr
+ ; DIAG-initializer
+
+" /" find-device
+
+new-device
+ " memory" device-name
+ \ 12230 encode-int " reg" property
+ external
+ : open true ;
+ : close ;
+ \ claim ( phys size align -- base )
+ \ release ( phys size -- )
+finish-device
+
+new-device
+ " cpus" device-name
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+ : decode-unit parse-hex ;
+
+finish-device
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+:noname
+ set-defaults
+; SYSTEM-initializer
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " memory" " /memory" preopen
+ " mmu" " /cpus/@0" preopen
+ " stdout" " /builtin/console" preopen
+ " stdin" " /builtin/console" preopen
+
+; SYSTEM-initializer
+
+\ use the tty interface if available
+:noname
+ " /builtin/console" find-dev if drop
+ " /builtin/console" " input-device" $setenv
+ " /builtin/console" " output-device" $setenv
+ then
+; SYSTEM-initializer
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+\ Load VGA FCode driver blob
+[IFDEF] CONFIG_DRIVER_VGA
+ -1 value vga-driver-fcode
+ " QEMU,VGA.bin" $encode-file to vga-driver-fcode
+[THEN]
diff --git a/roms/openbios/arch/amd64/ldscript b/roms/openbios/arch/amd64/ldscript
new file mode 100644
index 00000000..8976c7af
--- /dev/null
+++ b/roms/openbios/arch/amd64/ldscript
@@ -0,0 +1,73 @@
+OUTPUT_FORMAT(elf32-i386)
+OUTPUT_ARCH(i386)
+
+ENTRY(entry)
+
+/* Initial load address
+ * To be loaded by GRUB, this must be >= 1MB
+ */
+BASE_ADDR = 0x100000;
+
+/* 16KB heap and stack */
+HEAP_SIZE = 16384;
+STACK_SIZE = 16384;
+
+SECTIONS
+{
+ . = BASE_ADDR;
+
+ /* Put Multiboot header near beginning of file, if any. */
+ .hdr : { *(.hdr) *(.hdr.*) }
+
+ /* Start of the program.
+ * Now the version string is in the note, we must include it
+ * in the program. Otherwise we lose the string after relocation. */
+ . = ALIGN(16);
+ _start = .;
+
+ /* Putting ELF notes near beginning of file might help bootloaders.
+ * We discard .note sections other than .note.ELFBoot,
+ * because some versions of GCC generates useless ones. */
+ .note : { *(.note.ELFBoot) }
+
+ /* Normal sections */
+ .text : { *(.text) *(.text.*) }
+ .rodata : {
+ . = ALIGN(4);
+ sound_drivers_start = .;
+ *(.rodata.sound_drivers)
+ sound_drivers_end = .;
+ *(.rodata)
+ *(.rodata.*)
+ }
+ .data : { *(.data) *(.data.*) }
+
+ .bss : {
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+
+ /* Put heap and stack here, so they are included in PT_LOAD segment
+ * and the bootloader is aware of it. */
+
+ . = ALIGN(16);
+ _heap = .;
+ . += HEAP_SIZE;
+ . = ALIGN(16);
+ _eheap = .;
+
+ _stack = .;
+ . += STACK_SIZE;
+ . = ALIGN(16);
+ _estack = .;
+ }
+
+ .initctx : {
+ /* Initial contents of stack. This MUST BE just after the stack. */
+ *(.initctx)
+ }
+
+ _end = .;
+
+ /DISCARD/ : { *(.comment) *(.note) }
+}
diff --git a/roms/openbios/arch/amd64/lib.c b/roms/openbios/arch/amd64/lib.c
new file mode 100644
index 00000000..f04458e1
--- /dev/null
+++ b/roms/openbios/arch/amd64/lib.c
@@ -0,0 +1,56 @@
+/* lib.c
+ * tag: simple function library
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "asm/types.h"
+#include <stdarg.h>
+#include "libc/stdlib.h"
+#include "libc/vsprintf.h"
+#include "kernel/kernel.h"
+
+/* Format a string and print it on the screen, just like the libc
+ * function printf.
+ */
+int printk( const char *fmt, ... )
+{
+ char *p, buf[512];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ )
+ putchar(*p);
+ return i;
+}
+
+// dumb quick memory allocator until we get a decent thing here.
+
+#define MEMSIZE 128*1024
+static char memory[MEMSIZE];
+static void *memptr=memory;
+static int memsize=MEMSIZE;
+
+void *malloc(int size)
+{
+ void *ret=(void *)0;
+ if(memsize>=size) {
+ memsize-=size;
+ ret=memptr;
+ memptr+=size;
+ }
+ return ret;
+}
+
+void free(void *ptr)
+{
+ /* Nothing yet */
+}
diff --git a/roms/openbios/arch/amd64/linux_load.c b/roms/openbios/arch/amd64/linux_load.c
new file mode 100644
index 00000000..f1ed98df
--- /dev/null
+++ b/roms/openbios/arch/amd64/linux_load.c
@@ -0,0 +1,647 @@
+/*
+ * Linux/i386 loader
+ * Supports bzImage, zImage and Image format.
+ *
+ * Based on work by Steve Gehlbach.
+ * Portions are taken from mkelfImage.
+ *
+ * 2003-09 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/sys_info.h"
+#include "context.h"
+#include "segment.h"
+#include "loadfs.h"
+
+#define printf printk
+#define debug printk
+#define strtoull_with_suffix strtol
+
+#define LINUX_PARAM_LOC 0x90000
+#define COMMAND_LINE_LOC 0x91000
+#define GDT_LOC 0x92000
+#define STACK_LOC 0x93000
+
+#define E820MAX 32 /* number of entries in E820MAP */
+struct e820entry {
+ unsigned long long addr; /* start of memory segment */
+ unsigned long long size; /* size of memory segment */
+ unsigned long type; /* type of memory segment */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
+#define E820_NVS 4
+};
+
+/* The header of Linux/i386 kernel */
+struct linux_header {
+ uint8_t reserved1[0x1f1]; /* 0x000 */
+ uint8_t setup_sects; /* 0x1f1 */
+ uint16_t root_flags; /* 0x1f2 */
+ uint8_t reserved2[6]; /* 0x1f4 */
+ uint16_t vid_mode; /* 0x1fa */
+ uint16_t root_dev; /* 0x1fc */
+ uint16_t boot_sector_magic; /* 0x1fe */
+ /* 2.00+ */
+ uint8_t reserved3[2]; /* 0x200 */
+ uint8_t header_magic[4]; /* 0x202 */
+ uint16_t protocol_version; /* 0x206 */
+ uint32_t realmode_swtch; /* 0x208 */
+ uint16_t start_sys; /* 0x20c */
+ uint16_t kver_addr; /* 0x20e */
+ uint8_t type_of_loader; /* 0x210 */
+ uint8_t loadflags; /* 0x211 */
+ uint16_t setup_move_size; /* 0x212 */
+ uint32_t code32_start; /* 0x214 */
+ uint32_t ramdisk_image; /* 0x218 */
+ uint32_t ramdisk_size; /* 0x21c */
+ uint8_t reserved4[4]; /* 0x220 */
+ /* 2.01+ */
+ uint16_t heap_end_ptr; /* 0x224 */
+ uint8_t reserved5[2]; /* 0x226 */
+ /* 2.02+ */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ /* 2.03+ */
+ uint32_t initrd_addr_max; /* 0x22c */
+} __attribute__ ((packed));
+
+
+/* Paramters passed to 32-bit part of Linux
+ * This is another view of the structure above.. */
+struct linux_params {
+ uint8_t orig_x; /* 0x00 */
+ uint8_t orig_y; /* 0x01 */
+ uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */
+ uint16_t orig_video_page; /* 0x04 */
+ uint8_t orig_video_mode; /* 0x06 */
+ uint8_t orig_video_cols; /* 0x07 */
+ uint16_t unused2; /* 0x08 */
+ uint16_t orig_video_ega_bx; /* 0x0a */
+ uint16_t unused3; /* 0x0c */
+ uint8_t orig_video_lines; /* 0x0e */
+ uint8_t orig_video_isVGA; /* 0x0f */
+ uint16_t orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ uint16_t lfb_width; /* 0x12 */
+ uint16_t lfb_height; /* 0x14 */
+ uint16_t lfb_depth; /* 0x16 */
+ uint32_t lfb_base; /* 0x18 */
+ uint32_t lfb_size; /* 0x1c */
+ uint16_t cl_magic; /* 0x20 */
+#define CL_MAGIC_VALUE 0xA33F
+ uint16_t cl_offset; /* 0x22 */
+ uint16_t lfb_linelength; /* 0x24 */
+ uint8_t red_size; /* 0x26 */
+ uint8_t red_pos; /* 0x27 */
+ uint8_t green_size; /* 0x28 */
+ uint8_t green_pos; /* 0x29 */
+ uint8_t blue_size; /* 0x2a */
+ uint8_t blue_pos; /* 0x2b */
+ uint8_t rsvd_size; /* 0x2c */
+ uint8_t rsvd_pos; /* 0x2d */
+ uint16_t vesapm_seg; /* 0x2e */
+ uint16_t vesapm_off; /* 0x30 */
+ uint16_t pages; /* 0x32 */
+ uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */
+
+ //struct apm_bios_info apm_bios_info; /* 0x40 */
+ uint8_t apm_bios_info[0x40];
+ //struct drive_info_struct drive_info; /* 0x80 */
+ uint8_t drive_info[0x20];
+ //struct sys_desc_table sys_desc_table; /* 0xa0 */
+ uint8_t sys_desc_table[0x140];
+ uint32_t alt_mem_k; /* 0x1e0 */
+ uint8_t reserved5[4]; /* 0x1e4 */
+ uint8_t e820_map_nr; /* 0x1e8 */
+ uint8_t reserved6[9]; /* 0x1e9 */
+ uint16_t mount_root_rdonly; /* 0x1f2 */
+ uint8_t reserved7[4]; /* 0x1f4 */
+ uint16_t ramdisk_flags; /* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+ uint8_t reserved8[2]; /* 0x1fa */
+ uint16_t orig_root_dev; /* 0x1fc */
+ uint8_t reserved9[1]; /* 0x1fe */
+ uint8_t aux_device_info; /* 0x1ff */
+ uint8_t reserved10[2]; /* 0x200 */
+ uint8_t param_block_signature[4]; /* 0x202 */
+ uint16_t param_block_version; /* 0x206 */
+ uint8_t reserved11[8]; /* 0x208 */
+ uint8_t loader_type; /* 0x210 */
+#define LOADER_TYPE_LOADLIN 1
+#define LOADER_TYPE_BOOTSECT_LOADER 2
+#define LOADER_TYPE_SYSLINUX 3
+#define LOADER_TYPE_ETHERBOOT 4
+#define LOADER_TYPE_KERNEL 5
+ uint8_t loader_flags; /* 0x211 */
+ uint8_t reserved12[2]; /* 0x212 */
+ uint32_t kernel_start; /* 0x214 */
+ uint32_t initrd_start; /* 0x218 */
+ uint32_t initrd_size; /* 0x21c */
+ uint8_t reserved12_5[8]; /* 0x220 */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ uint8_t reserved13[164]; /* 0x22c */
+ struct e820entry e820_map[E820MAX]; /* 0x2d0 */
+ uint8_t reserved16[688]; /* 0x550 */
+#define COMMAND_LINE_SIZE 256
+ /* Command line is copied here by 32-bit i386/kernel/head.S.
+ * So I will follow the boot protocol, rather than putting it
+ * directly here. --ts1 */
+ uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */
+ uint8_t reserved17[1792]; /* 0x900 - 0x1000 */
+};
+
+uint64_t forced_memsize;
+
+/* Load the first part the file and check if it's Linux */
+static uint32_t load_linux_header(struct linux_header *hdr)
+{
+ int load_high;
+ uint32_t kern_addr;
+
+ if (lfile_read(hdr, sizeof *hdr) != sizeof *hdr) {
+ debug("Can't read Linux header\n");
+ return 0;
+ }
+ if (hdr->boot_sector_magic != 0xaa55) {
+ debug("Not a Linux kernel image\n");
+ return 0;
+ }
+
+ /* Linux is found. Print some information */
+ if (memcmp(hdr->header_magic, "HdrS", 4) != 0) {
+ /* This may be floppy disk image or something.
+ * Perform a simple (incomplete) sanity check. */
+ if (hdr->setup_sects >= 16
+ || file_size() - (hdr->setup_sects<<9) >= 512<<10) {
+ debug("This looks like a bootdisk image but not like Linux...\n");
+ return 0;
+ }
+
+ printf("Possible very old Linux");
+ /* This kernel does not even have a protocol version.
+ * Force the value. */
+ hdr->protocol_version = 0; /* pre-2.00 */
+ } else
+ printf("Found Linux");
+ if (hdr->protocol_version >= 0x200 && hdr->kver_addr) {
+ char kver[256];
+ file_seek(hdr->kver_addr + 0x200);
+ if (lfile_read(kver, sizeof kver) != 0) {
+ kver[255] = 0;
+ printf(" version %s", kver);
+ }
+ }
+ debug(" (protocol %#x)", hdr->protocol_version);
+ load_high = 0;
+ if (hdr->protocol_version >= 0x200) {
+ debug(" (loadflags %#x)", hdr->loadflags);
+ load_high = hdr->loadflags & 1;
+ }
+ if (load_high) {
+ printf(" bzImage");
+ kern_addr = 0x100000;
+ } else {
+ printf(" zImage or Image");
+ kern_addr = 0x1000;
+ }
+ printf(".\n");
+
+ return kern_addr;
+}
+
+/* Set up parameters for 32-bit kernel */
+static void
+init_linux_params(struct linux_params *params, struct linux_header *hdr)
+{
+ debug("Setting up paramters at %#lx\n", virt_to_phys(params));
+ memset(params, 0, sizeof *params);
+
+ /* Copy some useful values from header */
+ params->mount_root_rdonly = hdr->root_flags;
+ params->orig_root_dev = hdr->root_dev;
+
+ /* Video parameters.
+ * This assumes we have VGA in standard 80x25 text mode,
+ * just like our vga.c does.
+ * Cursor position is filled later to allow some more printf's. */
+ params->orig_video_mode = 3;
+ params->orig_video_cols = 80;
+ params->orig_video_lines = 25;
+ params->orig_video_isVGA = 1;
+ params->orig_video_points = 16;
+
+ params->loader_type = 0xff; /* Unregistered Linux loader */
+}
+
+/* Memory map */
+static void
+set_memory_size(struct linux_params *params, struct sys_info *info)
+{
+ int i;
+ uint64_t end;
+ uint32_t ramtop = 0;
+ struct e820entry *linux_map;
+ struct memrange *filo_map;
+
+ linux_map = params->e820_map;
+ filo_map = info->memrange;
+ for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) {
+ if (i < E820MAX) {
+ /* Convert to BIOS e820 style */
+ linux_map->addr = filo_map->base;
+ linux_map->size = filo_map->size;
+ linux_map->type = E820_RAM;
+ debug("%016Lx - %016Lx\n", linux_map->addr,
+ linux_map->addr + linux_map->size);
+ params->e820_map_nr = i+1;
+ }
+
+ /* Find out top of RAM. XXX This ignores hole above 1MB */
+ end = filo_map->base + filo_map->size;
+ if (end < (1ULL << 32)) { /* don't count memory above 4GB */
+ if (end > ramtop)
+ ramtop = (uint32_t) end;
+ }
+ }
+ debug("ramtop=%#x\n", ramtop);
+ /* Size of memory above 1MB in KB */
+ params->alt_mem_k = (ramtop - (1<<20)) >> 10;
+ /* old style, 64MB max */
+ if (ramtop >= (64<<20))
+ params->ext_mem_k = (63<<10);
+ else
+ params->ext_mem_k = params->alt_mem_k;
+ debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k);
+}
+
+/*
+ * Parse command line
+ * Some parameters, like initrd=<file>, are not passed to kernel,
+ * we are responsible to process them.
+ * Parameters for kernel are copied to kern_cmdline. Returns name of initrd.
+ */
+static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline)
+{
+ const char *start, *sep, *end, *val;
+ char name[64];
+ int len;
+ int k_len;
+ int to_kern;
+ char *initrd = 0;
+ int toolong = 0;
+
+ forced_memsize = 0;
+
+ if (!orig_cmdline) {
+ *kern_cmdline = 0;
+ return 0;
+ }
+
+ k_len = 0;
+ debug("original command line: \"%s\"\n", orig_cmdline);
+ debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline));
+
+ start = orig_cmdline;
+ while (*start == ' ')
+ start++;
+ while (*start) {
+ end = strchr(start, ' ');
+ if (!end)
+ end = start + strlen(start);
+ sep = strchr(start, '=');
+ if (!sep || sep > end)
+ sep = end;
+ len = sep - start;
+ if (len >= sizeof(name))
+ len = sizeof(name) - 1;
+ memcpy(name, start, len);
+ name[len] = 0;
+
+ if (*sep == '=') {
+ val = sep + 1;
+ len = end - val;
+ } else {
+ val = 0;
+ len = 0;
+ }
+
+ /* Only initrd= and mem= are handled here. vga= is not,
+ * which I believe is a paramter to the realmode part of Linux,
+ * which we don't execute. */
+ if (strcmp(name, "initrd") == 0) {
+ if (!val)
+ printf("Missing filename to initrd parameter\n");
+ else {
+ initrd = malloc(len + 1);
+ memcpy(initrd, val, len);
+ initrd[len] = 0;
+ debug("initrd=%s\n", initrd);
+ }
+ /* Don't pass this to kernel */
+ to_kern = 0;
+ } else if (strcmp(name, "mem") == 0) {
+ if (!val)
+ printf("Missing value for mem parameter\n");
+ else {
+ forced_memsize = strtoull_with_suffix(val, (char**)&val, 0);
+ if (forced_memsize == 0)
+ printf("Invalid mem option, ignored\n");
+ if (val != end) {
+ printf("Garbage after mem=<size>, ignored\n");
+ forced_memsize = 0;
+ }
+ debug("mem=%Lu\n", forced_memsize);
+ }
+ /* mem= is for both loader and kernel */
+ to_kern = 1;
+ } else
+ to_kern = 1;
+
+ if (to_kern) {
+ /* Copy to kernel command line buffer */
+ if (k_len != 0)
+ kern_cmdline[k_len++] = ' '; /* put separator */
+ len = end - start;
+ if (k_len + len >= COMMAND_LINE_SIZE) {
+ len = COMMAND_LINE_SIZE - k_len - 1;
+ if (!toolong) {
+ printf("Kernel command line is too long; truncated to "
+ "%d bytes\n", COMMAND_LINE_SIZE-1);
+ toolong = 1;
+ }
+ }
+ memcpy(kern_cmdline + k_len, start, len);
+ k_len += len;
+ }
+
+ start = end;
+ while (*start == ' ')
+ start++;
+ }
+ kern_cmdline[k_len] = 0;
+ debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline);
+
+ return initrd;
+}
+
+/* Set command line location */
+static void set_command_line_loc(struct linux_params *params,
+ struct linux_header *hdr)
+{
+ if (hdr->protocol_version >= 0x202) {
+ /* new style */
+ params->cmd_line_ptr = COMMAND_LINE_LOC;
+ } else {
+ /* old style */
+ params->cl_magic = CL_MAGIC_VALUE;
+ params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC;
+ }
+}
+
+/* Load 32-bit part of kernel */
+static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr)
+{
+ uint32_t kern_offset, kern_size;
+
+ if (hdr->setup_sects == 0)
+ hdr->setup_sects = 4;
+ kern_offset = (hdr->setup_sects + 1) * 512;
+ file_seek(kern_offset);
+ kern_size = file_size() - kern_offset;
+ debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size);
+
+#if 0
+ if (using_devsize) {
+ printf("Attempt to load up to end of device as kernel; "
+ "specify the image size\n");
+ return 0;
+ }
+#endif
+
+ printf("Loading kernel... ");
+ if (lfile_read(phys_to_virt(kern_addr), kern_size) != kern_size) {
+ printf("Can't read kernel\n");
+ return 0;
+ }
+ printf("ok\n");
+
+ return kern_size;
+}
+
+static int load_initrd(struct linux_header *hdr, struct sys_info *info,
+ uint32_t kern_end, struct linux_params *params, const char *initrd_file)
+{
+ uint32_t max;
+ uint32_t start, end, size;
+ uint64_t forced;
+ extern char _start[], _end[];
+
+ if (!file_open(initrd_file)) {
+ printf("Can't open initrd: %s\n", initrd_file);
+ return -1;
+ }
+
+#if 0
+ if (using_devsize) {
+ printf("Attempt to load up to end of device as initrd; "
+ "specify the image size\n");
+ return -1;
+ }
+#endif
+
+ size = file_size();
+
+
+ /* Find out the kernel's restriction on how high the initrd can be
+ * placed */
+ if (hdr->protocol_version >= 0x203)
+ max = hdr->initrd_addr_max;
+ else
+ max = 0x38000000; /* Hardcoded value for older kernels */
+
+ /* FILO itself is at the top of RAM. (relocated)
+ * So, try putting initrd just below us. */
+ end = virt_to_phys(_start);
+ if (end > max)
+ end = max;
+
+ /* If "mem=" option is given, we have to put the initrd within
+ * the specified range. */
+ if (forced_memsize) {
+ forced = forced_memsize;
+ if (forced > max)
+ forced = max;
+ /* If the "mem=" is lower, it's easy */
+ if (forced <= end)
+ end = forced;
+ else {
+ /* Otherwise, see if we can put it above us */
+ if (virt_to_phys(_end) + size <= forced)
+ end = forced; /* Ok */
+ }
+ }
+
+ start = end - size;
+ start &= ~0xfff; /* page align */
+ end = start + size;
+
+ debug("start=%#x end=%#x\n", start, end);
+
+ if (start < kern_end) {
+ printf("Initrd is too big to fit in memory\n");
+ return -1;
+ }
+
+ printf("Loading initrd... ");
+ if (lfile_read(phys_to_virt(start), size) != size) {
+ printf("Can't read initrd\n");
+ return -1;
+ }
+ printf("ok\n");
+
+ params->initrd_start = start;
+ params->initrd_size = size;
+
+ return 0;
+}
+
+static void hardware_setup(void)
+{
+ /* Disable nmi */
+ outb(0x80, 0x70);
+
+ /* Make sure any coprocessor is properly reset.. */
+ outb(0, 0xf0);
+ outb(0, 0xf1);
+
+ /* we're getting screwed again and again by this problem of the 8259.
+ * so we're going to leave this lying around for inclusion into
+ * crt0.S on an as-needed basis.
+ *
+ * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
+ * we put them right after the intel-reserved hardware interrupts, at
+ * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
+ * messed this up with the original PC, and they haven't been able to
+ * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
+ * which is used for the internal hardware interrupts as well. We just
+ * have to reprogram the 8259's, and it isn't fun.
+ */
+
+ outb(0x11, 0x20); /* initialization sequence to 8259A-1 */
+ outb(0x11, 0xA0); /* and to 8259A-2 */
+
+ outb(0x20, 0x21); /* start of hardware int's (0x20) */
+ outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */
+
+ outb(0x04, 0x21); /* 8259-1 is master */
+ outb(0x02, 0xA1); /* 8259-2 is slave */
+
+ outb(0x01, 0x21); /* 8086 mode for both */
+ outb(0x01, 0xA1);
+
+ outb(0xFF, 0xA1); /* mask off all interrupts for now */
+ outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */
+}
+
+/* Start Linux */
+static int start_linux(uint32_t kern_addr, struct linux_params *params)
+{
+ struct segment_desc *linux_gdt;
+ struct context *ctx;
+ //extern int cursor_x, cursor_y;
+
+ ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
+
+ /* Linux expects GDT being in low memory */
+ linux_gdt = phys_to_virt(GDT_LOC);
+ memset(linux_gdt, 0, 13*sizeof(struct segment_desc));
+ /* Normal kernel code/data segments */
+ linux_gdt[2] = gdt[FLAT_CODE];
+ linux_gdt[3] = gdt[FLAT_DATA];
+ /* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible
+ * segments (2 and 3), so it SHOULD not be a problem.
+ * However, some distro kernels (eg. RH9) with backported threading
+ * patch use 12 and 13 also when booting... */
+ linux_gdt[12] = gdt[FLAT_CODE];
+ linux_gdt[13] = gdt[FLAT_DATA];
+ ctx->gdt_base = GDT_LOC;
+ ctx->gdt_limit = 14*8-1;
+ ctx->cs = 0x10;
+ ctx->ds = 0x18;
+ ctx->es = 0x18;
+ ctx->fs = 0x18;
+ ctx->gs = 0x18;
+ ctx->ss = 0x18;
+
+ /* Parameter location */
+ ctx->esi = virt_to_phys(params);
+
+ /* Entry point */
+ ctx->eip = kern_addr;
+
+ debug("eip=%#x\n", kern_addr);
+ printf("Jumping to entry point...\n");
+
+#ifdef VGA_CONSOLE
+ /* Update VGA cursor position.
+ * This must be here because the printf changes the value! */
+ params->orig_x = cursor_x;
+ params->orig_y = cursor_y;
+#endif
+
+ /* Go... */
+ ctx = switch_to(ctx);
+
+ /* It's impossible but... */
+ printf("Returned with eax=%#x\n", ctx->eax);
+
+ return ctx->eax;
+}
+
+int linux_load(struct sys_info *info, const char *file, const char *cmdline)
+{
+ struct linux_header hdr;
+ struct linux_params *params;
+ uint32_t kern_addr, kern_size;
+ char *initrd_file = 0;
+
+ if (!file_open(file))
+ return -1;
+
+ kern_addr = load_linux_header(&hdr);
+ if (kern_addr == 0)
+ return LOADER_NOT_SUPPORT;
+
+ params = phys_to_virt(LINUX_PARAM_LOC);
+ init_linux_params(params, &hdr);
+ set_memory_size(params, info);
+ initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
+ set_command_line_loc(params, &hdr);
+
+ kern_size = load_linux_kernel(&hdr, kern_addr);
+ if (kern_size == 0) {
+ if (initrd_file)
+ free(initrd_file);
+ return -1;
+ }
+
+ if (initrd_file) {
+ if (load_initrd(&hdr, info, kern_addr+kern_size, params, initrd_file)
+ != 0) {
+ free(initrd_file);
+ return -1;
+ }
+ free(initrd_file);
+ }
+
+ hardware_setup();
+
+ start_linux(kern_addr, params);
+ return 0;
+}
diff --git a/roms/openbios/arch/amd64/multiboot.c b/roms/openbios/arch/amd64/multiboot.c
new file mode 100644
index 00000000..4271bd52
--- /dev/null
+++ b/roms/openbios/arch/amd64/multiboot.c
@@ -0,0 +1,125 @@
+/* Support for Multiboot */
+
+#include "config.h"
+#include "asm/io.h"
+#include "libopenbios/sys_info.h"
+#include "multiboot.h"
+
+#define printf printk
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+struct mbheader {
+ unsigned int magic, flags, checksum;
+};
+const struct mbheader multiboot_header
+ __attribute__((section (".hdr"))) =
+{
+ MULTIBOOT_HEADER_MAGIC,
+ MULTIBOOT_HEADER_FLAGS,
+ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+};
+
+/* Multiboot information structure, provided by loader to us */
+
+struct multiboot_mmap {
+ unsigned entry_size;
+ unsigned base_lo, base_hi;
+ unsigned size_lo, size_hi;
+ unsigned type;
+};
+
+#define MULTIBOOT_MEM_VALID 0x01
+#define MULTIBOOT_BOOT_DEV_VALID 0x02
+#define MULTIBOOT_CMDLINE_VALID 0x04
+#define MULTIBOOT_MODS_VALID 0x08
+#define MULTIBOOT_AOUT_SYMS_VALID 0x10
+#define MULTIBOOT_ELF_SYMS_VALID 0x20
+#define MULTIBOOT_MMAP_VALID 0x40
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ struct multiboot_info *mbinfo;
+ struct multiboot_mmap *mbmem;
+ unsigned mbcount, mbaddr;
+ int i;
+ struct memrange *mmap;
+ int mmap_count;
+ module_t *mod;
+
+ if (info->boot_type != 0x2BADB002)
+ return;
+
+ debug("Using Multiboot information at %#lx\n", info->boot_data);
+
+ mbinfo = phys_to_virt(info->boot_data);
+
+ if (mbinfo->mods_count != 1) {
+ printf("Multiboot: no dictionary\n");
+ return;
+ }
+
+ mod = (module_t *) mbinfo->mods_addr;
+ info->dict_start=(unsigned long *)mod->mod_start;
+ info->dict_end=(unsigned long *)mod->mod_end;
+
+ if (mbinfo->flags & MULTIBOOT_MMAP_VALID) {
+ /* convert mmap records */
+ mbmem = phys_to_virt(mbinfo->mmap_addr);
+ mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4);
+ mmap = malloc(mbcount * sizeof(struct memrange));
+ mmap_count = 0;
+ mbaddr = mbinfo->mmap_addr;
+ for (i = 0; i < mbcount; i++) {
+ mbmem = phys_to_virt(mbaddr);
+ debug("%08x%08x %08x%08x (%d)\n",
+ mbmem->base_hi,
+ mbmem->base_lo,
+ mbmem->size_hi,
+ mbmem->size_lo,
+ mbmem->type);
+ if (mbmem->type == 1) { /* Only normal RAM */
+ mmap[mmap_count].base = mbmem->base_lo
+ + (((unsigned long long) mbmem->base_hi) << 32);
+ mmap[mmap_count].size = mbmem->size_lo
+ + (((unsigned long long) mbmem->size_hi) << 32);
+ mmap_count++;
+ }
+ mbaddr += mbmem->entry_size + 4;
+ if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length)
+ break;
+ }
+ /* simple sanity check - there should be at least 2 RAM segments
+ * (base 640k and extended) */
+ if (mmap_count >= 2)
+ goto got_it;
+
+ printf("Multiboot mmap is broken\n");
+ free(mmap);
+ /* fall back to mem_lower/mem_upper */
+ }
+
+ if (mbinfo->flags & MULTIBOOT_MEM_VALID) {
+ /* use mem_lower and mem_upper */
+ mmap_count = 2;
+ mmap = malloc(2 * sizeof(*mmap));
+ mmap[0].base = 0;
+ mmap[0].size = mbinfo->mem_lower << 10;
+ mmap[1].base = 1 << 20; /* 1MB */
+ mmap[1].size = mbinfo->mem_upper << 10;
+ goto got_it;
+ }
+
+ printf("Can't get memory information from Multiboot\n");
+ return;
+
+got_it:
+ info->memrange = mmap;
+ info->n_memranges = mmap_count;
+
+ return;
+}
diff --git a/roms/openbios/arch/amd64/multiboot.h b/roms/openbios/arch/amd64/multiboot.h
new file mode 100644
index 00000000..17cf202e
--- /dev/null
+++ b/roms/openbios/arch/amd64/multiboot.h
@@ -0,0 +1,96 @@
+/* multiboot.h
+ * tag: header for multiboot
+ *
+ * Copyright (C) 2003-2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+/* magic number for multiboot header */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* flags for multiboot header */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* magic number passed by multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (8KB). */
+#define STACK_SIZE 0x2000
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* We don't want these declarations in boot.S */
+
+/* multiboot header */
+typedef struct multiboot_header {
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* symbol table for a.out */
+typedef struct aout_symbol_table {
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* section header table for ELF */
+typedef struct elf_section_header_table {
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* multiboot information */
+typedef struct multiboot_info {
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+} multiboot_info_t;
+
+/* module structure */
+typedef struct module {
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map {
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+#endif /* ! ASM */
diff --git a/roms/openbios/arch/amd64/openbios.c b/roms/openbios/arch/amd64/openbios.c
new file mode 100644
index 00000000..15d3b625
--- /dev/null
+++ b/roms/openbios/arch/amd64/openbios.c
@@ -0,0 +1,108 @@
+/* tag: openbios forth environment, executable code
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "asm/types.h"
+#include "dict.h"
+#include "kernel/kernel.h"
+#include "kernel/stack.h"
+#include "libopenbios/sys_info.h"
+#include "openbios.h"
+#include "relocate.h"
+
+void boot(void);
+
+#define DICTIONARY_SIZE (256*1024) /* 256K for the dictionary */
+static char intdict[DICTIONARY_SIZE];
+
+static void init_memory(void)
+{
+ /* push start and end of available memory to the stack
+ * so that the forth word QUIT can initialize memory
+ * management. For now we use hardcoded memory between
+ * 0x10000 and 0x9ffff (576k). If we need more memory
+ * than that we have serious bloat.
+ */
+
+ PUSH(0x10000);
+ PUSH(0x9FFFF);
+}
+
+static void
+arch_init( void )
+{
+ void setup_timers(void);
+
+ openbios_init();
+ modules_init();
+#ifdef CONFIG_DRIVER_IDE
+ setup_timers();
+ ob_ide_init("/pci/pci-ata", 0x1f0, 0x3f6, 0x170, 0x376);
+#endif
+ device_end();
+ bind_func("platform-boot", boot );
+}
+
+extern struct _console_ops arch_console_ops;
+
+int openbios(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE
+ init_console(arch_console_ops);
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED);
+#endif
+ /* Clear the screen. */
+ cls();
+#endif
+
+ collect_sys_info(&sys_info);
+
+ dict=intdict;
+ dictlimit = DICTIONARY_SIZE;
+
+ load_dictionary((char *)sys_info.dict_start,
+ sys_info.dict_end-sys_info.dict_start);
+ forth_init();
+
+ relocate(&sys_info);
+
+#ifdef CONFIG_DEBUG_CONSOLE
+ video_init();
+#endif
+#ifdef CONFIG_DEBUG_BOOT
+ printk("forth started.\n");
+ printk("initializing memory...");
+#endif
+
+ init_memory();
+
+#ifdef CONFIG_DEBUG_BOOT
+ printk("done\n");
+#endif
+
+ PUSH_xt( bind_noname_func(arch_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+
+ if (!PC) {
+ printk("panic: no dictionary entry point.\n");
+ return -1;
+ }
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("done (%d bytes).\n", dicthead);
+ printk("Jumping to dictionary...\n");
+#endif
+
+ enterforth((xt_t)PC);
+
+ return 0;
+}
diff --git a/roms/openbios/arch/amd64/openbios.h b/roms/openbios/arch/amd64/openbios.h
new file mode 100644
index 00000000..2d49dbf5
--- /dev/null
+++ b/roms/openbios/arch/amd64/openbios.h
@@ -0,0 +1,29 @@
+/*
+ * Creation Date: <2004/01/15 16:14:05 samuel>
+ * Time-stamp: <2004/01/15 16:14:05 samuel>
+ *
+ * <openbios.h>
+ *
+ *
+ *
+ * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_OPENBIOS
+#define _H_OPENBIOS
+
+int openbios(void);
+
+/* console.c */
+extern void cls(void);
+#ifdef CONFIG_DEBUG_CONSOLE
+extern int uart_init(int port, unsigned long speed);
+extern void video_init(void);
+#endif
+
+#endif /* _H_OPENBIOS */
diff --git a/roms/openbios/arch/amd64/plainboot.c b/roms/openbios/arch/amd64/plainboot.c
new file mode 100644
index 00000000..08dab2d1
--- /dev/null
+++ b/roms/openbios/arch/amd64/plainboot.c
@@ -0,0 +1,21 @@
+/* tag: openbios fixed address forth starter
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/sys_info.h"
+#include "multiboot.h"
+
+#define FIXED_DICTSTART 0xfffe0000
+#define FIXED_DICTEND 0xfffeffff
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ info->dict_start=(unsigned long *)FIXED_DICTSTART;
+ info->dict_end=(unsigned long *)FIXED_DICTEND;
+}
diff --git a/roms/openbios/arch/amd64/relocate.h b/roms/openbios/arch/amd64/relocate.h
new file mode 100644
index 00000000..d91160a0
--- /dev/null
+++ b/roms/openbios/arch/amd64/relocate.h
@@ -0,0 +1 @@
+void relocate(struct sys_info *);
diff --git a/roms/openbios/arch/amd64/segment.c b/roms/openbios/arch/amd64/segment.c
new file mode 100644
index 00000000..09763bd1
--- /dev/null
+++ b/roms/openbios/arch/amd64/segment.c
@@ -0,0 +1,134 @@
+/* Segmentation of the AMD64 architecture.
+ *
+ * 2003-07 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/sys_info.h"
+#include "relocate.h"
+#include "segment.h"
+
+#define printf printk
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+/* i386 lgdt argument */
+struct gdtarg {
+ unsigned short limit;
+ unsigned int base;
+} __attribute__((packed));
+
+/* How far the virtual address (used in C) is different from physical
+ * address. Since we start in flat mode, the initial value is zero. */
+unsigned long virt_offset = 0;
+
+/* GDT, the global descriptor table */
+struct segment_desc gdt[NUM_SEG] = {
+ /* 0x00: null segment */
+ {0, 0, 0, 0, 0, 0},
+ /* 0x08: flat code segment */
+ {0xffff, 0, 0, 0x9f, 0xcf, 0},
+ /* 0x10: flat data segment */
+ {0xffff, 0, 0, 0x93, 0xcf, 0},
+ /* 0x18: code segment for relocated execution */
+ {0xffff, 0, 0, 0x9f, 0xcf, 0},
+ /* 0x20: data segment for relocated execution */
+ {0xffff, 0, 0, 0x93, 0xcf, 0},
+};
+
+extern char _start[], _end[];
+
+void relocate(struct sys_info *info)
+{
+ int i;
+ unsigned long prog_addr;
+ unsigned long prog_size;
+ unsigned long addr, new_base;
+ unsigned long long segsize;
+ unsigned long new_offset;
+ unsigned d0, d1, d2;
+ struct gdtarg gdtarg;
+#define ALIGNMENT 16
+
+ prog_addr = virt_to_phys(&_start);
+ prog_size = virt_to_phys(&_end) - virt_to_phys(&_start);
+ debug("Current location: %#lx-%#lx\n", prog_addr, prog_addr+prog_size-1);
+
+ new_base = 0;
+ for (i = 0; i < info->n_memranges; i++) {
+ if (info->memrange[i].base >= 1ULL<<32)
+ continue;
+ segsize = info->memrange[i].size;
+ if (info->memrange[i].base + segsize > 1ULL<<32)
+ segsize = (1ULL<<32) - info->memrange[i].base;
+ if (segsize < prog_size+ALIGNMENT)
+ continue;
+ addr = info->memrange[i].base + segsize - prog_size;
+ addr &= ~(ALIGNMENT-1);
+ if (addr >= prog_addr && addr < prog_addr + prog_size)
+ continue;
+ if (prog_addr >= addr && prog_addr < addr + prog_size)
+ continue;
+ if (addr > new_base)
+ new_base = addr;
+ }
+ if (new_base == 0) {
+ printf("Can't find address to relocate\n");
+ return;
+ }
+
+ debug("Relocating to %#lx-%#lx... ",
+ new_base, new_base + prog_size - 1);
+
+ /* New virtual address offset */
+ new_offset = new_base - (unsigned long) &_start;
+
+ /* Tweak the GDT */
+ gdt[RELOC_CODE].base_0 = (unsigned short) new_offset;
+ gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset>>16);
+ gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset>>24);
+ gdt[RELOC_DATA].base_0 = (unsigned short) new_offset;
+ gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset>>16);
+ gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset>>24);
+
+ /* Load new GDT and reload segments */
+ gdtarg.base = new_offset + (unsigned long) gdt;
+ gdtarg.limit = GDT_LIMIT;
+ __asm__ __volatile__ (
+ "rep; movsb\n\t" /* copy everything */
+ "lgdt %3\n\t"
+ "ljmp %4, $1f\n1:\t"
+ "movw %5, %%ds\n\t"
+ "movw %5, %%es\n\t"
+ "movw %5, %%fs\n\t"
+ "movw %5, %%gs\n\t"
+ "movw %5, %%ss\n"
+ : "=&S" (d0), "=&D" (d1), "=&c" (d2)
+ : "m" (gdtarg), "n" (RELOC_CS), "q" ((unsigned short) RELOC_DS),
+ "0" (&_start), "1" (new_base), "2" (prog_size));
+
+ virt_offset = new_offset;
+ debug("ok\n");
+}
+
+#if 0
+/* Copy GDT to new location and reload it */
+void move_gdt(unsigned long newgdt)
+{
+ struct gdtarg gdtarg;
+
+ debug("Moving GDT to %#lx...", newgdt);
+ memcpy(phys_to_virt(newgdt), gdt, sizeof gdt);
+ gdtarg.base = newgdt;
+ gdtarg.limit = GDT_LIMIT;
+ debug("reloading GDT...");
+ __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
+ debug("reloading CS for fun...");
+ __asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS));
+ debug("ok\n");
+}
+#endif
diff --git a/roms/openbios/arch/amd64/segment.h b/roms/openbios/arch/amd64/segment.h
new file mode 100644
index 00000000..0371a80a
--- /dev/null
+++ b/roms/openbios/arch/amd64/segment.h
@@ -0,0 +1,30 @@
+
+/* Segment indexes. Must match the gdt definition in segment.c. */
+enum {
+ NULL_SEG,
+ FLAT_CODE,
+ FLAT_DATA,
+ RELOC_CODE,
+ RELOC_DATA,
+ NUM_SEG,
+};
+
+/* Values for segment selector register */
+#define FLAT_CS (FLAT_CODE << 3)
+#define FLAT_DS (FLAT_DATA << 3)
+#define RELOC_CS (RELOC_CODE << 3)
+#define RELOC_DS (RELOC_DATA << 3)
+
+/* i386 segment descriptor */
+struct segment_desc {
+ unsigned short limit_0;
+ unsigned short base_0;
+ unsigned char base_16;
+ unsigned char types;
+ unsigned char flags;
+ unsigned char base_24;
+};
+
+extern struct segment_desc gdt[NUM_SEG];
+
+#define GDT_LIMIT ((NUM_SEG << 3) - 1)
diff --git a/roms/openbios/arch/amd64/switch.S b/roms/openbios/arch/amd64/switch.S
new file mode 100644
index 00000000..66668150
--- /dev/null
+++ b/roms/openbios/arch/amd64/switch.S
@@ -0,0 +1,116 @@
+ .globl entry, __switch_context, __exit_context, halt
+
+ .text
+ .align 4
+
+/*
+ * Entry point
+ * We start execution from here.
+ * It is assumed that CPU is in 32-bit protected mode and
+ * all segments are 4GB and base zero (flat model).
+ */
+entry:
+ /* Save boot context and switch to our main context.
+ * Main context is statically defined in C.
+ */
+ pushl %cs
+ call __switch_context
+
+ /* We get here when the main context switches back to
+ * the boot context.
+ * Return to previous bootloader.
+ */
+ ret
+
+/*
+ * Switch execution context
+ * This saves registers, segments, and GDT in the stack, then
+ * switches the stack, and restores everything from the new stack.
+ * This function takes no argument. New stack pointer is
+ * taken from global variable __context, and old stack pointer
+ * is also saved to __context. This way we can just jump to
+ * this routine to get back to the original context.
+ *
+ * Call this routine with lcall or pushl %cs; call.
+ */
+__switch_context:
+ /* Save everything in current stack */
+ pushfl /* 56 */
+ pushl %ds /* 52 */
+ pushl %es /* 48 */
+ pushl %fs /* 44 */
+ pushl %gs /* 40 */
+ pushal /* 8 */
+ subl $8, %esp
+ movw %ss, (%esp) /* 0 */
+ sgdt 2(%esp) /* 2 */
+
+#if 0
+ /* Swap %cs and %eip on the stack, so lret will work */
+ movl 60(%esp), %eax
+ xchgl %eax, 64(%esp)
+ movl %eax, 60(%esp)
+#endif
+
+ /* At this point we don't know if we are on flat segment
+ * or relocated. So compute the address offset from %eip.
+ * Assuming CS.base==DS.base==SS.base.
+ */
+ call 1f
+1: popl %ebx
+ subl $1b, %ebx
+
+ /* Interrupts are not allowed... */
+ cli
+
+ /* Current context pointer is our stack pointer */
+ movl %esp, %esi
+
+ /* Normalize the ctx pointer */
+ subl %ebx, %esi
+
+ /* Swap it with new value */
+ xchgl %esi, __context(%ebx)
+
+ /* Adjust new ctx pointer for current address offset */
+ addl %ebx, %esi
+
+ /* Load new %ss and %esp to temporary */
+ movzwl (%esi), %edx
+ movl 20(%esi), %eax
+
+ /* Load new GDT */
+ lgdt 2(%esi)
+
+ /* Load new stack segment with new GDT */
+ movl %edx, %ss
+
+ /* Set new stack pointer, but we have to adjust it because
+ * pushal saves %esp value before pushal, and we want the value
+ * after pushal.
+ */
+ leal -32(%eax), %esp
+
+ /* Load the rest from new stack */
+ popal
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popfl
+
+ /* Finally, load new %cs and %eip */
+ lret
+
+__exit_context:
+ /* Get back to the original context */
+ pushl %cs
+ call __switch_context
+
+ /* We get here if the other context attempt to switch to this
+ * dead context. This should not happen. */
+
+halt:
+ cli
+ hlt
+ jmp halt
diff --git a/roms/openbios/arch/amd64/sys_info.c b/roms/openbios/arch/amd64/sys_info.c
new file mode 100644
index 00000000..d62070be
--- /dev/null
+++ b/roms/openbios/arch/amd64/sys_info.c
@@ -0,0 +1,58 @@
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/sys_info.h"
+#include "context.h"
+
+#define printf printk
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+void collect_multiboot_info(struct sys_info *);
+void collect_sys_info(struct sys_info *info);
+
+void collect_sys_info(struct sys_info *info)
+{
+ int i;
+ unsigned long long total = 0;
+ struct memrange *mmap;
+
+ /* Pick up paramters given by bootloader to us */
+ info->boot_type = boot_ctx->eax;
+ info->boot_data = boot_ctx->ebx;
+ info->boot_arg = boot_ctx->param[0];
+ debug("boot eax = %#lx\n", info->boot_type);
+ debug("boot ebx = %#lx\n", info->boot_data);
+ debug("boot arg = %#lx\n", info->boot_arg);
+
+ collect_elfboot_info(info);
+#ifdef CONFIG_LINUXBIOS
+ collect_linuxbios_info(info);
+#endif
+#ifdef CONFIG_IMAGE_ELF_MULTIBOOT
+ collect_multiboot_info(info);
+#endif
+
+ if (!info->memrange) {
+ printf("Can't get memory map from firmware. "
+ "Using hardcoded default.\n");
+ info->n_memranges = 2;
+ info->memrange = malloc(2 * sizeof(struct memrange));
+ info->memrange[0].base = 0;
+ info->memrange[0].size = 640*1024;
+ info->memrange[1].base = 1024*1024;
+ info->memrange[1].size = 32*1024*1024
+ - info->memrange[1].base;
+ }
+
+ debug("\n");
+ mmap=info->memrange;
+ for (i = 0; i < info->n_memranges; i++) {
+ debug("%016Lx-", mmap[i].base);
+ debug("%016Lx\n", mmap[i].base+mmap[i].size);
+ total += mmap[i].size;
+ }
+ debug("RAM %Ld MB\n", (total + 512*1024) >> 20);
+}
diff --git a/roms/openbios/arch/build.xml b/roms/openbios/arch/build.xml
new file mode 100644
index 00000000..e3f32441
--- /dev/null
+++ b/roms/openbios/arch/build.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<build>
+ <include href="x86/build.xml"/>
+ <include href="amd64/build.xml"/>
+ <include href="ppc/build.xml"/>
+ <include href="ia64/build.xml"/>
+ <include href="unix/build.xml"/>
+ <include href="sparc32/build.xml"/>
+ <include href="sparc64/build.xml"/>
+</build>
diff --git a/roms/openbios/arch/ia64/Kconfig b/roms/openbios/arch/ia64/Kconfig
new file mode 100644
index 00000000..6ba86de5
--- /dev/null
+++ b/roms/openbios/arch/ia64/Kconfig
@@ -0,0 +1,22 @@
+mainmenu "OpenBIOS Configuration"
+
+config IPF
+ bool
+ default y
+ help
+ Building for IPF hardware.
+
+config LITTLE_ENDIAN
+ bool
+ default y
+ help
+ IPF is little endian.
+
+menu "Build hosted UNIX Binary"
+source "arch/unix/Kconfig"
+endmenu
+
+source "kernel/Kconfig"
+source "forth/Kconfig"
+source "libopenbios/Kconfig"
+source "drivers/Kconfig"
diff --git a/roms/openbios/arch/ia64/build.xml b/roms/openbios/arch/ia64/build.xml
new file mode 100644
index 00000000..8f3ea0d8
--- /dev/null
+++ b/roms/openbios/arch/ia64/build.xml
@@ -0,0 +1,5 @@
+<build condition="IPF">
+ <dictionary name="openbios-ia64" init="openbios" target="forth">
+ <object source="init.fs"/>
+ </dictionary>
+</build>
diff --git a/roms/openbios/arch/ia64/defconfig b/roms/openbios/arch/ia64/defconfig
new file mode 100644
index 00000000..70cd97e5
--- /dev/null
+++ b/roms/openbios/arch/ia64/defconfig
@@ -0,0 +1,65 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_IPF=y
+CONFIG_LITTLE_ENDIAN=y
+
+#
+# Kernel binaries (x86)
+#
+# CONFIG_IMAGE_ELF is not set
+# CONFIG_IMAGE_ELF_EMBEDDED is not set
+# CONFIG_IMAGE_ELF_MULTIBOOT is not set
+
+#
+# Build hosted UNIX Binary
+#
+CONFIG_HOST_UNIX=y
+# CONFIG_PLUGIN_PCI is not set
+
+#
+# Kernel Debugging
+#
+# CONFIG_DEBUG is not set
+CONFIG_DEBUG_CONSOLE=y
+CONFIG_DEBUG_CONSOLE_SERIAL=y
+CONFIG_SERIAL_PORT=1
+CONFIG_SERIAL_SPEED=115200
+CONFIG_DEBUG_CONSOLE_VGA=y
+
+#
+# Module Configuration
+#
+CONFIG_CMDLINE=y
+CONFIG_DEBLOCKER=y
+
+#
+# Filesystem Configuration
+#
+CONFIG_DISK_LABEL=y
+CONFIG_PART_SUPPORT=y
+CONFIG_PC_PARTS=y
+CONFIG_FS=y
+CONFIG_GRUBFS=y
+CONFIG_FSYS_EXT2FS=y
+CONFIG_FSYS_FAT=y
+CONFIG_FSYS_JFS=y
+# CONFIG_FSYS_MINIX is not set
+CONFIG_FSYS_REISERFS=y
+CONFIG_FSYS_XFS=y
+CONFIG_FSYS_ISO9660=y
+# CONFIG_FSYS_FFS is not set
+# CONFIG_FSYS_VSTAFS is not set
+# CONFIG_DEBUG_FS is not set
+
+#
+# Miscellaneous
+#
+CONFIG_LINUXBIOS=y
+
+#
+# Drivers
+#
+CONFIG_DRIVER_PCI=y
+CONFIG_DRIVER_IDE=y
+# CONFIG_DEBUG_IDE is not set
diff --git a/roms/openbios/arch/ia64/init.fs b/roms/openbios/arch/ia64/init.fs
new file mode 100644
index 00000000..5b65dd10
--- /dev/null
+++ b/roms/openbios/arch/ia64/init.fs
@@ -0,0 +1,76 @@
+:noname
+ ." Type 'help' for detailed information" cr
+ \ ." boot secondary slave cdrom: " cr
+ \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr
+ ; DIAG-initializer
+
+" /" find-device
+
+new-device
+ " memory" device-name
+ \ 12230 encode-int " reg" property
+ external
+ : open true ;
+ : close ;
+ \ claim ( phys size align -- base )
+ \ release ( phys size -- )
+finish-device
+
+new-device
+ " cpus" device-name
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+ : decode-unit parse-hex ;
+
+finish-device
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+:noname
+ set-defaults
+; SYSTEM-initializer
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " memory" " /memory" preopen
+ " mmu" " /cpus/@0" preopen
+ " stdout" " /builtin/console" preopen
+ " stdin" " /builtin/console" preopen
+
+; SYSTEM-initializer
+
+\ use the tty interface if available
+:noname
+ " /builtin/console" find-dev if drop
+ " /builtin/console" " input-device" $setenv
+ " /builtin/console" " output-device" $setenv
+ then
+; SYSTEM-initializer
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
diff --git a/roms/openbios/arch/ppc/Kconfig b/roms/openbios/arch/ppc/Kconfig
new file mode 100644
index 00000000..f317c0a4
--- /dev/null
+++ b/roms/openbios/arch/ppc/Kconfig
@@ -0,0 +1,48 @@
+mainmenu "OpenBIOS Configuration"
+
+config PPC
+ bool
+ default y
+ help
+ Building for PPC hardware.
+
+config BIG_ENDIAN
+ bool
+ default y
+ help
+ PPC hardware is big endian (per default)
+
+choice
+ prompt "Platform Type"
+ default MOL
+
+config MOL
+ bool "Mac-on-Linux"
+ help
+ Build an image for Mac-on-Linux
+
+config MPC107
+ bool "MPC107 board (Crescendo)"
+ help
+ Build for Crescendo board.
+
+config BRIQ
+ bool "Total Impact briQ"
+ help
+ Build an image for the Total Impact briQ
+
+config NO_ARCH
+ bool "None"
+ help
+ Don't build any images.
+
+endchoice
+
+menu "Build hosted UNIX Binary"
+source "arch/unix/Kconfig"
+endmenu
+
+source "kernel/Kconfig"
+source "forth/Kconfig"
+source "libopenbios/Kconfig"
+source "drivers/Kconfig"
diff --git a/roms/openbios/arch/ppc/Makefile b/roms/openbios/arch/ppc/Makefile
new file mode 100644
index 00000000..e182825e
--- /dev/null
+++ b/roms/openbios/arch/ppc/Makefile
@@ -0,0 +1,79 @@
+
+include ../../config/Makefile.top
+
+SUBDIRS =
+MOL = $(CONFIG_MOL:y=mol)
+BRIQ = $(CONFIG_BRIQ:y=briq)
+XTARGETS = $(MOL) $(BRIQ) ppc mollink
+DICTIONARIES = $(MOL) $(BRIQ)
+
+INCLUDES = -I../../kernel -I../../kernel/include \
+ -I../../include/molasm -I$(ODIR)/include
+
+#############################################################################
+
+mol-OBJS = mol/init.o mol/main.o mol/mol.o mol/console.o mol/osi-blk.o \
+ mol/osi-scsi.o mol/pseudodisk.o mol/methods.o ofmem.o \
+ mol/video.o mol/prom.o mol/tree.o misc.o mol/kernel.o
+
+briq-OBJS = briq/init.o briq/main.o briq/briq.o briq/vfd.o \
+ ofmem.o briq/methods.o briq/tree.o \
+ misc.o briq/kernel.o
+
+ppc-OBJS = $(KOBJS) $(MODULE_LIBS) \
+ $(FS_LIBS) $(DRIVER_LIBS) $(LIBC_LIBS)
+
+all-$(CONFIG_MOL) += $(ODIR)/mol.image
+all-$(CONFIG_BRIQ) += $(ODIR)/briq.image
+all-$(CONFIG_MPC107) += $(ODIR)/mpc107.image
+
+
+#############################################################################
+
+mol-SRC = ppc.fs tree.fs mol.fs $(ARCHDICT_SRC)
+briq-SRC = ppc.fs briq/tree.fs briq/briq.fs $(ARCHDICT_SRC)
+
+$(ODIR)/mol/kernel.o: $(ODIR)/include/mol-dict.h
+$(ODIR)/briq/kernel.o: $(ODIR)/include/briq-dict.h
+
+$(ODIR)/include/mol-dict.h: $(ODIR)/mol.dict
+ test -d $(dir $@) || $(INSTALL) -d $(dir $@)
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@
+
+$(ODIR)/include/briq-dict.h: $(ODIR)/briq.dict
+ test -d $(dir $@) || $(INSTALL) -d $(dir $@)
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@
+
+#############################################################################
+
+$(ODIR)/mol.image: $(ODIR)/start.o $(ODIR)/libmol.a $(ODIR)/libppc.a
+ @printf "= Building %-22s : " $@
+ building=
+ $(LD) -Ttext=0x01e01000 -Bstatic $^ $(LIBGCC) -o $@
+ @nm $@ | sort > $(ODIR)/mol.syms
+ strip -g $@
+ @echo "ok"
+
+$(ODIR)/briq.image: $(ODIR)/start.o $(ODIR)/timebase.o $(ODIR)/libbriq.a $(ODIR)/libppc.a
+ @printf "= Building %-22s : " $@
+ building=
+ $(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(LIBGCC) -o $@
+ @nm $@ | sort > $(ODIR)/briq.syms
+ #strip -g $@
+ @echo "ok"
+
+$(ODIR)/mpc107.image:
+ @echo "BUILDING mpc107.image (not yet implemented)"
+
+clean-local:
+ $(RM) $(ODIR)/*.image $(ODIR)/*.syms $(ODIR)/include/mol-dict.h
+
+include Makefile.asm
+include $(rules)/Rules.make
+include $(rules)/Rules.forth
diff --git a/roms/openbios/arch/ppc/Makefile.asm b/roms/openbios/arch/ppc/Makefile.asm
new file mode 100644
index 00000000..32d43376
--- /dev/null
+++ b/roms/openbios/arch/ppc/Makefile.asm
@@ -0,0 +1,32 @@
+# -*- makefile -*-
+#
+# Makefile.asm - assembly support
+#
+# Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2
+
+
+#################################################
+# Rules for asm targets
+#################################################
+
+ASMFLAGS = -D__ASSEMBLY__ -I$(top_srcdir) $(ALTIVEC)
+FILTERBIN = $(top_srcdir)/scripts/asfilter
+ASFILTER = $(shell if test -x $(FILTERBIN) ; then echo $(FILTERBIN) \
+ ; else echo "tr ';' '\n'" ; fi)
+INVOKE_M4 = | $(M4) -s $(M4_NO_GNU) | $(ASFILTER)
+
+$(ODIR)/%.o: %.S
+ @printf " Compiling %-20s: " $(notdir $@)
+ assembly=
+ @install -d $(dir $@)
+ @$(RM) $@ $@.s
+ @$(CPP) $(ASMFLAGS) $(IDIRS) $< > /dev/null
+ $(CPP) $(ASMFLAGS) $(IDIRS) $(DEPFLAGS) $< $(INVOKE_M4) > $@.s
+ $(AS) $@.s $(AS_FLAGS) -o $@
+ @$(DEPEXTRA)
+ @$(RM) $@.s
+ @echo "ok"
diff --git a/roms/openbios/arch/ppc/briq/briq.c b/roms/openbios/arch/ppc/briq/briq.c
new file mode 100644
index 00000000..a8541c37
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/briq.c
@@ -0,0 +1,194 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <briq.c>
+ *
+ * Copyright (C) 2004, Greg Watson
+ *
+ * derived from mol.c
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/nvram.h"
+#include "libc/vsprintf.h"
+#include "libc/string.h"
+#include "briq/briq.h"
+#include <stdarg.h>
+
+#define UART_BASE 0x3f8
+
+unsigned long virt_offset = 0;
+
+void
+exit( int status )
+{
+ for (;;);
+}
+
+void
+fatal_error( const char *err )
+{
+ printk("Fatal error: %s\n", err );
+ exit(0);
+}
+
+void
+panic( const char *err )
+{
+ printk("Panic: %s\n", err );
+ exit(0);
+
+ /* won't come here... this keeps the gcc happy */
+ for( ;; )
+ ;
+}
+
+
+/************************************************************************/
+/* print using OSI interface */
+/************************************************************************/
+
+static int do_indent;
+
+int
+printk( const char *fmt, ... )
+{
+ char *p, buf[1024];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vnsprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ ) {
+ if( *p == '\n' )
+ do_indent = 0;
+ if( do_indent++ == 1 ) {
+ putchar( '>' );
+ putchar( '>' );
+ putchar( ' ' );
+ }
+ putchar( *p );
+ }
+ return i;
+}
+
+
+/************************************************************************/
+/* TTY iface */
+/************************************************************************/
+
+static int ttychar = -1;
+
+static int
+tty_avail( void )
+{
+ return 1;
+}
+
+static int
+tty_putchar( int c )
+{
+ if( tty_avail() ) {
+ while (!(inb(UART_BASE + 0x05) & 0x20))
+ ;
+ outb(c, UART_BASE);
+ while (!(inb(UART_BASE + 0x05) & 0x40))
+ ;
+ }
+ return c;
+}
+
+int
+availchar( void )
+{
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ ttychar = inb(UART_BASE);
+ return (ttychar >= 0);
+}
+
+int
+getchar( void )
+{
+ int ch;
+
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ return inb(UART_BASE);
+ ch = ttychar;
+ ttychar = -1;
+ return ch;
+}
+
+int
+putchar( int c )
+{
+ if (c == '\n')
+ tty_putchar('\r');
+ return tty_putchar(c);
+}
+
+
+/************************************************************************/
+/* briQ specific stuff */
+/************************************************************************/
+
+static char nvram[2048];
+
+void
+dump_nvram(void)
+{
+ static char hexdigit[] = "0123456789abcdef";
+ int i;
+ for (i = 0; i < 16*4; i++)
+ {
+ printk ("%c", hexdigit[nvram[i] >> 4]);
+ printk ("%c", hexdigit[nvram[i] % 16]);
+ if (!((i + 1) % 16))
+ {
+ printk ("\n");
+ }
+ else
+ {
+ printk (" ");
+ }
+ }
+}
+
+
+int
+arch_nvram_size( void )
+{
+ return sizeof(nvram);
+}
+
+void
+arch_nvram_put( char *buf )
+{
+ memcpy(nvram, buf, sizeof(nvram));
+ printk("new nvram:\n");
+ dump_nvram();
+}
+
+void
+arch_nvram_get( char *buf )
+{
+ memcpy(buf, nvram, sizeof(nvram));
+ printk("current nvram:\n");
+ dump_nvram();
+}
diff --git a/roms/openbios/arch/ppc/briq/briq.fs b/roms/openbios/arch/ppc/briq/briq.fs
new file mode 100644
index 00000000..78d77970
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/briq.fs
@@ -0,0 +1,115 @@
+\ briq specific initialization code
+\
+\ Copyright (C) 2004 Greg Watson
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+
+\ -------------------------------------------------------------------------
+\ initialization
+\ -------------------------------------------------------------------------
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " rtc" " /pci/isa/rtc" preopen
+ " memory" " /memory" preopen
+ " mmu" " /cpu@0" preopen
+ " stdout" " /packages/terminal-emulator" preopen
+ " stdin" " keyboard" preopen
+
+; SYSTEM-initializer
+
+
+\ -------------------------------------------------------------------------
+\ device tree fixing
+\ -------------------------------------------------------------------------
+
+\ add decode-address methods
+: (make-decodable) ( phandle -- )
+
+ dup " #address-cells" rot get-package-property 0= if
+ decode-int nip nip
+ over " decode-unit" rot find-method if 2drop else
+ ( save phandle ncells )
+
+ over active-package!
+ case
+ 1 of ['] parse-hex " decode-unit" is-xt-func endof
+ 3 of
+ " bus-range" active-package get-package-property 0= if
+ decode-int nip nip
+ ['] encode-unit-pci " encode-unit" is-xt-func
+ " decode-unit" is-func-begin
+ ['] (lit) , ,
+ ['] decode-unit-pci-bus ,
+ is-func-end
+ then
+ endof
+ endcase
+ then
+ then
+ drop
+;
+
+: init-briq-tree ( -- )
+ active-package
+
+ iterate-tree-begin
+ begin ?dup while
+
+ dup (make-decodable)
+
+ iterate-tree
+ repeat
+
+ active-package!
+;
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /packages/terminal-emulator" find-dev if drop
+ " /packages/terminal-emulator" " input-device" $setenv
+ " /packages/terminal-emulator" " output-device" $setenv
+ then
+;
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+
+\ -------------------------------------------------------------------------
+\ pre-booting
+\ -------------------------------------------------------------------------
+
+: update-chosen
+ " /chosen" find-device
+ stdin @ encode-int " stdin" property
+ stdout @ encode-int " stdout" property
+ " /pci/isa/interrupt-controller" find-dev if encode-int " interrupt-controller" property then
+ device-end
+;
diff --git a/roms/openbios/arch/ppc/briq/briq.h b/roms/openbios/arch/ppc/briq/briq.h
new file mode 100644
index 00000000..33a2cafa
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/briq.h
@@ -0,0 +1,24 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <briq.h>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_BRIQ
+#define _H_BRIQ
+
+/* vfd.c */
+extern int vfd_draw_str( const char *str );
+extern void vfd_close( void );
+
+#include "kernel.h"
+
+#endif /* _H_BRIQ */
diff --git a/roms/openbios/arch/ppc/briq/init.c b/roms/openbios/arch/ppc/briq/init.c
new file mode 100644
index 00000000..b32e97aa
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/init.c
@@ -0,0 +1,130 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <init.c>
+ *
+ * Initialization for briq
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * based on mol/init.c:
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
+ * (samuel@ibrium.se, dary@lindesign.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "briq/briq.h"
+#include "libopenbios/ofmem.h"
+#include "openbios-version.h"
+
+extern void unexpected_excep( int vector );
+extern void setup_timers( void );
+
+#if 0
+int
+get_bool_res( const char *res )
+{
+ char buf[8], *p;
+
+ p = BootHGetStrRes( res, buf, sizeof(buf) );
+ if( !p )
+ return -1;
+ if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") )
+ return 1;
+ return 0;
+}
+#endif
+
+void
+unexpected_excep( int vector )
+{
+ printk("briQ panic: Unexpected exception %x\n", vector );
+ for( ;; )
+ ;
+}
+
+unsigned long isa_io_base;
+
+void
+entry( void )
+{
+ isa_io_base = 0x80000000;
+
+ printk("\n");
+ printk("=============================================================\n");
+ printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
+ OPENBIOS_BUILD_DATE);
+
+ ofmem_init();
+ initialize_forth();
+ /* won't return */
+
+ printk("of_startup returned!\n");
+ for( ;; )
+ ;
+}
+
+static void
+setenv( char *env, char *value )
+{
+ push_str( value );
+ push_str( env );
+ fword("$setenv");
+}
+
+void
+arch_of_init( void )
+{
+#if CONFIG_RTAS
+ phandle_t ph;
+#endif
+ int autoboot;
+
+ devtree_init();
+ node_methods_init();
+ modules_init();
+ setup_timers();
+#ifdef CONFIG_DRIVER_PCI
+ ob_pci_init();
+#endif
+
+#if CONFIG_RTAS
+ if( !(ph=find_dev("/rtas")) )
+ printk("Warning: No /rtas node\n");
+ else {
+ unsigned long size = 0x1000;
+ while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start )
+ size *= 2;
+ set_property( ph, "rtas-size", (char*)&size, sizeof(size) );
+ }
+#endif
+
+#if 0
+ /* tweak boot settings */
+ autoboot = !!get_bool_res("autoboot");
+#endif
+ autoboot = 0;
+ if( !autoboot )
+ printk("Autobooting disabled - dropping into OpenFirmware\n");
+ setenv("auto-boot?", autoboot ? "true" : "false" );
+ setenv("boot-command", "briqboot");
+
+#if 0
+ if( get_bool_res("tty-interface") == 1 )
+#endif
+ fword("activate-tty-interface");
+
+ /* hack */
+ device_end();
+ bind_func("briqboot", boot );
+}
diff --git a/roms/openbios/arch/ppc/briq/kernel.c b/roms/openbios/arch/ppc/briq/kernel.c
new file mode 100644
index 00000000..e85134d4
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/kernel.c
@@ -0,0 +1,16 @@
+/*
+ * Creation Date: <2004/08/28 18:03:25 stepan>
+ * Time-stamp: <2004/08/28 18:03:25 stepan>
+ *
+ * <briq/kernel.c>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "briq-dict.h"
+#include "../kernel.c"
diff --git a/roms/openbios/arch/ppc/briq/main.c b/roms/openbios/arch/ppc/briq/main.c
new file mode 100644
index 00000000..fbb2a26d
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/main.c
@@ -0,0 +1,145 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <main.c>
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elfload.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "briq/briq.h"
+#include "libopenbios/ofmem.h"
+
+static void
+transfer_control_to_elf( unsigned long entry )
+{
+ extern void call_elf( unsigned long entry );
+ printk("Starting ELF image at 0x%08lX\n", entry);
+ call_elf( 0x400000 );
+ //call_elf( entry );
+
+ fatal_error("call_elf returned unexpectedly\n");
+}
+
+static int
+load_elf_rom( unsigned long *entry, int fd )
+{
+ int i, lszz_offs, elf_offs;
+ char buf[128], *addr;
+ Elf_ehdr ehdr;
+ Elf_phdr *phdr;
+ size_t s;
+
+ printk("Loading '%s'\n", get_file_path(fd));
+
+ /* the ELF-image (usually) starts at offset 0x4000 */
+ if( (elf_offs=find_elf(fd)) < 0 ) {
+ printk("----> %s is not an ELF image\n", buf );
+ exit(1);
+ }
+ if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
+ fatal_error("elf_readhdrs failed\n");
+
+ *entry = ehdr.e_entry;
+
+ /* load segments. Compressed ROM-image assumed to be located immediately
+ * after the last segment */
+ lszz_offs = elf_offs;
+ for( i=0; i<ehdr.e_phnum; i++ ) {
+ /* p_memsz, p_flags */
+ s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
+ seek_io( fd, elf_offs + phdr[i].p_offset );
+
+ /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
+ phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
+ phdr[i].p_vaddr ); */
+
+ if( phdr[i].p_vaddr != phdr[i].p_paddr )
+ printk("WARNING: ELF segment virtual addr != physical addr\n");
+ lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
+ if( !s )
+ continue;
+ if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
+ fatal_error("Claim failed!\n");
+
+ addr = (char*)phdr[i].p_vaddr;
+ if( read_io(fd, addr, s) != s )
+ fatal_error("read failed\n");
+
+#if 0
+ /* patch CODE segment */
+ if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) {
+ patch_newworld_rom( (char*)phdr[i].p_vaddr, s );
+ newworld_timer_hack( (char*)phdr[i].p_vaddr, s );
+ }
+#endif
+ flush_icache_range( addr, addr+s );
+
+ /*printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
+ (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
+ }
+ free( phdr );
+ return lszz_offs;
+}
+
+
+static void
+encode_bootpath( const char *spec, const char *args )
+{
+ phandle_t chosen_ph = find_dev("/chosen");
+ set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 );
+ set_property( chosen_ph, "bootargs", args, strlen(args)+1 );
+}
+
+/************************************************************************/
+/* briq booting */
+/************************************************************************/
+
+static void
+briq_startup( void )
+{
+ const char *paths[] = { "hd:0,\\zImage.chrp", NULL };
+ const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL };
+ unsigned long entry;
+ int i, fd;
+
+ for( i=0; paths[i]; i++ ) {
+ if( (fd=open_io(paths[i])) == -1 )
+ continue;
+ (void) load_elf_rom( &entry, fd );
+ close_io( fd );
+ encode_bootpath( paths[i], args[i] );
+
+ update_nvram();
+ transfer_control_to_elf( entry );
+ /* won't come here */
+ }
+ printk("*** Boot failure! No secondary bootloader specified ***\n");
+}
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+void
+boot( void )
+{
+ fword("update-chosen");
+ briq_startup();
+}
diff --git a/roms/openbios/arch/ppc/briq/methods.c b/roms/openbios/arch/ppc/briq/methods.c
new file mode 100644
index 00000000..649e9baf
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/methods.c
@@ -0,0 +1,333 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "briq/briq.h"
+#include "libopenbios/ofmem.h"
+
+/************************************************************************/
+/* RTAS (run-time abstraction services) */
+/************************************************************************/
+
+#ifdef CONFIG_RTAS
+DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
+
+/* ( physbase -- rtas_callback ) */
+static void
+rtas_instantiate( void )
+{
+ int physbase = POP();
+ int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
+ unsigned long virt;
+
+ while( s < size )
+ s += 0x1000;
+ virt = ofmem_claim_virt( 0, s, 0x1000 );
+ ofmem_map( physbase, virt, s, -1 );
+ memcpy( (char*)virt, of_rtas_start, size );
+
+ printk("RTAS instantiated at %08x\n", physbase );
+ flush_icache_range( (char*)virt, (char*)virt + size );
+
+ PUSH( physbase );
+}
+
+NODE_METHODS( rtas ) = {
+ { "instantiate", rtas_instantiate },
+ { "instantiate-rtas", rtas_instantiate },
+};
+#endif
+
+
+/************************************************************************/
+/* stdout */
+/************************************************************************/
+
+DECLARE_NODE( vfd_stdout, INSTALL_OPEN, 0, "Tdisplay" );
+
+/* ( addr len -- actual ) */
+static void
+stdout_write( void )
+{
+ int len = POP();
+ char *addr = (char*)POP();
+ char *s = malloc( len + 1 );
+
+ strncpy_nopad( s, addr, len );
+ s[len]=0;
+
+ printk( "%s", s );
+ //vfd_draw_str( s );
+ free( s );
+
+ PUSH( len );
+}
+
+NODE_METHODS( vfd_stdout ) = {
+ { "write", stdout_write },
+};
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)POP();
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = getchar();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)POP();
+ for( i=0; i<len; i++ )
+ putchar( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+/************************************************************************/
+/* client interface 'quiesce' */
+/************************************************************************/
+
+DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
+
+/* ( -- ) */
+static void
+ciface_quiesce( unsigned long args[], unsigned long ret[] )
+{
+#if 0
+ unsigned long msr;
+ /* This seems to be the correct thing to do - but I'm not sure */
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr &= ~(MSR_IR | MSR_DR);
+ asm volatile("mtmsr %0" :: "r" (msr) );
+#endif
+ printk("=============================================================\n\n");
+}
+
+/* ( -- ms ) */
+static void
+ciface_milliseconds( unsigned long args[], unsigned long ret[] )
+{
+ extern unsigned long get_timer_freq();
+ static unsigned long mticks=0, usecs=0;
+ unsigned long t;
+
+ asm volatile("mftb %0" : "=r" (t) : );
+ if( mticks )
+ usecs += get_timer_freq() / 1000000 * ( t-mticks );
+ mticks = t;
+
+ PUSH( usecs/1000 );
+}
+
+
+NODE_METHODS( ciface ) = {
+ { "quiesce", ciface_quiesce },
+ { "milliseconds", ciface_milliseconds },
+};
+
+
+/************************************************************************/
+/* MMU/memory methods */
+/************************************************************************/
+
+DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
+DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" );
+DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
+
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ int align = POP();
+ int size = POP();
+ int phys = POP();
+ int ret = ofmem_claim_phys( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MEM: claim failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys size align --- base ) */
+static void
+mmu_claim( void )
+{
+ int align = POP();
+ int size = POP();
+ int phys = POP();
+ int ret = ofmem_claim_virt( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MMU: CLAIM failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mmu_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys virt size mode -- [ret???] ) */
+static void
+mmu_map( void )
+{
+ int mode = POP();
+ int size = POP();
+ int virt = POP();
+ int phys = POP();
+ int ret;
+
+ /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
+ ret = ofmem_map( phys, virt, size, mode );
+
+ if( ret ) {
+ printk("MMU: map failure\n");
+ throw( -13 );
+ return;
+ }
+}
+
+/* ( virt size -- ) */
+static void
+mmu_unmap( void )
+{
+ POP(); POP();
+}
+
+/* ( virt -- false | phys mode true ) */
+static void
+mmu_translate( void )
+{
+ ucell mode;
+ ucell virt = POP();
+ ucell phys = ofmem_translate( virt, &mode );
+
+ if( phys == -1 ) {
+ PUSH( 0 );
+ } else {
+ PUSH( phys );
+ PUSH( mode );
+ PUSH( -1 );
+ }
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ int align = POP();
+ int size = POP();
+ int virt = POP();
+ int ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ POP();
+ POP();
+}
+
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+};
+
+NODE_METHODS( mmu ) = {
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "translate", mmu_translate },
+};
+
+NODE_METHODS( mmu_ciface ) = {
+ { "cif-claim", ciface_claim },
+ { "cif-release", ciface_release },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( void )
+{
+#ifdef CONFIG_RTAS
+ REGISTER_NODE( rtas );
+#endif
+ REGISTER_NODE( vfd_stdout );
+ REGISTER_NODE( ciface );
+ REGISTER_NODE( memory );
+ REGISTER_NODE( mmu );
+ REGISTER_NODE( mmu_ciface );
+ REGISTER_NODE( tty );
+}
diff --git a/roms/openbios/arch/ppc/briq/tree.c b/roms/openbios/arch/ppc/briq/tree.c
new file mode 100644
index 00000000..17718388
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/tree.c
@@ -0,0 +1,23 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <tree.c>
+ *
+ * device tree setup
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+
+void devtree_init( void )
+{
+ fword("init-briq-tree");
+}
diff --git a/roms/openbios/arch/ppc/briq/tree.fs b/roms/openbios/arch/ppc/briq/tree.fs
new file mode 100644
index 00000000..ae503266
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/tree.fs
@@ -0,0 +1,305 @@
+\ briq specific initialization code
+\
+\ Copyright (C) 2004 Greg Watson
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
+" /" find-device
+
+" chrp" device-type
+" TotalImpact,BRIQ-1" model
+h# 80000000 encode-int " isa-io-base" property
+1 encode-int " #interrupt-cells" property
+1 encode-int " #size-cells" property
+
+new-device
+ " memory" device-name
+ " memory" device-type
+ 0 encode-int h# 1E00000 encode-int encode+
+ h# 2000000 encode-int encode+ h# 40000000 encode-int encode+
+ " available" property
+ 0 h# 40000000 reg
+ external
+ : open true ;
+ : close ;
+finish-device
+
+new-device
+ " cpu" device-name
+ " cpu" device-type
+ " " encode-string " translations" property
+ 0 encode-phys h# 8000000 encode-int encode+ " available" property
+ d# 32 encode-int " d-cache-block-size" property
+ 8 encode-int " d-cache-sets" property
+ d# 32768 encode-int " d-cache-size" property
+ d# 32 encode-int " i-cache-block-size" property
+ 8 encode-int " i-cache-sets" property
+ d# 32768 encode-int " i-cache-size" property
+ " " encode-string " cache-unified" property
+ 2 encode-int " i-tlb-sets" property
+ d# 128 encode-int " i-tlb-size" property
+ 2 encode-int " d-tlb-sets" property
+ d# 128 encode-int " d-tlb-size" property
+ " " encode-string " tlb-split" property
+ 2 encode-int " tlb-sets" property
+ d# 256 encode-int " tlb-size" property
+ " " encode-string " performance-monitor" property
+ " " encode-string " graphics" property
+ 4 encode-int " reservation-granule-size" property
+ d# 25000000 encode-int " timebase-frequency" property
+ d# 300000000 encode-int " clock-frequency" property
+ d# 66000000 encode-int " bus-frequency" property
+ h# 88201 encode-int " cpu-version" property
+ 0 encode-int " reg" property
+finish-device
+
+" /pci" find-device
+ h# 01000000 encode-int 0 encode-int encode+ 0 encode-int encode+
+ h# 80000000 encode-int encode+ 0 encode-int encode+
+ h# 01000000 encode-int encode+
+ h# 02000000 encode-int encode+ 0 encode-int encode+ 0 encode-int encode+
+ h# C0000000 encode-int encode+ 0 encode-int encode+
+ h# 08000000 encode-int encode+
+ " ranges" property
+ " IBM,CPC710" model
+ h# FF5F7700 encode-int " 8259-interrupt-acknowledge" property
+ h# 0000F800 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 7 encode-int encode+
+ " interrupt-map-mask" property
+ 1 encode-int " #interrupt-cells" property
+ h# 80000000 encode-int " system-dma-base" property
+ d# 33333333 encode-int " clock-frequency" property
+ " " encode-string " primary-bridge" property
+ 0 encode-int " pci-bridge-number" property
+ h# FF500000 encode-int h# 100000 encode-int encode+ " reg" property
+ 0 encode-int 0 encode-int encode+ " bus-range" property
+
+new-device
+ " isa" device-name
+ " isa" device-type
+ 2 encode-int " #address-cells" property
+ 1 encode-int " #size-cells" property
+
+ external
+ : open true ;
+ : close ;
+
+finish-device
+
+: ?devalias ( alias-str alias-len device-str device-len --
+ \ alias-str alias-len false | true )
+ active-package >r
+ " /aliases" find-device
+ \ 2dup ." Checking " type
+ 2dup find-dev if \ check if device exists
+ drop
+ 2over find-dev if \ do we already have an alias?
+ \ ." alias exists" cr
+ drop 2drop false
+ else
+ \ ." device exists" cr
+ encode-string
+ 2swap property
+ true
+ then
+ else
+ \ ." device doesn't exist" cr
+ 2drop false
+ then
+ r> active-package!
+ ;
+
+:noname
+ " hd"
+ " /pci/pci-ata/ata-1/disk@0" ?devalias not if
+ " /pci/pci-ata/ata-1/disk@1" ?devalias not if
+ " /pci/pci-ata/ata-2/disk@0" ?devalias not if
+ " /pci/pci-ata/ata-2/disk@1" ?devalias not if
+ 2drop ." No disk found." cr
+ then
+ then
+ then
+ then
+
+ " cdrom"
+ " /pci/pci-ata/ata-1/cdrom@0" ?devalias not if
+ " /pci/pci-ata/ata-1/cdrom@1" ?devalias not if
+ " /pci/pci-ata/ata-2/cdrom@0" ?devalias not if
+ " /pci/pci-ata/ata-2/cdrom@1" ?devalias not if
+ 2drop ." No cdrom found" cr
+ then
+ then
+ then
+ then
+; SYSTEM-initializer
+
+new-device
+ " ide" device-name
+ " ide" device-type
+ " WINBOND,82C553" model
+ h# 28 encode-int " max-latency" property
+ h# 2 encode-int " min-grant" property
+ h# 1 encode-int " devsel-speed" property
+ h# 0 encode-int " subsystem-vendor-id" property
+ h# 0 encode-int " subsystem-id" property
+ h# 1018A encode-int " class-code" property
+ h# 5 encode-int " revision-id" property
+ h# 105 encode-int " device-id" property
+ h# 10AD encode-int " vendor-id" property
+ h# 1003110 encode-int 0 encode-int encode+ h# 10020 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003114 encode-int 0 encode-int encode+ h# 10030 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003118 encode-int 0 encode-int encode+ h# 10040 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 100311C encode-int 0 encode-int encode+ h# 10034 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003120 encode-int 0 encode-int encode+ h# 10050 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003124 encode-int 0 encode-int encode+ h# 10060 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ " assigned-addresses" property
+ h# 3100 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+
+ h# 1003110 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003114 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003118 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 100311C encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003120 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003124 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ " reg" property
+finish-device
+
+new-device
+ " ethernet" device-name
+ " network" device-type
+ " AMD,79C973" model
+ h# 3800 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+
+ " reg" property
+finish-device
+
+" /pci/isa" find-device
+ 0 0 " assigned-addresses" property
+ 0 0 " ranges" property
+ 0 encode-int " slot-names" property
+ d# 8333333 encode-int " clock-frequency" property
+ 0 encode-int " eisa-slots" property
+ 2 encode-int " #interrupt-cells" property
+ " W83C553F" encode-string " compatible" property
+ " WINBOND,82C553" model
+ 0 encode-int " max-latency" property
+ 0 encode-int " min-grant" property
+ 1 encode-int " devsel-speed" property
+ 0 encode-int " subsystem-vendor-id" property
+ 0 encode-int " subsystem-id" property
+ h# 60100 encode-int " class-code" property
+ h# 10 encode-int " revision-id" property
+ h# 565 encode-int " device-id" property
+ h# 10AD encode-int " vendor-id" property
+ h# 3000 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+ " reg" property
+
+new-device
+ " rtc" device-name
+ " rtc" device-type
+ " DS17285S" model
+ " MC146818" encode-string
+ " DS17285S" encode-string encode+
+ " pnpPNP,b00" encode-string encode+ " compatible" property
+ 8 encode-int 0 encode-int encode+ " interrupts" property
+ h# 70 encode-int 1 encode-int encode+
+ 2 encode-int encode+ " reg" property
+finish-device
+
+new-device
+ " interrupt-controller" device-name
+ " interrupt-controller" device-type
+ " 8259" model
+ " " encode-string " interrupt-controller" property
+ 2 encode-int " #interrupt-cells" property
+ 1 encode-int
+ 2 encode-int encode+
+ 3 encode-int encode+
+ 6 encode-int encode+
+ " reserved-interrupts" property
+ " 8259" encode-string
+ " chrp,iic" encode-string encode+
+ " compatible" property
+ h# 20 encode-int 1 encode-int encode+
+ 2 encode-int encode+ " reg" property
+finish-device
+
+new-device
+ " serial" device-name
+ " serial" device-type
+ " no" encode-string " ctsrts" property
+ " no" encode-string " xon" property
+ " no" encode-string " parity" property
+ d# 115200 encode-int " bps" property
+ 1 encode-int " stop-bits" property
+ 8 encode-int " data-bits" property
+ h# 70800 encode-int " divisor" property
+ h# 708000 encode-int " clock-frequency" property
+ 4 encode-int 0 encode-int encode+ " interrupts" property
+ h# 3F8 encode-int 1 encode-int encode+
+ 8 encode-int encode+ " reg" property
+finish-device
+
+" /pci" find-device
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int " interrupt-parent" property
+ then
+ h# 3800 encode-int 0 encode-int encode+
+ 0 encode-int encode+ 1 encode-int encode+
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int encode+
+ then
+ h# 0C encode-int encode+ 1 encode-int encode+
+ " interrupt-map" property
+
+" /pci/isa" find-device
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int " interrupt-parent" property
+ then
+
+\ -------------------------------------------------------------
+\ /packages
+\ -------------------------------------------------------------
+
+" /packages" find-device
+
+ " packages" device-name
+ external
+ \ allow packages to be opened with open-dev
+ : open true ;
+ : close ;
+
+\ /packages/terminal-emulator
+new-device
+ " terminal-emulator" device-name
+ external
+ : open true ;
+ : close ;
+ \ : write ( addr len -- actual )
+ \ dup -rot type
+ \ ;
+finish-device
+
+\ -------------------------------------------------------------
+\ The END
+\ -------------------------------------------------------------
+device-end
diff --git a/roms/openbios/arch/ppc/briq/vfd.c b/roms/openbios/arch/ppc/briq/vfd.c
new file mode 100644
index 00000000..ffc87a07
--- /dev/null
+++ b/roms/openbios/arch/ppc/briq/vfd.c
@@ -0,0 +1,42 @@
+/*
+ * Creation Date: <2004/08/28 17:29:43 greg>
+ * Time-stamp: <2004/08/28 17:29:43 greg>
+ *
+ * <vfd.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "briq/briq.h"
+
+static int vfd_is_open;
+
+static int
+vfd_init( void )
+{
+ vfd_is_open = 1;
+ return 0;
+}
+
+void
+vfd_close( void )
+{
+}
+
+int
+vfd_draw_str( const char *str )
+{
+ if (!vfd_is_open)
+ vfd_init();
+
+ return 0;
+}
diff --git a/roms/openbios/arch/ppc/build.xml b/roms/openbios/arch/ppc/build.xml
new file mode 100644
index 00000000..29f6601f
--- /dev/null
+++ b/roms/openbios/arch/ppc/build.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0"?>
+<build condition="PPC">
+
+ <dictionary name="openbios-briq" init="openbios" target="forth" condition="BRIQ">
+ <object source="ppc.fs"/>
+ <object source="briq/tree.fs"/>
+ <object source="briq/briq.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <dictionary name="openbios-pearpc" init="openbios" target="forth" condition="PEARPC">
+ <object source="ppc.fs"/>
+ <object source="pearpc/tree.fs"/>
+ <object source="pearpc/pearpc.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <dictionary name="openbios-qemu" init="openbios" target="forth" condition="QEMU">
+ <object source="ppc.fs"/>
+ <object source="qemu/tree.fs"/>
+ <object source="qemu/qemu.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <dictionary name="openbios-mol" init="openbios" target="forth" condition="MOL">
+ <object source="ppc.fs"/>
+ <object source="mol/tree.fs"/>
+ <object source="mol/mol.fs"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <!-- HACK ALERT -->
+
+ <executable name="target/include/briq-dict.h" target="target" condition="BRIQ">
+ <rule><![CDATA[
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@]]></rule>
+ <external-object source="openbios-briq.dict"/>
+ </executable>
+
+ <executable name="target/arch/ppc/briq/kernel.o" target="target" condition="BRIQ">
+ <rule><![CDATA[ $(SRCDIR)/arch/ppc/briq/kernel.c $(ODIR)/target/include/static-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/briq/kernel.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+
+ <executable name="target/include/pearpc-dict.h" target="target" condition="PEARPC">
+ <rule><![CDATA[
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@]]></rule>
+ <external-object source="openbios-pearpc.dict"/>
+ </executable>
+
+ <executable name="target/arch/ppc/pearpc/kernel.o" target="target" condition="PEARPC">
+ <rule><![CDATA[ $(SRCDIR)/arch/ppc/pearpc/kernel.c $(ODIR)/target/include/pearpc-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/pearpc/kernel.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+ <executable name="target/include/qemu-dict.h" target="target" condition="QEMU">
+ <rule><![CDATA[
+ $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule>
+ <external-object source="openbios-qemu.dict"/>
+ </executable>
+
+ <executable name="target/arch/ppc/qemu/kernel.o" target="target" condition="QEMU">
+ <rule><![CDATA[ $(SRCDIR)/arch/ppc/qemu/kernel.c $(ODIR)/target/include/qemu-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/qemu/kernel.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+
+ <executable name="target/include/mol-dict.h" target="target" condition="MOL">
+ <rule><![CDATA[
+ $(call quiet-command,true, " GEN $(TARGET_DIR)$@")
+ @echo "static const char forth_dictionary[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@]]></rule>
+ <external-object source="openbios-mol.dict"/>
+ </executable>
+
+ <executable name="target/arch/ppc/mol/kernel.o" target="target" condition="MOL">
+ <rule><![CDATA[
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/mol/kernel.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+ <!-- END OF HACK ALERT -->
+
+ <library name="briq" target="target" type="static" condition="BRIQ">
+ <object source="misc.S"/>
+ <object source="ofmem.c"/>
+ <object source="briq/briq.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="briq/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <external-object source="target/arch/ppc/briq/kernel.o"/>
+ <object source="briq/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="briq/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="briq/tree.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="briq/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ </library>
+
+ <library name="pearpc" target="target" type="static" condition="PEARPC">
+ <object source="misc.S"/>
+ <object source="ofmem.c"/>
+ <object source="pearpc/pearpc.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="pearpc/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <external-object source="target/arch/ppc/pearpc/kernel.o"/>
+ <object source="pearpc/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="pearpc/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="pearpc/tree.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="pearpc/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <!-- taken from mol: generalize -->
+ <object source="pearpc/console.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ </library>
+
+ <library name="qemu" target="target" type="static" condition="QEMU">
+ <object source="qemu/ofmem.c"/>
+ <object source="qemu/qemu.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="qemu/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <external-object source="target/arch/ppc/qemu/kernel.o"/>
+ <object source="qemu/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="qemu/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="qemu/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="qemu/console.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ </library>
+
+ <library name="mol" target="target" type="static" condition="MOL">
+ <object source="misc.S"/>
+ <object source="ofmem.c"/>
+ <object source="mol/init.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/main.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/mol.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/console.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/osi-blk.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/osi-scsi.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/pseudodisk.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/methods.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/prom.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <object source="mol/tree.c" flags="-I$(SRCDIR)/arch/ppc"/>
+ <external-object source="target/arch/ppc/mol/kernel.o"/>
+ </library>
+
+ <executable name="openbios-briq.elf" target="target" condition="BRIQ">
+ <rule>
+ $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-briq.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="start.S"/>
+ <object source="timebase.S"/>
+ <external-object source="libbriq.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ </executable>
+
+ <executable name="openbios-pearpc.elf" target="target" condition="PEARPC">
+ <rule>
+ $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-pearpc.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="start.S"/>
+ <object source="timebase.S"/>
+ <external-object source="libpearpc.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ </executable>
+
+ <executable name="openbios-qemu.elf" target="target" condition="QEMU">
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/$(ARCH)/qemu/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-qemu.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="qemu/start.S"/>
+ <object source="timebase.S"/>
+ <external-object source="libqemu.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+ <executable name="openbios-mol.elf" target="target" condition="MOL">
+ <rule>
+ $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-mol.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="start.S"/>
+ <external-object source="libmol.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ </executable>
+
+</build>
diff --git a/roms/openbios/arch/ppc/defconfig b/roms/openbios/arch/ppc/defconfig
new file mode 100644
index 00000000..adfb181e
--- /dev/null
+++ b/roms/openbios/arch/ppc/defconfig
@@ -0,0 +1,48 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_PPC=y
+CONFIG_MOL=y
+# CONFIG_MPC107 is not set
+# CONFIG_NO_ARCH is not set
+
+#
+# Build hosted UNIX Binary
+#
+CONFIG_HOST_UNIX=y
+# CONFIG_PLUGIN_PCI is not set
+
+#
+# Kernel Debugging
+#
+CONFIG_DEBUG=y
+CONFIG_DEBUG_BOOT=y
+# CONFIG_DEBUG_DSTACK is not set
+# CONFIG_DEBUG_RSTACK is not set
+# CONFIG_DEBUG_DICTIONARY is not set
+# CONFIG_DEBUG_INTERNAL is not set
+# CONFIG_DEBUG_INTERPRETER is not set
+CONFIG_DEBUG_CONSOLE=y
+CONFIG_DEBUG_CONSOLE_SERIAL=y
+CONFIG_SERIAL_PORT=1
+CONFIG_SERIAL_SPEED=115200
+CONFIG_DEBUG_CONSOLE_VGA=y
+
+#
+# Packages
+#
+# CONFIG_PKG_DEBLOCKER is not set
+# CONFIG_PKG_DISKLABEL is not set
+# CONFIG_PKG_OBP_TFTP is not set
+# CONFIG_PKG_TERMINAL_EMULATOR is not set
+
+#
+# Module Configuration
+#
+CONFIG_DEBLOCKER=y
+CONFIG_DISK_LABEL=y
+CONFIG_PART_SUPPORT=y
+CONFIG_MAC_PARTS=y
+CONFIG_FS=y
+CONFIG_HFS=y
+CONFIG_HFSP=y
diff --git a/roms/openbios/arch/ppc/kernel.c b/roms/openbios/arch/ppc/kernel.c
new file mode 100644
index 00000000..28f2965b
--- /dev/null
+++ b/roms/openbios/arch/ppc/kernel.c
@@ -0,0 +1,99 @@
+/*
+ * Creation Date: <2003/10/25 14:07:17 samuel>
+ * Time-stamp: <2004/08/28 17:48:19 stepan>
+ *
+ * <kernel.c>
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * Based upon unix.c (from OpenBIOS):
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "dict.h"
+#include "libopenbios/bindings.h"
+#include "kernel/stack.h"
+#include "kernel/kernel.h"
+#include "libc/string.h"
+#include "kernel.h"
+
+#define MEMORY_SIZE (256*1024) /* 256K ram for hosted system */
+#define DICTIONARY_SIZE (512*1024) /* 512K for the dictionary */
+
+static ucell *memory;
+
+/************************************************************************/
+/* F U N C T I O N S */
+/************************************************************************/
+
+int
+forth_segv_handler( char *segv_addr )
+{
+ ucell addr = 0xdeadbeef;
+
+ if( PC >= (ucell) dict && PC <= (ucell) dict + dicthead )
+ addr = *(ucell *) PC;
+
+ printk("panic: segmentation violation at %x\n", (int)segv_addr);
+ printk("dict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n",
+ (int)dict, (int)(dict + dicthead), dicthead,
+ PC, PC - (ucell) dict);
+ printk("dstackcnt=%d rstackcnt=%d instruction=%x\n",
+ dstackcnt, rstackcnt, addr);
+
+#ifdef DEBUG_DSTACK
+ printdstack();
+#endif
+#ifdef DEBUG_RSTACK
+ printrstack();
+#endif
+ return -1;
+}
+
+/*
+ * allocate memory and prepare engine for memory management.
+ */
+
+static void
+init_memory( void )
+{
+ memory = malloc(MEMORY_SIZE);
+ if( !memory )
+ panic("panic: not enough memory on host system.\n");
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator
+ */
+
+ PUSH( (ucell)memory );
+ PUSH( (ucell)memory + MEMORY_SIZE );
+}
+
+int
+initialize_forth( void )
+{
+ dict = malloc(DICTIONARY_SIZE);
+ load_dictionary( forth_dictionary, sizeof(forth_dictionary) );
+ forth_init();
+
+ PUSH_xt( bind_noname_func(arch_of_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+ if( PC ) {
+ init_memory();
+ enterforth((xt_t)PC);
+ free( memory );
+ }
+ free( dict );
+ return 0;
+}
diff --git a/roms/openbios/arch/ppc/kernel.h b/roms/openbios/arch/ppc/kernel.h
new file mode 100644
index 00000000..20cda489
--- /dev/null
+++ b/roms/openbios/arch/ppc/kernel.h
@@ -0,0 +1,41 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <kernel.h>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef __KERNEL_H__
+#define __KERNEL_H__
+
+/* misc.c */
+extern void fatal_error( const char *str );
+extern void exit( int status );
+
+/* start.S */
+extern void flush_icache_range( char *start, char *stop );
+extern char of_rtas_start[], of_rtas_end[];
+
+/* methods.c */
+extern void node_methods_init( void );
+
+/* main.c */
+extern void boot( void );
+
+/* init.c */
+extern void entry( void );
+extern void arch_of_init( void );
+extern int get_bool_res( const char *str );
+
+/* tree.c */
+extern void devtree_init( void );
+
+
+#endif /* __KERNEL_H__ */
diff --git a/roms/openbios/arch/ppc/misc.S b/roms/openbios/arch/ppc/misc.S
new file mode 100644
index 00000000..435ce0ec
--- /dev/null
+++ b/roms/openbios/arch/ppc/misc.S
@@ -0,0 +1,74 @@
+/*
+ * Creation Date: <2002/10/20 15:54:50 samuel>
+ * Time-stamp: <2002/10/20 15:57:21 samuel>
+ *
+ * <misc.S>
+ *
+ * Low-level stuff
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * Based upon misc.S from the the linux kernel with the following
+ * copyrights:
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org),
+ * Cort Dougan (cort@cs.nmt.edu), Paul Mackerras
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5 has shift count
+ * result in R3/R4
+ *
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
+ */
+GLOBL(__ashrdi3):
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
+ sraw r7,r3,r7 # t2 = MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
+ sraw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
+
+GLOBL(__ashldi3):
+ subfic r6,r5,32
+ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ addi r7,r5,32 # could be xori, or addi with -32
+ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r3,r3,r6 # MSW |= t1
+ slw r4,r4,r5 # LSW = LSW << count
+ or r3,r3,r7 # MSW |= t2
+ blr
+
+GLOBL(__lshrdi3):
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ srw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
diff --git a/roms/openbios/arch/ppc/mmutypes.h b/roms/openbios/arch/ppc/mmutypes.h
new file mode 100644
index 00000000..441d7f8b
--- /dev/null
+++ b/roms/openbios/arch/ppc/mmutypes.h
@@ -0,0 +1,76 @@
+/*
+ * Creation Date: <2002/01/13 13:53:14 samuel>
+ * Time-stamp: <2002/01/27 19:56:11 samuel>
+ *
+ * <mmutypes.h>
+ *
+ * MMU definitions
+ *
+ * Most of these declarations originate from the Linux Kernel
+ *
+ * Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_MMUTYPES
+#define _H_MMUTYPES
+
+/* Hardware Page Table Entry */
+typedef struct mPTE {
+ unsigned long v:1; /* Entry is valid */
+ unsigned long vsid:24; /* Virtual segment identifier */
+ unsigned long h:1; /* Hash algorithm indicator */
+ unsigned long api:6; /* Abbreviated page index */
+
+ unsigned long rpn:20; /* Real (physical) page number */
+ unsigned long :3; /* Unused */
+ unsigned long r:1; /* Referenced */
+ unsigned long c:1; /* Changed */
+ unsigned long w:1; /* Write-thru cache mode */
+ unsigned long i:1; /* Cache inhibited */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page protection */
+} mPTE_t;
+
+
+typedef struct _mBATU { /* Upper part of BAT (all except 601) */
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+ unsigned long :4; /* Unused */
+ unsigned long bl:11; /* Block size mask */
+ unsigned long vs:1; /* Supervisor valid */
+ unsigned long vp:1; /* User valid */
+} mBATU;
+
+typedef struct _mBATL { /* Lower part of BAT (all except 601) */
+ unsigned long brpn:15; /* Real page index (physical address) */
+ unsigned long :10; /* Unused */
+ unsigned long w:1; /* Write-thru cache */
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded (MBZ in IBAT) */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page access protections */
+} mBATL;
+
+typedef struct _mBAT {
+ mBATU batu; /* Upper register */
+ mBATL batl; /* Lower register */
+} mBAT;
+
+typedef struct _mSEGREG {
+ unsigned long t:1; /* Normal or I/O type */
+ unsigned long ks:1; /* Supervisor 'key' (normally 0) */
+ unsigned long kp:1; /* User 'key' (normally 1) */
+ unsigned long n:1; /* No-execute */
+ unsigned long :4; /* Unused */
+ unsigned long vsid:24; /* Virtual Segment Identifier */
+} mSEGREG;
+
+
+#endif /* _H_MMUTYPES */
diff --git a/roms/openbios/arch/ppc/mol/console.c b/roms/openbios/arch/ppc/mol/console.c
new file mode 100644
index 00000000..966011e1
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/console.c
@@ -0,0 +1,30 @@
+/*
+ * Creation Date: <2002/10/29 18:59:05 samuel>
+ * Time-stamp: <2003/12/28 22:51:11 samuel>
+ *
+ * <console.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+#include "osi_calls.h"
+#include "libopenbios/ofmem.h"
+#include "mol/mol.h"
+#include "boothelper_sh.h"
+#include "video_sh.h"
+
+#define openbios_GetFBInfo(x) OSI_GetFBInfo(x)
+
+#include "../../../packages/video.c"
+#include "../../../libopenbios/console_common.c"
diff --git a/roms/openbios/arch/ppc/mol/init.c b/roms/openbios/arch/ppc/mol/init.c
new file mode 100644
index 00000000..15333b4e
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/init.c
@@ -0,0 +1,119 @@
+/*
+ * Creation Date: <1999/11/16 00:49:26 samuel>
+ * Time-stamp: <2004/04/12 16:26:50 samuel>
+ *
+ * <init.c>
+ *
+ * Initialization
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
+ # (samuel@ibrium.se, dary@lindesign.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "mol/mol.h"
+#include "libopenbios/ofmem.h"
+#include "mol/prom.h"
+#include "openbios-version.h"
+#include "osi_calls.h"
+#include "boothelper_sh.h"
+
+extern void unexpected_excep( int vector );
+
+int
+get_bool_res( const char *res )
+{
+ char buf[8], *p;
+
+ p = BootHGetStrRes( res, buf, sizeof(buf) );
+ if( !p )
+ return -1;
+ if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") )
+ return 1;
+ return 0;
+}
+
+void
+unexpected_excep( int vector )
+{
+ printk("MOL panic: Unexpected exception %x\n", vector );
+ for( ;; )
+ ;
+}
+
+unsigned long isa_io_base;
+
+void
+entry( void )
+{
+ isa_io_base = 0x80000000;
+
+ printk("\n");
+ printk("=============================================================\n");
+ printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
+ OPENBIOS_BUILD_DATE);
+
+ ofmem_init();
+ initialize_forth();
+ /* won't return */
+
+ printk("of_startup returned!\n");
+ for( ;; )
+ ;
+}
+
+static void
+setenv( char *env, char *value )
+{
+ push_str( value );
+ push_str( env );
+ fword("$setenv");
+}
+
+void
+arch_of_init( void )
+{
+ mol_phandle_t ph;
+ int autoboot;
+
+ devtree_init();
+ node_methods_init();
+ nvram_init("/pci/mac-io/nvram");
+ openbios_init();
+ modules_init();
+ pseudodisk_init();
+ osiblk_init();
+ osiscsi_init();
+ init_video();
+
+ if( (ph=prom_find_device("/rtas")) == -1 )
+ printk("Warning: No /rtas node\n");
+ else {
+ unsigned long size = 0x1000;
+ while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start )
+ size *= 2;
+ prom_set_prop( ph, "rtas-size", (char*)&size, sizeof(size) );
+ }
+
+ /* tweak boot settings */
+ autoboot = !!get_bool_res("autoboot");
+ if( !autoboot )
+ printk("Autobooting disabled - dropping into OpenFirmware\n");
+ setenv("auto-boot?", autoboot ? "true" : "false" );
+ setenv("boot-command", "molboot");
+
+ if( get_bool_res("tty-interface") == 1 )
+ fword("activate-tty-interface");
+
+ /* hack */
+ device_end();
+ bind_func("molboot", boot );
+}
diff --git a/roms/openbios/arch/ppc/mol/kernel.c b/roms/openbios/arch/ppc/mol/kernel.c
new file mode 100644
index 00000000..1454b8a8
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/kernel.c
@@ -0,0 +1,16 @@
+/*
+ * Creation Date: <2004/08/28 18:03:25 stepan>
+ * Time-stamp: <2004/08/28 18:03:25 stepan>
+ *
+ * <mol/kernel.c>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "mol-dict.h"
+#include "../kernel.c"
diff --git a/roms/openbios/arch/ppc/mol/main.c b/roms/openbios/arch/ppc/mol/main.c
new file mode 100644
index 00000000..f6ed934d
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/main.c
@@ -0,0 +1,370 @@
+/*
+ * Creation Date: <2002/10/02 22:24:24 samuel>
+ * Time-stamp: <2004/03/27 01:57:55 samuel>
+ *
+ * <main.c>
+ *
+ *
+ *
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elfload.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "mol/mol.h"
+#include "libopenbios/ofmem.h"
+#include "osi_calls.h"
+#include "ablk_sh.h"
+#include "boothelper_sh.h"
+
+
+static void patch_newworld_rom( char *start, size_t size );
+static void newworld_timer_hack( char *start, size_t size );
+
+static void
+transfer_control_to_elf( unsigned long entry )
+{
+ extern void call_elf( unsigned long entry );
+ printk("Starting ELF boot loader\n");
+ call_elf( entry );
+
+ fatal_error("call_elf returned unexpectedly\n");
+}
+
+static int
+load_elf_rom( unsigned long *entry, int fd )
+{
+ int i, lszz_offs, elf_offs;
+ char buf[128], *addr;
+ Elf_ehdr ehdr;
+ Elf_phdr *phdr;
+ size_t s;
+
+ printk("Loading '%s' from '%s'\n", get_file_path(fd),
+ get_volume_name(fd) );
+
+ /* the ELF-image (usually) starts at offset 0x4000 */
+ if( (elf_offs=find_elf(fd)) < 0 ) {
+ printk("----> %s is not an ELF image\n", buf );
+ exit(1);
+ }
+ if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
+ fatal_error("elf_readhdrs failed\n");
+
+ *entry = ehdr.e_entry;
+
+ /* load segments. Compressed ROM-image assumed to be located immediately
+ * after the last segment */
+ lszz_offs = elf_offs;
+ for( i=0; i<ehdr.e_phnum; i++ ) {
+ /* p_memsz, p_flags */
+ s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
+ seek_io( fd, elf_offs + phdr[i].p_offset );
+
+ /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
+ phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
+ phdr[i].p_vaddr ); */
+
+ if( phdr[i].p_vaddr != phdr[i].p_paddr )
+ printk("WARNING: ELF segment virtual addr != physical addr\n");
+ lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
+ if( !s )
+ continue;
+ if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
+ fatal_error("Claim failed!\n");
+
+ addr = (char*)phdr[i].p_vaddr;
+ if( read_io(fd, addr, s) != s )
+ fatal_error("read failed\n");
+
+ /* patch CODE segment */
+ if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) {
+ patch_newworld_rom( (char*)phdr[i].p_vaddr, s );
+ newworld_timer_hack( (char*)phdr[i].p_vaddr, s );
+ }
+ flush_icache_range( addr, addr+s );
+
+ /* printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
+ (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
+ }
+ free( phdr );
+ return lszz_offs;
+}
+
+
+/************************************************************************/
+/* newworld ROM loading */
+/************************************************************************/
+
+#define ROM_BASE 0x1100000 /* where we decide to put things */
+
+/* fix bug present in the 2.4 and the 3.0 Apple ROM */
+static void
+patch_newworld_rom( char *start, size_t size )
+{
+ int s;
+ unsigned long mark[] = { 0x7c7d1b78, /* mr r29,r3 */
+ 0x7c9c2378, /* mr r28,r4 */
+ 0x7cc33378, /* mr r3,r6 */
+ 0x7c864214, /* add r4,r6,r8 <------ BUG -- */
+ 0x80b10000, /* lwz r5,0(r17) */
+ 0x38a500e8 }; /* addi r5,r5,232 */
+
+ /* Correcting add r4,r6,r8 ----> addi r4,r6,8 */
+ for( s=0; s<size-sizeof(mark); s+=4 )
+ if( memcmp( start+s, mark, sizeof(mark)) == 0 ) {
+ printk("FIXING ROM BUG @ %X!\n", s+12);
+ ((unsigned long*)(start+s))[3] = 0x38860008; /* addi r4,r6,8 */
+ }
+}
+
+/* This hack is only needed on machines with a timebase slower than 12.5 MHz
+ * (50 MHz bus frequency). Typically only old, accelerated machines fall
+ * into this category. The cause of the problem is an overflow in Apple's
+ * calibration routine.
+ */
+static void
+newworld_timer_hack( char *start, size_t size )
+{
+ int s;
+ unsigned long mark[] = { 0x7d0000a6, 0x5507045e, 0x7ce00124, 0x4c00012c,
+ 0x38e00000, 0x3c80000f, 0x6084ffff, 0x98830c00,
+ 0x7c0006ac, 0x98830a00, 0x7c0006ac, 0x7c9603a6,
+ 0x4c00012c, 0x7cb602a6, 0x2c050000, 0x4181fff8,
+ 0x7c0004ac, 0x88830a00, 0x7c0006ac, 0x88a30800,
+ 0x7c0006ac, 0x88c30a00, 0x7c0006ac, 0x7c043040,
+ 0x40a2ffe4, 0x5085442e, 0x7ca500d0, 0x54a5043e,
+ 0x7c053840, 0x7ca72b78, 0x4082ff9c, 0x7ca32b78,
+ 0x7d000124, 0x4c00012c, 0x4e800020
+ };
+
+ /* return #via ticks corresponding to 0xfffff DEC ticks (VIA frequency == 47/60 MHz) */
+ for( s=0; s < size-sizeof(mark); s+=4 ) {
+ if( !memcmp( start+s, mark, sizeof(mark)) ) {
+ extern char timer_calib_start[], timer_calib_end[];
+ extern unsigned long nw_dec_calibration;
+ int hz = OSI_UsecsToMticks(1000);
+ nw_dec_calibration = OSI_MticksToUsecs(0xfffff*47)/60;
+ memcpy( start + s, timer_calib_start, timer_calib_end - timer_calib_start );
+
+ printk("Timer calibration fix: %d.%02d MHz [%ld]\n",
+ hz/1000, (hz/10)%100, nw_dec_calibration );
+ break;
+ }
+ }
+}
+
+static unsigned long
+load_newworld_rom( int fd )
+{
+ int lszz_offs, lszz_size;
+ unsigned long entry, data[2];
+ phandle_t ph;
+
+ lszz_offs = load_elf_rom( &entry, fd );
+ seek_io( fd, -1 );
+ lszz_size = tell(fd) - lszz_offs;
+ seek_io( fd, lszz_offs );
+
+ /* printk("Compressed ROM image: offset %08X, size %08X loaded at %08x\n",
+ lszz_offs, lszz_size, ROM_BASE ); */
+
+ if( ofmem_claim(ROM_BASE, lszz_size, 0) == -1 )
+ fatal_error("Claim failure (lszz)!\n");
+
+ read_io( fd, (char*)ROM_BASE, lszz_size );
+
+ /* Fix the /rom/macos/AAPL,toolbox-image,lzss property (phys, size) */
+#if 0
+ if( (ph=prom_create_node("/rom/macos/")) == -1 )
+ fatal_error("Failed creating /rom/macos/");
+#else
+ ph = find_dev("/rom/macos");
+#endif
+ data[0] = ROM_BASE;
+ data[1] = lszz_size;
+ set_property( ph, "AAPL,toolbox-image,lzss", (char*)data, sizeof(data) );
+
+ /* The 7.8 rom (MacOS 9.2) uses AAPL,toolbox-parcels instead of
+ * AAPL,toolbox-image,lzss. It probably doesn't hurt to have it
+ * always present (we don't have an easy way to determine ROM version...)
+ */
+ set_property( ph, "AAPL,toolbox-parcels", (char*)data, sizeof(data) );
+ return entry;
+}
+
+static int
+search_nwrom( int fd, int fast )
+{
+ char *s, buf[128];
+ int found = 0;
+
+ if( fast ) {
+ int ind;
+ found = !reopen( fd, "\\\\:tbxi" );
+ for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath", buf, sizeof(buf), ind++, 0)) ; )
+ found = !reopen( fd, s );
+ for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath_", buf, sizeof(buf), ind++, 0)) ; )
+ found = !reopen( fd, s );
+ } else {
+ printk("Searching %s for a 'Mac OS ROM' file\n", get_volume_name(fd) );
+ if( !(found=reopen_nwrom(fd)) ) {
+ printk(" \n**** HINT ***************************************************\n");
+ printk("* The booting can be speeded up by adding the line\n");
+ printk("* macos_rompath: '%s'\n", get_file_path(fd) );
+ printk("* to the /etc/mol/molrc.macos (recommended).\n");
+ printk("*************************************************************\n \n");
+ }
+ }
+ return found;
+}
+
+static void
+encode_bootpath( const char *spec, const char *args )
+{
+ phandle_t chosen_ph = find_dev("/chosen");
+ set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 );
+ set_property( chosen_ph, "bootargs", args, strlen(args)+1 );
+}
+
+static char *
+newworld_load( const char *node_path, const char *spec, int do_search )
+{
+ char *p, *entry, buf[80];
+ int fd, len;
+
+ if( (fd=open_io(spec)) == -1 )
+ return NULL;
+
+ if( !search_nwrom(fd, do_search) ) {
+ close_io(fd);
+ return NULL;
+ }
+ printk("Boot Disk: %s [%s]\n", spec, get_fstype(fd) );
+
+ entry = (char*)load_newworld_rom( fd );
+
+#if 1
+ PUSH_ih( get_ih_from_fd(fd) );
+ fword("get-instance-path");
+ len = POP();
+ p = (char*)POP();
+ buf[0] = 0;
+ if( len < sizeof(buf) ) {
+ memcpy( buf, p, len );
+ buf[len] =0;
+ }
+ strcat( buf, "/x@:" );
+ printk("boot_path: %s\n", buf );
+ encode_bootpath( buf, "" );
+#endif
+ close_io( fd );
+ return entry;
+}
+
+static void
+newworld_startup( void )
+{
+ int i, j, bootunit, type, fd;
+ ablk_disk_info_t info;
+ char *entry = NULL;
+ char spec[80];
+ phandle_t ph;
+
+ char path[]="/pci/pci-bridge/mol-blk";
+ if( !(ph=find_dev(path)) )
+ fatal_error("MOLBlockDriver node not found\n");
+
+ /* user-specified newworld ROMs take precedence */
+ if( (fd=open_io("pseudo:,nwrom")) >= 0 ) {
+ entry = (char*)load_newworld_rom( fd );
+ close_io( fd );
+ }
+
+ /* determine boot volume */
+ for( bootunit=-1, type=0; bootunit==-1 && type<3 ; type++ ) {
+ for( i=0; !OSI_ABlkDiskInfo(0, i, &info) ; i++ ) {
+ if( type<=1 && !(info.flags & ABLK_BOOT_HINT) )
+ continue;
+ if( type>1 && (info.flags & ABLK_BOOT_HINT) )
+ continue;
+
+ for( j=0; !entry && j<32; j++ ) {
+ snprintf( spec, sizeof(spec), "%s/disk@%x:%d",
+ path, i, j );
+ entry = newworld_load( path, spec, (!type || type==2) );
+ }
+ if( entry ) {
+ bootunit = i;
+ break;
+ }
+ }
+ }
+
+ if( entry ) {
+ OSI_ABlkBlessDisk( 0 /*channel*/, bootunit );
+
+ update_nvram();
+ transfer_control_to_elf( (unsigned long)entry );
+ /* won't come here */
+ return;
+ }
+
+ printk("\n--- No bootable disk was found! -----------------------------\n");
+ printk("If this is an oldworld machine, try booting from the MacOS\n");
+ printk("install CD and install MacOS from within MOL.\n");
+ printk("-------------------------------------------------------------\n");
+ exit(1);
+}
+
+
+/************************************************************************/
+/* yaboot booting */
+/************************************************************************/
+
+static void
+yaboot_startup( void )
+{
+ const char *paths[] = { "pseudo:,ofclient", "pseudo:,yaboot", NULL };
+ unsigned long entry;
+ int i, fd;
+
+ for( i=0; paths[i]; i++ ) {
+ if( (fd=open_io(paths[i])) == -1 )
+ continue;
+ (void) load_elf_rom( &entry, fd );
+ close_io( fd );
+ encode_bootpath( paths[i], "" );
+
+ update_nvram();
+ transfer_control_to_elf( entry );
+ /* won't come here */
+ }
+ printk("*** Boot failure! No secondary bootloader specified ***\n");
+ exit(1);
+}
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+void
+boot( void )
+{
+ fword("update-chosen");
+ if( find_dev("/mol-platform") )
+ yaboot_startup();
+ else
+ newworld_startup();
+}
diff --git a/roms/openbios/arch/ppc/mol/methods.c b/roms/openbios/arch/ppc/mol/methods.c
new file mode 100644
index 00000000..bfaf5150
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/methods.c
@@ -0,0 +1,470 @@
+/*
+ * Creation Date: <2003/10/18 13:24:29 samuel>
+ * Time-stamp: <2004/03/27 02:00:30 samuel>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "mol/mol.h"
+#include "libopenbios/ofmem.h"
+#include "mol/prom.h"
+#include "osi_calls.h"
+#include "kbd_sh.h"
+
+/************************************************************************/
+/* Power Management */
+/************************************************************************/
+
+DECLARE_NODE( powermgt, INSTALL_OPEN, 0, "/pci/pci-bridge/mac-io/power-mgt" );
+
+/* ( -- ) */
+static void
+set_hybernot_flag( void )
+{
+}
+
+NODE_METHODS( powermgt ) = {
+ { "set-hybernot-flag", set_hybernot_flag },
+};
+
+
+/************************************************************************/
+/* RTAS (run-time abstraction services) */
+/************************************************************************/
+
+DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
+
+/* ( physbase -- rtas_callback ) */
+static void
+rtas_instantiate( void )
+{
+ int physbase = POP();
+ int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
+ unsigned long virt;
+
+ while( s < size )
+ s += 0x1000;
+ virt = ofmem_claim_virt( 0, s, 0x1000 );
+ ofmem_map( physbase, virt, s, -1 );
+ memcpy( (char*)virt, of_rtas_start, size );
+
+ printk("RTAS instantiated at %08x\n", physbase );
+ flush_icache_range( (char*)virt, (char*)virt + size );
+
+ PUSH( physbase );
+}
+
+NODE_METHODS( rtas ) = {
+ { "instantiate", rtas_instantiate },
+ { "instantiate-rtas", rtas_instantiate },
+};
+
+
+
+/************************************************************************/
+/* stdout */
+/************************************************************************/
+
+DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" );
+
+/* ( addr len -- actual ) */
+static void
+stdout_write( void )
+{
+ int len = POP();
+ char *addr = (char*)POP();
+
+ /* printk( "%s", s ); */
+ console_draw_fstr(addr, len);
+
+ PUSH( len );
+}
+
+NODE_METHODS( video_stdout ) = {
+ { "write", stdout_write },
+};
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "+/mol/mol-tty" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)POP();
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = OSI_TTYGetc();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ OSI_USleep(1);
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)POP();
+ for( i=0; i<len; i++ )
+ OSI_TTYPutc( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+
+/************************************************************************/
+/* keyboard */
+/************************************************************************/
+
+typedef struct {
+ int cntrl;
+ int shift;
+ int meta;
+ int alt;
+ int save_key;
+ char keytable[32];
+} kbd_state_t;
+
+static const unsigned char adb_ascii_table[128] =
+ /* 0x00 */ "asdfhgzxcv`bqwer"
+ /* 0x10 */ "yt123465=97-80]o"
+ /* 0x20 */ "u[ip\nlj'k;\\,/nm."
+ /* 0x30 */ "\t <\b \e "
+ /* 0x40 */ " . * + / - "
+ /* 0x50 */ " =01234567 89 "
+ /* 0x60 */ " "
+ /* 0x70 */ " ";
+
+static const unsigned char adb_shift_table[128] =
+ /* 0x00 */ "ASDFHGZXCV~BQWER"
+ /* 0x10 */ "YT!@#$^%+(&_*)}O"
+ /* 0x20 */ "U{IP\nLJ\"K:|<?NM>"
+ /* 0x30 */ "\t <\b \e "
+ /* 0x40 */ " . * + / - "
+ /* 0x50 */ " =01234567 89 "
+ /* 0x60 */ " "
+ /* 0x70 */ " ";
+
+DECLARE_NODE( kbd, INSTALL_OPEN, sizeof(kbd_state_t),
+ "/psuedo-hid/keyboard",
+ "/mol/mol-keyboard",
+ "/mol/keyboard"
+);
+
+/* ( -- keymap ) (?) */
+/* should return a pointer to an array with 32 bytes (256 bits) */
+static void
+kbd_get_key_map( kbd_state_t *ks )
+{
+ /* printk("met_kbd_get_key_map\n"); */
+
+ /* keytable[5] = 0x40; */
+ PUSH( (int)ks->keytable );
+}
+
+/* ( buf len --- actlen ) */
+static void
+kbd_read( kbd_state_t *ks )
+{
+ int ret=0, len = POP();
+ char *p = (char*)POP();
+ int key;
+
+ if( !p || !len ) {
+ PUSH( -1 );
+ return;
+ }
+
+ if( ks->save_key ) {
+ *p = ks->save_key;
+ ks->save_key = 0;
+ RET( 1 );
+ }
+ OSI_USleep(1); /* be nice */
+
+ for( ; (key=OSI_GetAdbKey()) >= 0 ; ) {
+ int code = (key & 0x7f);
+ int down = !(key & 0x80);
+
+ if( code == 0x36 /* ctrl */ ) {
+ ks->cntrl = down;
+ continue;
+ }
+ if( code == 0x38 /* shift */ || code == 0x7b) {
+ ks->shift = down;
+ continue;
+ }
+ if( code == 0x37 /* command */ ) {
+ ks->meta = down;
+ continue;
+ }
+ if( code == 0x3a /* alt */ ) {
+ ks->alt = down;
+ continue;
+ }
+ if( !down )
+ continue;
+
+ ret = 1;
+ if( ks->shift )
+ key = adb_shift_table[ key & 0x7f ];
+ else
+ key = adb_ascii_table[ key & 0x7f ];
+
+ if( ks->meta ) {
+ ks->save_key = key;
+ key = 27;
+ } else if( ks->cntrl ) {
+ key = key - 'a' + 1;
+ }
+ *p = key;
+ if( !*p )
+ *p = 'x';
+ break;
+ }
+ PUSH( ret );
+}
+
+NODE_METHODS( kbd ) = {
+ { "read", kbd_read },
+ { "get-key-map", kbd_get_key_map },
+};
+
+
+/************************************************************************/
+/* client interface 'quiesce' */
+/************************************************************************/
+
+DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
+
+/* ( -- ) */
+static void
+ciface_quiesce( unsigned long args[], unsigned long ret[] )
+{
+#if 0
+ unsigned long msr;
+ /* This seems to be the correct thing to do - but I'm not sure */
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr &= ~(MSR_IR | MSR_DR);
+ asm volatile("mtmsr %0" :: "r" (msr) );
+#endif
+ printk("=============================================================\n\n");
+ prom_close();
+
+ OSI_KbdCntrl( kKbdCntrlSuspend );
+}
+
+/* ( -- ms ) */
+static void
+ciface_milliseconds( unsigned long args[], unsigned long ret[] )
+{
+ static unsigned long mticks=0, usecs=0;
+ unsigned long t;
+
+ asm volatile("mftb %0" : "=r" (t) : );
+ if( mticks )
+ usecs += OSI_MticksToUsecs( t-mticks );
+ mticks = t;
+
+ PUSH( usecs/1000 );
+}
+
+
+NODE_METHODS( ciface ) = {
+ { "quiesce", ciface_quiesce },
+ { "milliseconds", ciface_milliseconds },
+};
+
+
+/************************************************************************/
+/* MMU/memory methods */
+/************************************************************************/
+
+DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
+DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpus/@0" );
+DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
+
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_phys( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MEM: claim failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys size align --- base ) */
+static void
+mmu_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_virt( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MMU: CLAIM failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mmu_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys virt size mode -- [ret???] ) */
+static void
+mmu_map( void )
+{
+ ucell mode = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell phys = POP();
+ ucell ret;
+
+ /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
+ ret = ofmem_map( phys, virt, size, mode );
+
+ if( ret ) {
+ printk("MMU: map failure\n");
+ throw( -13 );
+ return;
+ }
+}
+
+/* ( virt size -- ) */
+static void
+mmu_unmap( void )
+{
+ POP(); POP();
+}
+
+/* ( virt -- false | phys mode true ) */
+static void
+mmu_translate( void )
+{
+ ucell mode;
+ ucell virt = POP();
+ ucell phys = ofmem_translate( virt, &mode );
+
+ if( phys == -1 ) {
+ PUSH( 0 );
+ } else {
+ PUSH( phys );
+ PUSH( mode );
+ PUSH( -1 );
+ }
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ POP();
+ POP();
+}
+
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+};
+
+NODE_METHODS( mmu ) = {
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "translate", mmu_translate },
+};
+
+NODE_METHODS( mmu_ciface ) = {
+ { "cif-claim", ciface_claim },
+ { "cif-release", ciface_release },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( void )
+{
+ REGISTER_NODE( rtas );
+ REGISTER_NODE( powermgt );
+ REGISTER_NODE( kbd );
+ REGISTER_NODE( video_stdout );
+ REGISTER_NODE( ciface );
+ REGISTER_NODE( memory );
+ REGISTER_NODE( mmu );
+ REGISTER_NODE( mmu_ciface );
+
+ if( OSI_CallAvailable(OSI_TTY_GETC) )
+ REGISTER_NODE( tty );
+
+ OSI_KbdCntrl( kKbdCntrlActivate );
+}
diff --git a/roms/openbios/arch/ppc/mol/mol.c b/roms/openbios/arch/ppc/mol/mol.c
new file mode 100644
index 00000000..86b3b66b
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/mol.c
@@ -0,0 +1,165 @@
+/*
+ * Creation Date: <2003/12/19 18:46:21 samuel>
+ * Time-stamp: <2004/04/12 16:27:12 samuel>
+ *
+ * <mol.c>
+ *
+ *
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/nvram.h"
+#include "libc/vsprintf.h"
+#include "libc/string.h"
+#include "mol/mol.h"
+#include "osi_calls.h"
+#include <stdarg.h>
+
+void
+exit( int status )
+{
+ OSI_Exit();
+}
+
+void
+fatal_error( const char *err )
+{
+ printk("Fatal error: %s\n", err );
+ OSI_Exit();
+}
+
+void
+panic( const char *err )
+{
+ printk("Panic: %s\n", err );
+ OSI_Exit();
+
+ /* won't come here... this keeps the gcc happy */
+ for( ;; )
+ ;
+}
+
+
+/************************************************************************/
+/* print using OSI interface */
+/************************************************************************/
+
+static int do_indent;
+
+int
+printk( const char *fmt, ... )
+{
+ char *p, buf[1024];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vnsprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ ) {
+ if( *p == '\n' )
+ do_indent = 0;
+ if( do_indent++ == 1 ) {
+ OSI_PutC( '>' );
+ OSI_PutC( '>' );
+ OSI_PutC( ' ' );
+ }
+ OSI_PutC( *p );
+ }
+ return i;
+}
+
+
+/************************************************************************/
+/* TTY iface */
+/************************************************************************/
+
+static int ttychar = -1;
+
+static int
+tty_avail( void )
+{
+ return OSI_CallAvailable( OSI_TTY_GETC );
+}
+
+int
+availchar( void )
+{
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ ttychar = OSI_TTYGetc();
+ if( ttychar < 0 )
+ OSI_USleep(1);
+ return (ttychar >= 0);
+}
+
+int
+getchar( void )
+{
+ int ch;
+
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ return OSI_TTYGetc();
+ ch = ttychar;
+ ttychar = -1;
+ return ch;
+}
+
+int
+putchar( int c )
+{
+ printk("%c", c );
+
+ if( tty_avail() )
+ OSI_TTYPutc( c );
+ return c;
+}
+
+
+/************************************************************************/
+/* MOL specific stuff */
+/************************************************************************/
+
+int
+arch_nvram_size( void )
+{
+ return OSI_NVRamSize();
+}
+
+void
+arch_nvram_put( char *buf )
+{
+ int i, size = arch_nvram_size();
+
+ for( i=0; i<size; i++ )
+ OSI_WriteNVRamByte( i, buf[i] );
+}
+
+void
+arch_nvram_get( char *buf )
+{
+ int i, size = arch_nvram_size();
+
+ /* support for zapping the nvram */
+ if( get_bool_res("zap_nvram") == 1 ) {
+ memset( buf, 0, size );
+ return;
+ }
+
+ for( i=0; i<size; i++ )
+ buf[i] = OSI_ReadNVRamByte( i );
+}
diff --git a/roms/openbios/arch/ppc/mol/mol.fs b/roms/openbios/arch/ppc/mol/mol.fs
new file mode 100644
index 00000000..10c99bd7
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/mol.fs
@@ -0,0 +1,107 @@
+
+
+\ -------------------------------------------------------------------------
+\ initialization
+\ -------------------------------------------------------------------------
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " memory" " /memory" preopen
+ " mmu" " /cpus/@0" preopen
+ " stdout" " /packages/mol-stdout" preopen
+ " stdin" " keyboard" preopen
+ " nvram" " /pci/pci-bridge/mac-io/nvram" preopen
+ " nvram" " /mol/nvram" preopen
+
+; SYSTEM-initializer
+
+
+\ -------------------------------------------------------------------------
+\ device tree fixing
+\ -------------------------------------------------------------------------
+
+\ add decode-address methods
+: (make-decodable) ( phandle -- )
+
+ dup " #address-cells" rot get-package-property 0= if
+ decode-int nip nip
+ over " decode-unit" rot find-method if 2drop else
+ ( save phandle ncells )
+
+ over active-package!
+ case
+ 1 of ['] parse-hex " decode-unit" is-xt-func endof
+ 3 of
+ " bus-range" active-package get-package-property 0= if
+ decode-int nip nip
+ ['] encode-unit-pci " encode-unit" is-xt-func
+ " decode-unit" is-func-begin
+ ['] (lit) , ,
+ ['] decode-unit-pci-bus ,
+ is-func-end
+ then
+ endof
+ endcase
+ then
+ then
+ drop
+;
+
+: tree-fixes ( -- )
+ active-package
+
+ iterate-tree-begin
+ begin ?dup while
+
+ dup (make-decodable)
+
+ iterate-tree
+ repeat
+
+ active-package!
+;
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /mol/mol-tty" find-dev if drop
+ " /mol/mol-tty" " input-device" $setenv
+ " /mol/mol-tty" " output-device" $setenv
+ then
+;
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+
+\ -------------------------------------------------------------------------
+\ pre-booting
+\ -------------------------------------------------------------------------
+
+: update-chosen
+ " /chosen" find-device
+ stdin @ encode-int " stdin" property
+ stdout @ encode-int " stdout" property
+ device-end
+;
diff --git a/roms/openbios/arch/ppc/mol/mol.h b/roms/openbios/arch/ppc/mol/mol.h
new file mode 100644
index 00000000..cea15a35
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/mol.h
@@ -0,0 +1,44 @@
+/*
+ * Creation Date: <2003/12/20 00:20:12 samuel>
+ * Time-stamp: <2004/03/27 01:52:50 samuel>
+ *
+ * <mol.h>
+ *
+ *
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_MOL
+#define _H_MOL
+
+/* video.c */
+extern void init_video( void );
+extern int video_get_res( int *w, int *h );
+extern void draw_pixel( int x, int y, int colind );
+extern void set_color( int index, unsigned long color );
+
+/* console.c */
+extern int console_draw_fstr(const char *str, int len);
+extern void console_close( void );
+
+/* pseudodisk.c */
+extern void pseudodisk_init( void );
+
+/* osi-blk.c */
+extern void osiblk_init( void );
+
+/* osi-scsi.c */
+extern void osiscsi_init( void );
+
+/* pseudofs.c */
+extern void pseudofs_init( void );
+
+#include "../kernel.h"
+
+#endif /* _H_MOL */
diff --git a/roms/openbios/arch/ppc/mol/osi-blk.c b/roms/openbios/arch/ppc/mol/osi-blk.c
new file mode 100644
index 00000000..4ed1b5ab
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/osi-blk.c
@@ -0,0 +1,119 @@
+/*
+ * Creation Date: <2003/12/07 19:08:33 samuel>
+ * Time-stamp: <2004/01/07 19:38:36 samuel>
+ *
+ * <osi-blk.c>
+ *
+ * OSI-block interface
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "mol/mol.h"
+#include "osi_calls.h"
+
+typedef struct {
+ int unit;
+ int channel;
+} osiblk_data_t;
+
+
+DECLARE_NODE( osiblk, INSTALL_OPEN, sizeof(osiblk_data_t),
+ "/pci/pci-bridge/mol-blk/disk", "/mol/mol-blk" );
+
+
+static void
+osiblk_open( osiblk_data_t *pb )
+{
+ phandle_t ph;
+
+ fword("my-unit");
+ pb->unit = POP();
+ pb->channel = 0; /* FIXME */
+
+ selfword("open-deblocker");
+
+ /* interpose disk-label */
+ ph = find_dev("/packages/disk-label");
+ fword("my-args");
+ PUSH_ph( ph );
+ fword("interpose");
+
+ /* printk("osi-blk: open %d\n", pb->unit ); */
+ PUSH( -1 );
+}
+
+static void
+osiblk_close( osiblk_data_t *pb )
+{
+ selfword("close-deblocker");
+}
+
+
+/* ( buf blk nblks -- actual ) */
+static void
+osiblk_read_blocks( osiblk_data_t *pb )
+{
+ int i, n = POP();
+ int blk = POP();
+ char *dest = (char*)POP();
+
+ /* printk("osiblk_read_blocks %x block=%d n=%d\n", (int)dest, blk, n ); */
+
+ for( i=0; i<n; ) {
+ char buf[4096];
+ int m = MIN( n-i, sizeof(buf)/512 );
+
+ if( OSI_ABlkSyncRead(pb->channel, pb->unit, blk+i, (int)buf, m*512) < 0 ) {
+ printk("SyncRead: error\n");
+ RET(0);
+ }
+ memcpy( dest, buf, m * 512 );
+ i += m;
+ dest += m * 512;
+ }
+ PUSH( n );
+}
+
+/* ( -- bs ) */
+static void
+osiblk_block_size( osiblk_data_t *pb )
+{
+ PUSH( 512 );
+}
+
+/* ( -- maxbytes ) */
+static void
+osiblk_max_transfer( osiblk_data_t *pb )
+{
+ PUSH( 1024*1024 );
+}
+
+static void
+osiblk_initialize( osiblk_data_t *pb )
+{
+ fword("is-deblocker");
+}
+
+
+NODE_METHODS( osiblk ) = {
+ { NULL, osiblk_initialize },
+ { "open", osiblk_open },
+ { "close", osiblk_close },
+ { "read-blocks", osiblk_read_blocks },
+ { "block-size", osiblk_block_size },
+ { "max-transfer", osiblk_max_transfer },
+};
+
+void
+osiblk_init( void )
+{
+ REGISTER_NODE( osiblk );
+}
diff --git a/roms/openbios/arch/ppc/mol/osi-scsi.c b/roms/openbios/arch/ppc/mol/osi-scsi.c
new file mode 100644
index 00000000..18f3dc57
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/osi-scsi.c
@@ -0,0 +1,271 @@
+/*
+ * Creation Date: <2003/12/11 21:23:54 samuel>
+ * Time-stamp: <2004/01/07 19:38:45 samuel>
+ *
+ * <osi-scsi.c>
+ *
+ * SCSI device node
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "mol/mol.h"
+#include "scsi_sh.h"
+#include "osi_calls.h"
+
+#define MAX_TARGETS 32
+
+typedef struct {
+ int probed;
+ int valid; /* a useable device found */
+
+ int is_cd;
+ int blocksize;
+} target_info_t;
+
+static target_info_t scsi_devs[ MAX_TARGETS ];
+
+typedef struct {
+ int target;
+ target_info_t *info;
+} instance_data_t;
+
+
+DECLARE_NODE( scsi, INSTALL_OPEN, sizeof(instance_data_t),
+ "/pci/pci-bridge/mol-scsi/sd", "/mol/mol-scsi/sd" );
+
+
+static int
+scsi_cmd_( instance_data_t *sd, const char *cmd, int cmdlen, char *dest,
+ int len, int prelen, int postlen )
+{
+ char prebuf[4096], postbuf[4096];
+ scsi_req_t r[2]; /* the [2] is a hack to get space for the sg-list */
+ char sb[32];
+
+ /* memset( dest, 0, len ); */
+
+ if( (unsigned int)prelen > sizeof(prebuf) || (unsigned int)postlen > sizeof(postbuf) ) {
+ printk("bad pre/post len %d %d\n", prelen, postlen );
+ return 1;
+ }
+
+ memset( r, 0, sizeof(r[0]) );
+ r->lun = 0;
+ r->target = sd->target;
+ r->is_write = 0;
+ memcpy( r->cdb, cmd, cmdlen );
+ r->client_addr = (int)&r;
+ r->cdb_len = cmdlen;
+ r->sense[0].base = (int)&sb;
+ r->sense[0].size = sizeof(sb);
+ r->size = prelen + len + postlen;
+ r->n_sg = 3;
+ r->sglist.n_el = 3;
+ r->sglist.vec[0].base = (int)prebuf;
+ r->sglist.vec[0].size = prelen;
+ r->sglist.vec[1].base = (int)dest;
+ r->sglist.vec[1].size = len;
+ r->sglist.vec[2].base = (int)postbuf;
+ r->sglist.vec[2].size = postlen;
+
+ if( OSI_SCSISubmit((int)&r) ) {
+ printk("OSI_SCSISubmit: error!\n");
+ return 1;
+ }
+ while( !OSI_SCSIAck() )
+ OSI_USleep( 10 );
+
+ if( r->adapter_status )
+ return -1;
+ if( r->scsi_status )
+ return ((sb[2] & 0xf) << 16) | (sb[12] << 8) | sb[13];
+ return 0;
+}
+
+static int
+scsi_cmd( instance_data_t *sd, const char *cmd, int cmdlen )
+{
+ return scsi_cmd_( sd, cmd, cmdlen, NULL, 0, 0, 0 );
+}
+
+/* ( buf blk nblks -- actual ) */
+static void
+scsi_read_blocks( instance_data_t *sd )
+{
+ int nblks = POP();
+ int blk = POP();
+ char *dest = (char*)POP();
+ unsigned char cmd[10];
+ int len = nblks * sd->info->blocksize;
+
+ memset( dest, 0, len );
+
+ /* printk("READ: blk: %d length %d\n", blk, len ); */
+ memset( cmd, 0, sizeof(cmd) );
+ cmd[0] = 0x28; /* READ_10 */
+ cmd[2] = blk >> 24;
+ cmd[3] = blk >> 16;
+ cmd[4] = blk >> 8;
+ cmd[5] = blk;
+ cmd[7] = nblks >> 8;
+ cmd[8] = nblks;
+
+ if( scsi_cmd_(sd, cmd, 10, dest, len, 0, 0) ) {
+ printk("read: scsi_cmd failed\n");
+ RET( -1 );
+ }
+ PUSH( nblks );
+}
+
+static int
+inquiry( instance_data_t *sd )
+{
+ char inquiry_cmd[6] = { 0x12, 0, 0, 0, 32, 0 };
+ char start_stop_unit_cmd[6] = { 0x1b, 0, 0, 0, 1, 0 };
+ char test_unit_ready_cmd[6] = { 0x00, 0, 0, 0, 0, 0 };
+ char prev_allow_medium_removal[6] = { 0x1e, 0, 0, 0, 1, 0 };
+ char set_cd_speed_cmd[12] = { 0xbb, 0, 0xff, 0xff, 0xff, 0xff,
+ 0, 0, 0, 0, 0, 0 };
+ target_info_t *info = &scsi_devs[sd->target];
+ char ret[32];
+ int i, sense;
+
+ if( sd->target >= MAX_TARGETS )
+ return -1;
+ sd->info = info;
+
+ if( info->probed )
+ return info->valid ? 0:-1;
+ info->probed = 1;
+
+ if( (sense=scsi_cmd_(sd, inquiry_cmd, 6, ret, 2, 0, 0)) ) {
+ if( sense < 0 )
+ return -1;
+ printk("INQUIRY failed\n");
+ return -1;
+ }
+
+ /* medium present? */
+ if( (scsi_cmd(sd, test_unit_ready_cmd, 6) >> 8) == 0x23a ) {
+ printk("no media\n");
+ return -1;
+ }
+
+ info->is_cd = 0;
+ info->blocksize = 512;
+
+ if( ret[0] == 5 /* CD/DVD */ ) {
+ info->blocksize = 2048;
+ info->is_cd = 1;
+
+ scsi_cmd( sd, prev_allow_medium_removal, 6 );
+ scsi_cmd( sd, set_cd_speed_cmd, 12 );
+ scsi_cmd( sd, start_stop_unit_cmd, 6 );
+
+ } else if( ret[0] == 0 /* DISK */ ) {
+ scsi_cmd( sd, test_unit_ready_cmd, 6 );
+ scsi_cmd( sd, start_stop_unit_cmd, 6 );
+ } else {
+ /* don't boot from this device (could be a scanner :-)) */
+ return -1;
+ }
+
+ /* wait for spin-up (or whatever) to complete */
+ for( i=0; ; i++ ) {
+ if( i > 300 ) {
+ printk("SCSI timeout (sense %x)\n", sense );
+ return -1;
+ }
+ sense = scsi_cmd( sd, test_unit_ready_cmd, 6 );
+ if( (sense & 0xf0000) == 0x20000 ) {
+ OSI_USleep( 10000 );
+ continue;
+ }
+ break;
+ }
+
+ info->valid = 1;
+ return 0;
+}
+
+/* ( -- success? ) */
+static void
+scsi_open( instance_data_t *sd )
+{
+ static int once = 0;
+ phandle_t ph;
+
+ fword("my-unit");
+ sd->target = POP();
+
+ if( !once ) {
+ once++;
+ OSI_SCSIControl( SCSI_CTRL_INIT, 0 );
+ }
+
+ /* obtiain device information */
+ if( inquiry(sd) )
+ RET(0);
+
+ selfword("open-deblocker");
+
+ /* interpose disk-label */
+ ph = find_dev("/packages/disk-label");
+ fword("my-args");
+ PUSH_ph( ph );
+ fword("interpose");
+
+ PUSH( -1 );
+}
+
+/* ( -- ) */
+static void
+scsi_close( instance_data_t *pb )
+{
+ selfword("close-deblocker");
+}
+
+
+/* ( -- bs ) */
+static void
+scsi_block_size( instance_data_t *sd )
+{
+ PUSH( sd->info->blocksize );
+}
+
+/* ( -- maxbytes ) */
+static void
+scsi_max_transfer( instance_data_t *sd )
+{
+ PUSH( 1024*1024 );
+}
+
+static void
+scsi_initialize( instance_data_t *sd )
+{
+ fword("is-deblocker");
+}
+
+
+NODE_METHODS( scsi ) = {
+ { NULL, scsi_initialize },
+ { "open", scsi_open },
+ { "close", scsi_close },
+ { "read-blocks", scsi_read_blocks },
+ { "block-size", scsi_block_size },
+ { "max-transfer", scsi_max_transfer },
+};
+
+void
+osiscsi_init( void )
+{
+ REGISTER_NODE( scsi );
+}
diff --git a/roms/openbios/arch/ppc/mol/prom.c b/roms/openbios/arch/ppc/mol/prom.c
new file mode 100644
index 00000000..0bc8bcfb
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/prom.c
@@ -0,0 +1,175 @@
+/*
+ * Creation Date: <2002/10/03 20:55:02 samuel>
+ * Time-stamp: <2002/10/29 13:00:23 samuel>
+ *
+ * <prom.c>
+ *
+ * oftree interface
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "osi_calls.h"
+#include "mol/prom.h"
+
+/* OSI_PromClose (free linux side device tree) */
+int
+prom_close( void )
+{
+ return OSI_PromIface( kPromClose, 0 );
+}
+
+/* ret: 0 no more peers, -1 if error */
+mol_phandle_t
+prom_peer( mol_phandle_t phandle )
+{
+ return OSI_PromIface( kPromPeer, phandle );
+}
+
+/* ret: 0 no child, -1 if error */
+mol_phandle_t
+prom_child( mol_phandle_t phandle )
+{
+ return OSI_PromIface( kPromChild, phandle );
+}
+
+/* ret: 0 if root node, -1 if error */
+mol_phandle_t
+prom_parent( mol_phandle_t phandle )
+{
+ return OSI_PromIface( kPromParent, phandle );
+}
+
+/* ret: -1 error */
+int
+prom_package_to_path( mol_phandle_t phandle, char *buf, long buflen )
+{
+ return OSI_PromIface2( kPromPackageToPath, phandle, (int)buf, buflen );
+}
+
+/* ret: -1 error */
+int
+prom_get_prop_len( mol_phandle_t phandle, const char *name )
+{
+ return OSI_PromIface1( kPromGetPropLen, phandle, (int)name );
+}
+
+/* ret: prop len or -1 if error */
+int
+prom_get_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen )
+{
+ return OSI_PromIface3( kPromGetProp, phandle, (int)name, (int)buf, buflen );
+}
+
+/* ret: prop len or -1 if error */
+int
+prom_get_prop_by_path( const char *path, const char *name, char *buf, long buflen )
+{
+ mol_phandle_t ph = prom_find_device(path);
+ return (ph != -1)? prom_get_prop( ph, name, buf, buflen) : -1;
+}
+
+/* ret: -1 error, 0 last prop, 1 otherwise */
+int
+prom_next_prop( mol_phandle_t phandle, const char *prev, char *buf )
+{
+ return OSI_PromIface2( kPromNextProp, phandle, (int)prev, (int)buf );
+}
+
+/* ret: -1 if error */
+int
+prom_set_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen )
+{
+ return OSI_PromIface3( kPromSetProp, phandle, (int)name, (int)buf, buflen );
+}
+
+/* ret: -1 if error */
+mol_phandle_t
+prom_create_node( const char *path )
+{
+ return OSI_PromPathIface( kPromCreateNode, path );
+}
+
+/* ret: -1 if not found */
+mol_phandle_t
+prom_find_device( const char *path )
+{
+ mol_phandle_t ph;
+ char buf2[256], ch, *p;
+
+ if( !path )
+ return -1;
+
+ if( (ph=OSI_PromPathIface( kPromFindDevice, path )) != -1 )
+ return ph;
+ else if( path[0] == '/' )
+ return -1;
+
+ /* might be an alias */
+ if( !(p=strpbrk(path, "@:/")) )
+ p = (char*)path + strlen(path);
+
+ ch = *p;
+ *p = 0;
+ if( (ph=prom_get_prop(prom_find_device("/aliases"), path, buf2, sizeof(buf2))) == -1 )
+ return -1;
+ *p = ch;
+ strncat( buf2, p, sizeof(buf2) );
+
+ if( buf2[0] != '/' ) {
+ printk("Error: aliases must be absolute!\n");
+ return -1;
+ }
+ ph = OSI_PromPathIface( kPromFindDevice, buf2 );
+ return ph;
+}
+
+
+
+/************************************************************************/
+/* search the tree for nodes with matching device_type */
+/************************************************************************/
+
+static mol_phandle_t
+prom_find_device_type_( mol_phandle_t ph, const char *type, int *icount, int index )
+{
+ char buf[64];
+ int ph2;
+
+ if( ph == -1 || !ph )
+ return -1;
+ if( prom_get_prop( ph, "device_type", buf, sizeof(buf)) > 0 )
+ if( !strcmp(buf, type) )
+ if( (*icount)++ == index )
+ return ph;
+ if( (ph2=prom_find_device_type_( prom_peer(ph), type, icount, index )) != -1 )
+ return ph2;
+ if( (ph2=prom_find_device_type_( prom_child(ph), type, icount, index )) != -1 )
+ return ph2;
+ return -1;
+}
+
+mol_phandle_t
+prom_find_device_type( const char *type, int index )
+{
+ int count = 0;
+ return prom_find_device_type_( prom_peer(0), type, &count, index );
+}
+
+
+/************************************************************************/
+/* device tree tweaking */
+/************************************************************************/
+
+/* -1 if error */
+int
+prom_change_phandle( mol_phandle_t old_ph, mol_phandle_t new_ph )
+{
+ return OSI_PromIface1( kPromChangePHandle, old_ph, (int)new_ph );
+}
diff --git a/roms/openbios/arch/ppc/mol/prom.h b/roms/openbios/arch/ppc/mol/prom.h
new file mode 100644
index 00000000..54a856c2
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/prom.h
@@ -0,0 +1,47 @@
+/*
+ * Creation Date: <2002/10/03 21:07:27 samuel>
+ * Time-stamp: <2003/10/22 22:45:26 samuel>
+ *
+ * <prom.h>
+ *
+ * device tree interface
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_PROM
+#define _H_PROM
+
+/* Note 1: MOL uses -1 as the invalid phandle while OpenFirmware uses 0 as the
+ * invalid phandle (it is also the root node).
+ *
+ * Note 2: phandles might be negative. For instance, phandles originating from
+ * a real Open Firmware tree might look like 0xff123000 (a ROM address)...
+ */
+
+typedef enum { kGetRootPhandle=0 } mol_phandle_t; /* must promote to int */
+
+extern int prom_close( void );
+
+extern mol_phandle_t prom_peer( mol_phandle_t phandle );
+extern mol_phandle_t prom_child( mol_phandle_t phandle );
+extern mol_phandle_t prom_parent( mol_phandle_t phandle );
+extern int prom_package_to_path( mol_phandle_t phandle, char *buf, long buflen );
+extern int prom_get_prop_len( mol_phandle_t phandle, const char *name );
+extern int prom_get_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen );
+extern int prom_get_prop_by_path( const char *path, const char *name, char *buf, long buflen );
+extern int prom_next_prop( mol_phandle_t phandle, const char *prev, char *buf );
+extern int prom_set_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen );
+extern mol_phandle_t prom_create_node( const char *path );
+extern mol_phandle_t prom_find_device( const char *path );
+
+extern mol_phandle_t prom_find_device_type( const char *type, int index );
+
+extern int prom_change_phandle( mol_phandle_t old_ph, mol_phandle_t new_ph );
+
+#endif /* _H_PROM */
diff --git a/roms/openbios/arch/ppc/mol/pseudodisk.c b/roms/openbios/arch/ppc/mol/pseudodisk.c
new file mode 100644
index 00000000..a98e5484
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/pseudodisk.c
@@ -0,0 +1,178 @@
+/*
+ * Creation Date: <2003/11/26 16:55:47 samuel>
+ * Time-stamp: <2004/01/07 19:41:54 samuel>
+ *
+ * <pseudodisk.c>
+ *
+ * pseudodisk (contains files exported from linux)
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "osi_calls.h"
+#include "libc/string.h"
+#include "libopenbios/ofmem.h"
+#include "mol/prom.h"
+#include "mol/mol.h"
+#include "osi_calls.h"
+#include "pseudofs_sh.h"
+
+typedef struct {
+ int seekpos;
+ int fd;
+ char *myargs;
+ char *name;
+ int size;
+} pdisk_data_t;
+
+
+DECLARE_NODE( pdisk, INSTALL_OPEN, sizeof(pdisk_data_t), "/mol/pseudo-disk/disk" );
+
+static void
+pdisk_open( pdisk_data_t *pb )
+{
+ char *ep, *name = NULL;
+ int part;
+
+ pb->myargs = my_args_copy();
+ /* printk("pdisk-open: %s\n", pb->myargs ); */
+
+ part = strtol( pb->myargs, &ep, 10 );
+ if( *ep ) {
+ if( (name=strchr(pb->myargs, ',')) ) {
+ *name = 0;
+ name++;
+ } else {
+ name = pb->myargs;
+ }
+ }
+ if( part )
+ goto err;
+
+ if( !name || !strlen(name) )
+ pb->fd = -1;
+ else {
+ if( (pb->fd=PseudoFSOpen(name)) < 0 )
+ goto err;
+ pb->size = PseudoFSGetSize( pb->fd );
+ }
+ pb->name = name;
+ RET( -1 );
+ err:
+ free( pb->myargs );
+ RET(0);
+}
+
+/* ( addr len -- actual ) */
+static void
+pdisk_read( pdisk_data_t *pb )
+{
+ int len = POP();
+ char *dest = (char*)POP();
+ int cnt;
+
+ if( pb->fd < 0 ) {
+ memset( dest, 0, len );
+ PUSH(len);
+ return;
+ }
+ /* dest is not "mol-DMA" safe (might have a nontrivial mapping) */
+ for( cnt=0; cnt<len; ) {
+ char buf[2048];
+ int n = MIN( len-cnt, sizeof(buf) );
+
+ n = PseudoFSRead( pb->fd, pb->seekpos, buf, n );
+ if( n <= 0 )
+ break;
+
+ memcpy( dest+cnt, buf, n );
+ cnt += n;
+ pb->seekpos += n;
+ }
+ PUSH( cnt );
+}
+
+/* ( addr len -- actual ) */
+static void
+pdisk_write( pdisk_data_t *pb )
+{
+ POP(); POP(); PUSH(-1);
+ printk("pdisk write\n");
+}
+
+/* ( pos.lo pos.hi -- status ) */
+static void
+pdisk_seek( pdisk_data_t *pb )
+{
+ int pos_lo;
+ POP();
+ pos_lo = POP();
+
+ if( pb->fd >= 0 ) {
+ if( pos_lo == -1 )
+ pos_lo = pb->size;
+ }
+
+ pb->seekpos = pos_lo;
+
+ PUSH(0); /* ??? */
+}
+
+/* ( -- pos.d ) */
+static void
+pdisk_tell( pdisk_data_t *pb )
+{
+ DPUSH( pb->seekpos );
+}
+
+/* ( -- cstr ) */
+static void
+pdisk_get_path( pdisk_data_t *pb )
+{
+ PUSH( (int)pb->name );
+}
+
+/* ( -- cstr ) */
+static void
+pdisk_get_fstype( pdisk_data_t *pb )
+{
+ PUSH( (int)"PSEUDO" );
+}
+
+/* ( -- cstr ) */
+static void
+pdisk_volume_name( pdisk_data_t *pb )
+{
+ PUSH( (int)"Virtual Volume" );
+}
+
+static void
+pdisk_block_size( pdisk_data_t *pb )
+{
+ PUSH(1);
+}
+
+NODE_METHODS( pdisk ) = {
+ { "open", pdisk_open },
+ { "read", pdisk_read },
+ { "write", pdisk_write },
+ { "seek", pdisk_seek },
+ { "tell", pdisk_tell },
+ { "block-size", pdisk_block_size },
+ { "get-path", pdisk_get_path },
+ { "get-fstype", pdisk_get_fstype },
+ { "volume-name", pdisk_volume_name },
+};
+
+void
+pseudodisk_init( void )
+{
+ REGISTER_NODE( pdisk );
+}
diff --git a/roms/openbios/arch/ppc/mol/tree.c b/roms/openbios/arch/ppc/mol/tree.c
new file mode 100644
index 00000000..b82c8c2c
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/tree.c
@@ -0,0 +1,165 @@
+/*
+ * Creation Date: <2003/11/18 14:55:05 samuel>
+ * Time-stamp: <2004/03/27 02:03:55 samuel>
+ *
+ * <tree.c>
+ *
+ * device tree setup
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "mol/mol.h"
+#include "mol/prom.h"
+
+
+/************************************************************************/
+/* copy device tree */
+/************************************************************************/
+
+static void
+copy_node( mol_phandle_t molph )
+{
+ char name[40], path[80];
+ int exists;
+ phandle_t ph;
+
+ if( !molph )
+ return;
+
+ prom_package_to_path( molph, path, sizeof(path) );
+
+ /* don't copy /options node */
+ if( !strcmp("/options", path) ) {
+ copy_node( prom_peer(molph) );
+ return;
+ }
+
+ exists = 1;
+ if( !(ph=find_dev(path)) ) {
+ exists = 0;
+ fword("new-device");
+ ph = get_cur_dev();
+ }
+ activate_dev( ph );
+
+ name[0] = 0;
+ while( prom_next_prop(molph, name, name) > 0 ) {
+ int len = prom_get_prop_len( molph, name );
+ char *p;
+#if 0
+ if( len > 0x1000 ) {
+ printk("prop to large (%d)\n", len );
+ continue;
+ }
+#endif
+ /* don't copy /chosen/{stdin,stdout} (XXX: ugly hack...) */
+ if( !strcmp("/chosen", path) )
+ if( !strcmp("stdio", name) || !strcmp("stdout", name) )
+ continue;
+
+ p = malloc( len );
+ prom_get_prop( molph, name, p, len );
+ set_property( ph, name, p, len );
+ free( p );
+ }
+
+ set_int_property( ph, "MOL,phandle", molph );
+ copy_node( prom_child(molph) );
+
+ if( !exists )
+ fword("finish-device");
+ else
+ activate_device("..");
+
+ copy_node( prom_peer(molph) );
+}
+
+
+
+/************************************************************************/
+/* device tree cloning and tweaking */
+/************************************************************************/
+
+static phandle_t
+translate_molph( mol_phandle_t molph )
+{
+ static mol_phandle_t cached_molph;
+ static phandle_t cached_ph;
+ phandle_t ph=0;
+
+ if( cached_molph == molph )
+ return cached_ph;
+
+ while( (ph=dt_iterate(ph)) )
+ if( get_int_property(ph, "MOL,phandle", NULL) == molph )
+ break;
+ cached_molph = molph;
+ cached_ph = ph;
+
+ if( !ph )
+ printk("failed to translate molph\n");
+ return ph;
+}
+
+static void
+fix_phandles( void )
+{
+ static char *pnames[] = { "interrupt-parent", "interrupt-controller", NULL } ;
+ int len, *map;
+ phandle_t ph=0;
+ char **pp;
+
+ while( (ph=dt_iterate(ph)) ) {
+ for( pp=pnames; *pp; pp++ ) {
+ phandle_t *p = (phandle_t*)get_property( ph, *pp, &len );
+ if( len == 4 )
+ *p = translate_molph( *(int*)p );
+ }
+
+ /* need to fix interrupt map properties too */
+ if( (map=(int*)get_property(ph, "interrupt-map", &len)) ) {
+ int i, acells = get_int_property(ph, "#address-cells", NULL);
+ int icells = get_int_property(ph, "#interrupt-cells", NULL);
+
+ len /= sizeof(int);
+ for( i=0; i<len; i++ ) {
+ phandle_t ch_ph;
+ int ch_acells, ch_icells;
+
+ i += acells + icells;
+ if( !(ch_ph=translate_molph(map[i])) )
+ break;
+ map[i] = (int)ch_ph;
+ ch_acells = get_int_property(ch_ph, "#address-cells", NULL);
+ ch_icells = get_int_property(ch_ph, "#interrupt-cells", NULL);
+ i += ch_acells + icells;
+ }
+ if( i != len )
+ printk("interrupt map fixing failure\n");
+ }
+ }
+ /* delete MOL,phandle properties */
+ for( ph=0; (ph=dt_iterate(ph)) ; ) {
+ push_str("MOL,phandle");
+ PUSH_ph(ph);
+ fword("(delete-property)");
+ }
+ fword("device-end");
+}
+
+void
+devtree_init( void )
+{
+ activate_device("/");
+ copy_node( prom_peer(0) );
+ fix_phandles();
+ fword("tree-fixes");
+}
diff --git a/roms/openbios/arch/ppc/mol/tree.fs b/roms/openbios/arch/ppc/mol/tree.fs
new file mode 100644
index 00000000..228163ff
--- /dev/null
+++ b/roms/openbios/arch/ppc/mol/tree.fs
@@ -0,0 +1,103 @@
+
+: int-property ( val name -- )
+ rot encode-int 2swap property
+;
+
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
+" /" find-device
+
+ " device-tree" device-name
+ " bootrom" device-type
+
+\ -------------------------------------------------------------
+\ /memory
+\ -------------------------------------------------------------
+
+new-device
+ " memory" device-name
+ \ 12230 encode-int " reg" property
+ external
+ : open true ;
+ : close ;
+ \ claim ( phys size align -- base )
+ \ release ( phys size -- )
+finish-device
+
+\ -------------------------------------------------------------
+\ /mol/
+\ -------------------------------------------------------------
+
+new-device
+ " mol" device-name
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+
+new-device
+ " test" device-name
+
+ external
+ : open
+ ." /mol/test opened" cr
+ " argument-str" " ipose" find-package drop interpose
+ true
+ ;
+finish-device
+finish-device
+
+\ -------------------------------------------------------------
+\ /cpus/
+\ -------------------------------------------------------------
+
+new-device
+ " cpus" device-name
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+ : decode-unit parse-hex ;
+
+finish-device
+
+\ -------------------------------------------------------------
+\ /packages
+\ -------------------------------------------------------------
+
+" /packages" find-device
+
+ " packages" device-name
+ external
+ \ allow packages to be opened with open-dev
+ : open true ;
+ : close ;
+
+\ /packages/mol-stdout
+new-device
+ " mol-stdout" device-name
+ external
+ : open true ;
+ : close ;
+ : write ( addr len -- actual )
+ dup -rot type
+ ;
+finish-device
+
+\ XXXXXXXXXXXXXXXXXXXXXXX TESTING
+" /" find-device
+new-device
+ " test" device-name
+finish-device
+
+\ -------------------------------------------------------------
+\ The END
+\ -------------------------------------------------------------
+device-end
diff --git a/roms/openbios/arch/ppc/ofmem.c b/roms/openbios/arch/ppc/ofmem.c
new file mode 100644
index 00000000..c9b066ed
--- /dev/null
+++ b/roms/openbios/arch/ppc/ofmem.c
@@ -0,0 +1,308 @@
+/*
+ * Creation Date: <1999/11/07 19:02:11 samuel>
+ * Time-stamp: <2004/01/07 19:42:36 samuel>
+ *
+ * <ofmem.c>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+/* TODO: Clean up MOLisms in a decent way */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "libopenbios/ofmem.h"
+#include "kernel.h"
+#ifdef I_WANT_MOLISMS
+#include "mol/prom.h"
+#include "mol/mol.h"
+#endif
+#include "mmutypes.h"
+#include "asm/processor.h"
+#ifdef I_WANT_MOLISMS
+#include "osi_calls.h"
+#endif
+
+#define BIT(n) (1U<<(31-(n)))
+
+/* called from assembly */
+extern void dsi_exception( void );
+extern void isi_exception( void );
+extern void setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize );
+
+/****************************************************************
+ * Memory usage (before of_quiesce is called)
+ *
+ * Physical
+ *
+ * 0x00000000 Exception vectors
+ * 0x00004000 Free space
+ * 0x01e00000 Open Firmware (us)
+ * 0x01f00000 OF allocations
+ * 0x01ff0000 PTE Hash
+ * 0x02000000- Free space
+ *
+ * Allocations grow downwards from 0x01e00000
+ *
+ ****************************************************************/
+
+#define HASH_SIZE (2 << 15)
+#define SEGR_BASE 0x400 /* segment number range to use */
+
+#define FREE_BASE_1 0x00004000
+#define OF_CODE_START 0x01e00000
+/* #define OF_MALLOC_BASE 0x01f00000 */
+extern char _end[];
+#define OF_MALLOC_BASE _end
+
+#define HASH_BASE (0x02000000 - HASH_SIZE)
+#define FREE_BASE_2 0x02000000
+
+#define RAMSIZE 0x02000000 /* XXXXXXXXXXXXXXXXXXX FIXME XXXXXXXXXXXXXXX */
+
+static ofmem_t s_ofmem;
+
+#define IO_BASE 0x80000000
+#define OFMEM (&s_ofmem)
+
+static inline unsigned long
+get_hash_base( void )
+{
+ return HASH_BASE;
+}
+
+static inline unsigned long
+get_hash_size( void )
+{
+ return HASH_SIZE;
+}
+
+static ucell get_heap_top( void )
+{
+ return HASH_BASE;
+}
+
+static inline size_t ALIGN_SIZE(size_t x, size_t a)
+{
+ return (x + a - 1) & ~(a-1);
+}
+
+ofmem_t* ofmem_arch_get_private(void)
+{
+ return OFMEM;
+}
+
+void* ofmem_arch_get_malloc_base(void)
+{
+ return OF_MALLOC_BASE;
+}
+
+ucell ofmem_arch_get_heap_top(void)
+{
+ return get_heap_top();
+}
+
+ucell ofmem_arch_get_virt_top(void)
+{
+ return IO_BASE;
+}
+
+void ofmem_arch_unmap_pages(ucell virt, ucell size)
+{
+ /* kill page mappings in provided range */
+}
+
+void ofmem_arch_map_pages(ucell phys, ucell virt, ucell size, ucell mode)
+{
+ /* none yet */
+}
+
+/************************************************************************/
+/* OF private allocations */
+/************************************************************************/
+
+void *
+malloc( int size )
+{
+ return ofmem_malloc(size);
+}
+
+void
+free( void *ptr )
+{
+ return ofmem_free(ptr);
+}
+
+void *
+realloc( void *ptr, size_t size )
+{
+ return ofmem_realloc(ptr, size);
+}
+
+
+/************************************************************************/
+/* misc */
+/************************************************************************/
+
+ucell ofmem_arch_default_translation_mode( ucell phys )
+{
+ /* XXX: Guard bit not set as it should! */
+ if( phys < IO_BASE || phys >= 0xffc00000 )
+ return 0x02; /*0xa*/ /* wim GxPp */
+ return 0x6a; /* WIm GxPp, I/O */
+}
+
+
+/************************************************************************/
+/* page fault handler */
+/************************************************************************/
+
+static ucell
+ea_to_phys( ucell ea, ucell *mode )
+{
+ ucell phys;
+
+ /* hardcode our translation needs */
+ if( ea >= OF_CODE_START && ea < FREE_BASE_2 ) {
+ *mode = ofmem_arch_default_translation_mode( ea );
+ return ea;
+ }
+
+ phys = ofmem_translate(ea, mode);
+ if( phys == (ucell)-1 ) {
+#ifdef I_WANT_MOLISMS
+ if( ea != 0x80816c00 )
+ printk("ea_to_phys: no translation for %08lx, using 1-1\n", ea );
+#endif
+ phys = ea;
+ *mode = ofmem_arch_default_translation_mode( phys );
+
+#ifdef I_WANT_MOLISMS
+ forth_segv_handler( (char*)ea );
+ OSI_Debugger(1);
+#endif
+ /* print_virt_range(); */
+ /* print_phys_range(); */
+ /* print_trans(); */
+ }
+ return phys;
+}
+
+static void
+hash_page( ucell ea, ucell phys, ucell mode )
+{
+ static int next_grab_slot=0;
+ unsigned long *upte, cmp, hash1;
+ int i, vsid, found;
+ mPTE_t *pp;
+
+ vsid = (ea>>28) + SEGR_BASE;
+ cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22);
+
+ hash1 = vsid;
+ hash1 ^= (ea >> 12) & 0xffff;
+ hash1 &= (get_hash_size() - 1) >> 6;
+
+ pp = (mPTE_t*)(get_hash_base() + (hash1 << 6));
+ upte = (unsigned long*)pp;
+
+ /* replace old translation */
+ for( found=0, i=0; !found && i<8; i++ )
+ if( cmp == upte[i*2] )
+ found=1;
+
+ /* otherwise use a free slot */
+ for( i=0; !found && i<8; i++ )
+ if( !pp[i].v )
+ found=1;
+
+ /* out of slots, just evict one */
+ if( !found ) {
+ i = next_grab_slot + 1;
+ next_grab_slot = (next_grab_slot + 1) % 8;
+ }
+ i--;
+ upte[i*2] = cmp;
+ upte[i*2+1] = (phys & ~0xfff) | mode;
+
+ asm volatile( "tlbie %0" :: "r"(ea) );
+}
+
+void
+dsi_exception( void )
+{
+ unsigned long dar, dsisr;
+ ucell mode;
+ ucell phys;
+
+ asm volatile("mfdar %0" : "=r" (dar) : );
+ asm volatile("mfdsisr %0" : "=r" (dsisr) : );
+
+ //printk("dsi-exception @ %08lx <%08lx>\n", dar, dsisr );
+
+ phys = ea_to_phys(dar, &mode);
+ hash_page( dar, phys, mode );
+}
+
+void
+isi_exception( void )
+{
+ unsigned long nip, srr1;
+ ucell mode;
+ ucell phys;
+
+ asm volatile("mfsrr0 %0" : "=r" (nip) : );
+ asm volatile("mfsrr1 %0" : "=r" (srr1) : );
+
+ //printk("isi-exception @ %08lx <%08lx>\n", nip, srr1 );
+
+ phys = ea_to_phys(nip, &mode);
+ hash_page( nip, phys, mode );
+}
+
+
+/************************************************************************/
+/* init / cleanup */
+/************************************************************************/
+
+void
+setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize )
+{
+ unsigned long sdr1 = HASH_BASE | ((HASH_SIZE-1) >> 16);
+ unsigned long sr_base = (0x20 << 24) | SEGR_BASE;
+ unsigned long msr;
+ int i;
+
+ asm volatile("mtsdr1 %0" :: "r" (sdr1) );
+ for( i=0; i<16; i++ ) {
+ int j = i << 28;
+ asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j) );
+ }
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr |= MSR_IR | MSR_DR;
+ asm volatile("mtmsr %0" :: "r" (msr) );
+}
+
+void
+ofmem_init( void )
+{
+ ofmem_t *ofmem = OFMEM;
+ /* In case we can't rely on memory being zero initialized */
+ memset(ofmem, 0, sizeof(ofmem));
+
+ ofmem->ramsize = RAMSIZE;
+
+ ofmem_claim_phys( 0, FREE_BASE_1, 0 );
+ ofmem_claim_virt( 0, FREE_BASE_1, 0 );
+ ofmem_claim_phys( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 );
+ ofmem_claim_virt( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 );
+}
diff --git a/roms/openbios/arch/ppc/osi.h b/roms/openbios/arch/ppc/osi.h
new file mode 100644
index 00000000..3baae157
--- /dev/null
+++ b/roms/openbios/arch/ppc/osi.h
@@ -0,0 +1,170 @@
+/*
+ * Creation Date: <1999/03/18 03:19:43 samuel>
+ * Time-stamp: <2003/12/26 16:58:19 samuel>
+ *
+ * <os_interface.h>
+ *
+ * This file includes definitions for drivers
+ * running in the "emulated" OS. (Mainly the 'sc'
+ * mechanism of communicating)
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_OSI
+#define _H_OSI
+
+/* Magic register values loaded into r3 and r4 before the 'sc' assembly instruction */
+#define OSI_SC_MAGIC_R3 0x113724FA
+#define OSI_SC_MAGIC_R4 0x77810F9B
+
+
+/************************************************************************/
+/* Selectors (passed in r5) */
+/************************************************************************/
+
+#define OSI_CALL_AVAILABLE 0
+#define OSI_DEBUGGER 1 /* enter debugger */
+/* obsolete OSI_LOG_STR 3 */
+#define OSI_CMOUNT_DRV_VOL 4 /* conditionally mount driver volume */
+/* obsolete OSI_SCSI_xxx 5-6 */
+#define OSI_GET_GMT_TIME 7
+#define OSI_MOUSE_CNTRL 8
+#define OSI_GET_LOCALTIME 9 /* return time in secs from 01/01/04 */
+
+#define OSI_ENET_OPEN 10
+#define OSI_ENET_CLOSE 11
+#define OSI_ENET_GET_ADDR 12
+#define OSI_ENET_GET_STATUS 13
+#define OSI_ENET_CONTROL 14
+#define OSI_ENET_ADD_MULTI 16
+#define OSI_ENET_DEL_MULTI 17
+#define OSI_ENET_GET_PACKET 18
+#define OSI_ENET_SEND_PACKET 19
+
+#define OSI_OF_INTERFACE 20
+#define OSI_OF_TRAP 21
+#define OSI_OF_RTAS 22
+
+#define OSI_SCSI_CNTRL 23
+#define OSI_SCSI_SUBMIT 24
+#define OSI_SCSI_ACK 25
+
+#define OSI_GET_MOUSE 26 /* -- r3 status, r4-r8 mouse data */
+#define OSI_ACK_MOUSE_IRQ 27 /* -- int */
+
+#define OSI_SET_VMODE 28 /* modeID, depth -- error */
+#define OSI_GET_VMODE_INFO 29 /* mode, depth -- r3 status, r4-r9 pb */
+#define OSI_GET_MOUSE_DPI 30 /* -- mouse_dpi */
+
+#define OSI_SET_VIDEO_POWER 31
+#define OSI_GET_FB_INFO 32 /* void -- r3 status, r4-r8 video data */
+
+#define OSI_SOUND_WRITE 33
+/* #define OSI_SOUND_FORMAT 34 */
+#define OSI_SOUND_SET_VOLUME 35
+#define OSI_SOUND_CNTL 36
+/* obsolete OSI_SOUND call 37 */
+
+#define OSI_VIDEO_ACK_IRQ 38
+#define OSI_VIDEO_CNTRL 39
+
+#define OSI_SOUND_IRQ_ACK 40
+#define OSI_SOUND_START_STOP 41
+
+#define OSI_REGISTER_IRQ 42 /* reg_property[0] appl_int -- irq_cookie */
+/* obsolete OSI_IRQ 43-46 */
+
+#define OSI_LOG_PUTC 47 /* char -- */
+
+#define OSI_KBD_CNTRL 50
+#define OSI_GET_ADB_KEY 51 /* -- adb_keycode (keycode | keycode_id in r4) */
+
+#define OSI_WRITE_NVRAM_BYTE 52 /* offs, byte -- */
+#define OSI_READ_NVRAM_BYTE 53 /* offs -- byte */
+
+#define OSI_EXIT 54
+
+#define OSI_KEYCODE_TO_ADB 55 /* (keycode | keycode_id) -- adb_keycode */
+#define OSI_MAP_ADB_KEY 56 /* keycode, adbcode -- */
+#define OSI_SAVE_KEYMAPPING 57 /* -- */
+#define OSI_USLEEP 58 /* usecs -- */
+#define OSI_SET_COLOR 59 /* index value -- */
+
+#define OSI_PIC_MASK_IRQ 60 /* irq -- */
+#define OSI_PIC_UNMASK_IRQ 61 /* irq -- */
+#define OSI_PIC_ACK_IRQ 62 /* irq mask_flag -- */
+#define OSI_PIC_GET_ACTIVE_IRQ 63
+
+#define OSI_GET_COLOR 64 /* index -- value */
+
+/* 65-67 old ablk implementation */
+#define OSI_IRQTEST 65
+
+#define OSI_ENET2_OPEN 68
+#define OSI_ENET2_CLOSE 69
+#define OSI_ENET2_CNTRL 70
+#define OSI_ENET2_RING_SETUP 71
+#define OSI_ENET2_KICK 72
+#define OSI_ENET2_GET_HWADDR 73
+#define OSI_ENET2_IRQ_ACK 74
+
+#define OSI_PROM_IFACE 76
+#define kPromClose 0
+#define kPromPeer 1
+#define kPromChild 2
+#define kPromParent 3
+#define kPromPackageToPath 4
+#define kPromGetPropLen 5
+#define kPromGetProp 6
+#define kPromNextProp 7
+#define kPromSetProp 8
+#define kPromChangePHandle 9
+
+#define OSI_PROM_PATH_IFACE 77
+#define kPromCreateNode 16
+#define kPromFindDevice 17
+
+#define OSI_BOOT_HELPER 78
+#define kBootHAscii2Unicode 32
+#define kBootHUnicode2Ascii 33
+#define kBootHGetStrResInd 34 /* key, buf, len -- buf */
+#define kBootHGetRAMSize 35 /* -- ramsize */
+
+#define OSI_ABLK_RING_SETUP 79
+#define OSI_ABLK_CNTRL 80
+#define OSI_ABLK_DISK_INFO 81
+#define OSI_ABLK_KICK 82
+#define OSI_ABLK_IRQ_ACK 83
+#define OSI_ABLK_SYNC_READ 84
+#define OSI_ABLK_SYNC_WRITE 85
+#define OSI_ABLK_BLESS_DISK 86
+
+#define OSI_EMUACCEL 89 /* EMULATE_xxx, nip -- index */
+#define OSI_MAPIN_MREGS 90 /* mphys */
+#define OSI_NVRAM_SIZE 91
+
+#define OSI_MTICKS_TO_USECS 92
+#define OSI_USECS_TO_MTICKS 93
+
+/* obsolete OSI_BLK 94-95 */
+
+#define OSI_PSEUDO_FS 96
+#define kPseudoFSOpen 1
+#define kPseudoFSClose 2
+#define kPseudoFSGetSize 3
+#define kPseudoFSRead 4
+#define kPseudoFSIndex2Name 5
+
+#define OSI_TTY_PUTC 97
+#define OSI_TTY_GETC 98
+#define OSI_TTY_IRQ_ACK 99
+
+#define NUM_OSI_SELECTORS 100 /* remember to increase this... */
+
+#endif /* _H_OSI */
diff --git a/roms/openbios/arch/ppc/osi_calls.h b/roms/openbios/arch/ppc/osi_calls.h
new file mode 100644
index 00000000..1d6b3dc5
--- /dev/null
+++ b/roms/openbios/arch/ppc/osi_calls.h
@@ -0,0 +1,454 @@
+/*
+ * Creation Date: <2002/06/16 01:40:57 samuel>
+ * Time-stamp: <2003/12/26 17:02:09 samuel>
+ *
+ * <osi_calls.h>
+ *
+ * OSI call inlines
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_OSI_CALLS
+#define _H_OSI_CALLS
+
+#include "osi.h"
+
+/* Old gcc versions have a limit on the number of registers used.
+ * Newer gcc versions (gcc 3.3) require that the clobber list does
+ * not overlap declared registers.
+ */
+#if __GNUC__ == 2 || ( __GNUC__ == 3 && __GNUC_MINOR__ < 3 )
+#define SHORT_REGLIST
+#endif
+
+
+/************************************************************************/
+/* OSI call instantiation macros */
+/************************************************************************/
+
+#define dreg(n) __oc_##n __asm__ (#n)
+#define ir(n) "r" (__oc_##n)
+#define rr(n) "=r" (__oc_##n)
+
+#define _oc_head( input_regs... ) \
+{ \
+ int _ret=0; \
+ { \
+ register unsigned long dreg(r3); \
+ register unsigned long dreg(r4); \
+ register unsigned long dreg(r5) \
+ ,##input_regs ;
+
+#define _oc_syscall( number, extra_ret_regs... ) \
+ __oc_r3 = OSI_SC_MAGIC_R3; \
+ __oc_r4 = OSI_SC_MAGIC_R4; \
+ __oc_r5 = number; \
+ __asm__ __volatile__ ( \
+ "sc " : rr(r3) ,## extra_ret_regs
+
+#define _oc_input( regs... ) \
+ : ir(r3), ir(r4), ir(r5) \
+ , ## regs \
+ : "memory" );
+
+/* the tail memory clobber is necessary since we violate the strict
+ * aliasing rules when we return structs through the registers.
+ */
+#define _oc_tail \
+ asm volatile ( "" : : : "memory" ); \
+ _ret = __oc_r3; \
+ } \
+ return _ret; \
+}
+
+
+/************************************************************************/
+/* Alternatives */
+/************************************************************************/
+
+#ifdef SHORT_REGLIST
+#define _oc_syscall_r10w6( number, inputregs... ) \
+ __oc_r3 = OSI_SC_MAGIC_R3; \
+ __oc_r4 = OSI_SC_MAGIC_R4; \
+ __oc_r5 = number; \
+ __asm__ __volatile__ ( \
+ "sc \n" \
+ "stw 4,0(10) \n" \
+ "stw 5,4(10) \n" \
+ "stw 6,8(10) \n" \
+ "stw 7,12(10) \n" \
+ "stw 8,16(10) \n" \
+ "stw 9,20(10) \n" \
+ : rr(r3) \
+ : ir(r3), ir(r4), ir(r5), ir(r10) \
+ ,## inputregs \
+ : "memory", \
+ "r4", "r5", "r6", "r7", "r8", "r9" );
+#endif
+
+
+/************************************************************************/
+/* Common helper functions */
+/************************************************************************/
+
+#define _osi_call0( type, name, number ) \
+type name( void ) \
+ _oc_head() \
+ _oc_syscall( number ) \
+ _oc_input() \
+ _oc_tail
+
+#define _osi_call1( type, name, number, type1, arg1 ) \
+type name( type1 arg1 ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)arg1; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6) ) \
+ _oc_tail
+
+#define _osi_call2( type, name, number, t1, a1, t2, a2 ) \
+type name( t1 a1, t2 a2 ) \
+ _oc_head( dreg(r6), dreg(r7) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7) ) \
+ _oc_tail
+
+#define _osi_call3( type, name, number, t1, a1, t2, a2, t3, a3 ) \
+type name( t1 a1, t2 a2, t3 a3 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r8 = (unsigned long)a3; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7), ir(r8) ) \
+ _oc_tail
+
+#define _osi_call4( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4 ) \
+type name( t1 a1, t2 a2, t3 a3, t4 a4 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r8 = (unsigned long)a3; \
+ __oc_r9 = (unsigned long)a4; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7), ir(r8), ir(r9) ) \
+ _oc_tail
+
+#define _osi_call5( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5 ) \
+type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r8 = (unsigned long)a3; \
+ __oc_r9 = (unsigned long)a4; \
+ __oc_r10 = (unsigned long)a5; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10) ) \
+ _oc_tail
+
+#define _osi_call6( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6 ) \
+type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10), dreg(r11) )\
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r8 = (unsigned long)a3; \
+ __oc_r9 = (unsigned long)a4; \
+ __oc_r10 = (unsigned long)a5; \
+ __oc_r11 = (unsigned long)a6; \
+ _oc_syscall( number ) \
+ _oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10), ir(r11) ) \
+ _oc_tail
+
+
+/************************************************************************/
+/* Special */
+/************************************************************************/
+
+/* r4 returned in retarg1 pointer */
+#define _osi_call0_w1( type, name, number, type1, retarg1 ) \
+type name( type1 retarg1 ) \
+ _oc_head() \
+ _oc_syscall( number, rr(r4) ) \
+ _oc_input() \
+ *retarg1 = __oc_r4; \
+ _oc_tail
+
+#define _osi_call0_w2( type, name, number, type1, retarg1 ) \
+type name( type1 retarg1 ) \
+ _oc_head() \
+ _oc_syscall( number, rr(r4), rr(r5) ) \
+ _oc_input() \
+ ((unsigned long*)retarg1)[0] = __oc_r4; \
+ ((unsigned long*)retarg1)[1] = __oc_r5; \
+ _oc_tail
+
+/* r4-r8 returned in retarg1 pointer */
+#define _osi_call0_w5( type, name, number, type1, retarg1 ) \
+type name( type1 retarg1 ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8) ) \
+ _oc_syscall( number, \
+ rr(r4), rr(r5), rr(r6), rr(r7), rr(r8) ) \
+ _oc_input() \
+ ((unsigned long*)retarg1)[0] = __oc_r4; \
+ ((unsigned long*)retarg1)[1] = __oc_r5; \
+ ((unsigned long*)retarg1)[2] = __oc_r6; \
+ ((unsigned long*)retarg1)[3] = __oc_r7; \
+ ((unsigned long*)retarg1)[4] = __oc_r8; \
+ _oc_tail
+
+/* r4 returned in retarg pointer */
+#define _osi_call1_w1( type, name, number, t1, a1, t2, retarg ) \
+type name( t1 a1, t2 retarg ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ _oc_tail
+
+/* r4,r5 returned in retarg1, retarg2 */
+#define _osi_call1_w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2 ) \
+type name( t1 a1, t2 retarg1, t3 retarg2 ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4), rr(r5) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg1)[0] = __oc_r4; \
+ ((unsigned long*)retarg2)[0] = __oc_r5; \
+ _oc_tail
+
+/* r4,r5 returned in retarg1, retarg2, retarg3 */
+#define _osi_call1_w1w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2, t4, retarg3 ) \
+type name( t1 a1, t2 retarg1, t3 retarg2, t4 retarg3 ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4), rr(r5), rr(r6) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg1)[0] = __oc_r4; \
+ ((unsigned long*)retarg2)[0] = __oc_r5; \
+ ((unsigned long*)retarg3)[0] = __oc_r6; \
+ _oc_tail
+
+/* r4,r5 returned in retarg pointer */
+#define _osi_call1_w2( type, name, number, t1, a1, t2, retarg ) \
+type name( t1 a1, t2 retarg ) \
+ _oc_head( dreg(r6) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4), rr(r5) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ _oc_tail
+
+/* r4-r7 returned in retarg pointer */
+#define _osi_call1_w4( type, name, number, t1, a1, t2, retarg ) \
+type name( t1 a1, t2 retarg ) \
+ _oc_head( dreg(r6), dreg(r7) ) \
+ __oc_r6 = (unsigned long)a1; \
+ _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \
+ _oc_input( ir(r6) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ ((unsigned long*)retarg)[2] = __oc_r6; \
+ ((unsigned long*)retarg)[3] = __oc_r7; \
+ _oc_tail
+
+
+/* r4-r5 returned in retarg pointer */
+#define _osi_call2_w2( type, name, number, t1, a1, t2, a2, t3, retarg ) \
+type name( t1 a1, t2 a2, t3 retarg ) \
+ _oc_head( dreg(r6), dreg(r7) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ _oc_syscall( number, rr(r4), rr(r5) ) \
+ _oc_input( ir(r6), ir(r7) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ _oc_tail
+
+/* r4-r7 returned in retarg pointer */
+#define _osi_call2_w4( type, name, number, t1, a1, t2, a2, t3, retarg ) \
+type name( t1 a1, t2 a2, t3 retarg ) \
+ _oc_head( dreg(r6), dreg(r7) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \
+ _oc_input( ir(r6), ir(r7) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ ((unsigned long*)retarg)[2] = __oc_r6; \
+ ((unsigned long*)retarg)[3] = __oc_r7; \
+ _oc_tail
+
+#ifdef SHORT_REGLIST
+/* r4-r9 returned in retarg pointer */
+#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \
+type name( t1 a1, t2 a2, t3 retarg ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r10) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ __oc_r10 = (unsigned long)retarg; \
+ _oc_syscall_r10w6( number, ir(r6), ir(r7) ) \
+ _oc_tail
+
+#else /* SHORT_REGLIST */
+
+/* r4-r9 returned in retarg pointer */
+#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \
+type name( t1 a1, t2 a2, t3 retarg ) \
+ _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) ) \
+ __oc_r6 = (unsigned long)a1; \
+ __oc_r7 = (unsigned long)a2; \
+ _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7), rr(r8), rr(r9) ) \
+ _oc_input( ir(r6), ir(r7) ) \
+ ((unsigned long*)retarg)[0] = __oc_r4; \
+ ((unsigned long*)retarg)[1] = __oc_r5; \
+ ((unsigned long*)retarg)[2] = __oc_r6; \
+ ((unsigned long*)retarg)[3] = __oc_r7; \
+ ((unsigned long*)retarg)[4] = __oc_r8; \
+ ((unsigned long*)retarg)[5] = __oc_r9; \
+ _oc_tail
+
+#endif /* SHORT_REGLIST */
+
+
+/************************************************************************/
+/* OSI call inlines */
+/************************************************************************/
+
+static inline _osi_call1( int, OSI_CallAvailable, OSI_CALL_AVAILABLE, int, osi_num );
+
+static inline _osi_call1( int, OSI_PutC, OSI_LOG_PUTC, int, ch );
+
+static inline _osi_call1( int, OSI_Debugger, OSI_DEBUGGER, int, num );
+static inline _osi_call0( int, OSI_Exit, OSI_EXIT );
+
+/* misc */
+static inline _osi_call0( unsigned long, OSI_GetLocalTime, OSI_GET_LOCALTIME );
+static inline _osi_call0( unsigned long, OSI_GetGMTTime, OSI_GET_GMT_TIME );
+static inline _osi_call1( int, OSI_USleep, OSI_USLEEP, int, usecs );
+
+/* NVRAM */
+static inline _osi_call0( int, OSI_NVRamSize, OSI_NVRAM_SIZE );
+static inline _osi_call1( int, OSI_ReadNVRamByte, OSI_READ_NVRAM_BYTE, int, offs );
+static inline _osi_call2( int, OSI_WriteNVRamByte, OSI_WRITE_NVRAM_BYTE, int, offs,
+ unsigned char, ch );
+
+/* keyboard stuff */
+static inline _osi_call0_w1( int, OSI_GetAdbKey2, OSI_GET_ADB_KEY, int *, raw_key );
+static inline _osi_call1( int, OSI_KbdCntrl, OSI_KBD_CNTRL, int, cmd );
+
+static inline int OSI_GetAdbKey( void )
+ { int dummy_raw_key; return OSI_GetAdbKey2( &dummy_raw_key ); }
+static inline _osi_call2( int, OSI_MapAdbKey, OSI_MAP_ADB_KEY, int, keycode, int, adbkey )
+static inline _osi_call1( int, OSI_KeycodeToAdb, OSI_KEYCODE_TO_ADB, int, keycode );
+static inline _osi_call0( int, OSI_SaveKeymapping, OSI_SAVE_KEYMAPPING );
+
+/* mouse support */
+struct osi_mouse;
+static inline _osi_call0_w5( int, OSI_GetMouse, OSI_GET_MOUSE, struct osi_mouse *, ret );
+static inline _osi_call0( int, OSI_GetMouseDPI, OSI_GET_MOUSE_DPI );
+
+/* video */
+static inline _osi_call2( int, OSI_SetVMode_, OSI_SET_VMODE, int, mode, int, depth_mode );
+struct osi_get_vmode_info;
+static inline _osi_call2_w6( int, OSI_GetVModeInfo_, OSI_GET_VMODE_INFO, int, mode, int, depth_mode,
+ struct osi_get_vmode_info *, ret );
+static inline _osi_call1( int, OSI_SetVPowerState, OSI_SET_VIDEO_POWER, int, power_state );
+static inline _osi_call2( int, OSI_SetColor, OSI_SET_COLOR, int, index, int, rgb );
+static inline _osi_call0_w1( int, OSI_VideoAckIRQ, OSI_VIDEO_ACK_IRQ, int *, events );
+
+static inline void OSI_RefreshPalette( void ) { OSI_SetColor(-1,0); }
+
+/* PIC (mac-io replacement) */
+static inline _osi_call1( int, OSI_PICMaskIRQ, OSI_PIC_MASK_IRQ, int, irq );
+static inline _osi_call1( int, OSI_PICUnmaskIRQ, OSI_PIC_UNMASK_IRQ, int, irq );
+static inline _osi_call2( int, OSI_PICAckIRQ, OSI_PIC_ACK_IRQ, int, irq, int, mask_it );
+static inline _osi_call0( int, OSI_PICGetActiveIRQ, OSI_PIC_GET_ACTIVE_IRQ );
+
+/* sound */
+static inline _osi_call1( int, OSI_SoundCntl, OSI_SOUND_CNTL, int, cmd );
+static inline _osi_call2( int, OSI_SoundCntl1, OSI_SOUND_CNTL, int, cmd, int, p1 );
+static inline _osi_call3( int, OSI_SoundCntl2, OSI_SOUND_CNTL, int, cmd, int, p1, int, p2 );
+static inline _osi_call0_w2( int, OSI_SoundIRQAck, OSI_SOUND_IRQ_ACK, unsigned long *, timestamp );
+static inline _osi_call3( int, OSI_SoundWrite, OSI_SOUND_WRITE, int, physbuf, int, len, int, restart );
+static inline _osi_call3( int, OSI_SoundSetVolume, OSI_SOUND_SET_VOLUME, int, hwvol, int, speakervol, int, mute );
+
+/* async block driver */
+struct ablk_disk_info;
+static inline _osi_call2_w4( int, OSI_ABlkDiskInfo, OSI_ABLK_DISK_INFO, int, channel, int, unit,
+ struct ablk_disk_info *, retinfo );
+static inline _osi_call1( int, OSI_ABlkKick, OSI_ABLK_KICK, int, channel );
+static inline _osi_call1_w1w1w1( int, OSI_ABlkIRQAck, OSI_ABLK_IRQ_ACK, int, channel, int *, req_count,
+ int *, active, int *, events );
+static inline _osi_call3( int, OSI_ABlkRingSetup, OSI_ABLK_RING_SETUP, int, channel, int, mphys, int, n_el );
+static inline _osi_call2( int, OSI_ABlkCntrl, OSI_ABLK_CNTRL, int, channel, int, cmd );
+static inline _osi_call3( int, OSI_ABlkCntrl1, OSI_ABLK_CNTRL, int, channel, int, cmd, int, param );
+static inline _osi_call5( int, OSI_ABlkSyncRead, OSI_ABLK_SYNC_READ, int, channel, int, unit,
+ int, blk, unsigned long, mphys, int, size );
+static inline _osi_call5( int, OSI_ABlkSyncWrite, OSI_ABLK_SYNC_WRITE, int, channel, int, unit,
+ int, blk, unsigned long, mphys, int, size );
+static inline _osi_call2( int, OSI_ABlkBlessDisk, OSI_ABLK_BLESS_DISK, int, channel, int, unit );
+
+static inline _osi_call0( int, OSI_CMountDrvVol, OSI_CMOUNT_DRV_VOL );
+
+/* enet2 */
+static inline _osi_call0( int, OSI_Enet2Open, OSI_ENET2_OPEN );
+static inline _osi_call0( int, OSI_Enet2Close, OSI_ENET2_CLOSE );
+static inline _osi_call3( int, OSI_Enet2RingSetup, OSI_ENET2_RING_SETUP, int, which_ring,
+ int, ring_mphys, int, n_el );
+static inline _osi_call2( int, OSI_Enet2Cntrl1, OSI_ENET2_CNTRL, int, cmd, int, param );
+static inline _osi_call1( int, OSI_Enet2Cntrl, OSI_ENET2_CNTRL, int, cmd );
+static inline _osi_call0( int, OSI_Enet2Kick, OSI_ENET2_KICK );
+
+static inline _osi_call0_w2( int, OSI_Enet2GetHWAddr__, OSI_ENET2_GET_HWADDR, unsigned long *, retbuf );
+static inline int OSI_Enet2GetHWAddr( unsigned char *addr ) {
+ int ret;
+ unsigned long buf[2];
+
+ ret = OSI_Enet2GetHWAddr__( buf );
+
+ ((unsigned long*)addr)[0] = buf[0];
+ ((unsigned short*)addr)[2] = (buf[1] >> 16);
+ return ret;
+}
+static inline _osi_call2( int, OSI_Enet2IRQAck, OSI_ENET2_IRQ_ACK, int, irq_enable, int, rx_head );
+
+/* PROM (device-tree) */
+static inline _osi_call2( int, OSI_PromIface, OSI_PROM_IFACE, int, what, int, ph );
+static inline _osi_call3( int, OSI_PromIface1, OSI_PROM_IFACE, int, what, int, ph, int, p1 );
+static inline _osi_call4( int, OSI_PromIface2, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2 );
+static inline _osi_call5( int, OSI_PromIface3, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2, int, p3 );
+static inline _osi_call2( int, OSI_PromPathIface, OSI_PROM_PATH_IFACE, int, what, const char *, p );
+
+/* emulation acceleration */
+static inline _osi_call1( int, OSI_MapinMregs, OSI_MAPIN_MREGS, unsigned long, mphys );
+static inline _osi_call3( int, OSI_EmuAccel, OSI_EMUACCEL, int, emuaccel_flags, int, param, int, inst_addr );
+
+/* timer frequency */
+static inline _osi_call1( int, OSI_MticksToUsecs, OSI_MTICKS_TO_USECS, unsigned long, mticks );
+static inline _osi_call1( int, OSI_UsecsToMticks, OSI_USECS_TO_MTICKS, unsigned long, usecs );
+
+/* fb info */
+struct osi_fb_info;
+static inline _osi_call0_w5( int, OSI_GetFBInfo, OSI_GET_FB_INFO, struct osi_fb_info *, retinfo );
+
+/* SCSI */
+static inline _osi_call0( int, OSI_SCSIAck, OSI_SCSI_ACK );
+static inline _osi_call1( int, OSI_SCSISubmit, OSI_SCSI_SUBMIT, int, req_mphys );
+static inline _osi_call2( int, OSI_SCSIControl, OSI_SCSI_CNTRL, int, sel, int, param );
+
+/* TTY */
+static inline _osi_call0( int, OSI_TTYGetc, OSI_TTY_GETC );
+static inline _osi_call1( int, OSI_TTYPutc, OSI_TTY_PUTC, int, ch );
+static inline _osi_call0( int, OSI_TTYIRQAck, OSI_TTY_IRQ_ACK );
+
+#endif /* _H_OSI_CALLS */
diff --git a/roms/openbios/arch/ppc/pearpc/console.c b/roms/openbios/arch/ppc/pearpc/console.c
new file mode 100644
index 00000000..3869cbab
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/console.c
@@ -0,0 +1,43 @@
+
+/*
+ * <console.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+#include "libopenbios/ofmem.h"
+#include "pearpc/pearpc.h"
+
+
+typedef struct osi_fb_info {
+ unsigned long mphys;
+ int rb, w, h, depth;
+} osi_fb_info_t;
+
+
+int PearPC_GetFBInfo( osi_fb_info_t *fb )
+{
+
+ fb->w=1024;
+ fb->h=768;
+ fb->depth=15;
+ fb->rb=2048;
+ fb->mphys=0x84000000;
+
+ return 0;
+}
+
+#define openbios_GetFBInfo(x) PearPC_GetFBInfo(x)
+
+#include "../../../packages/video.c"
+#include "../../../libopenbios/console_common.c"
diff --git a/roms/openbios/arch/ppc/pearpc/init.c b/roms/openbios/arch/ppc/pearpc/init.c
new file mode 100644
index 00000000..ca6da0a4
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/init.c
@@ -0,0 +1,136 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <init.c>
+ *
+ * Initialization for pearpc
+ *
+ * Copyright (C) 2004 Greg Watson
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * based on mol/init.c:
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
+ * (samuel@ibrium.se, dary@lindesign.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "pearpc/pearpc.h"
+#include "libopenbios/ofmem.h"
+#include "openbios-version.h"
+
+extern void unexpected_excep( int vector );
+extern void ob_pci_init( void );
+extern void ob_adb_init( void );
+extern void setup_timers( void );
+
+#if 0
+int
+get_bool_res( const char *res )
+{
+ char buf[8], *p;
+
+ p = BootHGetStrRes( res, buf, sizeof(buf) );
+ if( !p )
+ return -1;
+ if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") )
+ return 1;
+ return 0;
+}
+#endif
+
+void
+unexpected_excep( int vector )
+{
+ printk("openbios panic: Unexpected exception %x\n", vector );
+ for( ;; )
+ ;
+}
+
+unsigned long isa_io_base;
+
+void
+entry( void )
+{
+ isa_io_base = 0x80000000;
+
+ printk("\n");
+ printk("=============================================================\n");
+ printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
+ OPENBIOS_BUILD_DATE);
+
+ ofmem_init();
+ initialize_forth();
+ /* won't return */
+
+ printk("of_startup returned!\n");
+ for( ;; )
+ ;
+}
+
+static void
+setenv( char *env, char *value )
+{
+ push_str( value );
+ push_str( env );
+ fword("$setenv");
+}
+
+void
+arch_of_init( void )
+{
+#if CONFIG_RTAS
+ phandle_t ph;
+#endif
+ int autoboot;
+
+ devtree_init();
+ nvram_init("/pci/mac-io/nvram");
+ openbios_init();
+ modules_init();
+ setup_timers();
+#ifdef CONFIG_DRIVER_PCI
+ ob_pci_init();
+#endif
+ node_methods_init();
+ init_video();
+
+#if CONFIG_RTAS
+ if( !(ph=find_dev("/rtas")) )
+ printk("Warning: No /rtas node\n");
+ else {
+ unsigned long size = 0x1000;
+ while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start )
+ size *= 2;
+ set_property( ph, "rtas-size", (char*)&size, sizeof(size) );
+ }
+#endif
+
+#if 0
+ /* tweak boot settings */
+ autoboot = !!get_bool_res("autoboot");
+#endif
+ autoboot = 0;
+ if( !autoboot )
+ printk("Autobooting disabled - dropping into OpenFirmware\n");
+ setenv("auto-boot?", autoboot ? "true" : "false" );
+ setenv("boot-command", "pearpcboot");
+
+#if 0
+ if( get_bool_res("tty-interface") == 1 )
+#endif
+ fword("activate-tty-interface");
+
+ /* hack */
+ device_end();
+ bind_func("pearpcboot", boot );
+}
diff --git a/roms/openbios/arch/ppc/pearpc/kernel.c b/roms/openbios/arch/ppc/pearpc/kernel.c
new file mode 100644
index 00000000..6408e421
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/kernel.c
@@ -0,0 +1,16 @@
+/*
+ * Creation Date: <2004/08/28 18:03:25 stepan>
+ * Time-stamp: <2004/08/28 18:03:25 stepan>
+ *
+ * <pearpc/kernel.c>
+ *
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "pearpc-dict.h"
+#include "../kernel.c"
diff --git a/roms/openbios/arch/ppc/pearpc/main.c b/roms/openbios/arch/ppc/pearpc/main.c
new file mode 100644
index 00000000..085494e5
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/main.c
@@ -0,0 +1,145 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <main.c>
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elfload.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "pearpc/pearpc.h"
+#include "libopenbios/ofmem.h"
+
+static void
+transfer_control_to_elf( unsigned long entry )
+{
+ extern void call_elf( unsigned long entry );
+ printk("Starting ELF image at 0x%08lX\n", entry);
+ call_elf( 0x400000 );
+ //call_elf( entry );
+
+ fatal_error("call_elf returned unexpectedly\n");
+}
+
+static int
+load_elf_rom( unsigned long *entry, int fd )
+{
+ int i, lszz_offs, elf_offs;
+ char buf[128], *addr;
+ Elf_ehdr ehdr;
+ Elf_phdr *phdr;
+ size_t s;
+
+ printk("Loading '%s'\n", get_file_path(fd));
+
+ /* the ELF-image (usually) starts at offset 0x4000 */
+ if( (elf_offs=find_elf(fd)) < 0 ) {
+ printk("----> %s is not an ELF image\n", buf );
+ exit(1);
+ }
+ if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) )
+ fatal_error("elf_readhdrs failed\n");
+
+ *entry = ehdr.e_entry;
+
+ /* load segments. Compressed ROM-image assumed to be located immediately
+ * after the last segment */
+ lszz_offs = elf_offs;
+ for( i=0; i<ehdr.e_phnum; i++ ) {
+ /* p_memsz, p_flags */
+ s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
+ seek_io( fd, elf_offs + phdr[i].p_offset );
+
+ /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
+ phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
+ phdr[i].p_vaddr ); */
+
+ if( phdr[i].p_vaddr != phdr[i].p_paddr )
+ printk("WARNING: ELF segment virtual addr != physical addr\n");
+ lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
+ if( !s )
+ continue;
+ if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 )
+ fatal_error("Claim failed!\n");
+
+ addr = (char*)phdr[i].p_vaddr;
+ if( read_io(fd, addr, s) != s )
+ fatal_error("read failed\n");
+
+#if 0
+ /* patch CODE segment */
+ if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) {
+ patch_newworld_rom( (char*)phdr[i].p_vaddr, s );
+ newworld_timer_hack( (char*)phdr[i].p_vaddr, s );
+ }
+#endif
+ flush_icache_range( addr, addr+s );
+
+ /*printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
+ (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/
+ }
+ free( phdr );
+ return lszz_offs;
+}
+
+
+static void
+encode_bootpath( const char *spec, const char *args )
+{
+ phandle_t chosen_ph = find_dev("/chosen");
+ set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 );
+ set_property( chosen_ph, "bootargs", args, strlen(args)+1 );
+}
+
+/************************************************************************/
+/* pearpc booting */
+/************************************************************************/
+
+static void
+pearpc_startup( void )
+{
+ const char *paths[] = { "hd:0,\\zImage.chrp", NULL };
+ const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL };
+ unsigned long entry;
+ int i, fd;
+
+ for( i=0; paths[i]; i++ ) {
+ if( (fd=open_io(paths[i])) == -1 )
+ continue;
+ (void) load_elf_rom( &entry, fd );
+ close_io( fd );
+ encode_bootpath( paths[i], args[i] );
+
+ update_nvram();
+ transfer_control_to_elf( entry );
+ /* won't come here */
+ }
+ printk("*** Boot failure! No secondary bootloader specified ***\n");
+}
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+void
+boot( void )
+{
+ fword("update-chosen");
+ pearpc_startup();
+}
diff --git a/roms/openbios/arch/ppc/pearpc/methods.c b/roms/openbios/arch/ppc/pearpc/methods.c
new file mode 100644
index 00000000..f505b6ce
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/methods.c
@@ -0,0 +1,329 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "pearpc/pearpc.h"
+#include "libopenbios/ofmem.h"
+
+/************************************************************************/
+/* RTAS (run-time abstraction services) */
+/************************************************************************/
+
+#ifdef CONFIG_RTAS
+DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
+
+/* ( physbase -- rtas_callback ) */
+static void
+rtas_instantiate( void )
+{
+ int physbase = POP();
+ int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start;
+ unsigned long virt;
+
+ while( s < size )
+ s += 0x1000;
+ virt = ofmem_claim_virt( 0, s, 0x1000 );
+ ofmem_map( physbase, virt, s, -1 );
+ memcpy( (char*)virt, of_rtas_start, size );
+
+ printk("RTAS instantiated at %08x\n", physbase );
+ flush_icache_range( (char*)virt, (char*)virt + size );
+
+ PUSH( physbase );
+}
+
+NODE_METHODS( rtas ) = {
+ { "instantiate", rtas_instantiate },
+ { "instantiate-rtas", rtas_instantiate },
+};
+#endif
+
+
+/************************************************************************/
+/* stdout */
+/************************************************************************/
+
+DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" );
+
+/* ( addr len -- actual ) */
+static void
+stdout_write( void )
+{
+ int len = POP();
+ char *addr = (char*)POP();
+
+ printk( "%s", s );
+ //vfd_draw_str( s );
+ console_draw_fstr(addr, len);
+
+ PUSH( len );
+}
+
+NODE_METHODS( video_stdout ) = {
+ { "write", stdout_write },
+};
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)POP();
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = getchar();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)POP();
+ for( i=0; i<len; i++ )
+ putchar( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+/************************************************************************/
+/* client interface 'quiesce' */
+/************************************************************************/
+
+DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" );
+
+/* ( -- ) */
+static void
+ciface_quiesce( unsigned long args[], unsigned long ret[] )
+{
+#if 0
+ unsigned long msr;
+ /* This seems to be the correct thing to do - but I'm not sure */
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr &= ~(MSR_IR | MSR_DR);
+ asm volatile("mtmsr %0" :: "r" (msr) );
+#endif
+ printk("=============================================================\n\n");
+}
+
+/* ( -- ms ) */
+static void
+ciface_milliseconds( unsigned long args[], unsigned long ret[] )
+{
+ extern unsigned long get_timer_freq();
+ static unsigned long mticks=0, usecs=0;
+ unsigned long t;
+
+ asm volatile("mftb %0" : "=r" (t) : );
+ if( mticks )
+ usecs += get_timer_freq() / 1000000 * ( t-mticks );
+ mticks = t;
+
+ PUSH( usecs/1000 );
+}
+
+
+NODE_METHODS( ciface ) = {
+ { "quiesce", ciface_quiesce },
+ { "milliseconds", ciface_milliseconds },
+};
+
+
+/************************************************************************/
+/* MMU/memory methods */
+/************************************************************************/
+
+DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
+DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" );
+DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" );
+
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_phys( phys, size, align );
+
+ if( ret == (ucell)-1 ) {
+ printk("MEM: claim failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys size align --- base ) */
+static void
+mmu_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_virt( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MMU: CLAIM failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mmu_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys virt size mode -- [ret???] ) */
+static void
+mmu_map( void )
+{
+ ucell mode = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell phys = POP();
+ ucell ret;
+
+ /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
+ ret = ofmem_map( phys, virt, size, mode );
+
+ if( ret ) {
+ printk("MMU: map failure\n");
+ throw( -13 );
+ return;
+ }
+}
+
+/* ( virt size -- ) */
+static void
+mmu_unmap( void )
+{
+ POP(); POP();
+}
+
+/* ( virt -- false | phys mode true ) */
+static void
+mmu_translate( void )
+{
+ ucell mode;
+ ucell virt = POP();
+ ucell phys = ofmem_translate( virt, &mode );
+
+ if( phys == -1 ) {
+ PUSH( 0 );
+ } else {
+ PUSH( phys );
+ PUSH( mode );
+ PUSH( -1 );
+ }
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ POP();
+ POP();
+}
+
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+};
+
+NODE_METHODS( mmu ) = {
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "translate", mmu_translate },
+};
+
+NODE_METHODS( mmu_ciface ) = {
+ { "cif-claim", ciface_claim },
+ { "cif-release", ciface_release },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( void )
+{
+#ifdef CONFIG_RTAS
+ REGISTER_NODE( rtas );
+#endif
+ REGISTER_NODE( video_stdout );
+ REGISTER_NODE( ciface );
+ REGISTER_NODE( memory );
+ REGISTER_NODE( mmu );
+ REGISTER_NODE( mmu_ciface );
+ REGISTER_NODE( tty );
+}
diff --git a/roms/openbios/arch/ppc/pearpc/pearpc.c b/roms/openbios/arch/ppc/pearpc/pearpc.c
new file mode 100644
index 00000000..234052ce
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/pearpc.c
@@ -0,0 +1,206 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <pearpc.c>
+ *
+ * Copyright (C) 2004, Greg Watson
+ *
+ * derived from mol.c
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/nvram.h"
+#include "libc/vsprintf.h"
+#include "libc/string.h"
+#include "pearpc/pearpc.h"
+#include <stdarg.h>
+
+#define UART_BASE 0x3f8
+
+// FIXME
+unsigned long virt_offset = 0;
+
+
+void
+exit( int status )
+{
+ for (;;);
+}
+
+void
+fatal_error( const char *err )
+{
+ printk("Fatal error: %s\n", err );
+ exit(0);
+}
+
+void
+panic( const char *err )
+{
+ printk("Panic: %s\n", err );
+ exit(0);
+
+ /* won't come here... this keeps the gcc happy */
+ for( ;; )
+ ;
+}
+
+
+/************************************************************************/
+/* print using OSI interface */
+/************************************************************************/
+
+static int do_indent;
+
+int
+printk( const char *fmt, ... )
+{
+ char *p, buf[1024];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ ) {
+ if( *p == '\n' )
+ do_indent = 0;
+ if( do_indent++ == 1 ) {
+ putchar( '>' );
+ putchar( '>' );
+ putchar( ' ' );
+ }
+ putchar( *p );
+ }
+ return i;
+}
+
+
+/************************************************************************/
+/* TTY iface */
+/************************************************************************/
+
+static int ttychar = -1;
+
+static int
+tty_avail( void )
+{
+ return 1;
+}
+
+static int
+tty_putchar( int c )
+{
+ if( tty_avail() ) {
+ while (!(inb(UART_BASE + 0x05) & 0x20))
+ ;
+ outb(c, UART_BASE);
+ while (!(inb(UART_BASE + 0x05) & 0x40))
+ ;
+ }
+ return c;
+}
+
+int
+availchar( void )
+{
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ ttychar = inb(UART_BASE);
+ return (ttychar >= 0);
+}
+
+int
+getchar( void )
+{
+ int ch;
+
+ if( !tty_avail() )
+ return 0;
+
+ if( ttychar < 0 )
+ return inb(UART_BASE);
+ ch = ttychar;
+ ttychar = -1;
+ return ch;
+}
+
+int
+putchar( int c )
+{
+ if (c == '\n')
+ tty_putchar('\r');
+ return tty_putchar(c);
+}
+
+
+/************************************************************************/
+/* briQ specific stuff */
+/************************************************************************/
+
+#define IO_NVRAM_PA_START 0x80860000
+#define IO_NVRAM_PA_END 0x80880000
+
+static char *nvram=(char *)IO_NVRAM_PA_START;
+
+void
+dump_nvram(void)
+{
+ static char hexdigit[] = "0123456789abcdef";
+ int i;
+ for (i = 0; i < 16*4; i++)
+ {
+ printk ("%c", hexdigit[nvram[i<<4] >> 4]);
+ printk ("%c", hexdigit[nvram[i<<4] % 16]);
+ if (!((i + 1) % 16))
+ {
+ printk ("\n");
+ }
+ else
+ {
+ printk (" ");
+ }
+ }
+}
+
+
+int
+arch_nvram_size( void )
+{
+ return (IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4;
+}
+
+void
+arch_nvram_put( char *buf )
+{
+ int i;
+ for (i=0; i<(IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; i++)
+ nvram[i<<4]=buf[i];
+ // memcpy(nvram, buf, IO_NVRAM_PA_END-IO_NVRAM_PA_START);
+ printk("new nvram:\n");
+ dump_nvram();
+}
+
+void
+arch_nvram_get( char *buf )
+{
+ int i;
+ for (i=0; i<(IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; i++)
+ buf[i]=nvram[i<<4];
+
+ //memcpy(buf, nvram, IO_NVRAM_PA_END-IO_NVRAM_PA_START);
+ printk("current nvram:\n");
+ dump_nvram();
+}
diff --git a/roms/openbios/arch/ppc/pearpc/pearpc.fs b/roms/openbios/arch/ppc/pearpc/pearpc.fs
new file mode 100644
index 00000000..0d018b1c
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/pearpc.fs
@@ -0,0 +1,116 @@
+\ pearpc specific initialization code
+\
+\ Copyright (C) 2005 Stefan Reinauer
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+
+\ -------------------------------------------------------------------------
+\ initialization
+\ -------------------------------------------------------------------------
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " rtc" " /pci/isa/rtc" preopen
+ " memory" " /memory" preopen
+ " mmu" " /cpu@0" preopen
+ \ " stdout" " /packages/terminal-emulator" preopen
+ " stdout" " /pci/pci6666,6666" preopen
+ " stdin" " /pci/via-cuda/adb" preopen
+
+; SYSTEM-initializer
+
+
+\ -------------------------------------------------------------------------
+\ device tree fixing
+\ -------------------------------------------------------------------------
+
+\ add decode-address methods
+: (make-decodable) ( phandle -- )
+
+ dup " #address-cells" rot get-package-property 0= if
+ decode-int nip nip
+ over " decode-unit" rot find-method if 2drop else
+ ( save phandle ncells )
+
+ over active-package!
+ case
+ 1 of ['] parse-hex " decode-unit" is-xt-func endof
+ 3 of
+ " bus-range" active-package get-package-property 0= if
+ decode-int nip nip
+ ['] encode-unit-pci " encode-unit" is-xt-func
+ " decode-unit" is-func-begin
+ ['] (lit) , ,
+ ['] decode-unit-pci-bus ,
+ is-func-end
+ then
+ endof
+ endcase
+ then
+ then
+ drop
+;
+
+: init-pearpc-tree ( -- )
+ active-package
+
+ iterate-tree-begin
+ begin ?dup while
+
+ dup (make-decodable)
+
+ iterate-tree
+ repeat
+
+ active-package!
+;
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /packages/terminal-emulator" find-dev if drop
+ " /pci/via-cuda/adb" " input-device" $setenv
+ " /pci/pci6666,6666" " output-device" $setenv
+ then
+;
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+
+\ -------------------------------------------------------------------------
+\ pre-booting
+\ -------------------------------------------------------------------------
+
+: update-chosen
+ " /chosen" find-device
+ stdin @ encode-int " stdin" property
+ stdout @ encode-int " stdout" property
+ " /pci/isa/interrupt-controller" find-dev if encode-int " interrupt-controller" property then
+ device-end
+;
diff --git a/roms/openbios/arch/ppc/pearpc/pearpc.h b/roms/openbios/arch/ppc/pearpc/pearpc.h
new file mode 100644
index 00000000..44497d79
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/pearpc.h
@@ -0,0 +1,26 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <pearpc.h>
+ *
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_PEARPC
+#define _H_PEARPC
+
+/* vfd.c */
+extern int vfd_draw_str( const char *str );
+extern void vfd_close( void );
+
+extern int console_draw_fstr(const char *str, int len);
+
+#include "kernel.h"
+
+#endif /* _H_PEARPC */
diff --git a/roms/openbios/arch/ppc/pearpc/tree.c b/roms/openbios/arch/ppc/pearpc/tree.c
new file mode 100644
index 00000000..abd1bf02
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/tree.c
@@ -0,0 +1,23 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <tree.c>
+ *
+ * device tree setup
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+
+void devtree_init( void )
+{
+ fword("init-pearpc-tree");
+}
diff --git a/roms/openbios/arch/ppc/pearpc/tree.fs b/roms/openbios/arch/ppc/pearpc/tree.fs
new file mode 100644
index 00000000..d19b485f
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/tree.fs
@@ -0,0 +1,305 @@
+\ PearPC specific initialization code
+\
+\ Copyright (C) 2005 Stefan Reinauer
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
+" /" find-device
+
+" chrp" device-type
+" OpenSource,PEARPC" model
+h# 80000000 encode-int " isa-io-base" property
+1 encode-int " #interrupt-cells" property
+1 encode-int " #size-cells" property
+
+new-device
+ " memory" device-name
+ " memory" device-type
+ 0 encode-int h# 1E00000 encode-int encode+
+ h# 2000000 encode-int encode+ h# 40000000 encode-int encode+
+ " available" property
+ 0 h# 40000000 reg
+ external
+ : open true ;
+ : close ;
+finish-device
+
+new-device
+ " cpu" device-name
+ " cpu" device-type
+ " " encode-string " translations" property
+ 0 encode-phys h# 8000000 encode-int encode+ " available" property
+ d# 32 encode-int " d-cache-block-size" property
+ 8 encode-int " d-cache-sets" property
+ d# 32768 encode-int " d-cache-size" property
+ d# 32 encode-int " i-cache-block-size" property
+ 8 encode-int " i-cache-sets" property
+ d# 32768 encode-int " i-cache-size" property
+ " " encode-string " cache-unified" property
+ 2 encode-int " i-tlb-sets" property
+ d# 128 encode-int " i-tlb-size" property
+ 2 encode-int " d-tlb-sets" property
+ d# 128 encode-int " d-tlb-size" property
+ " " encode-string " tlb-split" property
+ 2 encode-int " tlb-sets" property
+ d# 256 encode-int " tlb-size" property
+ " " encode-string " performance-monitor" property
+ " " encode-string " graphics" property
+ 4 encode-int " reservation-granule-size" property
+ d# 25000000 encode-int " timebase-frequency" property
+ d# 300000000 encode-int " clock-frequency" property
+ d# 66000000 encode-int " bus-frequency" property
+ h# 88201 encode-int " cpu-version" property
+ 0 encode-int " reg" property
+finish-device
+
+" /pci" find-device
+ h# 01000000 encode-int 0 encode-int encode+ 0 encode-int encode+
+ h# 80000000 encode-int encode+ 0 encode-int encode+
+ h# 01000000 encode-int encode+
+ h# 02000000 encode-int encode+ 0 encode-int encode+ 0 encode-int encode+
+ h# C0000000 encode-int encode+ 0 encode-int encode+
+ h# 08000000 encode-int encode+
+ " ranges" property
+ " IBM,CPC710" model
+ h# FF5F7700 encode-int " 8259-interrupt-acknowledge" property
+ h# 0000F800 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 7 encode-int encode+
+ " interrupt-map-mask" property
+ 1 encode-int " #interrupt-cells" property
+ h# 80000000 encode-int " system-dma-base" property
+ d# 33333333 encode-int " clock-frequency" property
+ " " encode-string " primary-bridge" property
+ 0 encode-int " pci-bridge-number" property
+ h# FEC00000 encode-int h# 100000 encode-int encode+ " reg" property
+ 0 encode-int 0 encode-int encode+ " bus-range" property
+
+new-device
+ " isa" device-name
+ " isa" device-type
+ 2 encode-int " #address-cells" property
+ 1 encode-int " #size-cells" property
+
+ external
+ : open true ;
+ : close ;
+
+finish-device
+
+: ?devalias ( alias-str alias-len device-str device-len --
+ \ alias-str alias-len false | true )
+ active-package >r
+ " /aliases" find-device
+ \ 2dup ." Checking " type
+ 2dup find-dev if \ check if device exists
+ drop
+ 2over find-dev if \ do we already have an alias?
+ \ ." alias exists" cr
+ drop 2drop false
+ else
+ \ ." device exists" cr
+ encode-string
+ 2swap property
+ true
+ then
+ else
+ \ ." device doesn't exist" cr
+ 2drop false
+ then
+ r> active-package!
+ ;
+
+:noname
+ " hd"
+ " /pci/pci-ata/ata-1/disk@0" ?devalias not if
+ " /pci/pci-ata/ata-1/disk@1" ?devalias not if
+ " /pci/pci-ata/ata-2/disk@0" ?devalias not if
+ " /pci/pci-ata/ata-2/disk@1" ?devalias not if
+ 2drop ." No disk found." cr
+ then
+ then
+ then
+ then
+
+ " cdrom"
+ " /pci/pci-ata/ata-1/cdrom@0" ?devalias not if
+ " /pci/pci-ata/ata-1/cdrom@1" ?devalias not if
+ " /pci/pci-ata/ata-2/cdrom@0" ?devalias not if
+ " /pci/pci-ata/ata-2/cdrom@1" ?devalias not if
+ 2drop ." No cdrom found" cr
+ then
+ then
+ then
+ then
+; SYSTEM-initializer
+
+new-device
+ " ide" device-name
+ " ide" device-type
+ " WINBOND,82C553" model
+ h# 28 encode-int " max-latency" property
+ h# 2 encode-int " min-grant" property
+ h# 1 encode-int " devsel-speed" property
+ h# 0 encode-int " subsystem-vendor-id" property
+ h# 0 encode-int " subsystem-id" property
+ h# 1018A encode-int " class-code" property
+ h# 5 encode-int " revision-id" property
+ h# 105 encode-int " device-id" property
+ h# 10AD encode-int " vendor-id" property
+ h# 1003110 encode-int 0 encode-int encode+ h# 10020 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003114 encode-int 0 encode-int encode+ h# 10030 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003118 encode-int 0 encode-int encode+ h# 10040 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 100311C encode-int 0 encode-int encode+ h# 10034 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003120 encode-int 0 encode-int encode+ h# 10050 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003124 encode-int 0 encode-int encode+ h# 10060 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ " assigned-addresses" property
+ h# 3100 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+
+ h# 1003110 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003114 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003118 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 100311C encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 4 encode-int encode+ 0 encode-int encode+
+ h# 1003120 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ h# 1003124 encode-int 0 encode-int encode+ h# 0 encode-int encode+
+ h# 10 encode-int encode+ 0 encode-int encode+
+ " reg" property
+finish-device
+
+new-device
+ " ethernet" device-name
+ " network" device-type
+ " AMD,79C973" model
+ h# 3800 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+
+ " reg" property
+finish-device
+
+" /pci/isa" find-device
+ 0 0 " assigned-addresses" property
+ 0 0 " ranges" property
+ 0 encode-int " slot-names" property
+ d# 8333333 encode-int " clock-frequency" property
+ 0 encode-int " eisa-slots" property
+ 2 encode-int " #interrupt-cells" property
+ " W83C553F" encode-string " compatible" property
+ " WINBOND,82C553" model
+ 0 encode-int " max-latency" property
+ 0 encode-int " min-grant" property
+ 1 encode-int " devsel-speed" property
+ 0 encode-int " subsystem-vendor-id" property
+ 0 encode-int " subsystem-id" property
+ h# 60100 encode-int " class-code" property
+ h# 10 encode-int " revision-id" property
+ h# 565 encode-int " device-id" property
+ h# 10AD encode-int " vendor-id" property
+ h# 3000 encode-int 0 encode-int encode+ 0 encode-int encode+
+ 0 encode-int encode+ 0 encode-int encode+ " reg" property
+
+new-device
+ " rtc" device-name
+ " rtc" device-type
+ " DS17285S" model
+ " MC146818" encode-string
+ " DS17285S" encode-string encode+
+ " pnpPNP,b00" encode-string encode+ " compatible" property
+ 8 encode-int 0 encode-int encode+ " interrupts" property
+ h# 70 encode-int 1 encode-int encode+
+ 2 encode-int encode+ " reg" property
+finish-device
+
+new-device
+ " interrupt-controller" device-name
+ " interrupt-controller" device-type
+ " 8259" model
+ " " encode-string " interrupt-controller" property
+ 2 encode-int " #interrupt-cells" property
+ 1 encode-int
+ 2 encode-int encode+
+ 3 encode-int encode+
+ 6 encode-int encode+
+ " reserved-interrupts" property
+ " 8259" encode-string
+ " chrp,iic" encode-string encode+
+ " compatible" property
+ h# 20 encode-int 1 encode-int encode+
+ 2 encode-int encode+ " reg" property
+finish-device
+
+new-device
+ " serial" device-name
+ " serial" device-type
+ " no" encode-string " ctsrts" property
+ " no" encode-string " xon" property
+ " no" encode-string " parity" property
+ d# 115200 encode-int " bps" property
+ 1 encode-int " stop-bits" property
+ 8 encode-int " data-bits" property
+ h# 70800 encode-int " divisor" property
+ h# 708000 encode-int " clock-frequency" property
+ 4 encode-int 0 encode-int encode+ " interrupts" property
+ h# 3F8 encode-int 1 encode-int encode+
+ 8 encode-int encode+ " reg" property
+finish-device
+
+" /pci" find-device
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int " interrupt-parent" property
+ then
+ h# 3800 encode-int 0 encode-int encode+
+ 0 encode-int encode+ 1 encode-int encode+
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int encode+
+ then
+ h# 0C encode-int encode+ 1 encode-int encode+
+ " interrupt-map" property
+
+" /pci/isa" find-device
+ " /pci/isa/interrupt-controller" find-dev if
+ encode-int " interrupt-parent" property
+ then
+
+\ -------------------------------------------------------------
+\ /packages
+\ -------------------------------------------------------------
+
+" /packages" find-device
+
+ " packages" device-name
+ external
+ \ allow packages to be opened with open-dev
+ : open true ;
+ : close ;
+
+\ /packages/terminal-emulator
+new-device
+ " terminal-emulator" device-name
+ external
+ : open true ;
+ : close ;
+ \ : write ( addr len -- actual )
+ \ dup -rot type
+ \ ;
+finish-device
+
+\ -------------------------------------------------------------
+\ The END
+\ -------------------------------------------------------------
+device-end
diff --git a/roms/openbios/arch/ppc/pearpc/vfd.c b/roms/openbios/arch/ppc/pearpc/vfd.c
new file mode 100644
index 00000000..06485f2d
--- /dev/null
+++ b/roms/openbios/arch/ppc/pearpc/vfd.c
@@ -0,0 +1,42 @@
+/*
+ * Creation Date: <2004/08/28 17:29:43 greg>
+ * Time-stamp: <2004/08/28 17:29:43 greg>
+ *
+ * <vfd.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "pearpc/pearpc.h"
+
+static int vfd_is_open;
+
+static int
+vfd_init( void )
+{
+ vfd_is_open = 1;
+ return 0;
+}
+
+void
+vfd_close( void )
+{
+}
+
+int
+vfd_draw_str( const char *str )
+{
+ if (!vfd_is_open)
+ vfd_init();
+
+ return 0;
+}
diff --git a/roms/openbios/arch/ppc/ppc.fs b/roms/openbios/arch/ppc/ppc.fs
new file mode 100644
index 00000000..0414f22c
--- /dev/null
+++ b/roms/openbios/arch/ppc/ppc.fs
@@ -0,0 +1,68 @@
+include config.fs
+
+\ -------------------------------------------------------------------------
+\ registers
+\ -------------------------------------------------------------------------
+
+0 value %cr
+0 value %ctr
+0 value %lr
+0 value %msr
+0 value %srr0
+0 value %srr1
+0 value %pc \ should be an alias for %srr0
+
+0 value %r0
+0 value %r1
+0 value %r2
+0 value %r3
+0 value %r4
+0 value %r5
+0 value %r6
+0 value %r7
+0 value %r8
+0 value %r9
+0 value %r10
+0 value %r11
+0 value %r12
+0 value %r13
+0 value %r14
+0 value %r15
+0 value %r16
+0 value %r17
+0 value %r18
+0 value %r19
+0 value %r20
+0 value %r21
+0 value %r22
+0 value %r23
+0 value %r24
+0 value %r25
+0 value %r26
+0 value %r27
+0 value %r28
+0 value %r29
+0 value %r30
+0 value %r31
+
+0 value %xer
+0 value %sprg0
+0 value %sprg1
+0 value %sprg2
+0 value %sprg3
+
+\ -------------------------------------------------------------------------
+\ Load VGA FCode driver blob
+\ -------------------------------------------------------------------------
+
+[IFDEF] CONFIG_DRIVER_VGA
+ -1 value vga-driver-fcode
+ " QEMU,VGA.bin" $encode-file to vga-driver-fcode
+[THEN]
+
+\ -------------------------------------------------------------------------
+\ other
+\ -------------------------------------------------------------------------
+
+\ Set by BootX when booting Mac OS X
+defer spin
diff --git a/roms/openbios/arch/ppc/qemu/console.c b/roms/openbios/arch/ppc/qemu/console.c
new file mode 100644
index 00000000..53a32152
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/console.c
@@ -0,0 +1,88 @@
+/*
+ * <console.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "drivers/drivers.h"
+
+#ifdef CONFIG_DEBUG_CONSOLE
+/* ******************************************************************
+ * common functions, implementing simple concurrent console
+ * ****************************************************************** */
+
+static int mac_putchar(int c)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ escc_uart_putchar(c & 0xff);
+#endif
+ return c;
+}
+
+static int mac_availchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (escc_uart_charav(CONFIG_SERIAL_PORT))
+ return 1;
+#endif
+ return 0;
+}
+
+static int mac_getchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (escc_uart_charav(CONFIG_SERIAL_PORT))
+ return (escc_uart_getchar(CONFIG_SERIAL_PORT));
+#endif
+ return 0;
+}
+
+struct _console_ops mac_console_ops = {
+ .putchar = mac_putchar,
+ .availchar = mac_availchar,
+ .getchar = mac_getchar
+};
+
+static int prep_putchar(int c)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ uart_putchar(c & 0xff);
+#endif
+ return c;
+}
+
+static int prep_availchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return 1;
+#endif
+ return 0;
+}
+
+static int prep_getchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return (uart_getchar(CONFIG_SERIAL_PORT));
+#endif
+ return 0;
+}
+
+struct _console_ops prep_console_ops = {
+ .putchar = prep_putchar,
+ .availchar = prep_availchar,
+ .getchar = prep_getchar
+};
+
+#endif // CONFIG_DEBUG_CONSOLE
diff --git a/roms/openbios/arch/ppc/qemu/init.c b/roms/openbios/arch/ppc/qemu/init.c
new file mode 100644
index 00000000..4fe8b722
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/init.c
@@ -0,0 +1,951 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <init.c>
+ *
+ * Initialization for qemu
+ *
+ * Copyright (C) 2004 Greg Watson
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * based on mol/init.c:
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh
+ * (samuel@ibrium.se, dary@lindesign.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "drivers/pci.h"
+#include "arch/common/nvram.h"
+#include "drivers/drivers.h"
+#include "qemu/qemu.h"
+#include "libopenbios/ofmem.h"
+#include "openbios-version.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+#include "arch/ppc/processor.h"
+
+#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
+struct cpudef {
+ unsigned int iu_version;
+ const char *name;
+ int icache_size, dcache_size;
+ int icache_sets, dcache_sets;
+ int icache_block_size, dcache_block_size;
+ int tlb_sets, tlb_size;
+ void (*initfn)(const struct cpudef *cpu);
+};
+
+static uint16_t machine_id = 0;
+
+extern void unexpected_excep(int vector);
+
+void
+unexpected_excep(int vector)
+{
+ printk("openbios panic: Unexpected exception %x\n", vector);
+ for (;;) {
+ }
+}
+
+extern void __divide_error(void);
+
+void
+__divide_error(void)
+{
+ return;
+}
+
+enum {
+ ARCH_PREP = 0,
+ ARCH_MAC99,
+ ARCH_HEATHROW,
+ ARCH_MAC99_U3,
+};
+
+int is_apple(void)
+{
+ return is_oldworld() || is_newworld();
+}
+
+int is_oldworld(void)
+{
+ return machine_id == ARCH_HEATHROW;
+}
+
+int is_newworld(void)
+{
+ return (machine_id == ARCH_MAC99) ||
+ (machine_id == ARCH_MAC99_U3);
+}
+
+static const pci_arch_t known_arch[] = {
+ [ARCH_PREP] = {
+ .name = "PREP",
+ .vendor_id = PCI_VENDOR_ID_MOTOROLA,
+ .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN,
+ .cfg_addr = 0x80000cf8,
+ .cfg_data = 0x80000cfc,
+ .cfg_base = 0x80000000,
+ .cfg_len = 0x00100000,
+ .host_pci_base = 0xc0000000,
+ .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */
+ .mem_len = 0x10000000,
+ .io_base = 0x80000000,
+ .io_len = 0x00010000,
+ .rbase = 0x00000000,
+ .rlen = 0x00400000,
+ .irqs = { 9, 11, 9, 11 }
+ },
+ [ARCH_MAC99] = {
+ .name = "MAC99",
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI,
+ .cfg_addr = 0xf2800000,
+ .cfg_data = 0xf2c00000,
+ .cfg_base = 0xf2000000,
+ .cfg_len = 0x02000000,
+ .host_pci_base = 0x0,
+ .pci_mem_base = 0x80000000,
+ .mem_len = 0x10000000,
+ .io_base = 0xf2000000,
+ .io_len = 0x00800000,
+ .rbase = 0x00000000,
+ .rlen = 0x01000000,
+ .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
+ },
+ [ARCH_MAC99_U3] = {
+ .name = "MAC99_U3",
+ .vendor_id = PCI_VENDOR_ID_APPLE,
+ .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
+ .cfg_addr = 0xf0800000,
+ .cfg_data = 0xf0c00000,
+ .cfg_base = 0xf0000000,
+ .cfg_len = 0x02000000,
+ .host_pci_base = 0x0,
+ .pci_mem_base = 0x80000000,
+ .mem_len = 0x10000000,
+ .io_base = 0xf2000000,
+ .io_len = 0x00800000,
+ .rbase = 0x00000000,
+ .rlen = 0x01000000,
+ .irqs = { 0x1b, 0x1c, 0x1d, 0x1e }
+ },
+ [ARCH_HEATHROW] = {
+ .name = "HEATHROW",
+ .vendor_id = PCI_VENDOR_ID_MOTOROLA,
+ .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106,
+ .cfg_addr = 0xfec00000,
+ .cfg_data = 0xfee00000,
+ .cfg_base = 0x80000000,
+ .cfg_len = 0x7f000000,
+ .host_pci_base = 0x0,
+ .pci_mem_base = 0x80000000,
+ .mem_len = 0x10000000,
+ .io_base = 0xfe000000,
+ .io_len = 0x00800000,
+ .rbase = 0xfd000000,
+ .rlen = 0x01000000,
+ .irqs = { 21, 22, 23, 24 }
+ },
+};
+unsigned long isa_io_base;
+
+extern struct _console_ops mac_console_ops, prep_console_ops;
+
+void
+entry(void)
+{
+ uint32_t temp = 0;
+ char buf[5];
+
+ arch = &known_arch[ARCH_HEATHROW];
+
+ fw_cfg_init();
+
+ fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
+ buf[4] = '\0';
+ if (strncmp(buf, "QEMU", 4) == 0) {
+ temp = fw_cfg_read_i32(FW_CFG_ID);
+ if (temp == 1) {
+ machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
+ arch = &known_arch[machine_id];
+ }
+ }
+
+ isa_io_base = arch->io_base;
+
+#ifdef CONFIG_DEBUG_CONSOLE
+ if (is_apple()) {
+ init_console(mac_console_ops);
+ } else {
+ init_console(prep_console_ops);
+ }
+#endif
+
+ if (temp != 1) {
+ printk("Incompatible configuration device version, freezing\n");
+ for (;;) {
+ }
+ }
+
+ ofmem_init();
+ initialize_forth();
+ /* won't return */
+
+ printk("of_startup returned!\n");
+ for (;;) {
+ }
+}
+
+/* -- phys.lo ... phys.hi */
+static void
+push_physaddr(phys_addr_t value)
+{
+ PUSH(value);
+#ifdef CONFIG_PPC64
+ PUSH(value >> 32);
+#endif
+}
+
+/* From drivers/timer.c */
+extern unsigned long timer_freq;
+
+static void
+cpu_generic_init(const struct cpudef *cpu)
+{
+ push_str("/cpus");
+ fword("find-device");
+
+ fword("new-device");
+
+ push_str(cpu->name);
+ fword("device-name");
+
+ push_str("cpu");
+ fword("device-type");
+
+ PUSH(mfpvr());
+ fword("encode-int");
+ push_str("cpu-version");
+ fword("property");
+
+ PUSH(cpu->dcache_size);
+ fword("encode-int");
+ push_str("d-cache-size");
+ fword("property");
+
+ PUSH(cpu->icache_size);
+ fword("encode-int");
+ push_str("i-cache-size");
+ fword("property");
+
+ PUSH(cpu->dcache_sets);
+ fword("encode-int");
+ push_str("d-cache-sets");
+ fword("property");
+
+ PUSH(cpu->icache_sets);
+ fword("encode-int");
+ push_str("i-cache-sets");
+ fword("property");
+
+ PUSH(cpu->dcache_block_size);
+ fword("encode-int");
+ push_str("d-cache-block-size");
+ fword("property");
+
+ PUSH(cpu->icache_block_size);
+ fword("encode-int");
+ push_str("i-cache-block-size");
+ fword("property");
+
+ PUSH(cpu->tlb_sets);
+ fword("encode-int");
+ push_str("tlb-sets");
+ fword("property");
+
+ PUSH(cpu->tlb_size);
+ fword("encode-int");
+ push_str("tlb-size");
+ fword("property");
+
+ timer_freq = fw_cfg_read_i32(FW_CFG_PPC_TBFREQ);
+ PUSH(timer_freq);
+ fword("encode-int");
+ push_str("timebase-frequency");
+ fword("property");
+
+ PUSH(fw_cfg_read_i32(FW_CFG_PPC_CLOCKFREQ));
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+
+ PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ));
+ fword("encode-int");
+ push_str("bus-frequency");
+ fword("property");
+
+ push_str("running");
+ fword("encode-string");
+ push_str("state");
+ fword("property");
+}
+
+static void
+cpu_add_pir_property(void)
+{
+ unsigned long pir;
+
+ asm("mfspr %0, 1023\n"
+ : "=r"(pir) :);
+ PUSH(pir);
+ fword("encode-int");
+ push_str("reg");
+ fword("property");
+}
+
+static void
+cpu_604_init(const struct cpudef *cpu)
+{
+ cpu_generic_init(cpu);
+ cpu_add_pir_property();
+
+ fword("finish-device");
+}
+
+static void
+cpu_750_init(const struct cpudef *cpu)
+{
+ cpu_generic_init(cpu);
+
+ PUSH(0);
+ fword("encode-int");
+ push_str("reg");
+ fword("property");
+
+ fword("finish-device");
+}
+
+static void
+cpu_g4_init(const struct cpudef *cpu)
+{
+ cpu_generic_init(cpu);
+ cpu_add_pir_property();
+
+ fword("finish-device");
+}
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+/* In order to get 64 bit aware handlers that rescue all our
+ GPRs from getting truncated to 32 bits, we need to patch the
+ existing handlers so they jump to our 64 bit aware ones. */
+static void
+ppc64_patch_handlers(void)
+{
+ uint32_t *dsi = (uint32_t *)0x300UL;
+ uint32_t *isi = (uint32_t *)0x400UL;
+
+ // Patch the first DSI handler instruction to: ba 0x2000
+ *dsi = 0x48002002;
+
+ // Patch the first ISI handler instruction to: ba 0x2200
+ *isi = 0x48002202;
+
+ // Invalidate the cache lines
+ asm ("icbi 0, %0" : : "r"(dsi));
+ asm ("icbi 0, %0" : : "r"(isi));
+}
+#endif
+
+static void
+cpu_970_init(const struct cpudef *cpu)
+{
+ cpu_generic_init(cpu);
+
+ PUSH(0);
+ fword("encode-int");
+ push_str("reg");
+ fword("property");
+
+ PUSH(0);
+ PUSH(0);
+ fword("encode-bytes");
+ push_str("64-bit");
+ fword("property");
+
+ fword("finish-device");
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+ /* The 970 is a PPC64 CPU, so we need to activate
+ * 64bit aware interrupt handlers */
+
+ ppc64_patch_handlers();
+#endif
+
+ /* The 970 also implements the HIOR which we need to set to 0 */
+
+ mtspr(S_HIOR, 0);
+}
+
+static const struct cpudef ppc_defs[] = {
+ {
+ .iu_version = 0x00040000,
+ .name = "PowerPC,604",
+ .icache_size = 0x4000,
+ .dcache_size = 0x4000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_604_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x00090000,
+ .name = "PowerPC,604e",
+ .icache_size = 0x4000,
+ .dcache_size = 0x4000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_604_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x000a0000,
+ .name = "PowerPC,604r",
+ .icache_size = 0x4000,
+ .dcache_size = 0x4000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_604_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x80040000,
+ .name = "PowerPC,MPC86xx",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ {
+ .iu_version = 0x000080000,
+ .name = "PowerPC,750",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x10080000,
+ .name = "PowerPC,750",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x70000000,
+ .name = "PowerPC,750",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x70020000,
+ .name = "PowerPC,750",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x800c0000,
+ .name = "PowerPC,74xx",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_750_init,
+ },
+ {
+ .iu_version = 0x0000c0000,
+ .name = "PowerPC,G4",
+ .icache_size = 0x8000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x20,
+ .dcache_block_size = 0x20,
+ .tlb_sets = 0x40,
+ .tlb_size = 0x80,
+ .initfn = cpu_g4_init,
+ },
+ {
+ .iu_version = 0x00390000,
+ .name = "PowerPC,970",
+ .icache_size = 0x10000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x200,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x80,
+ .dcache_block_size = 0x80,
+ .tlb_sets = 0x100,
+ .tlb_size = 0x1000,
+ .initfn = cpu_970_init,
+ },
+ { // XXX find out real values
+ .iu_version = 0x003C0000,
+ .name = "PowerPC,970FX",
+ .icache_size = 0x10000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x80,
+ .dcache_sets = 0x80,
+ .icache_block_size = 0x80,
+ .dcache_block_size = 0x80,
+ .tlb_sets = 0x100,
+ .tlb_size = 0x1000,
+ .initfn = cpu_970_init,
+ },
+ {
+ .iu_version = 0x00350000,
+ .name = "PowerPC,POWER4",
+ .icache_size = 0x10000,
+ .dcache_size = 0x8000,
+ .icache_sets = 0x100,
+ .dcache_sets = 0x40,
+ .icache_block_size = 0x80,
+ .dcache_block_size = 0x80,
+ .tlb_sets = 0x100,
+ .tlb_size = 0x1000,
+ .initfn = cpu_970_init,
+ },
+};
+
+static const struct cpudef *
+id_cpu(void)
+{
+ unsigned int iu_version;
+ unsigned int i;
+
+ iu_version = mfpvr() & 0xffff0000;
+
+ for (i = 0; i < sizeof(ppc_defs) / sizeof(struct cpudef); i++) {
+ if (iu_version == ppc_defs[i].iu_version)
+ return &ppc_defs[i];
+ }
+ printk("Unknown cpu (pvr %x), freezing!\n", iu_version);
+ for (;;) {
+ }
+}
+
+static void go(void);
+
+static void
+go(void)
+{
+ ucell addr;
+
+ feval("saved-program-state >sps.entry @");
+ addr = POP();
+
+ call_elf(0, 0, addr);
+}
+
+static void kvm_of_init(void)
+{
+ char hypercall[4 * 4];
+ uint32_t *hc32;
+
+ /* Don't expose /hypervisor when not in KVM */
+ if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM))
+ return;
+
+ push_str("/");
+ fword("find-device");
+
+ fword("new-device");
+
+ push_str("hypervisor");
+ fword("device-name");
+
+ push_str("hypervisor");
+ fword("device-type");
+
+ /* compatible */
+
+ push_str("linux,kvm");
+ fword("encode-string");
+ push_str("epapr,hypervisor-0.2");
+ fword("encode-string");
+ fword("encode+");
+ push_str("compatible");
+ fword("property");
+
+ /* Tell the guest about the hypercall instructions */
+ fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4);
+ hc32 = (uint32_t*)hypercall;
+ PUSH(hc32[0]);
+ fword("encode-int");
+ PUSH(hc32[1]);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(hc32[2]);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(hc32[3]);
+ fword("encode-int");
+ fword("encode+");
+ push_str("hcall-instructions");
+ fword("property");
+
+ /* ePAPR requires us to provide a unique guest id */
+ PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID));
+ fword("encode-int");
+ push_str("guest-id");
+ fword("property");
+
+ /* ePAPR requires us to provide a guest name */
+ push_str("KVM guest");
+ fword("encode-string");
+ push_str("guest-name");
+ fword("property");
+
+ fword("finish-device");
+}
+
+/*
+ * filll ( addr bytes quad -- )
+ */
+
+static void ffilll(void)
+{
+ const u32 longval = POP();
+ u32 bytes = POP();
+ u32 *laddr = (u32 *)cell2pointer(POP());
+ u32 len;
+
+ for (len = 0; len < bytes / sizeof(u32); len++) {
+ *laddr++ = longval;
+ }
+}
+
+void
+arch_of_init(void)
+{
+#ifdef CONFIG_RTAS
+ phandle_t ph;
+#endif
+ uint64_t ram_size;
+ const struct cpudef *cpu;
+ char buf[64], qemu_uuid[16];
+ const char *stdin_path, *stdout_path, *boot_path;
+ uint32_t temp = 0;
+ char *boot_device;
+ ofmem_t *ofmem = ofmem_arch_get_private();
+
+ openbios_init();
+ modules_init();
+ setup_timers();
+#ifdef CONFIG_DRIVER_PCI
+ ob_pci_init();
+#endif
+
+ printk("\n");
+ printk("=============================================================\n");
+ printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n",
+ OPENBIOS_BUILD_DATE);
+
+ fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
+ buf[4] = '\0';
+ printk("Configuration device id %s", buf);
+
+ temp = fw_cfg_read_i32(FW_CFG_ID);
+ printk(" version %d machine id %d\n", temp, machine_id);
+
+ temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
+
+ printk("CPUs: %x\n", temp);
+
+ ram_size = ofmem->ramsize;
+
+ printk("Memory: %lldM\n", ram_size / 1024 / 1024);
+
+ fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16);
+
+ printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
+ qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
+ qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
+ qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
+ qemu_uuid[15]);
+
+ /* set device tree root info */
+
+ push_str("/");
+ fword("find-device");
+
+ switch(machine_id) {
+ case ARCH_HEATHROW: /* OldWorld */
+
+ /* model */
+
+ push_str("Power Macintosh");
+ fword("model");
+
+ /* compatible */
+
+ push_str("AAPL,PowerMac G3");
+ fword("encode-string");
+ push_str("MacRISC");
+ fword("encode-string");
+ fword("encode+");
+ push_str("compatible");
+ fword("property");
+
+ /* misc */
+
+ push_str("device-tree");
+ fword("encode-string");
+ push_str("AAPL,original-name");
+ fword("property");
+
+ PUSH(0);
+ fword("encode-int");
+ push_str("AAPL,cpu-id");
+ fword("property");
+
+ PUSH(66 * 1000 * 1000);
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+ break;
+
+ case ARCH_MAC99:
+ case ARCH_MAC99_U3:
+ case ARCH_PREP:
+ default:
+
+ /* model */
+
+ push_str("PowerMac3,1");
+ fword("model");
+
+ /* compatible */
+
+ push_str("PowerMac3,1");
+ fword("encode-string");
+ push_str("MacRISC");
+ fword("encode-string");
+ fword("encode+");
+ push_str("MacRISC2");
+ fword("encode-string");
+ fword("encode+");
+ push_str("Power Macintosh");
+ fword("encode-string");
+ fword("encode+");
+ push_str("compatible");
+ fword("property");
+
+ /* misc */
+
+ push_str("bootrom");
+ fword("device-type");
+
+ PUSH(100 * 1000 * 1000);
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+ break;
+ }
+
+ /* Perhaps we can store UUID here ? */
+
+ push_str("0000000000000");
+ fword("encode-string");
+ push_str("system-id");
+ fword("property");
+
+ /* memory info */
+
+ push_str("/memory");
+ fword("find-device");
+
+ /* all memory */
+
+ push_physaddr(0);
+ fword("encode-phys");
+ /* This needs adjusting if #size-cells gets increased.
+ Alternatively use multiple (address, size) tuples. */
+ PUSH(ram_size & 0xffffffff);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ cpu = id_cpu();
+ cpu->initfn(cpu);
+ printk("CPU type %s\n", cpu->name);
+
+ snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name);
+ ofmem_register(find_dev("/memory"), find_dev(buf));
+ node_methods_init(buf);
+
+#ifdef CONFIG_RTAS
+ /* OldWorld Macs don't have an /rtas node. */
+ switch (machine_id) {
+ case ARCH_MAC99:
+ case ARCH_MAC99_U3:
+ if (!(ph = find_dev("/rtas"))) {
+ printk("Warning: No /rtas node\n");
+ } else {
+ unsigned long size = 0x1000;
+ while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start)
+ size *= 2;
+ set_property(ph, "rtas-size", (char*)&size, sizeof(size));
+ set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1);
+ }
+ break;
+ }
+#endif
+
+ if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
+ if (is_apple()) {
+ if (CONFIG_SERIAL_PORT) {
+ stdin_path = "scca";
+ stdout_path = "scca";
+ } else {
+ stdin_path = "sccb";
+ stdout_path = "sccb";
+ }
+ } else {
+ stdin_path = "ttya";
+ stdout_path = "ttya";
+ }
+
+ /* Some bootloaders force the output to the screen device, so
+ let's create a screen alias for the serial device too */
+
+ push_str("/aliases");
+ fword("find-device");
+
+ push_str(stdout_path);
+ fword("pathres-resolve-aliases");
+ fword("encode-string");
+ push_str("screen");
+ fword("property");
+ } else {
+ if (is_apple()) {
+ stdin_path = "adb-keyboard";
+ stdout_path = "screen";
+ } else {
+ stdin_path = "keyboard";
+ stdout_path = "screen";
+ }
+ }
+
+ kvm_of_init();
+
+ /* Setup nvram variables */
+ push_str("/options");
+ fword("find-device");
+
+ /* Setup default boot devices (not overriding user settings) */
+ fword("boot-device");
+ boot_device = pop_fstr_copy();
+ if (boot_device && strcmp(boot_device, "disk") == 0) {
+ switch (fw_cfg_read_i16(FW_CFG_BOOT_DEVICE)) {
+ case 'c':
+ boot_path = "hd";
+ break;
+ default:
+ case 'd':
+ boot_path = "cd";
+ break;
+ }
+
+ snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt %s:,%%BOOT", boot_path, boot_path, boot_path);
+ push_str(buf);
+ fword("encode-string");
+ push_str("boot-device");
+ fword("property");
+ }
+ free(boot_device);
+
+ /* Set up other properties */
+
+ push_str("/chosen");
+ fword("find-device");
+
+ push_str(stdin_path);
+ fword("pathres-resolve-aliases");
+ push_str("input-device");
+ fword("$setenv");
+
+ push_str(stdout_path);
+ fword("pathres-resolve-aliases");
+ push_str("output-device");
+ fword("$setenv");
+
+#if 0
+ if(getbool("tty-interface?") == 1)
+#endif
+ fword("activate-tty-interface");
+
+ device_end();
+
+ /* Implementation of filll word (required by BootX) */
+ bind_func("filll", ffilll);
+
+ bind_func("platform-boot", boot);
+ bind_func("(go)", go);
+}
diff --git a/roms/openbios/arch/ppc/qemu/kernel.c b/roms/openbios/arch/ppc/qemu/kernel.c
new file mode 100644
index 00000000..b26fba5f
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/kernel.c
@@ -0,0 +1,115 @@
+/*
+ * Creation Date: <2003/10/25 14:07:17 samuel>
+ * Time-stamp: <2004/08/28 17:48:19 stepan>
+ *
+ * <kernel.c>
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * Based upon unix.c (from OpenBIOS):
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "dict.h"
+#include "libopenbios/bindings.h"
+#include "kernel/stack.h"
+#include "kernel/kernel.h"
+#include "libc/string.h"
+#include "kernel.h"
+
+#define MEMORY_SIZE (256*1024) /* 256K ram for hosted system */
+/* 512K for the dictionary */
+#define DICTIONARY_SIZE (512 * 1024 / sizeof(ucell))
+#ifdef __powerpc64__
+#define DICTIONARY_BASE 0xfff08000 /* this must match the value in ldscript! */
+#define DICTIONARY_SECTION __attribute__((section(".data.dict")))
+#else
+#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary))
+#define DICTIONARY_SECTION
+#endif
+
+static ucell forth_dictionary[DICTIONARY_SIZE] DICTIONARY_SECTION = {
+#include "qemu-dict.h"
+};
+
+static ucell *memory;
+
+/************************************************************************/
+/* F U N C T I O N S */
+/************************************************************************/
+
+int
+forth_segv_handler( char *segv_addr )
+{
+ ucell addr = 0xdeadbeef;
+
+ if( PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead )
+ addr = *(ucell *)cell2pointer(PC);
+
+ printk("panic: segmentation violation at 0x%p\n", segv_addr);
+ printk("dict=0x%p here=0x%p(dict+0x%x) pc=0x%x(dict+0x%x)\n",
+ dict, (char*)dict + dicthead, dicthead,
+ PC, PC - pointer2cell(dict));
+ printk("dstackcnt=%d rstackcnt=%d instruction=%x\n",
+ dstackcnt, rstackcnt, addr);
+
+#ifdef DEBUG_DSTACK
+ printdstack();
+#endif
+#ifdef DEBUG_RSTACK
+ printrstack();
+#endif
+ return -1;
+}
+
+/*
+ * allocate memory and prepare engine for memory management.
+ */
+
+static void
+init_memory( void )
+{
+ memory = malloc(MEMORY_SIZE);
+ if( !memory )
+ panic("panic: not enough memory on host system.\n");
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator
+ */
+
+ PUSH( pointer2cell(memory) );
+ PUSH( pointer2cell(memory) + MEMORY_SIZE );
+}
+
+int
+initialize_forth( void )
+{
+ dict = (unsigned char *)forth_dictionary;
+ dicthead = (ucell)FORTH_DICTIONARY_END;
+ last = (ucell *)((unsigned char *)forth_dictionary +
+ FORTH_DICTIONARY_LAST);
+ dictlimit = sizeof(forth_dictionary);
+
+ forth_init();
+
+ PUSH_xt( bind_noname_func(arch_of_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+ if( PC ) {
+ init_memory();
+ enterforth((xt_t)PC);
+ free( memory );
+ }
+ free( dict );
+ return 0;
+}
diff --git a/roms/openbios/arch/ppc/qemu/kernel.h b/roms/openbios/arch/ppc/qemu/kernel.h
new file mode 100644
index 00000000..fe9be83d
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/kernel.h
@@ -0,0 +1,42 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <kernel.h>
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef __KERNEL_H__
+#define __KERNEL_H__
+
+/* misc.c */
+extern void fatal_error( const char *str );
+extern void exit( int status ) __attribute__ ((noreturn));
+
+/* start.S */
+extern void flush_icache_range( char *start, char *stop );
+extern char of_rtas_start[], of_rtas_end[];
+extern void call_elf( unsigned long arg1, unsigned long arg2, unsigned long elf_entry );
+
+/* methods.c */
+extern void node_methods_init( const char *cpuname );
+
+/* main.c */
+extern void boot( void );
+
+/* init.c */
+extern void entry( void );
+extern void arch_of_init( void );
+extern int get_bool_res( const char *str );
+
+/* tree.c */
+extern void devtree_init( void );
+
+
+#endif /* __KERNEL_H__ */
diff --git a/roms/openbios/arch/ppc/qemu/ldscript b/roms/openbios/arch/ppc/qemu/ldscript
new file mode 100644
index 00000000..8027b39d
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/ldscript
@@ -0,0 +1,68 @@
+OUTPUT_FORMAT(elf32-powerpc)
+OUTPUT_ARCH(powerpc:common)
+
+/* Initial load address
+ */
+BASE_ADDR = 0xfff00000;
+
+/* As NVRAM is at 0xfff04000, the .text needs to be after that
+ */
+TEXT_ADDR = 0xfff08000;
+
+/* Hard reset vector address
+ */
+HRESET_ADDR = 0xfffffffc;
+
+CSTACK_SIZE = 32768; /* client stack size */
+
+SECTIONS
+{
+ . = BASE_ADDR;
+
+ _start = BASE_ADDR + 0x0100;
+ .text.vectors ALIGN(4096): {
+ *(.text.vectors)
+ }
+
+ . = TEXT_ADDR;
+ /* Normal sections */
+ .text ALIGN(4096): {
+ *(.text)
+ *(.text.*)
+ }
+
+ .rodata ALIGN(4096): {
+ _rodata = .;
+ *(.rodata)
+ *(.rodata.*)
+ *(.note.ELFBoot)
+ }
+ .data ALIGN(4096): {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ _edata = .;
+ }
+
+ .bss ALIGN(4096): {
+ _bss = .;
+ *(.sbss)
+ *(.sbss.*)
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _ebss = .;
+ }
+
+ . = HRESET_ADDR;
+
+ .romentry : { *(.romentry) }
+
+ . = ALIGN(4096);
+ _end = .;
+
+ /* We discard .note sections other than .note.ELFBoot,
+ * because some versions of GCC generates useless ones. */
+
+ /DISCARD/ : { *(.comment*) *(.note.*) }
+}
diff --git a/roms/openbios/arch/ppc/qemu/main.c b/roms/openbios/arch/ppc/qemu/main.c
new file mode 100644
index 00000000..44b16666
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/main.c
@@ -0,0 +1,85 @@
+/*
+ * Creation Date: <2002/10/02 22:24:24 samuel>
+ * Time-stamp: <2004/03/27 01:57:55 samuel>
+ *
+ * <main.c>
+ *
+ *
+ *
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elf_load.h"
+#include "arch/common/nvram.h"
+#include "packages/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "kernel.h"
+#include "drivers/drivers.h"
+#include "libopenbios/ofmem.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+
+//#define DEBUG_QEMU
+
+#ifdef DEBUG_QEMU
+#define SUBSYS_DPRINTF(subsys, fmt, args...) \
+ do { printk("%s - %s: " fmt, subsys, __func__ , ##args); } while (0)
+#else
+#define SUBSYS_DPRINTF(subsys, fmt, args...) \
+ do { } while (0)
+#endif
+#define CHRP_DPRINTF(fmt, args...) SUBSYS_DPRINTF("CHRP", fmt, ##args)
+#define ELF_DPRINTF(fmt, args...) SUBSYS_DPRINTF("ELF", fmt, ##args)
+#define NEWWORLD_DPRINTF(fmt, args...) SUBSYS_DPRINTF("NEWWORLD", fmt, ##args)
+
+static void check_preloaded_kernel(void)
+{
+ unsigned long kernel_image, kernel_size;
+ unsigned long initrd_image, initrd_size;
+ const char * kernel_cmdline;
+
+ kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
+ if (kernel_size) {
+ kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
+ kernel_cmdline = (const char *)(uintptr_t) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
+ initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR);
+ initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE);
+ printk("[ppc] Kernel already loaded (0x%8.8lx + 0x%8.8lx) "
+ "(initrd 0x%8.8lx + 0x%8.8lx)\n",
+ kernel_image, kernel_size, initrd_image, initrd_size);
+ if (kernel_cmdline) {
+ phandle_t ph;
+ printk("[ppc] Kernel command line: %s\n", kernel_cmdline);
+ ph = find_dev("/chosen");
+ set_property(ph, "bootargs", strdup(kernel_cmdline), strlen(kernel_cmdline) + 1);
+ }
+ call_elf(initrd_image, initrd_size, kernel_image);
+ }
+}
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+void
+boot( void )
+{
+ uint16_t boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
+
+ fword("update-chosen");
+ if (boot_device == 'm') {
+ check_preloaded_kernel();
+ }
+
+ if (is_apple()) {
+ update_nvram();
+ }
+}
diff --git a/roms/openbios/arch/ppc/qemu/methods.c b/roms/openbios/arch/ppc/qemu/methods.c
new file mode 100644
index 00000000..fd993daa
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/methods.c
@@ -0,0 +1,327 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "drivers/drivers.h"
+#include "libc/string.h"
+#include "qemu/qemu.h"
+#include "libopenbios/ofmem.h"
+#include "arch/ppc/processor.h"
+#include "drivers/usb.h"
+
+/************************************************************************/
+/* RTAS (run-time abstraction services) */
+/************************************************************************/
+
+#ifdef CONFIG_RTAS
+DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" );
+
+/* ( physbase -- rtas_callback ) */
+static void
+rtas_instantiate( void )
+{
+ ucell physbase = POP();
+ ucell s=0x1000, size = (ucell)of_rtas_end - (ucell)of_rtas_start;
+ unsigned long virt;
+
+ while( s < size )
+ s += 0x1000;
+ virt = ofmem_claim_virt( 0, s, 0x1000 );
+ ofmem_map( physbase, virt, s, -1 );
+ memcpy( (char*)virt, of_rtas_start, size );
+
+ printk("RTAS instantiated at %08x\n", physbase );
+ flush_icache_range( (char*)virt, (char*)virt + size );
+
+ PUSH( physbase );
+}
+
+NODE_METHODS( rtas ) = {
+ { "instantiate", rtas_instantiate },
+ { "instantiate-rtas", rtas_instantiate },
+};
+#endif
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)cell2pointer(POP());
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = getchar();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)cell2pointer(POP());
+ for( i=0; i<len; i++ )
+ putchar( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+/************************************************************************/
+/* client interface 'quiesce' */
+/************************************************************************/
+
+DECLARE_NODE( ciface, 0, 0, "+/openprom/client-services" );
+
+/* ( -- ) */
+static void
+ciface_quiesce( unsigned long args[], unsigned long ret[] )
+{
+ usb_exit();
+#if 0
+ unsigned long msr;
+ /* This seems to be the correct thing to do - but I'm not sure */
+ asm volatile("mfmsr %0" : "=r" (msr) : );
+ msr &= ~(MSR_IR | MSR_DR);
+ asm volatile("mtmsr %0" :: "r" (msr) );
+#endif
+}
+
+/* ( -- ms ) */
+#define TIMER_FREQUENCY 16600000ULL
+
+static void
+ciface_milliseconds( unsigned long args[], unsigned long ret[] )
+{
+ unsigned long tbu, tbl, temp;
+ unsigned long long ticks, msecs;
+
+ asm volatile(
+ "1:\n"
+ "mftbu %2\n"
+ "mftb %0\n"
+ "mftbu %1\n"
+ "cmpw %2,%1\n"
+ "bne 1b\n"
+ : "=r"(tbl), "=r"(tbu), "=r"(temp)
+ :
+ : "cc");
+
+ ticks = (((unsigned long long)tbu) << 32) | (unsigned long long)tbl;
+ msecs = (1000 * ticks) / TIMER_FREQUENCY;
+ PUSH( msecs );
+}
+
+
+NODE_METHODS( ciface ) = {
+ { "quiesce", ciface_quiesce },
+ { "milliseconds", ciface_milliseconds },
+};
+
+
+/************************************************************************/
+/* MMU/memory methods */
+/************************************************************************/
+
+DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" );
+DECLARE_UNNAMED_NODE( mmu, INSTALL_OPEN, 0 );
+DECLARE_NODE( mmu_ciface, 0, 0, "+/openprom/client-services" );
+
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_phys( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MEM: claim failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys size align --- base ) */
+static void
+mmu_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell phys = POP();
+ ucell ret = ofmem_claim_virt( phys, size, align );
+
+ if( ret == -1 ) {
+ printk("MMU: CLAIM failure\n");
+ throw( -13 );
+ return;
+ }
+ PUSH( ret );
+}
+
+/* ( phys size --- ) */
+static void
+mmu_release( void )
+{
+ POP(); POP();
+}
+
+/* ( phys virt size mode -- [ret???] ) */
+static void
+mmu_map( void )
+{
+ ucell mode = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell phys = POP();
+ ucell ret;
+
+ /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */
+ ret = ofmem_map( phys, virt, size, mode );
+
+ if( ret ) {
+ printk("MMU: map failure\n");
+ throw( -13 );
+ return;
+ }
+}
+
+/* ( virt size -- ) */
+static void
+mmu_unmap( void )
+{
+ POP(); POP();
+}
+
+/* ( virt -- false | phys mode true ) */
+static void
+mmu_translate( void )
+{
+ ucell mode;
+ ucell virt = POP();
+ ucell phys = ofmem_translate( virt, &mode );
+
+ if( phys == -1 ) {
+ PUSH( 0 );
+ } else {
+ PUSH( phys );
+ PUSH( mode );
+ PUSH( -1 );
+ }
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ ucell size = POP();
+ ucell virt = POP();
+ ofmem_release(virt, size);
+}
+
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+};
+
+NODE_METHODS( mmu ) = {
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "translate", mmu_translate },
+};
+
+NODE_METHODS( mmu_ciface ) = {
+ { "cif-claim", ciface_claim },
+ { "cif-release", ciface_release },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( const char *cpuname )
+{
+ phandle_t chosen, ph;
+#ifdef CONFIG_RTAS
+ if (is_newworld()) {
+ REGISTER_NODE( rtas );
+ }
+#endif
+ REGISTER_NODE( ciface );
+ REGISTER_NODE( memory );
+ REGISTER_NODE_METHODS( mmu, cpuname );
+ REGISTER_NODE( mmu_ciface );
+ REGISTER_NODE( tty );
+
+ chosen = find_dev("/chosen");
+ if (chosen) {
+ push_str(cpuname);
+ fword("open-dev");
+ ph = POP();
+ set_int_property(chosen, "mmu", ph);
+ }
+}
diff --git a/roms/openbios/arch/ppc/qemu/mmutypes.h b/roms/openbios/arch/ppc/qemu/mmutypes.h
new file mode 100644
index 00000000..512c23d0
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/mmutypes.h
@@ -0,0 +1,97 @@
+/*
+ * Creation Date: <2002/01/13 13:53:14 samuel>
+ * Time-stamp: <2002/01/27 19:56:11 samuel>
+ *
+ * <mmutypes.h>
+ *
+ * MMU definitions
+ *
+ * Most of these declarations originate from the Linux Kernel
+ *
+ * Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_MMUTYPES
+#define _H_MMUTYPES
+
+/* Hardware Page Table Entry */
+typedef struct mPTE {
+ unsigned long v:1; /* Entry is valid */
+ unsigned long vsid:24; /* Virtual segment identifier */
+ unsigned long h:1; /* Hash algorithm indicator */
+ unsigned long api:6; /* Abbreviated page index */
+
+ unsigned long rpn:20; /* Real (physical) page number */
+ unsigned long :3; /* Unused */
+ unsigned long r:1; /* Referenced */
+ unsigned long c:1; /* Changed */
+ unsigned long w:1; /* Write-thru cache mode */
+ unsigned long i:1; /* Cache inhibited */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page protection */
+} mPTE_t;
+
+typedef struct mPTE_64 {
+ uint32_t avpn_low; /* Abbreviated Virtual Page Number (unused) */
+ uint32_t avpn:25; /* Abbreviated Virtual Page Number */
+ uint32_t sw:4; /* Software Use */
+ uint32_t :1; /* Reserved */
+ uint32_t h:1; /* Hash algorithm indicator */
+ uint32_t v:1; /* Entry is valid */
+
+ uint32_t rpn_low; /* Real (physical) page number (unused) */
+ uint32_t rpn:20; /* Real (physical) page number */
+ uint32_t :2; /* Reserved */
+ uint32_t ac:1; /* Address Compare*/
+ uint32_t r:1; /* Referenced */
+ uint32_t c:1; /* Changed */
+ uint32_t w:1; /* Write-thru cache mode */
+ uint32_t i:1; /* Cache inhibited */
+ uint32_t m:1; /* Memory coherence */
+ uint32_t g:1; /* Guarded */
+ uint32_t n:1; /* No-Execute */
+ uint32_t pp:2; /* Page protection */
+} mPTE_64_t;
+
+typedef struct _mBATU { /* Upper part of BAT (all except 601) */
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+ unsigned long :4; /* Unused */
+ unsigned long bl:11; /* Block size mask */
+ unsigned long vs:1; /* Supervisor valid */
+ unsigned long vp:1; /* User valid */
+} mBATU;
+
+typedef struct _mBATL { /* Lower part of BAT (all except 601) */
+ unsigned long brpn:15; /* Real page index (physical address) */
+ unsigned long :10; /* Unused */
+ unsigned long w:1; /* Write-thru cache */
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded (MBZ in IBAT) */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page access protections */
+} mBATL;
+
+typedef struct _mBAT {
+ mBATU batu; /* Upper register */
+ mBATL batl; /* Lower register */
+} mBAT;
+
+typedef struct _mSEGREG {
+ unsigned long t:1; /* Normal or I/O type */
+ unsigned long ks:1; /* Supervisor 'key' (normally 0) */
+ unsigned long kp:1; /* User 'key' (normally 1) */
+ unsigned long n:1; /* No-execute */
+ unsigned long :4; /* Unused */
+ unsigned long vsid:24; /* Virtual Segment Identifier */
+} mSEGREG;
+
+
+#endif /* _H_MMUTYPES */
diff --git a/roms/openbios/arch/ppc/qemu/ofmem.c b/roms/openbios/arch/ppc/qemu/ofmem.c
new file mode 100644
index 00000000..6f346a3d
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/ofmem.c
@@ -0,0 +1,563 @@
+/*
+ * Creation Date: <1999/11/07 19:02:11 samuel>
+ * Time-stamp: <2004/01/07 19:42:36 samuel>
+ *
+ * <ofmem.c>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "libopenbios/ofmem.h"
+#include "kernel.h"
+#include "mmutypes.h"
+#include "asm/processor.h"
+
+#define BIT(n) (1U << (31 - (n)))
+
+#define SLB_VSID_SHIFT 12
+
+/* called from assembly */
+extern void dsi_exception(void);
+extern void isi_exception(void);
+extern void setup_mmu(unsigned long code_base);
+
+/*
+ * From Apple's BootX source comments:
+ *
+ * 96 MB map (currently unused - 4363357 tracks re-adoption)
+ * 00000000 - 00003FFF : Exception Vectors
+ * 00004000 - 03FFFFFF : Kernel Image, Boot Struct and Drivers (~64 MB)
+ * 04000000 - 04FFFFFF : File Load Area (16 MB) [80 MB]
+ * 05000000 - 053FFFFF : FS Cache (4 MB) [84 MB]
+ * 05400000 - 055FFFFF : Malloc Zone (2 MB) [86 MB]
+ * 05600000 - 057FFFFF : BootX Image (2 MB) [88 MB]
+ * 05800000 - 05FFFFFF : Unused/OF (8 MB) [96 MB]
+ *
+ */
+
+#define FREE_BASE 0x00004000UL
+#define OF_CODE_START 0xfff00000UL
+#define OF_CODE_SIZE 0x00100000
+#define IO_BASE 0x80000000UL
+
+#ifdef __powerpc64__
+#define HASH_BITS 18
+#else
+#define HASH_BITS 15
+#endif
+#define HASH_SIZE (2 << HASH_BITS)
+#define OFMEM_SIZE (1 * 1024 * 1024 + 512 * 1024)
+
+#define SEGR_USER BIT(2)
+#define SEGR_BASE 0x0400
+
+static inline unsigned long
+get_hash_base(void)
+{
+ return (mfsdr1() & SDR1_HTABORG_MASK);
+}
+
+static inline unsigned long
+get_rom_base(void)
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ return ofmem->ramsize - OF_CODE_SIZE;
+}
+
+static unsigned long
+get_ram_top(void)
+{
+ return get_hash_base() - (32 + 64 + 64) * 1024 - OFMEM_SIZE;
+}
+
+static unsigned long
+get_ram_bottom(void)
+{
+ return FREE_BASE;
+}
+
+static unsigned long get_heap_top(void)
+{
+ return get_hash_base() - (32 + 64 + 64) * 1024;
+}
+
+static inline size_t ALIGN_SIZE(size_t x, size_t a)
+{
+ return (x + a - 1) & ~(a - 1);
+}
+
+ofmem_t* ofmem_arch_get_private(void)
+{
+ return (ofmem_t*)cell2pointer(get_heap_top() - OFMEM_SIZE);
+}
+
+void* ofmem_arch_get_malloc_base(void)
+{
+ return (char*)ofmem_arch_get_private() + ALIGN_SIZE(sizeof(ofmem_t), 4);
+}
+
+ucell ofmem_arch_get_heap_top(void)
+{
+ return get_heap_top();
+}
+
+ucell ofmem_arch_get_virt_top(void)
+{
+ return IO_BASE;
+}
+
+void ofmem_arch_unmap_pages(ucell virt, ucell size)
+{
+ /* kill page mappings in provided range */
+}
+
+void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode)
+{
+ /* none yet */
+}
+
+ucell ofmem_arch_get_iomem_base(void)
+{
+ /* Currently unused */
+ return 0;
+}
+
+ucell ofmem_arch_get_iomem_top(void)
+{
+ /* Currently unused */
+ return 0;
+}
+
+retain_t *ofmem_arch_get_retained(void)
+{
+ /* not implemented */
+ return NULL;
+}
+
+int ofmem_arch_get_physaddr_cellsize(void)
+{
+#ifdef CONFIG_PPC64
+ return 2;
+#else
+ return 1;
+#endif
+}
+
+int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value)
+{
+ int n = 0;
+#ifdef CONFIG_PPC64
+ p[n++] = value >> 32;
+#endif
+ p[n++] = value;
+ return n;
+}
+
+/* Return size of a single MMU package translation property entry in cells */
+int ofmem_arch_get_translation_entry_size(void)
+{
+ return 3 + ofmem_arch_get_physaddr_cellsize();
+}
+
+/* Generate translation property entry for PPC.
+ * According to the platform bindings for PPC
+ * (http://www.openfirmware.org/1275/bindings/ppc/release/ppc-2_1.html#REF34579)
+ * a translation property entry has the following layout:
+ *
+ * virtual address
+ * length
+ * physical address
+ * mode
+ */
+void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t)
+{
+ int i = 0;
+
+ transentry[i++] = t->virt;
+ transentry[i++] = t->size;
+ i += ofmem_arch_encode_physaddr(&transentry[i], t->phys);
+ transentry[i++] = t->mode;
+}
+
+/* Return the size of a memory available entry given the phandle in cells */
+int ofmem_arch_get_available_entry_size(phandle_t ph)
+{
+ if (ph == s_phandle_memory) {
+ return 1 + ofmem_arch_get_physaddr_cellsize();
+ } else {
+ return 1 + 1;
+ }
+}
+
+/* Generate memory available property entry for PPC */
+void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size)
+{
+ int i = 0;
+
+ if (ph == s_phandle_memory) {
+ i += ofmem_arch_encode_physaddr(availentry, start);
+ } else {
+ availentry[i++] = start;
+ }
+
+ availentry[i] = size;
+}
+
+/************************************************************************/
+/* OF private allocations */
+/************************************************************************/
+
+/* Private functions for mapping between physical/virtual addresses */
+phys_addr_t
+va2pa(unsigned long va)
+{
+ if (va >= OF_CODE_START && va < OF_CODE_START + OF_CODE_SIZE) {
+ return (phys_addr_t)get_rom_base() - OF_CODE_START + va;
+ } else {
+ return (phys_addr_t)va;
+ }
+}
+
+unsigned long
+pa2va(phys_addr_t pa)
+{
+ if ((pa - get_rom_base() + OF_CODE_START >= OF_CODE_START) &&
+ (pa - get_rom_base() + OF_CODE_START < OF_CODE_START + OF_CODE_SIZE))
+ return (unsigned long)pa - get_rom_base() + OF_CODE_START;
+ else
+ return (unsigned long)pa;
+}
+
+void *
+malloc(int size)
+{
+ return ofmem_malloc(size);
+}
+
+void
+free(void *ptr)
+{
+ ofmem_free(ptr);
+}
+
+void *
+realloc(void *ptr, size_t size)
+{
+ return ofmem_realloc(ptr, size);
+}
+
+
+/************************************************************************/
+/* misc */
+/************************************************************************/
+
+ucell ofmem_arch_default_translation_mode(phys_addr_t phys)
+{
+ /* XXX: Guard bit not set as it should! */
+ if (phys < IO_BASE)
+ return 0x02; /*0xa*/ /* wim GxPp */
+ return 0x6a; /* WIm GxPp, I/O */
+}
+
+ucell ofmem_arch_io_translation_mode(phys_addr_t phys)
+{
+ return 0x6a; /* WIm GxPp, I/O */
+}
+
+/************************************************************************/
+/* page fault handler */
+/************************************************************************/
+
+static phys_addr_t
+ea_to_phys(unsigned long ea, ucell *mode)
+{
+ phys_addr_t phys;
+
+ if (ea >= OF_CODE_START && ea <= 0xffffffffUL) {
+ /* ROM into RAM */
+ ea -= OF_CODE_START;
+ phys = get_rom_base() + ea;
+ *mode = 0x02;
+ return phys;
+ }
+
+ phys = ofmem_translate(ea, mode);
+ if (phys == -1) {
+ phys = ea;
+ *mode = ofmem_arch_default_translation_mode(phys);
+
+ /* print_virt_range(); */
+ /* print_phys_range(); */
+ /* print_trans(); */
+ }
+ return phys;
+}
+
+/* Converts a global variable (from .data or .bss) into a pointer that
+ can be accessed from real mode */
+static void *
+global_ptr_real(void *p)
+{
+ return (void*)((uintptr_t)p - OF_CODE_START + get_rom_base());
+}
+
+/* Return the next slot to evict, in the range of [0..7] */
+static int
+next_evicted_slot(void)
+{
+ static int next_grab_slot;
+ int *next_grab_slot_va;
+ int r;
+
+ next_grab_slot_va = global_ptr_real(&next_grab_slot);
+ r = *next_grab_slot_va;
+ *next_grab_slot_va = (r + 1) % 8;
+
+ return r;
+}
+
+static void
+hash_page_64(unsigned long ea, phys_addr_t phys, ucell mode)
+{
+ uint64_t vsid_mask, page_mask, pgidx, hash;
+ uint64_t htab_mask, mask, avpn;
+ unsigned long pgaddr;
+ int i, found;
+ unsigned int vsid, vsid_sh, sdr, sdr_sh, sdr_mask;
+ mPTE_64_t *pp;
+
+ vsid = (ea >> 28) + SEGR_BASE;
+ vsid_sh = 7;
+ vsid_mask = 0x00003FFFFFFFFF80ULL;
+ sdr = mfsdr1();
+ sdr_sh = 18;
+ sdr_mask = 0x3FF80;
+ page_mask = 0x0FFFFFFF; // XXX correct?
+ pgidx = (ea & page_mask) >> PAGE_SHIFT;
+ avpn = (vsid << 12) | ((pgidx >> 4) & 0x0F80);;
+
+ hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
+ htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
+ mask = (htab_mask << sdr_sh) | sdr_mask;
+ pgaddr = sdr | (hash & mask);
+ pp = (mPTE_64_t *)pgaddr;
+
+ /* replace old translation */
+ for (found = 0, i = 0; !found && i < 8; i++)
+ if (pp[i].avpn == avpn)
+ found = 1;
+
+ /* otherwise use a free slot */
+ for (i = 0; !found && i < 8; i++)
+ if (!pp[i].v)
+ found = 1;
+
+ /* out of slots, just evict one */
+ if (!found)
+ i = next_evicted_slot() + 1;
+ i--;
+ {
+ mPTE_64_t p = {
+ // .avpn_low = avpn,
+ .avpn = avpn >> 7,
+ .h = 0,
+ .v = 1,
+
+ .rpn = (phys & ~0xfffUL) >> 12,
+ .r = mode & (1 << 8) ? 1 : 0,
+ .c = mode & (1 << 7) ? 1 : 0,
+ .w = mode & (1 << 6) ? 1 : 0,
+ .i = mode & (1 << 5) ? 1 : 0,
+ .m = mode & (1 << 4) ? 1 : 0,
+ .g = mode & (1 << 3) ? 1 : 0,
+ .n = mode & (1 << 2) ? 1 : 0,
+ .pp = mode & 3,
+ };
+ pp[i] = p;
+ }
+
+ asm volatile("tlbie %0" :: "r"(ea));
+}
+
+static void
+hash_page_32(unsigned long ea, phys_addr_t phys, ucell mode)
+{
+#ifndef __powerpc64__
+ unsigned long *upte, cmp, hash1;
+ int i, vsid, found;
+ mPTE_t *pp;
+
+ vsid = (ea >> 28) + SEGR_BASE;
+ cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22);
+
+ hash1 = vsid;
+ hash1 ^= (ea >> 12) & 0xffff;
+ hash1 &= (((mfsdr1() & 0x1ff) << 16) | 0xffff) >> 6;
+
+ pp = (mPTE_t*)(get_hash_base() + (hash1 << 6));
+ upte = (unsigned long*)pp;
+
+ /* replace old translation */
+ for (found = 0, i = 0; !found && i < 8; i++)
+ if (cmp == upte[i*2])
+ found = 1;
+
+ /* otherwise use a free slot */
+ for (i = 0; !found && i < 8; i++)
+ if (!pp[i].v)
+ found = 1;
+
+ /* out of slots, just evict one */
+ if (!found)
+ i = next_evicted_slot() + 1;
+ i--;
+ upte[i * 2] = cmp;
+ upte[i * 2 + 1] = (phys & ~0xfff) | mode;
+
+ asm volatile("tlbie %0" :: "r"(ea));
+#endif
+}
+
+static int is_ppc64(void)
+{
+#ifdef __powerpc64__
+ return 1;
+#elif defined(CONFIG_PPC_64BITSUPPORT)
+ unsigned int pvr = mfpvr();
+ return ((pvr >= 0x330000) && (pvr < 0x70330000));
+#else
+ return 0;
+#endif
+}
+
+/* XXX Remove these ugly constructs when legacy 64-bit support is dropped. */
+static void hash_page(unsigned long ea, phys_addr_t phys, ucell mode)
+{
+ if (is_ppc64())
+ hash_page_64(ea, phys, mode);
+ else
+ hash_page_32(ea, phys, mode);
+}
+
+void
+dsi_exception(void)
+{
+ unsigned long dar, dsisr;
+ ucell mode;
+ phys_addr_t phys;
+
+ asm volatile("mfdar %0" : "=r" (dar) : );
+ asm volatile("mfdsisr %0" : "=r" (dsisr) : );
+
+ phys = ea_to_phys(dar, &mode);
+ hash_page(dar, phys, mode);
+}
+
+void
+isi_exception(void)
+{
+ unsigned long nip, srr1;
+ ucell mode;
+ phys_addr_t phys;
+
+ asm volatile("mfsrr0 %0" : "=r" (nip) : );
+ asm volatile("mfsrr1 %0" : "=r" (srr1) : );
+
+ phys = ea_to_phys(nip, &mode);
+ hash_page(nip, phys, mode);
+}
+
+
+/************************************************************************/
+/* init / cleanup */
+/************************************************************************/
+
+void
+setup_mmu(unsigned long ramsize)
+{
+ ofmem_t *ofmem;
+#ifndef __powerpc64__
+ unsigned long sr_base;
+#endif
+ unsigned long hash_base;
+ unsigned long hash_mask = ~0x000fffffUL; /* alignment for ppc64 */
+ int i;
+
+ /* SDR1: Storage Description Register 1 */
+
+ hash_base = (ramsize - OF_CODE_SIZE - HASH_SIZE) & hash_mask;
+ memset((void *)hash_base, 0, HASH_SIZE);
+ if (is_ppc64())
+ mtsdr1(hash_base | MAX(HASH_BITS - 18, 0));
+ else
+ mtsdr1(hash_base | ((HASH_SIZE - 1) >> 16));
+
+#ifdef __powerpc64__
+
+ /* Segment Lookaside Buffer */
+
+ slbia(); /* Invalidate all SLBs except SLB 0 */
+ for (i = 0; i < 16; i++) {
+ unsigned long rs = (0x400 + i) << SLB_VSID_SHIFT;
+ unsigned long rb = ((unsigned long)i << 28) | (1 << 27) | i;
+ slbmte(rs, rb);
+ }
+
+#else
+
+ /* Segment Register */
+
+ sr_base = SEGR_USER | SEGR_BASE ;
+ for (i = 0; i < 16; i++) {
+ int j = i << 28;
+ asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j));
+ }
+
+#endif
+
+ ofmem = ofmem_arch_get_private();
+ memset(ofmem, 0, sizeof(ofmem_t));
+ ofmem->ramsize = ramsize;
+
+ memcpy((void *)get_rom_base(), (void *)OF_CODE_START, OF_CODE_SIZE);
+
+ /* Enable MMU */
+
+ mtmsr(mfmsr() | MSR_IR | MSR_DR);
+}
+
+void
+ofmem_init(void)
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+
+ /* Map the memory (don't map page 0 to allow catching of NULL dereferences) */
+ ofmem_claim_phys(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0);
+ ofmem_claim_virt(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0);
+ ofmem_map(PAGE_SIZE, PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0);
+
+ /* Mark the first page as non-free */
+ ofmem_claim_phys(0, PAGE_SIZE, 0);
+ ofmem_claim_virt(0, PAGE_SIZE, 0);
+
+ /* Map everything at the top of physical RAM 1:1, minus the OpenBIOS ROM in RAM copy */
+ ofmem_claim_phys(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0);
+ ofmem_claim_virt(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0);
+ ofmem_map(get_ram_top(), get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0);
+
+ /* Map the OpenBIOS ROM in RAM copy */
+ ofmem_claim_phys(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_SIZE, 0);
+ ofmem_claim_virt(OF_CODE_START, OF_CODE_SIZE, 0);
+ ofmem_map(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_START, OF_CODE_SIZE, 0);
+}
diff --git a/roms/openbios/arch/ppc/qemu/qemu.c b/roms/openbios/arch/ppc/qemu/qemu.c
new file mode 100644
index 00000000..381affb7
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/qemu.c
@@ -0,0 +1,106 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <qemu.c>
+ *
+ * Copyright (C) 2004, Greg Watson
+ *
+ * derived from mol.c
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/nvram.h"
+#include "libopenbios/bindings.h"
+#include "drivers/drivers.h"
+#include "libc/vsprintf.h"
+#include "libc/string.h"
+#include "libc/byteorder.h"
+#include "qemu/qemu.h"
+#include <stdarg.h>
+
+//#define DUMP_NVRAM
+
+unsigned long virt_offset = 0;
+
+void
+exit( int status __attribute__ ((unused)))
+{
+ for (;;);
+}
+
+void
+fatal_error( const char *err )
+{
+ printk("Fatal error: %s\n", err );
+ exit(0);
+}
+
+void
+panic( const char *err )
+{
+ printk("Panic: %s\n", err );
+ exit(0);
+}
+
+static int do_indent;
+
+int
+printk( const char *fmt, ... )
+{
+ char *p, buf[1024];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ ) {
+ if( *p == '\n' )
+ do_indent = 0;
+ if( do_indent++ == 1 ) {
+ putchar( '>' );
+ putchar( '>' );
+ putchar( ' ' );
+ }
+ putchar( *p );
+ }
+ return i;
+}
+
+int arch_nvram_size(void)
+{
+ if (is_apple()) {
+ return macio_get_nvram_size();
+ } else {
+ // not implemented
+ }
+ return 0;
+}
+
+void arch_nvram_put(char *buf)
+{
+ if (is_apple()) {
+ macio_nvram_put(buf);
+ } else {
+ // not implemented
+ }
+}
+
+void arch_nvram_get(char *buf)
+{
+ if (is_apple()) {
+ macio_nvram_get(buf);
+ } else {
+ // not implemented
+ }
+}
diff --git a/roms/openbios/arch/ppc/qemu/qemu.fs b/roms/openbios/arch/ppc/qemu/qemu.fs
new file mode 100644
index 00000000..458af1bc
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/qemu.fs
@@ -0,0 +1,95 @@
+\ qemu specific initialization code
+\
+\ Copyright (C) 2005 Stefan Reinauer
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+
+\ -------------------------------------------------------------------------
+\ initialization
+\ -------------------------------------------------------------------------
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " rtc" " rtc" preopen
+ " memory" " /memory" preopen
+; SYSTEM-initializer
+
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /packages/terminal-emulator" find-dev if drop
+ then
+;
+
+variable keyboard-phandle 0 keyboard-phandle !
+
+: (find-keyboard-device) ( phandle -- )
+ recursive
+ keyboard-phandle @ 0= if \ Return first match
+ >dn.child @
+ begin ?dup while
+ dup dup " device_type" rot get-package-property 0= if
+ drop dup cstrlen
+ " keyboard" strcmp 0= if
+ dup to keyboard-phandle
+ then
+ then
+ (find-keyboard-device)
+ >dn.peer @
+ repeat
+ else
+ drop
+ then
+;
+
+\ create the keyboard devalias
+:noname
+ device-tree @ (find-keyboard-device)
+ keyboard-phandle @ if
+ active-package
+ " /aliases" find-device
+ keyboard-phandle @ get-package-path
+ encode-string " keyboard" property
+ active-package!
+ then
+; SYSTEM-initializer
+
+\ -------------------------------------------------------------------------
+\ pre-booting
+\ -------------------------------------------------------------------------
+
+: update-chosen
+ " /chosen" find-device
+ stdin @ encode-int " stdin" property
+ stdout @ encode-int " stdout" property
+ device-end
+;
+
+:noname
+ set-defaults
+; PREPOST-initializer
diff --git a/roms/openbios/arch/ppc/qemu/qemu.h b/roms/openbios/arch/ppc/qemu/qemu.h
new file mode 100644
index 00000000..6edf4d45
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/qemu.h
@@ -0,0 +1,24 @@
+/*
+ * Creation Date: <2004/08/28 17:50:12 stepan>
+ * Time-stamp: <2004/08/28 17:50:12 stepan>
+ *
+ * <qemu.h>
+ *
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_QEMU
+#define _H_QEMU
+
+/* vfd.c */
+extern int vfd_draw_str( const char *str );
+extern void vfd_close( void );
+
+#include "kernel.h"
+
+#endif /* _H_QEMU */
diff --git a/roms/openbios/arch/ppc/qemu/start.S b/roms/openbios/arch/ppc/qemu/start.S
new file mode 100644
index 00000000..ae2fd53d
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/start.S
@@ -0,0 +1,729 @@
+/*
+ * Creation Date: <2001/06/16 21:30:18 samuel>
+ * Time-stamp: <2003/04/04 16:32:06 samuel>
+ *
+ * <init.S>
+ *
+ * Asm glue for ELF images
+ *
+ * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "autoconf.h"
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+
+/************************************************************************/
+/* Macros */
+/************************************************************************/
+
+#define ILLEGAL_VECTOR( v ) .org __vectors + v ; vector__##v: bl trap_error ;
+#define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+
+/* We're trying to use the same code for the ppc32 and ppc64 handlers here.
+ * On ppc32 we only save/restore the registers, C considers volatile.
+ *
+ * On ppc64 on the other hand, we have to save/restore all registers, because
+ * all OF code is 32 bits, which only saves/restores the low 32 bits of the
+ * registers it clobbers.
+ */
+
+#define EXCEPTION_PREAMBLE_TEMPLATE \
+ mtsprg1 r1 ; /* scratch */ \
+ mfcr r1 ; \
+ mtsprg2 r1 ; /* scratch */ \
+ lis r1, 0x8000 ; /* r1=0x80000000 */ \
+ add. r1,r1,r1 ; /* r1=r1+r1 (high 32bit !0) */ \
+ beq 1f; \
+ \
+ mfmsr r1 ; /* unset MSR_SF */ \
+ clrldi r1,r1,1 ; \
+ mtmsrd r1 ; \
+1: \
+ mfsprg0 r1 ; /* exception stack in sprg0 */ \
+.ifc ULONG_SIZE, 8 ; \
+ addi r1,r1,-(40 * ULONG_SIZE) ; /* push exception frame */ \
+.else ; \
+ addi r1,r1,-(20 * ULONG_SIZE) ; /* push exception frame */ \
+.endif ; \
+ \
+ stl r0,(0 * ULONG_SIZE)(r1) ; /* save r0 */ \
+ mfsprg1 r0 ; \
+ stl r0,(1 * ULONG_SIZE)(r1) ; /* save r1 */ \
+ stl r2,(2 * ULONG_SIZE)(r1) ; /* save r2 */ \
+ stl r3,(3 * ULONG_SIZE)(r1) ; /* save r3 */ \
+ stl r4,(4 * ULONG_SIZE)(r1) ; \
+ stl r5,(5 * ULONG_SIZE)(r1) ; \
+ stl r6,(6 * ULONG_SIZE)(r1) ; \
+ stl r7,(7 * ULONG_SIZE)(r1) ; \
+ stl r8,(8 * ULONG_SIZE)(r1) ; \
+ stl r9,(9 * ULONG_SIZE)(r1) ; \
+ stl r10,(10 * ULONG_SIZE)(r1) ; \
+ stl r11,(11 * ULONG_SIZE)(r1) ; \
+ stl r12,(12 * ULONG_SIZE)(r1) ; \
+.ifc ULONG_SIZE, 8 ; \
+ stl r13,(17 * ULONG_SIZE)(r1) ; \
+ stl r14,(18 * ULONG_SIZE)(r1) ; \
+ stl r15,(19 * ULONG_SIZE)(r1) ; \
+ stl r16,(20 * ULONG_SIZE)(r1) ; \
+ stl r17,(21 * ULONG_SIZE)(r1) ; \
+ stl r18,(22 * ULONG_SIZE)(r1) ; \
+ stl r19,(23 * ULONG_SIZE)(r1) ; \
+ stl r20,(24 * ULONG_SIZE)(r1) ; \
+ stl r21,(25 * ULONG_SIZE)(r1) ; \
+ stl r22,(26 * ULONG_SIZE)(r1) ; \
+ stl r23,(27 * ULONG_SIZE)(r1) ; \
+ stl r24,(28 * ULONG_SIZE)(r1) ; \
+ stl r25,(29 * ULONG_SIZE)(r1) ; \
+ stl r26,(30 * ULONG_SIZE)(r1) ; \
+ stl r27,(31 * ULONG_SIZE)(r1) ; \
+ stl r28,(32 * ULONG_SIZE)(r1) ; \
+ stl r29,(33 * ULONG_SIZE)(r1) ; \
+ stl r30,(34 * ULONG_SIZE)(r1) ; \
+ stl r31,(35 * ULONG_SIZE)(r1) ; \
+.endif ; \
+ \
+ mflr r0 ; \
+ stl r0,(13 * ULONG_SIZE)(r1) ; \
+ mfsprg2 r0 ; \
+ stl r0,(14 * ULONG_SIZE)(r1) ; \
+ mfctr r0 ; \
+ stl r0,(15 * ULONG_SIZE)(r1) ; \
+ mfxer r0 ; \
+ stl r0,(16 * ULONG_SIZE)(r1) ; \
+ \
+ /* 76(r1) unused */ \
+ addi r1,r1,-16 ; /* C ABI uses 0(r1) and 4(r1)... */
+
+#define EXCEPTION_EPILOGUE_TEMPLATE \
+ addi r1,r1,16 ; /* pop ABI frame */ \
+\
+ ll r0,(13 * ULONG_SIZE)(r1) ; \
+ mtlr r0 ; \
+ ll r0,(14 * ULONG_SIZE)(r1) ; \
+ mtcr r0 ; \
+ ll r0,(15 * ULONG_SIZE)(r1) ; \
+ mtctr r0 ; \
+ ll r0,(16 * ULONG_SIZE)(r1) ; \
+ mtxer r0 ; \
+\
+ ll r0,(0 * ULONG_SIZE)(r1) ; \
+ ll r2,(2 * ULONG_SIZE)(r1) ; \
+ ll r3,(3 * ULONG_SIZE)(r1) ; \
+ ll r4,(4 * ULONG_SIZE)(r1) ; \
+ ll r5,(5 * ULONG_SIZE)(r1) ; \
+ ll r6,(6 * ULONG_SIZE)(r1) ; \
+ ll r7,(7 * ULONG_SIZE)(r1) ; \
+ ll r8,(8 * ULONG_SIZE)(r1) ; \
+ ll r9,(9 * ULONG_SIZE)(r1) ; \
+ ll r10,(10 * ULONG_SIZE)(r1) ; \
+ ll r11,(11 * ULONG_SIZE)(r1) ; \
+ ll r12,(12 * ULONG_SIZE)(r1) ; \
+.ifc ULONG_SIZE, 8 ; \
+ ll r13,(17 * ULONG_SIZE)(r1) ; \
+ ll r14,(18 * ULONG_SIZE)(r1) ; \
+ ll r15,(19 * ULONG_SIZE)(r1) ; \
+ ll r16,(20 * ULONG_SIZE)(r1) ; \
+ ll r17,(21 * ULONG_SIZE)(r1) ; \
+ ll r18,(22 * ULONG_SIZE)(r1) ; \
+ ll r19,(23 * ULONG_SIZE)(r1) ; \
+ ll r20,(24 * ULONG_SIZE)(r1) ; \
+ ll r21,(25 * ULONG_SIZE)(r1) ; \
+ ll r22,(26 * ULONG_SIZE)(r1) ; \
+ ll r23,(27 * ULONG_SIZE)(r1) ; \
+ ll r24,(28 * ULONG_SIZE)(r1) ; \
+ ll r25,(29 * ULONG_SIZE)(r1) ; \
+ ll r26,(30 * ULONG_SIZE)(r1) ; \
+ ll r27,(31 * ULONG_SIZE)(r1) ; \
+ ll r28,(32 * ULONG_SIZE)(r1) ; \
+ ll r29,(33 * ULONG_SIZE)(r1) ; \
+ ll r30,(34 * ULONG_SIZE)(r1) ; \
+ ll r31,(35 * ULONG_SIZE)(r1) ; \
+.endif ; \
+ ll r1,(1 * ULONG_SIZE)(r1) ; /* restore stack at last */ \
+ rfi
+
+// PPC32
+
+#define ULONG_SIZE 4
+#define stl stw
+#define ll lwz
+
+.macro EXCEPTION_PREAMBLE
+ EXCEPTION_PREAMBLE_TEMPLATE
+.endm
+
+.macro EXCEPTION_EPILOGUE
+ EXCEPTION_EPILOGUE_TEMPLATE
+.endm
+
+#undef ULONG_SIZE
+#undef stl
+#undef ll
+
+// PPC64
+
+#define ULONG_SIZE 8
+#define stl std
+#define ll ld
+
+.macro EXCEPTION_PREAMBLE_64
+ EXCEPTION_PREAMBLE_TEMPLATE
+.endm
+
+.macro EXCEPTION_EPILOGUE_64
+ EXCEPTION_EPILOGUE_TEMPLATE
+.endm
+
+#undef ULONG_SIZE
+#undef stl
+#undef ll
+
+#define ULONG_SIZE 4
+#define STACKFRAME_MINSIZE 16
+
+#else /* !CONFIG_PPC_64BITSUPPORT */
+
+#ifdef __powerpc64__
+
+#define ULONG_SIZE 8
+#define STACKFRAME_MINSIZE 48
+#define stl std
+#define ll ld
+
+#else
+
+#define ULONG_SIZE 4
+#define STACKFRAME_MINSIZE 16
+#define stl stw
+#define ll lwz
+
+#endif
+
+.macro EXCEPTION_PREAMBLE
+ mtsprg1 r1 /* scratch */
+ mfsprg0 r1 /* exception stack in sprg0 */
+ addi r1, r1, -(20 * ULONG_SIZE) /* push exception frame */
+
+ stl r0, ( 0 * ULONG_SIZE)(r1) /* save r0 */
+ mfsprg1 r0
+ stl r0, ( 1 * ULONG_SIZE)(r1) /* save r1 */
+ stl r2, ( 2 * ULONG_SIZE)(r1) /* save r2 */
+ stl r3, ( 3 * ULONG_SIZE)(r1) /* save r3 */
+ stl r4, ( 4 * ULONG_SIZE)(r1)
+ stl r5, ( 5 * ULONG_SIZE)(r1)
+ stl r6, ( 6 * ULONG_SIZE)(r1)
+ stl r7, ( 7 * ULONG_SIZE)(r1)
+ stl r8, ( 8 * ULONG_SIZE)(r1)
+ stl r9, ( 9 * ULONG_SIZE)(r1)
+ stl r10, (10 * ULONG_SIZE)(r1)
+ stl r11, (11 * ULONG_SIZE)(r1)
+ stl r12, (12 * ULONG_SIZE)(r1)
+
+ mflr r0
+ stl r0, (13 * ULONG_SIZE)(r1)
+ mfcr r0
+ stl r0, (14 * ULONG_SIZE)(r1)
+ mfctr r0
+ stl r0, (15 * ULONG_SIZE)(r1)
+ mfxer r0
+ stl r0, (16 * ULONG_SIZE)(r1)
+
+ addi r1, r1, -STACKFRAME_MINSIZE /* C ABI saves LR and SP */
+.endm
+
+.macro EXCEPTION_EPILOGUE
+ addi r1, r1, STACKFRAME_MINSIZE /* pop ABI frame */
+
+ ll r0, (13 * ULONG_SIZE)(r1)
+ mtlr r0
+ ll r0, (14 * ULONG_SIZE)(r1)
+ mtcr r0
+ ll r0, (15 * ULONG_SIZE)(r1)
+ mtctr r0
+ ll r0, (16 * ULONG_SIZE)(r1)
+ mtxer r0
+
+ ll r0, ( 0 * ULONG_SIZE)(r1)
+ ll r2, ( 2 * ULONG_SIZE)(r1)
+ ll r3, ( 3 * ULONG_SIZE)(r1)
+ ll r4, ( 4 * ULONG_SIZE)(r1)
+ ll r5, ( 5 * ULONG_SIZE)(r1)
+ ll r6, ( 6 * ULONG_SIZE)(r1)
+ ll r7, ( 7 * ULONG_SIZE)(r1)
+ ll r8, ( 8 * ULONG_SIZE)(r1)
+ ll r9, ( 9 * ULONG_SIZE)(r1)
+ ll r10, (10 * ULONG_SIZE)(r1)
+ ll r11, (11 * ULONG_SIZE)(r1)
+ ll r12, (12 * ULONG_SIZE)(r1)
+
+ ll r1, ( 1 * ULONG_SIZE)(r1) /* restore stack at last */
+ RFI
+.endm
+
+#endif /* !CONFIG_PPC_64BITSUPPORT */
+
+/************************************************************************/
+/* vectors */
+/************************************************************************/
+
+ .section .text.vectors, "ax"
+GLOBL(__vectors):
+ nop // NULL-jmp trap
+1: nop //
+ b 1b
+
+VECTOR( 0x100, "SRE" ):
+ b _entry
+
+trap_error:
+ lis r1, 0x8000 /* r1=0x80000000 */
+ add. r1,r1,r1 /* r1=r1+r1 (high 32bit !0) */
+ beq 1f
+
+ mfmsr r1 /* unset MSR_SF */
+ clrldi r1,r1,1
+ mtmsrd r1
+1:
+ mflr r3
+ LOAD_REG_FUNC(r4, unexpected_excep)
+ mtctr r4
+ bctr
+
+ILLEGAL_VECTOR( 0x200 )
+
+VECTOR( 0x300, "DSI" ):
+ b real_dsi
+
+ILLEGAL_VECTOR( 0x380 )
+
+VECTOR( 0x400, "ISI" ):
+ b real_isi
+
+ILLEGAL_VECTOR( 0x480 )
+
+ ILLEGAL_VECTOR( 0x500 )
+ ILLEGAL_VECTOR( 0x600 )
+ ILLEGAL_VECTOR( 0x700 )
+
+VECTOR( 0x800, "FPU" ):
+ mtsprg1 r3
+ mfsrr1 r3
+ ori r3,r3,0x2000
+ mtsrr1 r3
+ mfsprg1 r3
+ RFI
+
+ILLEGAL_VECTOR( 0x900 )
+ILLEGAL_VECTOR( 0xa00 )
+ILLEGAL_VECTOR( 0xb00 )
+ILLEGAL_VECTOR( 0xc00 )
+ILLEGAL_VECTOR( 0xd00 )
+ILLEGAL_VECTOR( 0xe00 )
+ILLEGAL_VECTOR( 0xf00 )
+ILLEGAL_VECTOR( 0xf20 )
+ILLEGAL_VECTOR( 0x1000 )
+ILLEGAL_VECTOR( 0x1100 )
+ILLEGAL_VECTOR( 0x1200 )
+ILLEGAL_VECTOR( 0x1300 )
+ILLEGAL_VECTOR( 0x1400 )
+ILLEGAL_VECTOR( 0x1500 )
+ILLEGAL_VECTOR( 0x1600 )
+ILLEGAL_VECTOR( 0x1700 )
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+
+VECTOR( 0x2000, "DSI_64" ):
+ EXCEPTION_PREAMBLE_64
+ LOAD_REG_IMMEDIATE(r3, dsi_exception)
+ mtctr r3
+ bctrl
+ EXCEPTION_EPILOGUE_64
+
+VECTOR( 0x2200, "ISI_64" ):
+ EXCEPTION_PREAMBLE_64
+ LOAD_REG_IMMEDIATE(r3, isi_exception)
+ mtctr r3
+ bctrl
+ EXCEPTION_EPILOGUE_64
+
+#endif
+
+real_dsi:
+ EXCEPTION_PREAMBLE
+ LOAD_REG_FUNC(r3, dsi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+real_isi:
+ EXCEPTION_PREAMBLE
+ LOAD_REG_FUNC(r3, isi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+exception_return:
+ EXCEPTION_EPILOGUE
+
+GLOBL(__vectors_end):
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+GLOBL(_entry):
+
+#ifdef CONFIG_PPC_64BITSUPPORT
+ li r0,0
+
+ lis r3, 0x8000 /* r1=0x80000000 */
+ add. r3,r3,r3 /* r1=r1+r1 (high 32bit !0) */
+ beq no_64bit /* only true when !MSR_SF */
+
+ /* clear MSR, disable MMU, SF */
+ mtmsrd r0
+ b real_entry
+
+no_64bit:
+ /* clear MSR, disable MMU */
+ mtmsr r0
+
+real_entry:
+#endif
+
+ /* copy exception vectors */
+
+ LOAD_REG_IMMEDIATE(r3, __vectors)
+ li r4,0
+ li r5,__vectors_end - __vectors + 16
+ rlwinm r5,r5,0,0,28
+1: lwz r6,0(r3)
+ lwz r7,4(r3)
+ lwz r8,8(r3)
+ lwz r9,12(r3)
+ stw r6,0(r4)
+ stw r7,4(r4)
+ stw r8,8(r4)
+ stw r9,12(r4)
+ dcbst 0,r4
+ sync
+ icbi 0,r4
+ sync
+ addi r5,r5,-16
+ addi r3,r3,16
+ addi r4,r4,16
+ cmpwi r5,0
+ bgt 1b
+ isync
+
+ bl compute_ramsize
+
+ /* Memory map:
+ *
+ * Top +-------------------------+
+ * | |
+ * | ROM into RAM (1 MB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | MMU Hash Table (64 kB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Exception Stack (32 kB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Stack (64 kB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Client Stack (64 kB) |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Malloc Zone (2 MiB) |
+ * | |
+ * +-------------------------+
+ * : :
+ * Bottom
+ */
+
+ addis r1, r3, -16 /* ramsize - 1MB */
+
+ /* setup hash table */
+
+ addis r1, r1, -1 /* - 64 kB */
+ clrrwi r1, r1, 5*4 /* & ~0xfffff */
+
+ /* setup exception stack */
+
+ mtsprg0 r1
+
+ /* setup stack */
+
+ addi r1, r1, -32768 /* - 32 kB */
+
+ /* save memory size in stack */
+
+#ifdef __powerpc64__
+ /* set up TOC pointer */
+
+ LOAD_REG_IMMEDIATE(r2, setup_mmu)
+ ld r2, 8(r2)
+#endif
+
+ bl BRANCH_LABEL(setup_mmu)
+ bl BRANCH_LABEL(entry)
+1: nop
+ b 1b
+
+
+ /* According to IEEE 1275, PPC bindings:
+ *
+ * MSR = FP, ME + (DR|IR)
+ * r1 = stack (32 K + 32 bytes link area above)
+ * r5 = client interface handler
+ * r6 = address of client program arguments (unused)
+ * r7 = length of client program arguments (unused)
+ *
+ * Yaboot and Linux use r3 and r4 for initrd address and size
+ */
+ .data
+saved_stack:
+ DATA_LONG(0)
+ .previous
+ /* void call_elf( arg1, arg2, entry ) */
+_GLOBAL(call_elf):
+ mflr r0
+ PPC_STLU r1, -STACKFRAME_MINSIZE(r1)
+ PPC_STL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1)
+ mtlr r5
+ LOAD_REG_IMMEDIATE(r8, saved_stack) // save our stack pointer
+ PPC_STL r1,0(r8)
+ mfsdr1 r1
+ addi r1, r1, -32768 /* - 32 KiB exception stack */
+ addis r1, r1, -1 /* - 64 KiB stack */
+ LOAD_REG_IMMEDIATE(r5, of_client_callback) // r5 = callback
+ li r6,0 // r6 = address of client program arguments (unused)
+ li r7,0 // r7 = length of client program arguments (unused)
+ li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR
+ MTMSRD(r0)
+ blrl
+
+#ifdef CONFIG_PPC64
+ /* Restore SF bit */
+ LOAD_REG_IMMEDIATE(r0, MSR_SF | MSR_FP | MSR_ME | MSR_DR | MSR_IR)
+ MTMSRD(r0)
+#endif
+ LOAD_REG_IMMEDIATE(r8, saved_stack) // restore stack pointer
+ mr r1,r8
+ PPC_LL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1)
+ mtlr r0
+ addi r1, r1, STACKFRAME_MINSIZE
+ // XXX: should restore r12-r31 etc..
+ // we should not really come here though
+ blr
+
+#ifdef __powerpc64__
+#define STKOFF STACKFRAME_MINSIZE
+#define SAVE_SPACE 320
+#else
+#define STKOFF 8
+#define SAVE_SPACE 144
+#endif
+GLOBL(of_client_callback):
+
+#ifdef CONFIG_PPC64
+ PPC_STLU r1, -(STACKFRAME_MINSIZE + 16)(r1)
+#else
+ PPC_STLU r1, -STACKFRAME_MINSIZE(r1) /* fits within alignment */
+#endif
+
+ /* save r4 */
+
+ PPC_STL r4, STKOFF(r1)
+
+ /* save lr */
+
+ mflr r4
+ PPC_STL r4, PPC_LR_STKOFF(r1)
+
+ /* restore OF stack */
+
+ LOAD_REG_IMMEDIATE(r4, saved_stack)
+ PPC_LL r4, 0(r4)
+
+ PPC_STLU r4,-SAVE_SPACE(r4)
+ PPC_STL r1,(STKOFF)(r4) // save caller stack
+ mr r1,r4
+
+ PPC_STL r2, (STKOFF + 1 * ULONG_SIZE)(r1)
+ PPC_STL r0, (STKOFF + 2 * ULONG_SIZE)(r1)
+
+ /* save ctr, cr and xer */
+
+ mfctr r2
+ PPC_STL r2, (STKOFF + 3 * ULONG_SIZE)(r1)
+ mfcr r2
+ PPC_STL r2, (STKOFF + 4 * ULONG_SIZE)(r1)
+ mfxer r2
+ PPC_STL r2, (STKOFF + 5 * ULONG_SIZE)(r1)
+
+ /* save r5 - r31 */
+
+ PPC_STL r5, (STKOFF + 6 * ULONG_SIZE)(r1)
+ PPC_STL r6, (STKOFF + 7 * ULONG_SIZE)(r1)
+ PPC_STL r7, (STKOFF + 8 * ULONG_SIZE)(r1)
+ PPC_STL r8, (STKOFF + 9 * ULONG_SIZE)(r1)
+ PPC_STL r9, (STKOFF + 10 * ULONG_SIZE)(r1)
+ PPC_STL r10, (STKOFF + 11 * ULONG_SIZE)(r1)
+ PPC_STL r11, (STKOFF + 12 * ULONG_SIZE)(r1)
+ PPC_STL r12, (STKOFF + 13 * ULONG_SIZE)(r1)
+ PPC_STL r13, (STKOFF + 14 * ULONG_SIZE)(r1)
+ PPC_STL r14, (STKOFF + 15 * ULONG_SIZE)(r1)
+ PPC_STL r15, (STKOFF + 16 * ULONG_SIZE)(r1)
+ PPC_STL r16, (STKOFF + 17 * ULONG_SIZE)(r1)
+ PPC_STL r17, (STKOFF + 18 * ULONG_SIZE)(r1)
+ PPC_STL r18, (STKOFF + 19 * ULONG_SIZE)(r1)
+ PPC_STL r19, (STKOFF + 20 * ULONG_SIZE)(r1)
+ PPC_STL r20, (STKOFF + 21 * ULONG_SIZE)(r1)
+ PPC_STL r21, (STKOFF + 22 * ULONG_SIZE)(r1)
+ PPC_STL r22, (STKOFF + 23 * ULONG_SIZE)(r1)
+ PPC_STL r23, (STKOFF + 24 * ULONG_SIZE)(r1)
+ PPC_STL r24, (STKOFF + 25 * ULONG_SIZE)(r1)
+ PPC_STL r25, (STKOFF + 26 * ULONG_SIZE)(r1)
+ PPC_STL r26, (STKOFF + 27 * ULONG_SIZE)(r1)
+ PPC_STL r27, (STKOFF + 28 * ULONG_SIZE)(r1)
+ PPC_STL r28, (STKOFF + 29 * ULONG_SIZE)(r1)
+ PPC_STL r29, (STKOFF + 30 * ULONG_SIZE)(r1)
+ PPC_STL r30, (STKOFF + 31 * ULONG_SIZE)(r1)
+ PPC_STL r31, (STKOFF + 32 * ULONG_SIZE)(r1)
+
+#ifdef CONFIG_PPC64
+ LOAD_REG_IMMEDIATE(r2, of_client_interface)
+ ld r2, 8(r2)
+#endif
+ bl BRANCH_LABEL(of_client_interface)
+
+ /* restore r5 - r31 */
+
+ PPC_LL r5, (STKOFF + 6 * ULONG_SIZE)(r1)
+ PPC_LL r6, (STKOFF + 7 * ULONG_SIZE)(r1)
+ PPC_LL r7, (STKOFF + 8 * ULONG_SIZE)(r1)
+ PPC_LL r8, (STKOFF + 9 * ULONG_SIZE)(r1)
+ PPC_LL r9, (STKOFF + 10 * ULONG_SIZE)(r1)
+ PPC_LL r10, (STKOFF + 11 * ULONG_SIZE)(r1)
+ PPC_LL r11, (STKOFF + 12 * ULONG_SIZE)(r1)
+ PPC_LL r12, (STKOFF + 13 * ULONG_SIZE)(r1)
+ PPC_LL r13, (STKOFF + 14 * ULONG_SIZE)(r1)
+ PPC_LL r14, (STKOFF + 15 * ULONG_SIZE)(r1)
+ PPC_LL r15, (STKOFF + 16 * ULONG_SIZE)(r1)
+ PPC_LL r16, (STKOFF + 17 * ULONG_SIZE)(r1)
+ PPC_LL r17, (STKOFF + 18 * ULONG_SIZE)(r1)
+ PPC_LL r18, (STKOFF + 19 * ULONG_SIZE)(r1)
+ PPC_LL r19, (STKOFF + 20 * ULONG_SIZE)(r1)
+ PPC_LL r20, (STKOFF + 21 * ULONG_SIZE)(r1)
+ PPC_LL r21, (STKOFF + 22 * ULONG_SIZE)(r1)
+ PPC_LL r22, (STKOFF + 23 * ULONG_SIZE)(r1)
+ PPC_LL r23, (STKOFF + 24 * ULONG_SIZE)(r1)
+ PPC_LL r24, (STKOFF + 25 * ULONG_SIZE)(r1)
+ PPC_LL r25, (STKOFF + 26 * ULONG_SIZE)(r1)
+ PPC_LL r26, (STKOFF + 27 * ULONG_SIZE)(r1)
+ PPC_LL r27, (STKOFF + 28 * ULONG_SIZE)(r1)
+ PPC_LL r28, (STKOFF + 29 * ULONG_SIZE)(r1)
+ PPC_LL r29, (STKOFF + 30 * ULONG_SIZE)(r1)
+ PPC_LL r30, (STKOFF + 31 * ULONG_SIZE)(r1)
+ PPC_LL r31, (STKOFF + 32 * ULONG_SIZE)(r1)
+
+ /* restore ctr, cr and xer */
+
+ PPC_LL r2, (STKOFF + 3 * ULONG_SIZE)(r1)
+ mtctr r2
+ PPC_LL r2, (STKOFF + 4 * ULONG_SIZE)(r1)
+ mtcr r2
+ PPC_LL r2, (STKOFF + 5 * ULONG_SIZE)(r1)
+ mtxer r2
+
+ /* restore r0 and r2 */
+
+ PPC_LL r2, (STKOFF + 1 * ULONG_SIZE)(r1)
+ PPC_LL r0, (STKOFF + 2 * ULONG_SIZE)(r1)
+
+ /* restore caller stack */
+
+ PPC_LL r1, (STKOFF)(r1)
+
+ PPC_LL r4, PPC_LR_STKOFF(r1)
+ mtlr r4
+ PPC_LL r4, STKOFF(r1)
+ PPC_LL r1, 0(r1)
+
+ blr
+
+ /* rtas glue (must be reloctable) */
+GLOBL(of_rtas_start):
+ /* r3 = argument buffer, r4 = of_rtas_start */
+ /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
+ blr
+GLOBL(of_rtas_end):
+
+
+#define CACHE_LINE_SIZE 32
+#define LG_CACHE_LINE_SIZE 5
+
+/* flush_icache_range( unsigned long start, unsigned long stop) */
+_GLOBAL(flush_icache_range):
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+ blr
+
+ /* Get RAM size from QEMU configuration device */
+
+#define CFG_ADDR 0xf0000510
+#define FW_CFG_RAM_SIZE 0x03
+
+compute_ramsize:
+ LOAD_REG_IMMEDIATE(r9, CFG_ADDR)
+ li r0,FW_CFG_RAM_SIZE
+ sth r0,0(r9)
+ LOAD_REG_IMMEDIATE(r9, CFG_ADDR + 2)
+ lbz r1,0(r9)
+ lbz r0,0(r9)
+ slwi r0,r0,8
+ or r1,r1,r0
+ lbz r0,0(r9)
+ slwi r0,r0,16
+ or r1,r1,r0
+ lbz r0,0(r9)
+ slwi r0,r0,24
+ or r3,r1,r0
+ blr
+
+ /* Hard reset vector */
+ .section .romentry,"ax"
+ bl _entry
diff --git a/roms/openbios/arch/ppc/qemu/tree.fs b/roms/openbios/arch/ppc/qemu/tree.fs
new file mode 100644
index 00000000..1ed83839
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/tree.fs
@@ -0,0 +1,71 @@
+\ QEMU specific initialization code
+\
+\ This program is free software; you can redistribute it and/or
+\ modify it under the terms of the GNU General Public License
+\ as published by the Free Software Foundation
+\
+
+include config.fs
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
+" /" find-device
+\ Apple calls the root node device-tree
+" device-tree" device-name
+[IFDEF] CONFIG_PPC64 2 [ELSE] 1 [THEN] encode-int " #address-cells" property
+1 encode-int " #size-cells" property
+h# 05f5e100 encode-int " clock-frequency" property
+
+new-device
+ " cpus" device-name
+ 1 encode-int " #address-cells" property
+ 0 encode-int " #size-cells" property
+ external
+
+ : encode-unit ( unit -- str len )
+ pocket tohexstr
+ ;
+
+ : decode-unit ( str len -- unit )
+ parse-hex
+ ;
+
+finish-device
+
+new-device
+ " memory" device-name
+ " memory" device-type
+ external
+ : open true ;
+ : close ;
+finish-device
+
+\ -------------------------------------------------------------
+\ /packages
+\ -------------------------------------------------------------
+
+" /packages" find-device
+
+ " packages" device-name
+ external
+ \ allow packages to be opened with open-dev
+ : open true ;
+ : close ;
+
+\ /packages/terminal-emulator
+new-device
+ " terminal-emulator" device-name
+ external
+ : open true ;
+ : close ;
+ \ : write ( addr len -- actual )
+ \ dup -rot type
+ \ ;
+finish-device
+
+\ -------------------------------------------------------------
+\ The END
+\ -------------------------------------------------------------
+device-end
diff --git a/roms/openbios/arch/ppc/qemu/vfd.c b/roms/openbios/arch/ppc/qemu/vfd.c
new file mode 100644
index 00000000..308d0e33
--- /dev/null
+++ b/roms/openbios/arch/ppc/qemu/vfd.c
@@ -0,0 +1,42 @@
+/*
+ * Creation Date: <2004/08/28 17:29:43 greg>
+ * Time-stamp: <2004/08/28 17:29:43 greg>
+ *
+ * <vfd.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "qemu/qemu.h"
+
+static int vfd_is_open;
+
+static int
+vfd_init( void )
+{
+ vfd_is_open = 1;
+ return 0;
+}
+
+void
+vfd_close( void )
+{
+}
+
+int
+vfd_draw_str( const char *str )
+{
+ if (!vfd_is_open)
+ vfd_init();
+
+ return 0;
+}
diff --git a/roms/openbios/arch/ppc/start.S b/roms/openbios/arch/ppc/start.S
new file mode 100644
index 00000000..40ee0896
--- /dev/null
+++ b/roms/openbios/arch/ppc/start.S
@@ -0,0 +1,335 @@
+/*
+ * Creation Date: <2001/06/16 21:30:18 samuel>
+ * Time-stamp: <2003/04/04 16:32:06 samuel>
+ *
+ * <init.S>
+ *
+ * Asm glue for ELF images run inside MOL
+ *
+ * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+#include "osi.h"
+
+/************************************************************************/
+/* Macros */
+/************************************************************************/
+
+#define ILLEGAL_VECTOR( v ) .org __vectors + v ; bl trap_error ;
+#define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v
+
+#define EXCEPTION_PREAMBLE \
+ mtsprg1 r1 ; /* scratch */ \
+ mfsprg0 r1 ; /* exception stack in sprg0 */ \
+ addi r1,r1,-80 ; /* push exception frame */ \
+ \
+ stw r0,0(r1) ; /* save r0 */ \
+ mfsprg1 r0 ; \
+ stw r0,4(r1) ; /* save r1 */ \
+ stw r2,8(r1) ; /* save r2 */ \
+ stw r3,12(r1) ; /* save r3 */ \
+ stw r4,16(r1) ; \
+ stw r5,20(r1) ; \
+ stw r6,24(r1) ; \
+ stw r7,28(r1) ; \
+ stw r8,32(r1) ; \
+ stw r9,36(r1) ; \
+ stw r10,40(r1) ; \
+ stw r11,44(r1) ; \
+ stw r12,48(r1) ; \
+ \
+ mflr r0 ; \
+ stw r0,52(r1) ; \
+ mfcr r0 ; \
+ stw r0,56(r1) ; \
+ mfctr r0 ; \
+ stw r0,60(r1) ; \
+ mfxer r0 ; \
+ stw r0,64(r1) ; \
+ \
+ /* 76(r1) unused */ \
+ addi r1,r1,-16 ; /* call conventions uses 0(r1) and 4(r1)... */
+
+
+/************************************************************************/
+/* stack space */
+/************************************************************************/
+
+ .section .bss
+ .balign 32
+ .space 32*1024 // 32 K client stack
+client_stack:
+ .space 128
+
+ .space 64*1024 // 64 K stack
+stack: .space 64
+
+ .space 32*1024 // 32 K exception stack
+estack: .space 128
+
+
+/************************************************************************/
+/* entry */
+/************************************************************************/
+
+ .text
+GLOBL(_start):
+ li r0,0
+ mtmsr r0
+
+ lis r1,HA(estack)
+ addi r1,r1,LO(estack)
+ mtsprg0 r1 // setup exception stack
+ lis r1,HA(stack)
+ addi r1,r1,LO(stack)
+
+ // copy exception vectors
+ lis r3,HA(__vectors)
+ addi r3,r3,LO(__vectors)
+ li r4,0
+ li r5,__vectors_end - __vectors + 16
+ rlwinm r5,r5,0,0,28
+1: lwz r6,0(r3)
+ lwz r7,4(r3)
+ lwz r8,8(r3)
+ lwz r9,12(r3)
+ stw r6,0(r4)
+ stw r7,4(r4)
+ stw r8,8(r4)
+ stw r9,12(r4)
+ dcbst 0,r4
+ sync
+ icbi 0,r4
+ sync
+ addi r5,r5,-16
+ addi r3,r3,16
+ addi r4,r4,16
+ cmpwi r5,0
+ bgt 1b
+ isync
+
+ bl setup_mmu
+ bl entry
+1: nop
+ b 1b
+
+
+ /* According to IEEE 1275, PPC bindings:
+ *
+ * MSR = FP, ME + (DR|IR)
+ * r1 = stack (32 K + 32 bytes link area above)
+ * r5 = clint interface handler
+ * r6 = address of client program arguments (unused)
+ * r7 = length of client program arguments (unsed)
+ */
+saved_stack:
+ .long 0
+ /* void call_elf( entry ) */
+GLOBL(call_elf):
+ mflr r0
+ stwu r1,-16(r1)
+ stw r0,20(r1)
+ mtlr r3
+ lis r8,HA(saved_stack)
+ addi r8,r8,LO(saved_stack) // save our stack pointer
+ stw r1,0(r8)
+ lis r1,HA(client_stack)
+ addi r1,r1,LO(client_stack)
+ lis r5,HA(of_client_callback)
+ addi r5,r5,LO(of_client_callback) // r5 = callback
+ li r6,0 // r6 = address of client program arguments (unused)
+ li r7,0 // r7 = length of client program arguments (unused)
+ li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR
+ mtmsr r0
+ blrl
+
+ lis r8,HA(saved_stack)
+ addi r8,r8,LO(saved_stack) // restore stack pointer
+ mr r1,r8
+ lwz r0,20(r1)
+ mtlr r0
+ addi r1,r1,16
+ // XXX: should restore r12-r31 etc..
+ // we should not really come here though
+ blr
+
+GLOBL(of_client_callback):
+ lis r4,HA(saved_stack)
+ addi r4,r4,LO(saved_stack)
+ lwz r4,0(r4)
+ stwu r4,-32(r4)
+ mflr r5
+ stw r5,32+4(r4)
+ stw r1,8(r4) // save caller stack
+ mr r1,r4
+ stw r2,12(r1)
+ stw r0,16(r1)
+ mfctr r2
+ stw r2,20(r1)
+ mfcr r2
+ stw r2,24(r1)
+ mfxer r2
+ stw r2,28(r1)
+ // do we need to save more registers?
+ bl of_client_interface
+ lwz r4,32+4(r1)
+ mtlr r4
+ lwz r2,20(r1)
+ mtctr r2
+ lwz r2,24(r1)
+ mtcr r2
+ lwz r2,28(r1)
+ mtxer r2
+ lwz r2,12(r1)
+ lwz r0,16(r1)
+ lwz r1,8(r1) // restore caller stack
+ blr
+
+ /* rtas glue (must be reloctable) */
+GLOBL(of_rtas_start):
+ /* r3 = argument buffer, r4 = of_rtas_start */
+ /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
+ mr r6,r3
+ lis r3,HA(OSI_SC_MAGIC_R3)
+ addi r3,r3,LO(OSI_SC_MAGIC_R3)
+ lis r4,HA(OSI_SC_MAGIC_R4)
+ addi r4,r4,LO(OSI_SC_MAGIC_R4)
+ li r5,OSI_OF_RTAS
+ sc
+ blr
+GLOBL(of_rtas_end):
+
+
+ /* used in a hack to the newworld calibration */
+GLOBL(nw_dec_calibration):
+ .long 0
+GLOBL(timer_calib_start):
+ lis r3,HA(nw_dec_calibration)
+ addi r3,r3,LO(nw_dec_calibration)
+ lwz r3,0(r3)
+ blr
+GLOBL(timer_calib_end):
+
+
+/************************************************************************/
+/* vectors */
+/************************************************************************/
+
+GLOBL(__vectors):
+ nop // NULL-jmp trap
+1: nop //
+ b 1b
+
+exception_return:
+ addi r1,r1,16 // pop ABI frame
+
+ lwz r0,52(r1)
+ mtlr r0
+ lwz r0,56(r1)
+ mtcr r0
+ lwz r0,60(r1)
+ mtctr r0
+ lwz r0,64(r1)
+ mtxer r0
+
+ lwz r0,0(r1) // restore r0
+ lwz r2,8(r1) // restore r2
+ lwz r3,12(r1) // restore r3
+ lwz r4,16(r1)
+ lwz r5,20(r1)
+ lwz r6,24(r1)
+ lwz r7,28(r1)
+ lwz r8,32(r1)
+ lwz r9,36(r1)
+ lwz r10,40(r1)
+ lwz r11,44(r1)
+ lwz r12,48(r1)
+ lwz r1,4(r1) // restore r1
+ rfi
+
+trap_error:
+ mflr r3
+ b unexpected_excep
+
+ILLEGAL_VECTOR( 0x100 )
+ILLEGAL_VECTOR( 0x200 )
+
+VECTOR( 0x300, "DSI" ):
+ EXCEPTION_PREAMBLE
+ lis r3,HA(dsi_exception)
+ addi r3,r3,LO(dsi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+VECTOR( 0x400, "ISI" ):
+ EXCEPTION_PREAMBLE
+ lis r3,HA(isi_exception)
+ addi r3,r3,LO(isi_exception)
+ mtctr r3
+ bctrl
+ b exception_return
+
+ ILLEGAL_VECTOR( 0x500 )
+ ILLEGAL_VECTOR( 0x600 )
+ ILLEGAL_VECTOR( 0x700 )
+
+VECTOR( 0x800, "FPU" ):
+ mtsprg1 r3
+ mfsrr1 r3
+ ori r3,r3,0x2000
+ mtsrr1 r3
+ mfsprg1 r3
+ rfi
+
+ILLEGAL_VECTOR( 0x900 )
+ILLEGAL_VECTOR( 0xa00 )
+ILLEGAL_VECTOR( 0xb00 )
+ILLEGAL_VECTOR( 0xc00 )
+ILLEGAL_VECTOR( 0xd00 )
+ILLEGAL_VECTOR( 0xe00 )
+ILLEGAL_VECTOR( 0xf00 )
+ILLEGAL_VECTOR( 0xf20 )
+ILLEGAL_VECTOR( 0x1000 )
+ILLEGAL_VECTOR( 0x1100 )
+ILLEGAL_VECTOR( 0x1200 )
+ILLEGAL_VECTOR( 0x1300 )
+ILLEGAL_VECTOR( 0x1400 )
+ILLEGAL_VECTOR( 0x1500 )
+ILLEGAL_VECTOR( 0x1600 )
+ILLEGAL_VECTOR( 0x1700 )
+
+GLOBL(__vectors_end):
+
+
+#define CACHE_LINE_SIZE 32
+#define LG_CACHE_LINE_SIZE 5
+
+/* flush_icache_range( unsigned long start, unsigned long stop) */
+GLOBL(flush_icache_range):
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+ blr
diff --git a/roms/openbios/arch/ppc/timebase.S b/roms/openbios/arch/ppc/timebase.S
new file mode 100644
index 00000000..19faed49
--- /dev/null
+++ b/roms/openbios/arch/ppc/timebase.S
@@ -0,0 +1,33 @@
+#include "asm/asmdefs.h"
+#include "asm/processor.h"
+
+/*
+ * unsigned long long _get_ticks(void);
+ */
+_GLOBAL(_get_ticks):
+1: mftbu r3
+ mftb r4
+ mftbu r5
+ cmpw 0,r3,r5
+ bne 1b
+ blr
+
+/*
+ * Delay for a number of ticks
+ */
+_GLOBAL(_wait_ticks):
+ mflr r8 /* save link register */
+ mr r7, r3 /* save tick count */
+ bl BRANCH_LABEL(_get_ticks) /* Get start time */
+
+ /* Calculate end time */
+ addc r7, r4, r7 /* Compute end time lower */
+ addze r6, r3 /* and end time upper */
+
+1: bl BRANCH_LABEL(_get_ticks) /* Get current time */
+ subfc r4, r4, r7 /* Subtract current time from end time */
+ subfe. r3, r3, r6
+ bge 1b /* Loop until time expired */
+
+ mtlr r8 /* restore link register */
+ blr
diff --git a/roms/openbios/arch/ppc64/qemu/ldscript b/roms/openbios/arch/ppc64/qemu/ldscript
new file mode 100644
index 00000000..fbbcc546
--- /dev/null
+++ b/roms/openbios/arch/ppc64/qemu/ldscript
@@ -0,0 +1,85 @@
+OUTPUT_FORMAT(elf64-powerpc)
+OUTPUT_ARCH(powerpc:common64)
+
+/* Initial load address
+ */
+BASE_ADDR = 0xfff00000;
+
+/* As NVRAM is at 0xfff04000, the .text needs to be after that
+ * The value in arch/ppc/qemu/kernel.c must match this value!
+ */
+TEXT_ADDR = 0xfff08000;
+
+/* Hard reset vector address
+ */
+HRESET_ADDR = 0xfffffffc;
+
+CSTACK_SIZE = 32768; /* client stack size */
+
+SECTIONS
+{
+ . = BASE_ADDR;
+
+ _start = BASE_ADDR + 0x0100;
+ .text.vectors ALIGN(4096): {
+ *(.text.vectors)
+ }
+
+ . = TEXT_ADDR;
+ /* Normal sections */
+ .data.dict ALIGN(4096): {
+ _dict_start = .;
+ *(.data.dict)
+ _dict_end = .;
+ }
+
+ .text ALIGN(4096): {
+ *(.text)
+ *(.text.*)
+ }
+
+ .rodata ALIGN(4096): {
+ _rodata = .;
+ *(.rodata)
+ *(.rodata.*)
+ *(.note.ELFBoot)
+ }
+ .data ALIGN(4096): {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ *(.toc1)
+ *(.branch_lt)
+ _edata = .;
+ }
+ .opd : {
+ *(.opd)
+ }
+ .got : {
+ __toc_start = .;
+ *(.got)
+ *(.toc)
+ }
+
+ .bss ALIGN(4096): {
+ _bss = .;
+ *(.sbss)
+ *(.sbss.*)
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ _ebss = .;
+ }
+
+ . = HRESET_ADDR;
+
+ .romentry : { *(.romentry) }
+
+ . = ALIGN(4096);
+ _end = .;
+
+ /* We discard .note sections other than .note.ELFBoot,
+ * because some versions of GCC generates useless ones. */
+
+ /DISCARD/ : { *(.comment*) *(.note.*) }
+}
diff --git a/roms/openbios/arch/sparc32/boot.c b/roms/openbios/arch/sparc32/boot.c
new file mode 100644
index 00000000..49ec4cfb
--- /dev/null
+++ b/roms/openbios/arch/sparc32/boot.c
@@ -0,0 +1,261 @@
+/*
+ *
+ */
+#undef BOOTSTRAP
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "drivers/drivers.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "libopenbios/ofmem.h"
+#include "libopenbios/sys_info.h"
+#include "openprom.h"
+#include "boot.h"
+#include "context.h"
+
+uint32_t kernel_image;
+uint32_t kernel_size;
+uint32_t qemu_cmdline;
+uint32_t cmdline_size;
+char boot_device;
+const void *romvec;
+
+static struct linux_mlist_v0 *totphyslist, *availlist, *prommaplist;
+
+static void setup_romvec(void)
+{
+ /* SPARC32 is slightly unusual in that before invoking any loaders, a romvec array
+ needs to be set up to pass certain parameters using a C struct. Hence this function
+ extracts the relevant boot information and places it in obp_arg. */
+
+ int intprop, proplen, target, device, i;
+ unsigned int *intprop_ptr;
+ phandle_t chosen;
+ char *prop, *id, *name;
+ static char bootpathbuf[128], bootargsbuf[128], buf[128];
+ struct linux_mlist_v0 **pp;
+
+ /* Get the stdin and stdout paths */
+ chosen = find_dev("/chosen");
+ intprop = get_int_property(chosen, "stdin", &proplen);
+ PUSH(intprop);
+ fword("get-instance-path");
+ ((struct linux_romvec *)romvec)->pv_stdin = pop_fstr_copy();
+
+ intprop = get_int_property(chosen, "stdout", &proplen);
+ PUSH(intprop);
+ fword("get-instance-path");
+ ((struct linux_romvec *)romvec)->pv_stdout = pop_fstr_copy();
+
+ /* Get the name of the selected boot device, along with the device and unit number */
+ prop = get_property(chosen, "bootpath", &proplen);
+ strncpy(bootpathbuf, prop, proplen);
+ prop = get_property(chosen, "bootargs", &proplen);
+ strncpy(bootargsbuf, prop, proplen);
+
+ /* Set bootpath pointer used in romvec table to the bootpath */
+ push_str(bootpathbuf);
+ fword("pathres-resolve-aliases");
+ bootpath = pop_fstr_copy();
+ printk("bootpath: %s\n", bootpath);
+
+ /* Now do some work to get hold of the target, partition etc. */
+ push_str(bootpathbuf);
+ feval("open-dev");
+ feval("ihandle>boot-device-handle drop to my-self");
+ push_str("name");
+ fword("get-my-property");
+ POP();
+ name = pop_fstr_copy();
+
+ if (!strncmp(name, "sd", 2)) {
+
+ /*
+ Old-style SunOS disk paths are given in the form:
+
+ sd(c,t,d):s
+
+ where:
+ c = controller (Nth controller in system, usually 0)
+ t = target (my-unit phys.hi)
+ d = device/LUN (my-unit phys.lo)
+ s = slice/partition (my-args)
+ */
+
+ /* Controller currently always 0 */
+ obp_arg.boot_dev_ctrl = 0;
+
+ /* Get the target, device and slice */
+ fword("my-unit");
+ target = POP();
+ device = POP();
+
+ fword("my-args");
+ id = pop_fstr_copy();
+
+ if (id != NULL) {
+ snprintf(buf, sizeof(buf), "sd(0,%d,%d):%c", target, device, id[0]);
+ obp_arg.dev_partition = id[0] - 'a';
+ } else {
+ snprintf(buf, sizeof(buf), "sd(0,%d,%d)", target, device);
+ obp_arg.dev_partition = 0;
+ }
+
+ obp_arg.boot_dev_unit = target;
+
+ obp_arg.boot_dev[0] = buf[0];
+ obp_arg.boot_dev[1] = buf[1];
+ obp_arg.argv[0] = buf;
+ obp_arg.argv[1] = bootargsbuf;
+
+ } else if (!strncmp(name, "SUNW,fdtwo", 10)) {
+
+ obp_arg.boot_dev_ctrl = 0;
+ obp_arg.boot_dev_unit = 0;
+ obp_arg.dev_partition = 0;
+
+ strcpy(buf, "fd()");
+
+ obp_arg.boot_dev[0] = buf[0];
+ obp_arg.boot_dev[1] = buf[1];
+ obp_arg.argv[0] = buf;
+ obp_arg.argv[1] = bootargsbuf;
+
+ } else if (!strncmp(name, "le", 2)) {
+
+ obp_arg.boot_dev_ctrl = 0;
+ obp_arg.boot_dev_unit = 0;
+ obp_arg.dev_partition = 0;
+
+ strcpy(buf, "le()");
+
+ obp_arg.boot_dev[0] = buf[0];
+ obp_arg.boot_dev[1] = buf[1];
+ obp_arg.argv[0] = buf;
+ obp_arg.argv[1] = bootargsbuf;
+
+ }
+
+ /* Generate the totphys (total memory available) list */
+ prop = get_property(s_phandle_memory, "reg", &proplen);
+ intprop_ptr = (unsigned int *)prop;
+
+ for (pp = &totphyslist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) {
+ *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0));
+ (**pp).theres_more = NULL;
+ (**pp).start_adr = (char *)intprop_ptr[1];
+ (**pp).num_bytes = intprop_ptr[2];
+
+ intprop_ptr += 3;
+ }
+
+ /* Generate the avail (physical memory available) list */
+ prop = get_property(s_phandle_memory, "available", &proplen);
+ intprop_ptr = (unsigned int *)prop;
+
+ for (pp = &availlist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) {
+ *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0));
+ (**pp).theres_more = NULL;
+ (**pp).start_adr = (char *)intprop_ptr[1];
+ (**pp).num_bytes = intprop_ptr[2];
+
+ intprop_ptr += 3;
+ }
+
+ /* Generate the prommap (taken virtual memory) list from inverse of available */
+ prop = get_property(s_phandle_mmu, "available", &proplen);
+ intprop_ptr = (unsigned int *)prop;
+
+ for (pp = &prommaplist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) {
+ *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0));
+ (**pp).theres_more = NULL;
+ (**pp).start_adr = (char *)(intprop_ptr[1] + intprop_ptr[2]);
+
+ if (i + 3 < (proplen / sizeof(int))) {
+ /* Size from next entry */
+ (**pp).num_bytes = (intprop_ptr[4] + intprop_ptr[5]) - (intprop_ptr[1] + intprop_ptr[2]);
+ } else {
+ /* Tail (size from top of virtual memory) */
+ (**pp).num_bytes = 0xffffffffUL - (intprop_ptr[1] + intprop_ptr[2]) + 1;
+ }
+
+ intprop_ptr += 3;
+ }
+
+ /* Finally set the memory properties */
+ ((struct linux_romvec *)romvec)->pv_v0mem.v0_totphys = &totphyslist;
+ ((struct linux_romvec *)romvec)->pv_v0mem.v0_available = &availlist;
+ ((struct linux_romvec *)romvec)->pv_v0mem.v0_prommap = &prommaplist;
+}
+
+
+void go(void)
+{
+ ucell address, type, size;
+ int image_retval = 0;
+
+ /* Get the entry point and the type (see forth/debugging/client.fs) */
+ feval("saved-program-state >sps.entry @");
+ address = POP();
+ feval("saved-program-state >sps.file-type @");
+ type = POP();
+ feval("saved-program-state >sps.file-size @");
+ size = POP();
+
+ setup_romvec();
+
+ printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type);
+
+ switch (type) {
+ case 0x0:
+ /* Start ELF boot image */
+ image_retval = start_elf((unsigned long)address,
+ (unsigned long)romvec);
+
+ break;
+
+ case 0x1:
+ /* Start ELF image */
+ image_retval = start_elf((unsigned long)address,
+ (unsigned long)romvec);
+
+ break;
+
+ case 0x5:
+ /* Start a.out image */
+ image_retval = start_elf((unsigned long)address,
+ (unsigned long)romvec);
+
+ break;
+
+ case 0x10:
+ /* Start Fcode image */
+ printk("Evaluating FCode...\n");
+ PUSH(address);
+ PUSH(1);
+ fword("byte-load");
+ image_retval = 0;
+ break;
+
+ case 0x11:
+ /* Start Forth image */
+ PUSH(address);
+ PUSH(size);
+ fword("eval2");
+ image_retval = 0;
+ break;
+ }
+
+ printk("Image returned with return value %#x\n", image_retval);
+}
+
+
+void boot(void)
+{
+ /* Boot preloaded kernel */
+ if (kernel_size) {
+ printk("[sparc] Kernel already loaded\n");
+ start_elf(kernel_image, (unsigned long)romvec);
+ }
+}
diff --git a/roms/openbios/arch/sparc32/boot.h b/roms/openbios/arch/sparc32/boot.h
new file mode 100644
index 00000000..55e391ac
--- /dev/null
+++ b/roms/openbios/arch/sparc32/boot.h
@@ -0,0 +1,41 @@
+/* tag: openbios loader prototypes for sparc32
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+// linux_load.c
+int linux_load(struct sys_info *info, const char *file, const char *cmdline);
+
+// context.c
+extern struct context *__context;
+unsigned int start_elf(unsigned long entry_point, unsigned long param);
+
+// boot.c
+extern const char *bootpath;
+extern void boot(void);
+extern void go(void);
+
+// sys_info.c
+extern unsigned int qemu_mem_size;
+extern void collect_sys_info(struct sys_info *info);
+
+// romvec.c
+extern struct linux_arguments_v0 obp_arg;
+extern const void *romvec;
+extern const char *obp_stdin_path, *obp_stdout_path;
+extern char obp_stdin, obp_stdout;
+
+// openbios.c
+extern int qemu_machine_type;
+
+// arch/sparc32/lib.c
+struct linux_mlist_v0;
+extern struct linux_mlist_v0 *ptphys;
+extern struct linux_mlist_v0 *ptmap;
+extern struct linux_mlist_v0 *ptavail;
+
+void ob_init_mmu(void);
+void init_mmu_swift(void);
diff --git a/roms/openbios/arch/sparc32/build.xml b/roms/openbios/arch/sparc32/build.xml
new file mode 100644
index 00000000..81c3586e
--- /dev/null
+++ b/roms/openbios/arch/sparc32/build.xml
@@ -0,0 +1,74 @@
+<build condition="SPARC32">
+
+ <dictionary name="openbios-sparc32" init="openbios">
+ <object source="tree.fs" target="forth"/>
+ <object source="init.fs" target="forth"/>
+ <object source="QEMU,tcx.bin" target="fcode" condition="DRIVER_SBUS"/>
+ <object source="QEMU,cgthree.bin" target="fcode" condition="DRIVER_SBUS"/>
+ </dictionary>
+
+ <library name="sparc32" type="static" target="target">
+ <object source="openbios.c"/>
+ <object source="console.c"/>
+ <object source="lib.c"/>
+ <object source="boot.c"/>
+ <object source="context.c"/>
+ <object source="switch.S"/>
+ <object source="udiv.S"/>
+ <object source="linux_load.c"/>
+ <object source="sys_info.c"/>
+ <object source="ofmem_sparc32.c"/>
+ <object source="romvec.c"/>
+ <object source="call-romvec.S"/>
+ <object source="entry.S"/>
+ <object source="vectors.S"/>
+ </library>
+
+ <executable name="openbios-plain.elf" target="target" condition="IMAGE_ELF">
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/sparc32/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-plain.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="plainboot.c"/>
+ <external-object source="libsparc32.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+ <!-- HACK ALERT -->
+
+ <executable name="target/include/static-dict.h" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <rule><![CDATA[
+ $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule>
+ <external-object source="openbios-sparc32.dict"/>
+ </executable>
+
+ <executable name="target/arch/sparc32/builtin.o" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <rule><![CDATA[ $(SRCDIR)/arch/sparc32/builtin.c $(ODIR)/target/include/static-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/sparc32/builtin.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+ <!-- END OF HACK ALERT -->
+
+ <executable name="openbios-builtin.elf" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/sparc32/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-builtin.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <external-object source="target/arch/sparc32/builtin.o"/>
+ <external-object source="libsparc32.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+</build>
diff --git a/roms/openbios/arch/sparc32/builtin.c b/roms/openbios/arch/sparc32/builtin.c
new file mode 100644
index 00000000..971a4009
--- /dev/null
+++ b/roms/openbios/arch/sparc32/builtin.c
@@ -0,0 +1,33 @@
+/* tag: openbios forth starter for builtin dictionary for sparc32
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "asm/types.h"
+#include "libopenbios/sys_info.h"
+
+/*
+ * wrap an array around the hex'ed dictionary file
+ */
+
+/* 256K for the dictionary */
+#define DICTIONARY_SIZE (256 * 1024 / sizeof(ucell))
+#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary))
+
+static ucell forth_dictionary[DICTIONARY_SIZE] = {
+#include "static-dict.h"
+};
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ info->dict_start=(unsigned long *)forth_dictionary;
+ info->dict_end = (unsigned long *)FORTH_DICTIONARY_END;
+ info->dict_last = (ucell *)((unsigned char *)forth_dictionary +
+ FORTH_DICTIONARY_LAST);
+ info->dict_limit = sizeof(forth_dictionary);
+}
diff --git a/roms/openbios/arch/sparc32/call-romvec.S b/roms/openbios/arch/sparc32/call-romvec.S
new file mode 100644
index 00000000..be77b232
--- /dev/null
+++ b/roms/openbios/arch/sparc32/call-romvec.S
@@ -0,0 +1,94 @@
+#define __ASSEMBLY
+#include "psr.h"
+#include "asm/asi.h"
+
+ .text
+ .align 4
+
+#define STACKFRAME_SZ 0x60
+
+/* These are just handy. */
+#define _SV save %sp, -STACKFRAME_SZ, %sp
+#define _RS restore
+
+#define FLUSH_ALL_KERNEL_WINDOWS \
+ _SV; _SV; _SV; _SV; _SV; _SV; _SV; \
+ _RS; _RS; _RS; _RS; _RS; _RS; _RS;
+
+/* Macro for romvec handlers */
+#define ROMVEC_HANDLER(type) \
+ \
+ .globl type##_handler; \
+ \
+type##_handler: \
+ \
+ FLUSH_ALL_KERNEL_WINDOWS; \
+ \
+ save %sp, -STACKFRAME_SZ - 0x20, %sp; \
+ \
+ st %g1, [ %sp + STACKFRAME_SZ + 0x0]; \
+ st %g2, [ %sp + STACKFRAME_SZ + 0x4]; \
+ st %g3, [ %sp + STACKFRAME_SZ + 0x8]; \
+ st %g4, [ %sp + STACKFRAME_SZ + 0xc]; \
+ st %g5, [ %sp + STACKFRAME_SZ + 0x10]; \
+ st %g6, [ %sp + STACKFRAME_SZ + 0x14]; \
+ st %g7, [ %sp + STACKFRAME_SZ + 0x18]; \
+ \
+ mov %i0, %o0; \
+ mov %i1, %o1; \
+ mov %i2, %o2; \
+ mov %i3, %o3; \
+ mov %i4, %o4; \
+ mov %i5, %o5; \
+ \
+ call type; \
+ nop; \
+ \
+ mov %o0, %i0; \
+ \
+ ld [ %sp + STACKFRAME_SZ + 0x0], %g1; \
+ ld [ %sp + STACKFRAME_SZ + 0x4], %g2; \
+ ld [ %sp + STACKFRAME_SZ + 0x8], %g3; \
+ ld [ %sp + STACKFRAME_SZ + 0xc], %g4; \
+ ld [ %sp + STACKFRAME_SZ + 0x10], %g5; \
+ ld [ %sp + STACKFRAME_SZ + 0x14], %g6; \
+ ld [ %sp + STACKFRAME_SZ + 0x18], %g7; \
+ \
+ ret; \
+ restore; \
+
+
+/* Generate handlers which are proxy functions to the
+ real C functions that correctly save the globals
+ and stack */
+ROMVEC_HANDLER(obp_devopen)
+ROMVEC_HANDLER(obp_devclose)
+ROMVEC_HANDLER(obp_rdblkdev)
+ROMVEC_HANDLER(obp_nbgetchar)
+ROMVEC_HANDLER(obp_nbputchar)
+ROMVEC_HANDLER(obp_putstr)
+ROMVEC_HANDLER(obp_printf)
+ROMVEC_HANDLER(obp_reboot)
+ROMVEC_HANDLER(obp_abort)
+ROMVEC_HANDLER(obp_halt)
+ROMVEC_HANDLER(obp_fortheval_v2)
+ROMVEC_HANDLER(obp_inst2pkg)
+ROMVEC_HANDLER(obp_dumb_memalloc)
+ROMVEC_HANDLER(obp_dumb_memfree)
+ROMVEC_HANDLER(obp_dumb_mmap)
+ROMVEC_HANDLER(obp_dumb_munmap)
+ROMVEC_HANDLER(obp_devread)
+ROMVEC_HANDLER(obp_devwrite)
+ROMVEC_HANDLER(obp_devseek)
+ROMVEC_HANDLER(obp_cpustart)
+ROMVEC_HANDLER(obp_cpustop)
+ROMVEC_HANDLER(obp_cpuidle)
+ROMVEC_HANDLER(obp_cpuresume)
+ROMVEC_HANDLER(obp_nextnode)
+ROMVEC_HANDLER(obp_child)
+ROMVEC_HANDLER(obp_proplen)
+ROMVEC_HANDLER(obp_getprop)
+ROMVEC_HANDLER(obp_setprop)
+ROMVEC_HANDLER(obp_nextprop)
+ROMVEC_HANDLER(obp_memalloc)
+
diff --git a/roms/openbios/arch/sparc32/console.c b/roms/openbios/arch/sparc32/console.c
new file mode 100644
index 00000000..61c2e238
--- /dev/null
+++ b/roms/openbios/arch/sparc32/console.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "drivers/drivers.h"
+#include "openbios.h"
+#include "libopenbios/console.h"
+#include "libopenbios/ofmem.h"
+#include "libopenbios/video.h"
+
+#ifdef CONFIG_DEBUG_CONSOLE
+
+/* ******************************************************************
+ * common functions, implementing simple concurrent console
+ * ****************************************************************** */
+
+static int arch_putchar(int c)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ escc_uart_putchar(c);
+#endif
+ return c;
+}
+
+static int arch_availchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (escc_uart_charav(CONFIG_SERIAL_PORT))
+ return 1;
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
+ if (keyboard_dataready())
+ return 1;
+#endif
+ return 0;
+}
+
+static int arch_getchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (escc_uart_charav(CONFIG_SERIAL_PORT))
+ return (escc_uart_getchar(CONFIG_SERIAL_PORT));
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
+ if (keyboard_dataready())
+ return (keyboard_readdata());
+#endif
+ return 0;
+}
+
+struct _console_ops arch_console_ops = {
+ .putchar = arch_putchar,
+ .availchar = arch_availchar,
+ .getchar = arch_getchar
+};
+
+#endif // CONFIG_DEBUG_CONSOLE
diff --git a/roms/openbios/arch/sparc32/context.c b/roms/openbios/arch/sparc32/context.c
new file mode 100644
index 00000000..d4d8530d
--- /dev/null
+++ b/roms/openbios/arch/sparc32/context.c
@@ -0,0 +1,113 @@
+/*
+ * context switching
+ * 2003-10 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "context.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+#include "openbios.h"
+
+#define MAIN_STACK_SIZE 16384
+#define IMAGE_STACK_SIZE 4096*2
+
+#define debug printk
+
+static void start_main(void); /* forward decl. */
+void __exit_context(void); /* assembly routine */
+
+/*
+ * Main context structure
+ * It is placed at the bottom of our stack, and loaded by assembly routine
+ * to start us up.
+ */
+static struct context main_ctx = {
+ .regs[REG_SP] = (uint32_t) &_estack - 96,
+ .pc = (uint32_t) start_main,
+ .npc = (uint32_t) start_main + 4,
+ .return_addr = (uint32_t) __exit_context,
+};
+
+/* This is used by assembly routine to load/store the context which
+ * it is to switch/switched. */
+struct context *__context = &main_ctx;
+
+/* Stack for loaded ELF image */
+static uint8_t image_stack[IMAGE_STACK_SIZE];
+
+/* Pointer to startup context (physical address) */
+unsigned long __boot_ctx;
+
+/*
+ * Main starter
+ * This is the C function that runs first.
+ */
+static void start_main(void)
+{
+ /* Save startup context, so we can refer to it later.
+ * We have to keep it in physical address since we will relocate. */
+ __boot_ctx = virt_to_phys(__context);
+
+ /* Start the real fun */
+ openbios();
+
+ /* Returning from here should jump to __exit_context */
+ __context = boot_ctx;
+}
+
+/* Setup a new context using the given stack.
+ */
+struct context *
+init_context(uint8_t *stack, uint32_t stack_size, int num_params)
+{
+ struct context *ctx;
+
+ ctx = (struct context *)
+ (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t)));
+ memset(ctx, 0, sizeof(*ctx));
+
+ /* Fill in reasonable default for flat memory model */
+ ctx->regs[REG_SP] = virt_to_phys(SP_LOC(ctx));
+ ctx->return_addr = virt_to_phys(__exit_context);
+
+ return ctx;
+}
+
+/* Switch to another context. */
+struct context *switch_to(struct context *ctx)
+{
+ volatile struct context *save;
+ struct context *ret;
+
+ debug("switching to new context:\n");
+ save = __context;
+ __context = ctx;
+ asm __volatile__ ("\n\tcall __switch_context"
+ "\n\tnop" ::: "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+ "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
+ "i0", "i1", "i2", "i3", "i4", "i5", "i7",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
+ "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19",
+ "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29",
+ "f30", "f31",
+ "memory");
+ ret = __context;
+ __context = (struct context *)save;
+ return ret;
+}
+
+/* Start ELF Boot image */
+unsigned int start_elf(unsigned long entry_point, unsigned long param)
+{
+ struct context *ctx;
+
+ ctx = init_context(image_stack, sizeof image_stack, 1);
+ ctx->pc = entry_point;
+ ctx->param[0] = param;
+
+ ctx = switch_to(ctx);
+ return ctx->regs[REG_O0];
+}
diff --git a/roms/openbios/arch/sparc32/context.h b/roms/openbios/arch/sparc32/context.h
new file mode 100644
index 00000000..8689d563
--- /dev/null
+++ b/roms/openbios/arch/sparc32/context.h
@@ -0,0 +1,31 @@
+#ifndef SPARC32_CONTEXT_H
+#define SPARC32_CONTEXT_H
+
+struct context {
+ /* General registers */
+ uint32_t regs[32];
+ uint32_t pc;
+ uint32_t npc;
+#define REG_O0 8
+#define REG_SP 14
+#define SP_LOC(ctx) (&(ctx)->regs[REG_SP])
+ /* Flags */
+ /* Optional stack contents */
+ uint32_t return_addr;
+ uint32_t param[0];
+};
+
+/* Create a new context in the given stack */
+struct context *
+init_context(uint8_t *stack, uint32_t stack_size, int num_param);
+
+/* Switch context */
+struct context *switch_to(struct context *);
+
+/* Holds physical address of boot context */
+extern unsigned long __boot_ctx;
+
+/* This can always be safely used to refer to the boot context */
+#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx))
+
+#endif /* SPARC32_CONTEXT_H */
diff --git a/roms/openbios/arch/sparc32/crs.h b/roms/openbios/arch/sparc32/crs.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/roms/openbios/arch/sparc32/crs.h
diff --git a/roms/openbios/arch/sparc32/entry.S b/roms/openbios/arch/sparc32/entry.S
new file mode 100644
index 00000000..72cb3386
--- /dev/null
+++ b/roms/openbios/arch/sparc32/entry.S
@@ -0,0 +1,532 @@
+/**
+ ** Standalone startup code for Linux PROM emulator.
+ ** Copyright 1999 Pete A. Zaitcev
+ ** This code is licensed under GNU General Public License.
+ **/
+/*
+ * $Id: head.S,v 1.12 2002/07/23 05:47:09 zaitcev Exp $
+ */
+
+#define __ASSEMBLY
+#include "psr.h"
+#include "asm/asi.h"
+#include "asm/crs.h"
+#define NO_QEMU_PROTOS
+#define NO_OPENBIOS_PROTOS
+#include "arch/common/fw_cfg.h"
+
+#define CFG_ADDR 0x00000510
+#define CFG_ASI 0x2d
+
+#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
+
+#define PHYS_SS10_INTR0 0xf1400000
+
+#define PHYS_SS2_INTR0 0xf5000000
+#define SER_ADDR2 0xf1000004
+
+#define PHYS_SS1000_SBI 0x02800000
+#define SER_ADDR1000 0x00200004
+
+#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
+
+ .globl entry, _entry
+
+ .section ".text", "ax"
+ .align 8
+
+ /* Memory map:
+ *
+ * Top +-------------------------+
+ * | SMP CPU table |
+ * | s + 0x1f00 ... 0x1f0f |
+ * | s + 0x1f0c valid |
+ * | s + 0x1f08 entry |
+ * | s + 0x1f04 ctxtbl |
+ * | s + 0x1f00 ctx |
+ * +-------------------------+
+ * | Bootstrap |
+ * | MMU L3 tables 8 * 0x100 |
+ * | s + 0xa00 ... 0x11ff |
+ * +-------------------------+
+ * | Bootstrap |
+ * | MMU L2 tables 2 * 0x100 |
+ * | s + 0x800 ... 0x9ff |
+ * +-------------------------+
+ * | Bootstrap |
+ * | MMU L1 table 0x400 |
+ * | s + 0x400 ... 0x7ff |
+ * +-------------------------+
+ * | Bootstrap |
+ * | MMU L0/ctx table 0x400 |
+ * | s + 0x000 ... 0x3ff |
+ * +-------------------------+
+ * | |
+ * | ROM into RAM |
+ * | |
+ * +-------------------------+
+ * : :
+ * Bottom
+ */
+
+/*
+ * Entry point
+ * We start execution from here.
+ */
+_entry:
+entry:
+ /* Switch to our main context.
+ * Main context is statically defined in C.
+ */
+
+ ! Check signature "QEMU"
+ set CFG_ADDR, %g5
+ mov FW_CFG_SIGNATURE, %g2
+ stha %g2, [%g5] CFG_ASI
+ add %g5, 2, %g5
+ lduba [%g5] CFG_ASI, %g2
+ cmp %g2, 'Q'
+ bne bad_conf
+ nop
+ lduba [%g5] CFG_ASI, %g2
+ cmp %g2, 'E'
+ bne bad_conf
+ nop
+ lduba [%g5] CFG_ASI, %g2
+ cmp %g2, 'M'
+ bne bad_conf
+ nop
+ lduba [%g5] CFG_ASI, %g2
+ cmp %g2, 'U'
+ bne bad_conf
+ nop
+
+ ! Get memory size from configuration device
+ ! NB: little endian format
+ mov FW_CFG_RAM_SIZE, %g2
+ sub %g5, 2, %g5
+ stha %g2, [%g5] CFG_ASI
+ add %g5, 2, %g5
+ lduba [%g5] CFG_ASI, %g4
+
+ lduba [%g5] CFG_ASI, %g3
+ sll %g3, 8, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] CFG_ASI, %g3
+ sll %g3, 16, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] CFG_ASI, %g3
+ sll %g3, 24, %g3
+ or %g3, %g4, %g1
+ ! %g1 contains end of memory
+
+ ! Get kernel address from configuration device
+ ! NB: little endian format
+ mov FW_CFG_KERNEL_ADDR, %g2
+ sub %g5, 2, %g5
+ stha %g2, [%g5] CFG_ASI
+ add %g5, 2, %g5
+ lduba [%g5] CFG_ASI, %g4
+
+ lduba [%g5] CFG_ASI, %g3
+ sll %g3, 8, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] CFG_ASI, %g3
+ sll %g3, 16, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] CFG_ASI, %g3
+ sll %g3, 24, %g3
+ or %g3, %g4, %g4
+
+ ! If kernel address is set, don't clear from base of RAM in order to
+ ! leave the kernel image intact
+ mov 0, %g6
+ cmp %g4, 0
+ beq clear_mem
+ nop
+
+ ! Start from 16M
+ set 0x1000000, %g6
+
+clear_mem:
+ sta %g0, [%g6] ASI_M_BYPASS
+ add %g6, 0x4, %g6
+ cmp %g6, %g1
+ bl clear_mem
+ nop
+
+clear_done:
+ ! Start of private memory in %g6
+ set 0x2000, %g3
+ sub %g1, %g3, %g6
+
+ ! Check if this is the boot CPU and skip SMP table check if yes
+ ! XXX: not all CPUs should have MXCC
+ set 0x1c00f00, %g2
+ ldda [%g2] ASI_CONTROL, %g2
+ srl %g3, 24, %g7
+ sub %g7, 8, %g7
+ tst %g7
+ bz skip_table
+ nop
+
+ ! Calculate SMP table location
+ set 0x1f0c, %g2
+ add %g6, %g2, %g2 ! valid?
+ lda [%g2] ASI_M_BYPASS, %g7
+ sta %g0, [%g2] ASI_M_BYPASS
+
+skip_table:
+ ! Get machine ID from configuration device
+ mov FW_CFG_MACHINE_ID, %g2
+ sub %g5, 2, %g5
+ stha %g2, [%g5] CFG_ASI
+ add %g5, 2, %g5
+ lduba [%g5] CFG_ASI, %g4
+
+ lduba [%g5] CFG_ASI, %g3
+ sll %g3, 8, %g3
+ or %g3, %g4, %g4
+ mov %g4, %y
+
+ cmp %g4, 96
+ bgeu ss1000
+ cmp %g4, 64
+ bgeu ss10
+ cmp %g4, 32
+ blu ss2
+ nop
+
+ ! Ok, this is SS-5
+
+ tst %g7
+ bz first_cpu
+ nop
+
+ ! Clear softints used for SMP CPU startup
+ set PHYS_JJ_INTR0 + 0x04, %g1
+ sll %g2, 12, %g2
+ add %g1, %g2, %g2
+ set 0xffffffff, %g1
+ sta %g1, [%g2] ASI_M_BYPASS ! clear softints
+ add %g2, 4, %g2
+ sta %g0, [%g2] ASI_M_BYPASS ! clear softints
+
+load_ctx:
+ ! SMP init, jump to user specified address
+ set 0x1f04, %g5
+ add %g6, %g5, %g5 ! ctxtbl
+ lda [%g5] ASI_M_BYPASS, %g2
+ sta %g0, [%g5] ASI_M_BYPASS
+ set AC_M_CTPR, %g1
+ sta %g2, [%g1] ASI_M_MMUREGS ! set ctx table ptr
+ set 0x1f00, %g5
+ add %g6, %g5, %g5 ! ctx
+ lda [%g5] ASI_M_BYPASS, %g2
+ sta %g0, [%g5] ASI_M_BYPASS
+ set AC_M_CXR, %g1
+ sta %g2, [%g1] ASI_M_MMUREGS ! set context
+ set 0x1f08, %g5
+ add %g6, %g5, %g5 ! entry
+ lda [%g5] ASI_M_BYPASS, %g2
+ sta %g0, [%g5] ASI_M_BYPASS
+ set 1, %g1
+ jmp %g2 ! jump to kernel
+ sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu
+
+ss10:
+ ! Ok, this is SS-10 or SS-600MP
+ tst %g7
+ bz first_cpu
+ nop
+
+ ! Clear softints used for SMP CPU startup
+ set PHYS_SS10_INTR0 + 0x04, %g1
+ sll %g2, 12, %g2
+ add %g1, %g2, %g2
+ set 0xffffffff, %g1
+ sta %g1, [%g2] ASI_M_CTL ! clear softints
+ add %g2, 4, %g2
+ b load_ctx
+ sta %g0, [%g2] ASI_M_CTL ! clear softints
+
+ss2:
+ ! Ok, this is SS-2
+ set ss2_error, %o2
+ b ss2_ss1000_halt
+ nop
+
+ss1000:
+ ! Ok, this is SS-1000 or SS-2000
+ set ss1000_error, %o2
+ b ss2_ss1000_halt
+ nop
+
+first_cpu:
+ /* Create temporary page tables and map the ROM area to end of
+ RAM. This will be done properly in iommu.c later. */
+ ! Calculate start of page tables etc. to %g6
+ set 0x2000, %g4
+ sub %g1, %g4, %g6 ! start of private memory
+
+ mov %g6, %g2 ! ctx table at s+0x0
+ add %g2, 0x400, %g3 ! l1 table at s+0x400
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 0x400, %g2 ! s+0x400
+ add %g2, 0x400, %g3 ! l2 table for ram (00xxxxxx) at s+0x800
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 0x500, %g3 ! l2 table for rom (ffxxxxxx) at s+0x900
+ add %g2, 0x3fc, %g2 ! s+0x7fc
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 0x4, %g2 ! s+0x800
+#if 0
+ set 0x40, %g6
+ set ((7 << 2) | 2), %g3 ! 7 = U: --- S: RWX (main memory)
+1: sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2
+ deccc %g6
+ bne 1b
+ nop
+#else
+ add %g2, 0x100, %g2
+#endif
+ ! s+0x900
+ add %g2, 0xa00 - 0x900, %g3 ! l3 table for rom at s+0xa00
+ add %g2, 0x0d0, %g2 ! s+0x9d0
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2 ! s+0x9d4
+ add %g2, 0xb00 - 0x9d4, %g3 ! 2nd l3 table for rom at s+0xb00
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2 ! s+0x9d8
+ add %g2, 0xc00 - 0x9d8, %g3 ! 3rd l3 table for rom at s+0xc00
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2 ! s+0x9dc
+ add %g2, 0xd00 - 0x9dc, %g3 ! 4th l3 table for rom at s+0xd00
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2 ! s+0x9e0
+ add %g2, 0xe00 - 0x9e0, %g3 ! 5th l3 table for rom at s+0xe00
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2 ! s+0x9e4
+ add %g2, 0xf00 - 0x9e4, %g3 ! 6th l3 table for rom at s+0xf00
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2 ! s+0x9e8
+ add %g2, 0x1000 - 0x9e8, %g3 ! 7th l3 table for rom at s+0x1000
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2 ! s+0x9ec
+ add %g2, 0x1100 - 0x9ec, %g3 ! 8th l3 table for rom at s+0x1100
+ srl %g3, 0x4, %g3
+ or %g3, 0x1, %g3
+ sta %g3, [%g2] ASI_M_BYPASS
+ add %g2, 0xa00-0x9ec, %g2 ! s+0xa00
+
+ /* Use end of ram for code, rodata, data, and bss
+ sections. SunOS wants to write to trap table... */
+ set _end, %g6
+ set _start, %g4
+ sub %g6, %g4, %g6
+ sub %g1, %g6, %g3
+ set 0x1000, %g5
+ sub %g3, %g5, %g3
+ sub %g3, %g5, %g3 ! start of ROM copy
+ mov %g3, %g7 ! save in %g7
+ srl %g6, 12, %g6 ! # of all pages
+1: srl %g3, 0x4, %g4
+ or %g4, ((7 << 2) | 2), %g4 ! 7 = U: --- S: RWX
+ sta %g4, [%g2] ASI_M_BYPASS
+ add %g2, 4, %g2
+ add %g3, %g5, %g3
+ deccc %g6
+ bne 1b
+ nop
+
+ mov %g1, %g6 ! %g6 = memory size
+
+ /* Copy the code, rodata and data sections from ROM. */
+ sub %g7, 4, %g3
+ set _start - 4, %g4 ! First address of TEXT - 4
+ set _bss, %g5 ! Last address of DATA
+ ba 2f
+ nop
+1:
+ lda [%g4] ASI_M_KERNELTXT, %g1
+ sta %g1, [%g3] ASI_M_BYPASS
+2:
+ cmp %g4, %g5
+ add %g3, 0x4, %g3
+ bl 1b
+ add %g4, 0x4, %g4
+
+ set 0x2000, %g3
+ sub %g6, %g3, %g7 ! ctx table at s+0x0
+ set AC_M_CTPR, %g2
+ srl %g7, 4, %g7
+ sta %g7, [%g2] ASI_M_MMUREGS ! set ctx table ptr
+ set AC_M_CXR, %g2
+ sta %g0, [%g2] ASI_M_MMUREGS ! context 0
+ set highmem, %g2
+ set 1, %g1
+ jmp %g2
+ sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu
+highmem:
+ /*
+ * The code which enables traps is a simplified version of
+ * kernel head.S.
+ *
+ * We know number of windows as 8 so we do not calculate them.
+ * The deadwood is here for any case.
+ */
+
+ /* Turn on Supervisor, EnableFloating, and all the PIL bits.
+ * Also puts us in register window zero with traps off.
+ */
+ set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
+ wr %g2, 0x0, %psr
+ WRITE_PAUSE
+
+ /* Zero out our BSS section. */
+ set _bss - 4, %o0 ! First address of BSS
+ set _estack - 4, %o1 ! Last address of BSS
+ ba 2f
+ nop
+1:
+ st %g0, [%o0]
+2:
+ subcc %o0, %o1, %g0
+ bl 1b
+ add %o0, 0x4, %o0
+
+ set trap_table, %g1
+ wr %g1, 0x0, %tbr
+
+ set qemu_mem_size, %g1
+ st %g6, [%g1]
+
+ set _end, %o0 ! Store va->pa conversion factor
+ set _start, %o2
+ sub %o0, %o2, %o0
+ sub %g6, %o0, %o0
+ set 0x2000, %o1
+ sub %o0, %o1, %o0 ! start of ROM copy
+ sub %o2, %o0, %o0 ! start of ROM copy
+ set va_shift, %g1
+ st %o0, [%g1]
+
+ set qemu_machine_type, %g1
+ mov %y, %g2
+ st %g2, [%g1]
+
+ /* Compute NWINDOWS and stash it away. Now uses %wim trick explained
+ * in the V8 manual. Ok, this method seems to work, Sparc is cool...
+ * No, it doesn't work, have to play the save/readCWP/restore trick.
+ */
+
+ wr %g0, 0x0, %wim ! so we do not get a trap
+ WRITE_PAUSE
+
+ save
+
+ rd %psr, %g3
+
+ restore
+
+ and %g3, 0x1f, %g3
+ add %g3, 0x1, %g3
+
+ mov 2, %g1
+ wr %g1, 0x0, %wim ! make window 1 invalid
+ WRITE_PAUSE
+
+ cmp %g3, 0x7
+ bne 1f
+ nop
+
+ /* Adjust our window handling routines to
+ * do things correctly on 7 window Sparcs.
+ */
+#define PATCH_INSN(src, dest) \
+ set src, %g5; \
+ set dest, %g2; \
+ ld [%g5], %g4; \
+ st %g4, [%g2];
+
+ /* Patch for window spills... */
+ PATCH_INSN(spnwin_patch1_7win, spnwin_patch1)
+ PATCH_INSN(spnwin_patch2_7win, spnwin_patch2)
+
+ /* Patch for window fills... */
+ PATCH_INSN(fnwin_patch1_7win, fnwin_patch1)
+ PATCH_INSN(fnwin_patch2_7win, fnwin_patch2)
+
+1:
+ /* Finally, turn on traps so that we can call c-code. */
+ rd %psr, %g3
+ wr %g3, 0x0, %psr
+ WRITE_PAUSE
+
+ wr %g3, PSR_ET, %psr
+ WRITE_PAUSE
+
+ set 0, %fp
+ call __switch_context_nosave
+ nop
+
+ /* We get here when the main context switches back to
+ * the boot context.
+ * Return to previous bootloader.
+ */
+ ret
+ nop
+
+ss2_ss1000_halt:
+ set SER_ADDR2, %o0
+ set SER_ADDR1000, %o1
+ mov 0x05, %o3 /* Reg 5, TXCTRL2 */
+ stba %o3, [%o0] ASI_M_BYPASS
+ stba %o3, [%o1] ASI_M_CTL
+ mov 0x68, %o3 /* 8 bits, Tx enabled */
+ stba %o3, [%o0] ASI_M_BYPASS
+ stba %o3, [%o1] ASI_M_CTL
+ add %o0, 2, %o0
+ add %o1, 2, %o1
+
+1: lduba [%o2] ASI_M_KERNELTXT, %o3
+ cmp %o3, 0
+ be 2f
+ nop
+ stba %o3, [%o0] ASI_M_BYPASS
+ stba %o3, [%o1] ASI_M_CTL
+ b 1b
+ inc %o2
+bad_conf:
+2: b 2b
+ nop
+
+ .section .rodata
+ss2_error:
+ .string "Sun4c machines are not supported by OpenBIOS yet, freezing\r\n"
+ss1000_error:
+ .string "Sun4d machines are not supported by OpenBIOS yet, freezing\r\n"
diff --git a/roms/openbios/arch/sparc32/init.fs b/roms/openbios/arch/sparc32/init.fs
new file mode 100644
index 00000000..814c720c
--- /dev/null
+++ b/roms/openbios/arch/sparc32/init.fs
@@ -0,0 +1,83 @@
+:noname
+ ." Type 'help' for detailed information" cr
+ \ ." boot secondary slave cdrom: " cr
+ \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr
+ ; DIAG-initializer
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+:noname
+ set-defaults
+; PREPOST-initializer
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " memory" " /memory" preopen
+ " mmu" " /virtual-memory" preopen
+; SYSTEM-initializer
+
+device-end
+
+: rmap@ ( virt -- rmentry )
+ drop 0
+ ;
+
+\ D5.3 SBus specific on-board memory address space
+: obmem ( -- space )
+ 0
+ ;
+
+\ (peek) and (poke) implementation
+defer sfsr@
+defer ignore-dfault
+
+:noname
+ \ ( addr xt -- false | value true )
+ sfsr@ drop \ Clear any existing MMU fault status
+
+ -1 ignore-dfault ! \ Disable data fault trap
+ execute
+ 0 ignore-dfault ! \ Enable data fault trap
+
+ sfsr@ 0= if
+ true
+ else
+ drop false \ Failed, drop the read value
+ then
+; to (peek)
+
+:noname
+ \ ( value addr xt -- okay? )
+ sfsr@ drop \ Clear any existing MMU fault status
+
+ -1 ignore-dfault ! \ Disable data fault trap
+ execute
+ 0 ignore-dfault ! \ Enable data fault trap
+
+ sfsr@ 0= \ true if no fault
+; to (poke)
+
+\ Load TCX FCode driver blob
+[IFDEF] CONFIG_DRIVER_SBUS
+ -1 value tcx-driver-fcode
+ " QEMU,tcx.bin" $encode-file to tcx-driver-fcode
+[THEN]
diff --git a/roms/openbios/arch/sparc32/ldscript b/roms/openbios/arch/sparc32/ldscript
new file mode 100644
index 00000000..b543c159
--- /dev/null
+++ b/roms/openbios/arch/sparc32/ldscript
@@ -0,0 +1,73 @@
+OUTPUT_FORMAT(elf32-sparc)
+OUTPUT_ARCH(sparc)
+
+/* QEMU ELF loader can't handle very complex files, so we put ELFBoot
+info to rodata and put initctx to data.*/
+
+ENTRY(trap_table)
+
+/* Initial load address
+ */
+BASE_ADDR = 0xffd00000;
+
+/* 16KB stack */
+STACK_SIZE = 16384;
+VMEM_SIZE = 128 * 1024;
+IOMEM_SIZE = 256 * 1024 + 768 * 1024;
+
+SECTIONS
+{
+ . = BASE_ADDR;
+
+ /* Start of the program.
+ * Now the version string is in the note, we must include it
+ * in the program. Otherwise we lose the string after relocation. */
+ _start = .;
+
+ /* Normal sections */
+ .text ALIGN(4096): {
+ *(.text.vectors)
+ *(.text)
+ *(.text.*)
+ }
+ .rodata ALIGN(4096): {
+ _rodata = .;
+ sound_drivers_start = .;
+ *(.rodata.sound_drivers)
+ sound_drivers_end = .;
+ *(.rodata)
+ *(.rodata.*)
+ *(.note.ELFBoot)
+ }
+ .data ALIGN(4096): {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ }
+
+ .bss ALIGN(4096): {
+ _bss = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+
+ . = ALIGN(4096);
+ _vmem = .;
+ . += VMEM_SIZE;
+ _evmem = .;
+
+ _stack = .;
+ . += STACK_SIZE;
+ . = ALIGN(16);
+ _estack = .;
+ }
+
+ . = ALIGN(4096);
+ _end = .;
+ _iomem = _end + IOMEM_SIZE;
+
+ /* We discard .note sections other than .note.ELFBoot,
+ * because some versions of GCC generates useless ones. */
+
+ /DISCARD/ : { *(.comment*) *(.note.*) }
+}
diff --git a/roms/openbios/arch/sparc32/lib.c b/roms/openbios/arch/sparc32/lib.c
new file mode 100644
index 00000000..d27b604c
--- /dev/null
+++ b/roms/openbios/arch/sparc32/lib.c
@@ -0,0 +1,397 @@
+/* lib.c
+ * tag: simple function library
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "libc/vsprintf.h"
+#include "libopenbios/bindings.h"
+#include "arch/sparc32/ofmem_sparc32.h"
+#include "asm/asi.h"
+#include "pgtsrmmu.h"
+#include "openprom.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+#include "romvec.h"
+
+#define NCTX_SWIFT 0x100
+#define LOWMEMSZ 32 * 1024 * 1024
+
+#ifdef CONFIG_DEBUG_MEM
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+/* Format a string and print it on the screen, just like the libc
+ * function printf.
+ */
+int printk( const char *fmt, ... )
+{
+ char *p, buf[512];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ )
+ putchar(*p);
+ return i;
+}
+
+/*
+ * Allocatable memory chunk.
+ */
+struct mem {
+ char *start, *uplim;
+ char *curp;
+};
+
+struct mem cdvmem; /* Current device virtual memory space */
+
+unsigned int va_shift;
+unsigned long *l1;
+static unsigned long *context_table;
+
+struct linux_mlist_v0 *ptphys;
+struct linux_mlist_v0 *ptmap;
+struct linux_mlist_v0 *ptavail;
+
+/* Private functions for mapping between physical/virtual addresses */
+phys_addr_t
+va2pa(unsigned long va)
+{
+ if ((va >= (unsigned long)&_start) &&
+ (va < (unsigned long)&_end))
+ return va - va_shift;
+ else
+ return va;
+}
+
+unsigned long
+pa2va(phys_addr_t pa)
+{
+ if ((pa + va_shift >= (unsigned long)&_start) &&
+ (pa + va_shift < (unsigned long)&_end))
+ return pa + va_shift;
+ else
+ return pa;
+}
+
+void *
+malloc(int size)
+{
+ return ofmem_malloc(size);
+}
+
+void *
+realloc( void *ptr, size_t size )
+{
+ return ofmem_realloc(ptr, size);
+}
+
+void
+free(void *ptr)
+{
+ ofmem_free(ptr);
+}
+
+/*
+ * Allocate memory. This is reusable.
+ */
+void
+mem_init(struct mem *t, char *begin, char *limit)
+{
+ t->start = begin;
+ t->uplim = limit;
+ t->curp = begin;
+}
+
+void *
+mem_alloc(struct mem *t, int size, int align)
+{
+ char *p;
+ unsigned long pa;
+
+ // The alignment restrictions refer to physical, not virtual
+ // addresses
+ pa = va2pa((unsigned long)t->curp) + (align - 1);
+ pa &= ~(align - 1);
+ p = (char *)pa2va(pa);
+
+ if ((unsigned long)p >= (unsigned long)t->uplim ||
+ (unsigned long)p + size > (unsigned long)t->uplim)
+ return NULL;
+ t->curp = p + size;
+
+ return p;
+}
+
+/*
+ * D5.3 pgmap@ ( va -- pte )
+ */
+static void
+pgmap_fetch(void)
+{
+ uint32_t pte;
+ unsigned long va, pa;
+
+ va = POP();
+
+ pa = find_pte(va, 0);
+ if (pa == 1 || pa == 2)
+ goto error;
+ pte = *(uint32_t *)pa;
+ DPRINTF("pgmap@: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
+
+ PUSH(pte);
+ return;
+ error:
+ PUSH(0);
+}
+
+/*
+ * D5.3 pgmap! ( pte va -- )
+ */
+static void
+pgmap_store(void)
+{
+ uint32_t pte;
+ unsigned long va, pa;
+
+ va = POP();
+ pte = POP();
+
+ pa = find_pte(va, 1);
+ *(uint32_t *)pa = pte;
+ DPRINTF("pgmap!: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
+}
+
+/*
+ * D5.3 map-pages ( pa space va size -- )
+ */
+static void
+ob_map_pages(void)
+{
+ unsigned long va;
+ int size;
+ uint64_t pa;
+
+ size = POP();
+ va = POP();
+ pa = POP();
+ pa <<= 32;
+ pa |= POP() & 0xffffffff;
+
+ ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa));
+}
+
+char *obp_dumb_mmap(char *va, int which_io, unsigned int pa,
+ unsigned int size)
+{
+ uint64_t mpa = ((uint64_t)which_io << 32) | (uint64_t)pa;
+
+ ofmem_arch_map_pages(mpa, (unsigned long)va, size, ofmem_arch_default_translation_mode(mpa));
+ return va;
+}
+
+void obp_dumb_munmap(__attribute__((unused)) char *va,
+ __attribute__((unused)) unsigned int size)
+{
+ DPRINTF("obp_dumb_munmap: virta 0x%x, sz %d\n", (unsigned int)va, size);
+}
+
+char *obp_memalloc(char *va, unsigned int size, unsigned int align)
+{
+ phys_addr_t phys;
+ ucell virt;
+
+ DPRINTF("obp_memalloc: virta 0x%x, sz %d, align %d\n", (unsigned int)va, size, align);
+
+ /* Claim physical memory */
+ phys = ofmem_claim_phys(-1, size, align);
+
+ /* Claim virtual memory */
+ virt = ofmem_claim_virt(pointer2cell(va), size, 0);
+
+ /* Map the memory */
+ ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys));
+
+ return cell2pointer(virt);
+}
+
+char *obp_dumb_memalloc(char *va, unsigned int size)
+{
+ unsigned long align = size;
+ phys_addr_t phys;
+ ucell virt;
+
+ DPRINTF("obp_dumb_memalloc: virta 0x%x, sz %d\n", (unsigned int)va, size);
+
+ /* Solaris seems to assume that the returned value is physically aligned to size.
+ e.g. it is used for setting up page tables. */
+
+ /* Claim physical memory */
+ phys = ofmem_claim_phys(-1, size, align);
+
+ /* Claim virtual memory - if va == NULL then we choose va address */
+ if (va == NULL) {
+ virt = ofmem_claim_virt((ucell)-1, size, align);
+ } else {
+ virt = ofmem_claim_virt(pointer2cell(va), size, 0);
+ }
+
+ /* Map the memory */
+ ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys));
+
+ return cell2pointer(virt);
+}
+
+void obp_dumb_memfree(char *va, unsigned size)
+{
+ phys_addr_t phys;
+ ucell cellmode;
+
+ DPRINTF("obp_dumb_memfree: virta 0x%x, sz %d\n", (unsigned int)va, size);
+
+ phys = ofmem_translate(pointer2cell(va), &cellmode);
+
+ ofmem_unmap(pointer2cell(va), size);
+ ofmem_release_virt(pointer2cell(va), size);
+ ofmem_release_phys(phys, size);
+}
+
+/* Data fault handling routines */
+
+extern unsigned int ignore_dfault;
+
+/* ( -- reg ) */
+static void srmmu_get_sfsr(void)
+{
+ PUSH(srmmu_get_fstatus());
+}
+
+/* ( -- addr ) */
+static void ignore_dfault_addr(void)
+{
+ PUSH(pointer2cell(&ignore_dfault));
+}
+
+void
+ob_init_mmu(void)
+{
+ ucell *memreg;
+ ucell *virtreg;
+ phys_addr_t virtregsize;
+ ofmem_t *ofmem = ofmem_arch_get_private();
+
+ /* Find the phandles for the /memory and /virtual-memory nodes */
+ push_str("/memory");
+ fword("find-package");
+ POP();
+ s_phandle_memory = POP();
+
+ push_str("/virtual-memory");
+ fword("find-package");
+ POP();
+ s_phandle_mmu = POP();
+
+ ofmem_register(s_phandle_memory, s_phandle_mmu);
+
+ /* Setup /memory:reg (totphys) property */
+ memreg = malloc(3 * sizeof(ucell));
+ ofmem_arch_encode_physaddr(memreg, 0); /* physical base */
+ memreg[2] = (ucell)ofmem->ramsize; /* size */
+
+ push_str("/memory");
+ fword("find-device");
+ PUSH(pointer2cell(memreg));
+ PUSH(3 * sizeof(ucell));
+ push_str("reg");
+ PUSH_ph(s_phandle_memory);
+ fword("encode-property");
+
+ /* Setup /virtual-memory:reg property */
+ virtregsize = ((phys_addr_t)((ucell)-1) + 1) / 2;
+
+ virtreg = malloc(6 * sizeof(ucell));
+ ofmem_arch_encode_physaddr(virtreg, 0);
+ virtreg[2] = virtregsize;
+ ofmem_arch_encode_physaddr(&virtreg[3], virtregsize);
+ virtreg[5] = virtregsize;
+
+ push_str("/virtual-memory");
+ fword("find-device");
+ PUSH(pointer2cell(virtreg));
+ PUSH(6 * sizeof(ucell));
+ push_str("reg");
+ PUSH_ph(s_phandle_mmu);
+ fword("encode-property");
+
+ PUSH(0);
+ fword("active-package!");
+ bind_func("pgmap@", pgmap_fetch);
+ bind_func("pgmap!", pgmap_store);
+ bind_func("map-pages", ob_map_pages);
+
+ /* Install data fault handler words for cpeek etc. */
+ PUSH_xt(bind_noname_func(srmmu_get_sfsr));
+ feval("to sfsr@");
+ PUSH_xt(bind_noname_func(ignore_dfault_addr));
+ feval("to ignore-dfault");
+}
+
+/*
+ * Switch page tables.
+ */
+void
+init_mmu_swift(void)
+{
+ unsigned int addr, i;
+ unsigned long pa, va;
+ int size;
+
+ ofmem_posix_memalign((void *)&context_table, NCTX_SWIFT * sizeof(int),
+ NCTX_SWIFT * sizeof(int));
+ ofmem_posix_memalign((void *)&l1, 256 * sizeof(int), 256 * sizeof(int));
+
+ context_table[0] = (((unsigned long)va2pa((unsigned long)l1)) >> 4) |
+ SRMMU_ET_PTD;
+
+ for (i = 1; i < NCTX_SWIFT; i++) {
+ context_table[i] = SRMMU_ET_INVALID;
+ }
+ for (i = 0; i < 256; i++) {
+ l1[i] = SRMMU_ET_INVALID;
+ }
+
+ // text, rodata, data, and bss mapped to end of RAM
+ va = (unsigned long)&_start;
+ size = (unsigned long)&_end - (unsigned long)&_start;
+ pa = va2pa(va);
+ ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa));
+ ofmem_map_page_range(pa, va, size, ofmem_arch_default_translation_mode(pa));
+
+ // 1:1 mapping for RAM (don't map page 0 to allow catching of NULL dereferences)
+ ofmem_arch_map_pages(PAGE_SIZE, PAGE_SIZE, LOWMEMSZ - PAGE_SIZE, ofmem_arch_default_translation_mode(0));
+ ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, LOWMEMSZ - PAGE_SIZE, ofmem_arch_default_translation_mode(0));
+
+ /*
+ * Flush cache
+ */
+ for (addr = 0; addr < 0x2000; addr += 0x10) {
+ __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
+ "r" (addr), "i" (ASI_M_DATAC_TAG));
+ __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
+ "r" (addr<<1), "i" (ASI_M_TXTC_TAG));
+ }
+ srmmu_set_context(0);
+ srmmu_set_ctable_ptr(va2pa((unsigned long)context_table));
+ srmmu_flush_whole_tlb();
+}
diff --git a/roms/openbios/arch/sparc32/linux_load.c b/roms/openbios/arch/sparc32/linux_load.c
new file mode 100644
index 00000000..26f7fc6b
--- /dev/null
+++ b/roms/openbios/arch/sparc32/linux_load.c
@@ -0,0 +1,648 @@
+/*
+ * Linux/i386 loader
+ * Supports bzImage, zImage and Image format.
+ *
+ * Based on work by Steve Gehlbach.
+ * Portions are taken from mkelfImage.
+ *
+ * 2003-09 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/sys_info.h"
+#include "context.h"
+#include "libc/diskio.h"
+#include "boot.h"
+
+#define printf printk
+#define debug printk
+#define strtoull_with_suffix strtol
+
+#define LINUX_PARAM_LOC 0x90000
+#define COMMAND_LINE_LOC 0x91000
+#define GDT_LOC 0x92000
+#define STACK_LOC 0x93000
+
+#define E820MAX 32 /* number of entries in E820MAP */
+struct e820entry {
+ unsigned long long addr; /* start of memory segment */
+ unsigned long long size; /* size of memory segment */
+ unsigned long type; /* type of memory segment */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
+#define E820_NVS 4
+};
+
+/* The header of Linux/i386 kernel */
+struct linux_header {
+ uint8_t reserved1[0x1f1]; /* 0x000 */
+ uint8_t setup_sects; /* 0x1f1 */
+ uint16_t root_flags; /* 0x1f2 */
+ uint8_t reserved2[6]; /* 0x1f4 */
+ uint16_t vid_mode; /* 0x1fa */
+ uint16_t root_dev; /* 0x1fc */
+ uint16_t boot_sector_magic; /* 0x1fe */
+ /* 2.00+ */
+ uint8_t reserved3[2]; /* 0x200 */
+ uint8_t header_magic[4]; /* 0x202 */
+ uint16_t protocol_version; /* 0x206 */
+ uint32_t realmode_swtch; /* 0x208 */
+ uint16_t start_sys; /* 0x20c */
+ uint16_t kver_addr; /* 0x20e */
+ uint8_t type_of_loader; /* 0x210 */
+ uint8_t loadflags; /* 0x211 */
+ uint16_t setup_move_size; /* 0x212 */
+ uint32_t code32_start; /* 0x214 */
+ uint32_t ramdisk_image; /* 0x218 */
+ uint32_t ramdisk_size; /* 0x21c */
+ uint8_t reserved4[4]; /* 0x220 */
+ /* 2.01+ */
+ uint16_t heap_end_ptr; /* 0x224 */
+ uint8_t reserved5[2]; /* 0x226 */
+ /* 2.02+ */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ /* 2.03+ */
+ uint32_t initrd_addr_max; /* 0x22c */
+} __attribute__ ((packed));
+
+
+/* Paramters passed to 32-bit part of Linux
+ * This is another view of the structure above.. */
+struct linux_params {
+ uint8_t orig_x; /* 0x00 */
+ uint8_t orig_y; /* 0x01 */
+ uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */
+ uint16_t orig_video_page; /* 0x04 */
+ uint8_t orig_video_mode; /* 0x06 */
+ uint8_t orig_video_cols; /* 0x07 */
+ uint16_t unused2; /* 0x08 */
+ uint16_t orig_video_ega_bx; /* 0x0a */
+ uint16_t unused3; /* 0x0c */
+ uint8_t orig_video_lines; /* 0x0e */
+ uint8_t orig_video_isVGA; /* 0x0f */
+ uint16_t orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ uint16_t lfb_width; /* 0x12 */
+ uint16_t lfb_height; /* 0x14 */
+ uint16_t lfb_depth; /* 0x16 */
+ uint32_t lfb_base; /* 0x18 */
+ uint32_t lfb_size; /* 0x1c */
+ uint16_t cl_magic; /* 0x20 */
+#define CL_MAGIC_VALUE 0xA33F
+ uint16_t cl_offset; /* 0x22 */
+ uint16_t lfb_linelength; /* 0x24 */
+ uint8_t red_size; /* 0x26 */
+ uint8_t red_pos; /* 0x27 */
+ uint8_t green_size; /* 0x28 */
+ uint8_t green_pos; /* 0x29 */
+ uint8_t blue_size; /* 0x2a */
+ uint8_t blue_pos; /* 0x2b */
+ uint8_t rsvd_size; /* 0x2c */
+ uint8_t rsvd_pos; /* 0x2d */
+ uint16_t vesapm_seg; /* 0x2e */
+ uint16_t vesapm_off; /* 0x30 */
+ uint16_t pages; /* 0x32 */
+ uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */
+
+ //struct apm_bios_info apm_bios_info; /* 0x40 */
+ uint8_t apm_bios_info[0x40];
+ //struct drive_info_struct drive_info; /* 0x80 */
+ uint8_t drive_info[0x20];
+ //struct sys_desc_table sys_desc_table; /* 0xa0 */
+ uint8_t sys_desc_table[0x140];
+ uint32_t alt_mem_k; /* 0x1e0 */
+ uint8_t reserved5[4]; /* 0x1e4 */
+ uint8_t e820_map_nr; /* 0x1e8 */
+ uint8_t reserved6[9]; /* 0x1e9 */
+ uint16_t mount_root_rdonly; /* 0x1f2 */
+ uint8_t reserved7[4]; /* 0x1f4 */
+ uint16_t ramdisk_flags; /* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+ uint8_t reserved8[2]; /* 0x1fa */
+ uint16_t orig_root_dev; /* 0x1fc */
+ uint8_t reserved9[1]; /* 0x1fe */
+ uint8_t aux_device_info; /* 0x1ff */
+ uint8_t reserved10[2]; /* 0x200 */
+ uint8_t param_block_signature[4]; /* 0x202 */
+ uint16_t param_block_version; /* 0x206 */
+ uint8_t reserved11[8]; /* 0x208 */
+ uint8_t loader_type; /* 0x210 */
+#define LOADER_TYPE_LOADLIN 1
+#define LOADER_TYPE_BOOTSECT_LOADER 2
+#define LOADER_TYPE_SYSLINUX 3
+#define LOADER_TYPE_ETHERBOOT 4
+#define LOADER_TYPE_KERNEL 5
+ uint8_t loader_flags; /* 0x211 */
+ uint8_t reserved12[2]; /* 0x212 */
+ uint32_t kernel_start; /* 0x214 */
+ uint32_t initrd_start; /* 0x218 */
+ uint32_t initrd_size; /* 0x21c */
+ uint8_t reserved12_5[8]; /* 0x220 */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ uint8_t reserved13[164]; /* 0x22c */
+ struct e820entry e820_map[E820MAX]; /* 0x2d0 */
+ uint8_t reserved16[688]; /* 0x550 */
+#define COMMAND_LINE_SIZE 256
+ /* Command line is copied here by 32-bit i386/kernel/head.S.
+ * So I will follow the boot protocol, rather than putting it
+ * directly here. --ts1 */
+ uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */
+ uint8_t reserved17[1792]; /* 0x900 - 0x1000 */
+};
+
+static uint64_t forced_memsize;
+static int fd;
+
+static unsigned long file_size(void)
+{
+ long long fpos, fsize;
+
+ /* Save current position */
+ fpos = tell(fd);
+
+ /* Go to end of file and get position */
+ seek_io(fd, -1);
+ fsize = tell(fd);
+
+ /* Go back to old position */
+ seek_io(fd, 0);
+ seek_io(fd, fpos);
+
+ return fsize;
+}
+
+/* Load the first part the file and check if it's Linux */
+static uint32_t load_linux_header(struct linux_header *hdr)
+{
+ int load_high;
+ uint32_t kern_addr;
+
+ if (read_io(fd, hdr, sizeof *hdr) != sizeof *hdr) {
+ debug("Can't read Linux header\n");
+ return 0;
+ }
+ if (hdr->boot_sector_magic != 0xaa55) {
+ debug("Not a Linux kernel image\n");
+ return 0;
+ }
+
+ /* Linux is found. Print some information */
+ if (memcmp(hdr->header_magic, "HdrS", 4) != 0) {
+ /* This may be floppy disk image or something.
+ * Perform a simple (incomplete) sanity check. */
+ if (hdr->setup_sects >= 16
+ || file_size() - (hdr->setup_sects<<9) >= 512<<10) {
+ debug("This looks like a bootdisk image but not like Linux...\n");
+ return 0;
+ }
+
+ printf("Possible very old Linux");
+ /* This kernel does not even have a protocol version.
+ * Force the value. */
+ hdr->protocol_version = 0; /* pre-2.00 */
+ } else
+ printf("Found Linux");
+ if (hdr->protocol_version >= 0x200 && hdr->kver_addr) {
+ char kver[256];
+ seek_io(fd, hdr->kver_addr + 0x200);
+ if (read_io(fd, kver, sizeof kver) != 0) {
+ kver[255] = 0;
+ printf(" version %s", kver);
+ }
+ }
+ debug(" (protocol %#x)", hdr->protocol_version);
+ load_high = 0;
+ if (hdr->protocol_version >= 0x200) {
+ debug(" (loadflags %#x)", hdr->loadflags);
+ load_high = hdr->loadflags & 1;
+ }
+ if (load_high) {
+ printf(" bzImage");
+ kern_addr = 0x100000;
+ } else {
+ printf(" zImage or Image");
+ kern_addr = 0x1000;
+ }
+ printf(".\n");
+
+ return kern_addr;
+}
+
+/* Set up parameters for 32-bit kernel */
+static void
+init_linux_params(struct linux_params *params, struct linux_header *hdr)
+{
+ debug("Setting up paramters at %#lx\n", virt_to_phys(params));
+ memset(params, 0, sizeof *params);
+
+ /* Copy some useful values from header */
+ params->mount_root_rdonly = hdr->root_flags;
+ params->orig_root_dev = hdr->root_dev;
+
+ /* Video parameters.
+ * This assumes we have VGA in standard 80x25 text mode,
+ * just like our vga.c does.
+ * Cursor position is filled later to allow some more printf's. */
+ params->orig_video_mode = 3;
+ params->orig_video_cols = 80;
+ params->orig_video_lines = 25;
+ params->orig_video_isVGA = 1;
+ params->orig_video_points = 16;
+
+ params->loader_type = 0xff; /* Unregistered Linux loader */
+}
+
+/* Memory map */
+static void
+set_memory_size(struct linux_params *params, struct sys_info *info)
+{
+ int i;
+ uint64_t end;
+ uint32_t ramtop = 0;
+ struct e820entry *linux_map;
+ struct memrange *filo_map;
+
+ linux_map = params->e820_map;
+ filo_map = info->memrange;
+ for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) {
+ if (i < E820MAX) {
+ /* Convert to BIOS e820 style */
+ linux_map->addr = filo_map->base;
+ linux_map->size = filo_map->size;
+ linux_map->type = E820_RAM;
+ debug("%016Lx - %016Lx\n", linux_map->addr,
+ linux_map->addr + linux_map->size);
+ params->e820_map_nr = i+1;
+ }
+
+ /* Find out top of RAM. XXX This ignores hole above 1MB */
+ end = filo_map->base + filo_map->size;
+ if (end < (1ULL << 32)) { /* don't count memory above 4GB */
+ if (end > ramtop)
+ ramtop = (uint32_t) end;
+ }
+ }
+ debug("ramtop=%#x\n", ramtop);
+ /* Size of memory above 1MB in KB */
+ params->alt_mem_k = (ramtop - (1<<20)) >> 10;
+ /* old style, 64MB max */
+ if (ramtop >= (64<<20))
+ params->ext_mem_k = (63<<10);
+ else
+ params->ext_mem_k = params->alt_mem_k;
+ debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k);
+}
+
+/*
+ * Parse command line
+ * Some parameters, like initrd=<file>, are not passed to kernel,
+ * we are responsible to process them.
+ * Parameters for kernel are copied to kern_cmdline. Returns name of initrd.
+ */
+static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline)
+{
+ const char *start, *sep, *end, *val;
+ char name[64];
+ unsigned long len;
+ int k_len;
+ int to_kern;
+ char *initrd = NULL;
+ int toolong = 0;
+
+ forced_memsize = 0;
+
+ if (!orig_cmdline) {
+ *kern_cmdline = '\0';
+ return NULL;
+ }
+
+ k_len = 0;
+ debug("original command line: \"%s\"\n", orig_cmdline);
+ debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline));
+
+ start = orig_cmdline;
+ while (*start == ' ')
+ start++;
+ while (*start) {
+ end = strchr(start, ' ');
+ if (!end)
+ end = start + strlen(start);
+ sep = strchr(start, '=');
+ if (!sep || sep > end)
+ sep = end;
+ len = sep - start;
+ if (len >= sizeof(name))
+ len = sizeof(name) - 1;
+ memcpy(name, start, len);
+ name[len] = 0;
+
+ if (*sep == '=') {
+ val = sep + 1;
+ len = end - val;
+ } else {
+ val = NULL;
+ len = 0;
+ }
+
+ /* Only initrd= and mem= are handled here. vga= is not,
+ * which I believe is a paramter to the realmode part of Linux,
+ * which we don't execute. */
+ if (strcmp(name, "initrd") == 0) {
+ if (!val)
+ printf("Missing filename to initrd parameter\n");
+ else {
+ initrd = malloc(len + 1);
+ memcpy(initrd, val, len);
+ initrd[len] = 0;
+ debug("initrd=%s\n", initrd);
+ }
+ /* Don't pass this to kernel */
+ to_kern = 0;
+ } else if (strcmp(name, "mem") == 0) {
+ if (!val)
+ printf("Missing value for mem parameter\n");
+ else {
+ forced_memsize = strtoull_with_suffix(val, (char**)&val, 0);
+ if (forced_memsize == 0)
+ printf("Invalid mem option, ignored\n");
+ if (val != end) {
+ printf("Garbage after mem=<size>, ignored\n");
+ forced_memsize = 0;
+ }
+ debug("mem=%Lu\n", forced_memsize);
+ }
+ /* mem= is for both loader and kernel */
+ to_kern = 1;
+ } else
+ to_kern = 1;
+
+ if (to_kern) {
+ /* Copy to kernel command line buffer */
+ if (k_len != 0)
+ kern_cmdline[k_len++] = ' '; /* put separator */
+ len = end - start;
+ if (k_len + len >= COMMAND_LINE_SIZE) {
+ len = COMMAND_LINE_SIZE - k_len - 1;
+ if (!toolong) {
+ printf("Kernel command line is too long; truncated to "
+ "%d bytes\n", COMMAND_LINE_SIZE-1);
+ toolong = 1;
+ }
+ }
+ memcpy(kern_cmdline + k_len, start, len);
+ k_len += len;
+ }
+
+ start = end;
+ while (*start == ' ')
+ start++;
+ }
+ kern_cmdline[k_len] = 0;
+ debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline);
+
+ return initrd;
+}
+
+/* Set command line location */
+static void set_command_line_loc(struct linux_params *params,
+ struct linux_header *hdr)
+{
+ if (hdr->protocol_version >= 0x202) {
+ /* new style */
+ params->cmd_line_ptr = COMMAND_LINE_LOC;
+ } else {
+ /* old style */
+ params->cl_magic = CL_MAGIC_VALUE;
+ params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC;
+ }
+}
+
+/* Load 32-bit part of kernel */
+static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr)
+{
+ uint32_t kern_offset, kern_size;
+
+ if (hdr->setup_sects == 0)
+ hdr->setup_sects = 4;
+ kern_offset = (hdr->setup_sects + 1) * 512;
+ seek_io(fd, kern_offset);
+ kern_size = file_size() - kern_offset;
+ debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size);
+
+#if 0
+ if (using_devsize) {
+ printf("Attempt to load up to end of device as kernel; "
+ "specify the image size\n");
+ return 0;
+ }
+#endif
+
+ printf("Loading kernel... ");
+ if ((uint32_t)read_io(fd, phys_to_virt(kern_addr), kern_size) != kern_size) {
+ printf("Can't read kernel\n");
+ return 0;
+ }
+ printf("ok\n");
+
+ return kern_size;
+}
+
+static int load_initrd(struct linux_header *hdr, uint32_t kern_end,
+ struct linux_params *params, const char *initrd_file)
+{
+ uint32_t max;
+ uint32_t start, end, size;
+ uint64_t forced;
+
+ fd = open_io(initrd_file);
+ if (fd == -1) {
+ printf("Can't open initrd: %s\n", initrd_file);
+ return -1;
+ }
+
+#if 0
+ if (using_devsize) {
+ printf("Attempt to load up to end of device as initrd; "
+ "specify the image size\n");
+ return -1;
+ }
+#endif
+
+ size = file_size();
+
+
+ /* Find out the kernel's restriction on how high the initrd can be
+ * placed */
+ if (hdr->protocol_version >= 0x203)
+ max = hdr->initrd_addr_max;
+ else
+ max = 0x38000000; /* Hardcoded value for older kernels */
+
+ /* FILO itself is at the top of RAM. (relocated)
+ * So, try putting initrd just below us. */
+ end = virt_to_phys(_start);
+ if (end > max)
+ end = max;
+
+ /* If "mem=" option is given, we have to put the initrd within
+ * the specified range. */
+ if (forced_memsize) {
+ forced = forced_memsize;
+ if (forced > max)
+ forced = max;
+ /* If the "mem=" is lower, it's easy */
+ if (forced <= end)
+ end = forced;
+ else {
+ /* Otherwise, see if we can put it above us */
+ if (virt_to_phys(_end) + size <= forced)
+ end = forced; /* Ok */
+ }
+ }
+
+ start = end - size;
+ start &= ~0xfff; /* page align */
+ end = start + size;
+
+ debug("start=%#x end=%#x\n", start, end);
+
+ if (start < kern_end) {
+ printf("Initrd is too big to fit in memory\n");
+ return -1;
+ }
+
+ printf("Loading initrd... ");
+ if ((uint32_t)read_io(fd, phys_to_virt(start), size) != size) {
+ printf("Can't read initrd\n");
+ return -1;
+ }
+ printf("ok\n");
+
+ params->initrd_start = start;
+ params->initrd_size = size;
+
+ close_io(fd);
+
+ return 0;
+}
+
+static void hardware_setup(void)
+{
+ /* Disable nmi */
+ outb(0x80, 0x70);
+
+ /* Make sure any coprocessor is properly reset.. */
+ outb(0, 0xf0);
+ outb(0, 0xf1);
+
+ /* we're getting screwed again and again by this problem of the 8259.
+ * so we're going to leave this lying around for inclusion into
+ * crt0.S on an as-needed basis.
+ *
+ * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
+ * we put them right after the intel-reserved hardware interrupts, at
+ * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
+ * messed this up with the original PC, and they haven't been able to
+ * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
+ * which is used for the internal hardware interrupts as well. We just
+ * have to reprogram the 8259's, and it isn't fun.
+ */
+
+ outb(0x11, 0x20); /* initialization sequence to 8259A-1 */
+ outb(0x11, 0xA0); /* and to 8259A-2 */
+
+ outb(0x20, 0x21); /* start of hardware int's (0x20) */
+ outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */
+
+ outb(0x04, 0x21); /* 8259-1 is master */
+ outb(0x02, 0xA1); /* 8259-2 is slave */
+
+ outb(0x01, 0x21); /* 8086 mode for both */
+ outb(0x01, 0xA1);
+
+ outb(0xFF, 0xA1); /* mask off all interrupts for now */
+ outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */
+}
+
+/* Start Linux */
+static int start_linux(uint32_t kern_addr)
+{
+ struct context *ctx;
+ //extern int cursor_x, cursor_y;
+
+ ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
+
+ /* Entry point */
+ ctx->pc = kern_addr;
+ ctx->npc = kern_addr + 4;
+
+ debug("pc=%#x\n", kern_addr);
+ printf("Jumping to entry point...\n");
+
+#ifdef VGA_CONSOLE
+ /* Update VGA cursor position.
+ * This must be here because the printf changes the value! */
+ params->orig_x = cursor_x;
+ params->orig_y = cursor_y;
+#endif
+
+ /* Go... */
+ ctx = switch_to(ctx);
+
+ /* It's impossible but... */
+ printf("Returned with o0=%#x\n", ctx->regs[REG_O0]);
+
+ return ctx->regs[REG_O0];
+}
+
+int linux_load(struct sys_info *info, const char *file, const char *cmdline)
+{
+ struct linux_header hdr;
+ struct linux_params *params;
+ uint32_t kern_addr, kern_size;
+ char *initrd_file = NULL;
+
+ fd = open_io(file);
+ if (fd == -1) {
+ return -1;
+ }
+
+ kern_addr = load_linux_header(&hdr);
+ if (kern_addr == 0) {
+ close_io(fd);
+ return LOADER_NOT_SUPPORT;
+ }
+
+ params = phys_to_virt(LINUX_PARAM_LOC);
+ init_linux_params(params, &hdr);
+ set_memory_size(params, info);
+ initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
+ set_command_line_loc(params, &hdr);
+
+ kern_size = load_linux_kernel(&hdr, kern_addr);
+ if (kern_size == 0) {
+ if (initrd_file)
+ free(initrd_file);
+ return -1;
+ }
+
+ if (initrd_file) {
+ if (load_initrd(&hdr, kern_addr+kern_size, params, initrd_file)
+ != 0) {
+ free(initrd_file);
+ return -1;
+ }
+ free(initrd_file);
+ }
+
+ hardware_setup();
+
+ start_linux(kern_addr);
+ return 0;
+}
diff --git a/roms/openbios/arch/sparc32/multiboot.c b/roms/openbios/arch/sparc32/multiboot.c
new file mode 100644
index 00000000..8514ca0a
--- /dev/null
+++ b/roms/openbios/arch/sparc32/multiboot.c
@@ -0,0 +1,125 @@
+/* Support for Multiboot */
+
+#include "config.h"
+#include "asm/io.h"
+#include "libopenbios/sys_info.h"
+#include "multiboot.h"
+
+#define printf printk
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+struct mbheader {
+ unsigned int magic, flags, checksum;
+};
+const struct mbheader multiboot_header
+ __attribute__((section (".hdr"))) =
+{
+ MULTIBOOT_HEADER_MAGIC,
+ MULTIBOOT_HEADER_FLAGS,
+ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+};
+
+/* Multiboot information structure, provided by loader to us */
+
+struct multiboot_mmap {
+ unsigned entry_size;
+ unsigned base_lo, base_hi;
+ unsigned size_lo, size_hi;
+ unsigned type;
+};
+
+#define MULTIBOOT_MEM_VALID 0x01
+#define MULTIBOOT_BOOT_DEV_VALID 0x02
+#define MULTIBOOT_CMDLINE_VALID 0x04
+#define MULTIBOOT_MODS_VALID 0x08
+#define MULTIBOOT_AOUT_SYMS_VALID 0x10
+#define MULTIBOOT_ELF_SYMS_VALID 0x20
+#define MULTIBOOT_MMAP_VALID 0x40
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ struct multiboot_info *mbinfo;
+ struct multiboot_mmap *mbmem;
+ unsigned mbcount, mbaddr;
+ unsigned int i;
+ struct memrange *mmap;
+ int mmap_count;
+ module_t *mod;
+
+ if (info->boot_type != 0x2BADB002)
+ return;
+
+ debug("Using Multiboot information at %#lx\n", info->boot_data);
+
+ mbinfo = phys_to_virt(info->boot_data);
+
+ if (mbinfo->mods_count != 1) {
+ printf("Multiboot: no dictionary\n");
+ return;
+ }
+
+ mod = (module_t *) mbinfo->mods_addr;
+ info->dict_start=(unsigned long *)mod->mod_start;
+ info->dict_end=(unsigned long *)mod->mod_end;
+
+ if (mbinfo->flags & MULTIBOOT_MMAP_VALID) {
+ /* convert mmap records */
+ mbmem = phys_to_virt(mbinfo->mmap_addr);
+ mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4);
+ mmap = malloc(mbcount * sizeof(struct memrange));
+ mmap_count = 0;
+ mbaddr = mbinfo->mmap_addr;
+ for (i = 0; i < mbcount; i++) {
+ mbmem = phys_to_virt(mbaddr);
+ debug("%08x%08x %08x%08x (%d)\n",
+ mbmem->base_hi,
+ mbmem->base_lo,
+ mbmem->size_hi,
+ mbmem->size_lo,
+ mbmem->type);
+ if (mbmem->type == 1) { /* Only normal RAM */
+ mmap[mmap_count].base = mbmem->base_lo
+ + (((unsigned long long) mbmem->base_hi) << 32);
+ mmap[mmap_count].size = mbmem->size_lo
+ + (((unsigned long long) mbmem->size_hi) << 32);
+ mmap_count++;
+ }
+ mbaddr += mbmem->entry_size + 4;
+ if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length)
+ break;
+ }
+ /* simple sanity check - there should be at least 2 RAM segments
+ * (base 640k and extended) */
+ if (mmap_count >= 2)
+ goto got_it;
+
+ printf("Multiboot mmap is broken\n");
+ free(mmap);
+ /* fall back to mem_lower/mem_upper */
+ }
+
+ if (mbinfo->flags & MULTIBOOT_MEM_VALID) {
+ /* use mem_lower and mem_upper */
+ mmap_count = 2;
+ mmap = malloc(2 * sizeof(*mmap));
+ mmap[0].base = 0;
+ mmap[0].size = mbinfo->mem_lower << 10;
+ mmap[1].base = 1 << 20; /* 1MB */
+ mmap[1].size = mbinfo->mem_upper << 10;
+ goto got_it;
+ }
+
+ printf("Can't get memory information from Multiboot\n");
+ return;
+
+got_it:
+ info->memrange = mmap;
+ info->n_memranges = mmap_count;
+
+ return;
+}
diff --git a/roms/openbios/arch/sparc32/multiboot.h b/roms/openbios/arch/sparc32/multiboot.h
new file mode 100644
index 00000000..17cf202e
--- /dev/null
+++ b/roms/openbios/arch/sparc32/multiboot.h
@@ -0,0 +1,96 @@
+/* multiboot.h
+ * tag: header for multiboot
+ *
+ * Copyright (C) 2003-2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+/* magic number for multiboot header */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* flags for multiboot header */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* magic number passed by multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (8KB). */
+#define STACK_SIZE 0x2000
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* We don't want these declarations in boot.S */
+
+/* multiboot header */
+typedef struct multiboot_header {
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* symbol table for a.out */
+typedef struct aout_symbol_table {
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* section header table for ELF */
+typedef struct elf_section_header_table {
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* multiboot information */
+typedef struct multiboot_info {
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+} multiboot_info_t;
+
+/* module structure */
+typedef struct module {
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map {
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+#endif /* ! ASM */
diff --git a/roms/openbios/arch/sparc32/ofmem_sparc32.c b/roms/openbios/arch/sparc32/ofmem_sparc32.c
new file mode 100644
index 00000000..f7af7536
--- /dev/null
+++ b/roms/openbios/arch/sparc32/ofmem_sparc32.c
@@ -0,0 +1,253 @@
+/*
+ * <ofmem_sparc32.c>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "arch/sparc32/ofmem_sparc32.h"
+#include "asm/asi.h"
+#include "pgtsrmmu.h"
+
+#define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8))
+
+#define MEMSIZE (256 * 1024)
+static union {
+ char memory[MEMSIZE];
+ ofmem_t ofmem;
+} s_ofmem_data;
+
+#define OFMEM (&s_ofmem_data.ofmem)
+#define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE)
+
+#define OFMEM_PHYS_RESERVED 0x1000000
+
+translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans;
+
+extern uint32_t qemu_mem_size;
+
+static inline size_t ALIGN_SIZE(size_t x, size_t a)
+{
+ return (x + a - 1) & ~(a-1);
+}
+
+static ucell get_heap_top( void )
+{
+ return (ucell)TOP_OF_RAM;
+}
+
+ofmem_t* ofmem_arch_get_private(void)
+{
+ return OFMEM;
+}
+
+void* ofmem_arch_get_malloc_base(void)
+{
+ return OF_MALLOC_BASE;
+}
+
+ucell ofmem_arch_get_heap_top(void)
+{
+ return get_heap_top();
+}
+
+ucell ofmem_arch_get_virt_top(void)
+{
+ return (ucell)OFMEM_VIRT_TOP;
+}
+
+ucell ofmem_arch_get_iomem_base(void)
+{
+ return pointer2cell(&_end);
+}
+
+ucell ofmem_arch_get_iomem_top(void)
+{
+ return pointer2cell(&_iomem);
+}
+
+retain_t *ofmem_arch_get_retained(void)
+{
+ /* Not used */
+ return 0;
+}
+
+int ofmem_arch_get_physaddr_cellsize(void)
+{
+ return 2;
+}
+
+int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value)
+{
+ int n = 0;
+
+ p[n++] = value >> 32;
+ p[n++] = value;
+
+ return n;
+}
+
+int ofmem_arch_get_translation_entry_size(void)
+{
+ /* Return size of a single MMU package translation property entry in cells */
+ return 3;
+}
+
+void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t)
+{
+ /* Generate translation property entry for SPARC. While there is no
+ formal documentation for this, both Linux kernel and OpenSolaris sources
+ expect a translation property entry to have the following layout:
+
+ virtual address
+ length
+ mode
+ */
+
+ transentry[0] = t->virt;
+ transentry[1] = t->size;
+ transentry[2] = t->mode;
+}
+
+/* Return the size of a memory available entry given the phandle in cells */
+int ofmem_arch_get_available_entry_size(phandle_t ph)
+{
+ return 1 + ofmem_arch_get_physaddr_cellsize();
+}
+
+/* Generate memory available property entry for Sparc32 */
+void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size)
+{
+ int i = 0;
+
+ i += ofmem_arch_encode_physaddr(availentry, start);
+ availentry[i] = size;
+}
+
+/* Unmap a set of pages */
+void ofmem_arch_unmap_pages(ucell virt, ucell size)
+{
+ unsigned long pa;
+ ucell i;
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ pa = find_pte(virt, 0);
+ *(uint32_t *)pa = 0;
+ virt += PAGE_SIZE;
+ }
+
+ srmmu_flush_whole_tlb();
+}
+
+/* Map a set of pages */
+void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode)
+{
+ unsigned long npages, off;
+ uint32_t pte;
+ unsigned long pa;
+
+ off = phys & (PAGE_SIZE - 1);
+ npages = (off + (size - 1) + (PAGE_SIZE - 1)) / PAGE_SIZE;
+ phys &= ~(uint64_t)(PAGE_SIZE - 1);
+
+ while (npages-- != 0) {
+ pa = find_pte(virt, 1);
+
+ pte = SRMMU_ET_PTE | ((phys & PAGE_MASK) >> 4);
+ pte |= mode;
+
+ *(uint32_t *)pa = pte;
+
+ virt += PAGE_SIZE;
+ phys += PAGE_SIZE;
+ }
+}
+
+/* Architecture-specific OFMEM helpers */
+unsigned long
+find_pte(unsigned long va, int alloc)
+{
+ uint32_t pte;
+ void *p;
+ unsigned long pa;
+ int ret;
+
+ pte = l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)];
+ if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
+ if (alloc) {
+ ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PMD * sizeof(int),
+ SRMMU_PTRS_PER_PMD * sizeof(int));
+ if (ret != 0)
+ return ret;
+ pte = SRMMU_ET_PTD | ((va2pa((unsigned long)p)) >> 4);
+ l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)] = pte;
+ /* barrier() */
+ } else {
+ return -1;
+ }
+ }
+
+ pa = (pte & 0xFFFFFFF0) << 4;
+ pa += ((va >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)) << 2;
+ pte = *(uint32_t *)pa2va(pa);
+ if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
+ if (alloc) {
+ ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PTE * sizeof(void *),
+ SRMMU_PTRS_PER_PTE * sizeof(void *));
+ if (ret != 0)
+ return ret;
+ pte = SRMMU_ET_PTD | ((va2pa((unsigned int)p)) >> 4);
+ *(uint32_t *)pa2va(pa) = pte;
+ } else {
+ return -2;
+ }
+ }
+
+ pa = (pte & 0xFFFFFFF0) << 4;
+ pa += ((va >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)) << 2;
+
+ return pa2va(pa);
+}
+
+/************************************************************************/
+/* misc */
+/************************************************************************/
+
+ucell ofmem_arch_default_translation_mode( phys_addr_t phys )
+{
+ return SRMMU_REF | SRMMU_CACHE | SRMMU_PRIV;
+}
+
+ucell ofmem_arch_io_translation_mode( phys_addr_t phys )
+{
+ return SRMMU_REF | SRMMU_PRIV;
+}
+
+/************************************************************************/
+/* init / cleanup */
+/************************************************************************/
+
+void ofmem_init( void )
+{
+ memset(&s_ofmem_data, 0, sizeof(s_ofmem_data));
+ s_ofmem_data.ofmem.ramsize = qemu_mem_size;
+
+ /* Mark the first page as non-free */
+ ofmem_claim_virt(0, PAGE_SIZE, 0);
+
+ /* Claim reserved physical addresses at top of RAM */
+ ofmem_claim_phys(s_ofmem_data.ofmem.ramsize - OFMEM_PHYS_RESERVED, OFMEM_PHYS_RESERVED, 0);
+
+ /* Claim OpenBIOS reserved space */
+ ofmem_claim_virt(0xffd00000, 0x200000, 0);
+}
diff --git a/roms/openbios/arch/sparc32/openbios.c b/roms/openbios/arch/sparc32/openbios.c
new file mode 100644
index 00000000..6f4ee454
--- /dev/null
+++ b/roms/openbios/arch/sparc32/openbios.c
@@ -0,0 +1,1005 @@
+/* tag: openbios forth environment, executable code
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "drivers/drivers.h"
+#include "asm/types.h"
+#include "dict.h"
+#include "kernel/kernel.h"
+#include "kernel/stack.h"
+#include "arch/common/nvram.h"
+#include "packages/nvram.h"
+#include "../../drivers/timer.h" // XXX
+#include "libopenbios/sys_info.h"
+#include "openbios.h"
+#include "boot.h"
+#include "romvec.h"
+#include "openprom.h"
+#include "psr.h"
+#include "libopenbios/video.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+#include "arch/sparc32/ofmem_sparc32.h"
+
+#define MEMORY_SIZE (128*1024) /* 128K ram for hosted system */
+#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+#define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
+
+int qemu_machine_type;
+
+struct hwdef {
+ uint64_t iommu_base, slavio_base;
+ uint64_t intctl_base, counter_base, nvram_base, ms_kb_base, serial_base;
+ unsigned long fd_offset, counter_offset, intr_offset;
+ unsigned long aux1_offset, aux2_offset;
+ uint64_t dma_base, esp_base, le_base;
+ uint64_t tcx_base;
+ int intr_ncpu;
+ int mid_offset;
+ int machine_id_low, machine_id_high;
+};
+
+static const struct hwdef hwdefs[] = {
+ /* SS-5 */
+ {
+ .iommu_base = 0x10000000,
+ .tcx_base = 0x50000000,
+ .slavio_base = 0x71000000,
+ .ms_kb_base = 0x71000000,
+ .serial_base = 0x71100000,
+ .nvram_base = 0x71200000,
+ .fd_offset = 0x00400000,
+ .counter_offset = 0x00d00000,
+ .intr_offset = 0x00e00000,
+ .intr_ncpu = 1,
+ .aux1_offset = 0x00900000,
+ .aux2_offset = 0x00910000,
+ .dma_base = 0x78400000,
+ .esp_base = 0x78800000,
+ .le_base = 0x78c00000,
+ .mid_offset = 0,
+ .machine_id_low = 32,
+ .machine_id_high = 63,
+ },
+ /* SS-10, SS-20 */
+ {
+ .iommu_base = 0xfe0000000ULL,
+ .tcx_base = 0xe20000000ULL,
+ .slavio_base = 0xff1000000ULL,
+ .ms_kb_base = 0xff1000000ULL,
+ .serial_base = 0xff1100000ULL,
+ .nvram_base = 0xff1200000ULL,
+ .fd_offset = 0x00700000, // 0xff1700000ULL,
+ .counter_offset = 0x00300000, // 0xff1300000ULL,
+ .intr_offset = 0x00400000, // 0xff1400000ULL,
+ .intr_ncpu = 4,
+ .aux1_offset = 0x00800000, // 0xff1800000ULL,
+ .aux2_offset = 0x00a01000, // 0xff1a01000ULL,
+ .dma_base = 0xef0400000ULL,
+ .esp_base = 0xef0800000ULL,
+ .le_base = 0xef0c00000ULL,
+ .mid_offset = 8,
+ .machine_id_low = 64,
+ .machine_id_high = 65,
+ },
+ /* SS-600MP */
+ {
+ .iommu_base = 0xfe0000000ULL,
+ .tcx_base = 0xe20000000ULL,
+ .slavio_base = 0xff1000000ULL,
+ .ms_kb_base = 0xff1000000ULL,
+ .serial_base = 0xff1100000ULL,
+ .nvram_base = 0xff1200000ULL,
+ .fd_offset = -1,
+ .counter_offset = 0x00300000, // 0xff1300000ULL,
+ .intr_offset = 0x00400000, // 0xff1400000ULL,
+ .intr_ncpu = 4,
+ .aux1_offset = 0x00800000, // 0xff1800000ULL,
+ .aux2_offset = 0x00a01000, // 0xff1a01000ULL, XXX should not exist
+ .dma_base = 0xef0081000ULL,
+ .esp_base = 0xef0080000ULL,
+ .le_base = 0xef0060000ULL,
+ .mid_offset = 8,
+ .machine_id_low = 66,
+ .machine_id_high = 66,
+ },
+};
+
+static const struct hwdef *hwdef;
+
+void setup_timers(void)
+{
+}
+
+void udelay(unsigned int usecs)
+{
+}
+
+void mdelay(unsigned int msecs)
+{
+}
+
+static void mb86904_init(void)
+{
+ PUSH(32);
+ fword("encode-int");
+ push_str("cache-line-size");
+ fword("property");
+
+ PUSH(512);
+ fword("encode-int");
+ push_str("cache-nlines");
+ fword("property");
+
+ PUSH(0x23);
+ fword("encode-int");
+ push_str("mask_rev");
+ fword("property");
+}
+
+static void tms390z55_init(void)
+{
+ push_str("");
+ fword("encode-string");
+ push_str("ecache-parity?");
+ fword("property");
+
+ push_str("");
+ fword("encode-string");
+ push_str("bfill?");
+ fword("property");
+
+ push_str("");
+ fword("encode-string");
+ push_str("bcopy?");
+ fword("property");
+
+ push_str("");
+ fword("encode-string");
+ push_str("cache-physical?");
+ fword("property");
+
+ PUSH(0xf);
+ fword("encode-int");
+ PUSH(0xf8fffffc);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(4);
+ fword("encode-int");
+ fword("encode+");
+
+ PUSH(0xf);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0xf8c00000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x1000);
+ fword("encode-int");
+ fword("encode+");
+
+ PUSH(0xf);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0xf8000000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x1000);
+ fword("encode-int");
+ fword("encode+");
+
+ PUSH(0xf);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0xf8800000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x1000);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+}
+
+static void rt625_init(void)
+{
+ PUSH(32);
+ fword("encode-int");
+ push_str("cache-line-size");
+ fword("property");
+
+ PUSH(512);
+ fword("encode-int");
+ push_str("cache-nlines");
+ fword("property");
+
+}
+
+static void bad_cpu_init(void)
+{
+ printk("This CPU is not supported yet, freezing.\n");
+ for(;;);
+}
+
+struct cpudef {
+ unsigned long iu_version;
+ const char *name;
+ int psr_impl, psr_vers, impl, vers;
+ int dcache_line_size, dcache_lines, dcache_assoc;
+ int icache_line_size, icache_lines, icache_assoc;
+ int ecache_line_size, ecache_lines, ecache_assoc;
+ int mmu_nctx;
+ void (*initfn)(void);
+};
+
+static const struct cpudef sparc_defs[] = {
+ {
+ .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
+ .name = "FMI,MB86900",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
+ .name = "FMI,MB86904",
+ .psr_impl = 0,
+ .psr_vers = 4,
+ .impl = 0,
+ .vers = 4,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x200,
+ .dcache_assoc = 1,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x200,
+ .icache_assoc = 1,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x4000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x100,
+ .initfn = mb86904_init,
+ },
+ {
+ .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
+ .name = "FMI,MB86907",
+ .psr_impl = 0,
+ .psr_vers = 5,
+ .impl = 0,
+ .vers = 5,
+ .dcache_line_size = 0x20,
+ .dcache_lines = 0x200,
+ .dcache_assoc = 1,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x200,
+ .icache_assoc = 1,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x4000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x100,
+ .initfn = mb86904_init,
+ },
+ {
+ .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
+ .name = "LSI,L64811",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
+ .name = "CY,CY7C601",
+ .psr_impl = 1,
+ .psr_vers = 1,
+ .impl = 1,
+ .vers = 1,
+ .mmu_nctx = 0x10,
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
+ .name = "CY,CY7C611",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x40000000,
+ .name = "TI,TMS390Z55",
+ .psr_impl = 4,
+ .psr_vers = 0,
+ .impl = 0,
+ .vers = 4,
+ .dcache_line_size = 0x20,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x40,
+ .icache_lines = 0x40,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x41000000,
+ .name = "TI,TMS390S10",
+ .psr_impl = 4,
+ .psr_vers = 1,
+ .impl = 4,
+ .vers = 1,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x80,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x42000000,
+ .name = "TI,TMS390S10",
+ .psr_impl = 4,
+ .psr_vers = 2,
+ .impl = 4,
+ .vers = 2,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x80,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x43000000,
+ .name = "TI,TMS390S10",
+ .psr_impl = 4,
+ .psr_vers = 3,
+ .impl = 4,
+ .vers = 3,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x80,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x44000000,
+ .name = "TI,TMS390S10",
+ .psr_impl = 4,
+ .psr_vers = 4,
+ .impl = 4,
+ .vers = 4,
+ .dcache_line_size = 0x10,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x20,
+ .icache_lines = 0x80,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = tms390z55_init,
+ },
+ {
+ .iu_version = 0x1e000000,
+ .name = "Ross,RT625",
+ .psr_impl = 1,
+ .psr_vers = 14,
+ .impl = 1,
+ .vers = 7,
+ .dcache_line_size = 0x20,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x40,
+ .icache_lines = 0x40,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = rt625_init,
+ },
+ {
+ .iu_version = 0x1f000000,
+ .name = "Ross,RT620",
+ .psr_impl = 1,
+ .psr_vers = 15,
+ .impl = 1,
+ .vers = 7,
+ .dcache_line_size = 0x20,
+ .dcache_lines = 0x80,
+ .dcache_assoc = 4,
+ .icache_line_size = 0x40,
+ .icache_lines = 0x40,
+ .icache_assoc = 5,
+ .ecache_line_size = 0x20,
+ .ecache_lines = 0x8000,
+ .ecache_assoc = 1,
+ .mmu_nctx = 0x10000,
+ .initfn = rt625_init,
+ },
+ {
+ .iu_version = 0x20000000,
+ .name = "BIT,B5010",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x50000000,
+ .name = "MC,MN10501",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
+ .name = "Weitek,W8601",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0xf2000000,
+ .name = "GR,LEON2",
+ .initfn = bad_cpu_init,
+ },
+ {
+ .iu_version = 0xf3000000,
+ .name = "GR,LEON3",
+ .initfn = bad_cpu_init,
+ },
+};
+
+static const struct cpudef *
+id_cpu(void)
+{
+ unsigned long iu_version;
+ unsigned int i;
+
+ asm("rd %%psr, %0\n"
+ : "=r"(iu_version) :);
+ iu_version &= 0xff000000;
+
+ for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) {
+ if (iu_version == sparc_defs[i].iu_version)
+ return &sparc_defs[i];
+ }
+ printk("Unknown cpu (psr %lx), freezing!\n", iu_version);
+ for (;;);
+}
+
+static void setup_cpu(int mid_offset)
+{
+ uint32_t temp;
+ unsigned int i;
+ const struct cpudef *cpu;
+
+ // Add cpus
+ temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
+
+ printk("CPUs: %x", temp);
+ cpu = id_cpu();
+ printk(" x %s\n", cpu->name);
+ for (i = 0; i < temp; i++) {
+ push_str("/");
+ fword("find-device");
+
+ fword("new-device");
+
+ push_str(cpu->name);
+ fword("device-name");
+
+ push_str("cpu");
+ fword("device-type");
+
+ PUSH(cpu->psr_impl);
+ fword("encode-int");
+ push_str("psr-implementation");
+ fword("property");
+
+ PUSH(cpu->psr_vers);
+ fword("encode-int");
+ push_str("psr-version");
+ fword("property");
+
+ PUSH(cpu->impl);
+ fword("encode-int");
+ push_str("implementation");
+ fword("property");
+
+ PUSH(cpu->vers);
+ fword("encode-int");
+ push_str("version");
+ fword("property");
+
+ PUSH(4096);
+ fword("encode-int");
+ push_str("page-size");
+ fword("property");
+
+ PUSH(cpu->dcache_line_size);
+ fword("encode-int");
+ push_str("dcache-line-size");
+ fword("property");
+
+ PUSH(cpu->dcache_lines);
+ fword("encode-int");
+ push_str("dcache-nlines");
+ fword("property");
+
+ PUSH(cpu->dcache_assoc);
+ fword("encode-int");
+ push_str("dcache-associativity");
+ fword("property");
+
+ PUSH(cpu->icache_line_size);
+ fword("encode-int");
+ push_str("icache-line-size");
+ fword("property");
+
+ PUSH(cpu->icache_lines);
+ fword("encode-int");
+ push_str("icache-nlines");
+ fword("property");
+
+ PUSH(cpu->icache_assoc);
+ fword("encode-int");
+ push_str("icache-associativity");
+ fword("property");
+
+ PUSH(cpu->ecache_line_size);
+ fword("encode-int");
+ push_str("ecache-line-size");
+ fword("property");
+
+ PUSH(cpu->ecache_lines);
+ fword("encode-int");
+ push_str("ecache-nlines");
+ fword("property");
+
+ PUSH(cpu->ecache_assoc);
+ fword("encode-int");
+ push_str("ecache-associativity");
+ fword("property");
+
+ PUSH(2);
+ fword("encode-int");
+ push_str("ncaches");
+ fword("property");
+
+ PUSH(cpu->mmu_nctx);
+ fword("encode-int");
+ push_str("mmu-nctx");
+ fword("property");
+
+ PUSH(8);
+ fword("encode-int");
+ push_str("sparc-version");
+ fword("property");
+
+ push_str("");
+ fword("encode-string");
+ push_str("cache-coherence?");
+ fword("property");
+
+ PUSH(i + mid_offset);
+ fword("encode-int");
+ push_str("mid");
+ fword("property");
+
+ cpu->initfn();
+
+ fword("finish-device");
+ }
+}
+
+static void dummy_mach_init(uint64_t base)
+{
+}
+
+struct machdef {
+ uint16_t machine_id;
+ const char *banner_name;
+ const char *model;
+ const char *name;
+ void (*initfn)(uint64_t base);
+};
+
+static const struct machdef sun4m_defs[] = {
+ {
+ .machine_id = 32,
+ .banner_name = "SPARCstation 5",
+ .model = "SUNW,501-3059",
+ .name = "SUNW,SPARCstation-5",
+ .initfn = ss5_init,
+ },
+ {
+ .machine_id = 33,
+ .banner_name = "SPARCstation Voyager",
+ .model = "SUNW,501-2581",
+ .name = "SUNW,SPARCstation-Voyager",
+ .initfn = dummy_mach_init,
+ },
+ {
+ .machine_id = 34,
+ .banner_name = "SPARCstation LX",
+ .model = "SUNW,501-2031",
+ .name = "SUNW,SPARCstation-LX",
+ .initfn = dummy_mach_init,
+ },
+ {
+ .machine_id = 35,
+ .banner_name = "SPARCstation 4",
+ .model = "SUNW,501-2572",
+ .name = "SUNW,SPARCstation-4",
+ .initfn = ss5_init,
+ },
+ {
+ .machine_id = 36,
+ .banner_name = "SPARCstation Classic",
+ .model = "SUNW,501-2326",
+ .name = "SUNW,SPARCstation-Classic",
+ .initfn = dummy_mach_init,
+ },
+ {
+ .machine_id = 37,
+ .banner_name = "Tadpole S3 GX",
+ .model = "S3",
+ .name = "Tadpole_S3GX",
+ .initfn = ss5_init,
+ },
+ {
+ .machine_id = 64,
+ .banner_name = "SPARCstation 10 (1 X 390Z55)",
+ .model = "SUNW,S10,501-2365",
+ .name = "SUNW,SPARCstation-10",
+ .initfn = ob_eccmemctl_init,
+ },
+ {
+ .machine_id = 65,
+ .banner_name = "SPARCstation 20 (1 X 390Z55)",
+ .model = "SUNW,S20,501-2324",
+ .name = "SUNW,SPARCstation-20",
+ .initfn = ob_eccmemctl_init,
+ },
+ {
+ .machine_id = 66,
+ .banner_name = "SPARCsystem 600(1 X 390Z55)",
+ .model = NULL,
+ .name = "SUNW,SPARCsystem-600",
+ .initfn = ob_eccmemctl_init,
+ },
+};
+
+static const struct machdef *
+id_machine(uint16_t machine_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(sun4m_defs)/sizeof(struct machdef); i++) {
+ if (machine_id == sun4m_defs[i].machine_id)
+ return &sun4m_defs[i];
+ }
+ printk("Unknown machine (ID %d), freezing!\n", machine_id);
+ for (;;);
+}
+
+static void setup_machine(uint64_t base)
+{
+ uint16_t machine_id;
+ const struct machdef *mach;
+
+ machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
+ mach = id_machine(machine_id);
+
+ push_str("/");
+ fword("find-device");
+ push_str(mach->banner_name);
+ fword("encode-string");
+ push_str("banner-name");
+ fword("property");
+
+ if (mach->model) {
+ push_str(mach->model);
+ fword("encode-string");
+ push_str("model");
+ fword("property");
+ }
+ push_str(mach->name);
+ fword("encode-string");
+ push_str("name");
+ fword("property");
+
+ mach->initfn(base);
+}
+
+/* Add /uuid */
+static void setup_uuid(void)
+{
+ static uint8_t qemu_uuid[16];
+
+ fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
+
+ printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
+ qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
+ qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
+ qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
+ qemu_uuid[15]);
+
+ push_str("/");
+ fword("find-device");
+
+ PUSH((long)&qemu_uuid);
+ PUSH(16);
+ fword("encode-bytes");
+ push_str("uuid");
+ fword("property");
+}
+
+static void setup_stdio(void)
+{
+ char nographic;
+ const char *stdin, *stdout;
+
+ fw_cfg_read(FW_CFG_NOGRAPHIC, &nographic, 1);
+ if (nographic) {
+ obp_stdin = PROMDEV_TTYA;
+ obp_stdout = PROMDEV_TTYA;
+ stdin = "ttya";
+ stdout = "ttya";
+ } else {
+ obp_stdin = PROMDEV_KBD;
+ obp_stdout = PROMDEV_SCREEN;
+ stdin = "keyboard";
+ stdout = "screen";
+ }
+
+ push_str(stdin);
+ push_str("input-device");
+ fword("$setenv");
+
+ push_str(stdout);
+ push_str("output-device");
+ fword("$setenv");
+
+ obp_stdin_path = stdin;
+ obp_stdout_path = stdout;
+}
+
+static void init_memory(void)
+{
+ phys_addr_t phys;
+ ucell virt;
+
+ /* Claim the memory from OFMEM */
+ phys = ofmem_claim_phys(-1, MEMORY_SIZE, PAGE_SIZE);
+ if (!phys)
+ printk("panic: not enough physical memory on host system.\n");
+
+ virt = ofmem_claim_virt(OF_CODE_START - MEMORY_SIZE, MEMORY_SIZE, 0);
+ if (!virt)
+ printk("panic: not enough virtual memory on host system.\n");
+
+ /* Generate the mapping (and lock translation into the TLBs) */
+ ofmem_map(phys, virt, MEMORY_SIZE, ofmem_arch_default_translation_mode(phys));
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator
+ */
+
+ PUSH(virt);
+ PUSH(virt + MEMORY_SIZE);
+}
+
+static void
+arch_init( void )
+{
+ char *cmdline;
+ const char *kernel_cmdline;
+ uint32_t temp;
+ uint16_t machine_id;
+ char buf[256];
+ unsigned long mem_size;
+
+ fw_cfg_init();
+
+ fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
+ buf[4] = '\0';
+
+ printk("Configuration device id %s", buf);
+
+ temp = fw_cfg_read_i32(FW_CFG_ID);
+ machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
+
+ printk(" version %d machine id %d\n", temp, machine_id);
+
+ if (temp != 1) {
+ printk("Incompatible configuration device version, freezing\n");
+ for(;;);
+ }
+
+ graphic_depth = fw_cfg_read_i16(FW_CFG_SUN4M_DEPTH);
+
+ openbios_init();
+ modules_init();
+ ob_init_mmu();
+ ob_init_iommu(hwdef->iommu_base);
+#ifdef CONFIG_DRIVER_OBIO
+ mem_size = fw_cfg_read_i32(FW_CFG_RAM_SIZE);
+ ob_obio_init(hwdef->slavio_base, hwdef->fd_offset,
+ hwdef->counter_offset, hwdef->intr_offset, hwdef->intr_ncpu,
+ hwdef->aux1_offset, hwdef->aux2_offset,
+ mem_size);
+
+ setup_machine(hwdef->slavio_base);
+
+ nvconf_init();
+#endif
+#ifdef CONFIG_DRIVER_SBUS
+#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
+ setup_video();
+#endif
+ ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type);
+#endif
+ device_end();
+
+ setup_cpu(hwdef->mid_offset);
+
+ setup_stdio();
+ /* Initialiase openprom romvec */
+ romvec = init_openprom();
+
+ kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
+ if (kernel_size) {
+ kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
+
+ /* Mark the kernel memory as in use */
+ ofmem_claim_phys(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0);
+ ofmem_claim_virt(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0);
+ }
+
+ kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
+ if (kernel_cmdline) {
+ cmdline = strdup(kernel_cmdline);
+ obp_arg.argv[1] = cmdline;
+ } else {
+ cmdline = strdup("");
+ }
+ qemu_cmdline = (uint32_t)cmdline;
+
+ /* Setup nvram variables */
+ push_str("/options");
+ fword("find-device");
+ push_str(cmdline);
+ fword("encode-string");
+ push_str("boot-file");
+ fword("property");
+
+ boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
+
+ switch (boot_device) {
+ case 'a':
+ push_str("floppy");
+ break;
+ case 'c':
+ push_str("disk");
+ break;
+ default:
+ case 'd':
+ push_str("cdrom:d cdrom");
+ break;
+ case 'n':
+ push_str("net");
+ break;
+ }
+
+ fword("encode-string");
+ push_str("boot-device");
+ fword("property");
+
+ device_end();
+
+ bind_func("platform-boot", boot );
+ bind_func("(go)", go );
+
+ /* Set up other properties */
+ push_str("/chosen");
+ fword("find-device");
+
+ setup_uuid();
+
+ /* Enable interrupts */
+ temp = get_psr();
+ temp = (temp & ~PSR_PIL) | (13 << 8); /* Enable CPU timer interrupt (level 14) */
+ put_psr(temp);
+}
+
+extern struct _console_ops arch_console_ops;
+
+int openbios(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
+ if (hwdefs[i].machine_id_low <= qemu_machine_type &&
+ hwdefs[i].machine_id_high >= qemu_machine_type) {
+ hwdef = &hwdefs[i];
+ break;
+ }
+ }
+ if (!hwdef)
+ for(;;); // Internal inconsistency, hang
+
+#ifdef CONFIG_DEBUG_CONSOLE
+ init_console(arch_console_ops);
+#endif
+ /* Make sure we setup OFMEM before the MMU as we need malloc() to setup page tables */
+ ofmem_init();
+
+#ifdef CONFIG_DRIVER_SBUS
+ init_mmu_swift();
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ escc_uart_init(hwdef->serial_base | (CONFIG_SERIAL_PORT? 0ULL: 4ULL),
+ CONFIG_SERIAL_SPEED);
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VIDEO
+ kbd_init(hwdef->ms_kb_base);
+#endif
+#endif
+
+ collect_sys_info(&sys_info);
+
+ dict = (unsigned char *)sys_info.dict_start;
+ dicthead = (cell)sys_info.dict_end;
+ last = sys_info.dict_last;
+ dictlimit = sys_info.dict_limit;
+
+ forth_init();
+
+#ifdef CONFIG_DEBUG_BOOT
+ printk("forth started.\n");
+ printk("initializing memory...");
+#endif
+
+ init_memory();
+
+#ifdef CONFIG_DEBUG_BOOT
+ printk("done\n");
+#endif
+
+ PUSH_xt( bind_noname_func(arch_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+
+ if (!PC) {
+ printk("panic: no dictionary entry point.\n");
+ return -1;
+ }
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("done (%d bytes).\n", dicthead);
+ printk("Jumping to dictionary...\n");
+#endif
+
+ enterforth((xt_t)PC);
+
+ free(dict);
+ return 0;
+}
diff --git a/roms/openbios/arch/sparc32/openbios.h b/roms/openbios/arch/sparc32/openbios.h
new file mode 100644
index 00000000..f7d47eab
--- /dev/null
+++ b/roms/openbios/arch/sparc32/openbios.h
@@ -0,0 +1,28 @@
+/*
+ * Creation Date: <2004/01/15 16:14:05 samuel>
+ * Time-stamp: <2004/01/15 16:14:05 samuel>
+ *
+ * <openbios.h>
+ *
+ *
+ *
+ * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_OPENBIOS
+#define _H_OPENBIOS
+
+int openbios(void);
+
+/* console.c */
+extern unsigned char *vmem;
+#ifdef CONFIG_DEBUG_CONSOLE
+extern void video_init(void);
+#endif
+
+#endif /* _H_OPENBIOS */
diff --git a/roms/openbios/arch/sparc32/openprom.h b/roms/openbios/arch/sparc32/openprom.h
new file mode 100644
index 00000000..0676be84
--- /dev/null
+++ b/roms/openbios/arch/sparc32/openprom.h
@@ -0,0 +1,260 @@
+#ifndef __SPARC_OPENPROM_H
+#define __SPARC_OPENPROM_H
+
+/* openprom.h: Prom structures and defines for access to the OPENBOOT
+ * prom routines and data areas.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+// #include <asm/vaddrs.h>
+
+/* Empirical constants... */
+#define LINUX_OPPROM_MAGIC 0x10010407
+
+#ifndef __ASSEMBLY__
+/* V0 prom device operations. */
+struct linux_dev_v0_funcs {
+ int (*v0_devopen)(char *device_str);
+ int (*v0_devclose)(int dev_desc);
+ int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
+};
+
+/* V2 and later prom device operations. */
+struct linux_dev_v2_funcs {
+ int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
+ char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
+ void (*v2_dumb_mem_free)(char *va, unsigned sz);
+
+ /* To map devices into virtual I/O space. */
+ char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
+ void (*v2_dumb_munmap)(char *virta, unsigned size);
+
+ int (*v2_dev_open)(char *devpath);
+ void (*v2_dev_close)(int d);
+ int (*v2_dev_read)(int d, char *buf, int nbytes);
+ int (*v2_dev_write)(int d, char *buf, int nbytes);
+ int (*v2_dev_seek)(int d, int hi, int lo);
+
+ /* Never issued (multistage load support) */
+ void (*v2_wheee2)(void);
+ void (*v2_wheee3)(void);
+};
+
+struct linux_mlist_v0 {
+ struct linux_mlist_v0 *theres_more;
+ char *start_adr;
+ unsigned num_bytes;
+};
+
+struct linux_mem_v0 {
+ struct linux_mlist_v0 * const *v0_totphys;
+ struct linux_mlist_v0 * const *v0_prommap;
+ struct linux_mlist_v0 * const *v0_available; /* What we can use */
+};
+
+/* Arguments sent to the kernel from the boot prompt. */
+struct linux_arguments_v0 {
+ const char *argv[8];
+ char args[100];
+ char boot_dev[2];
+ int boot_dev_ctrl;
+ int boot_dev_unit;
+ int dev_partition;
+ const char *kernel_file_name;
+ void *aieee1; /* XXX */
+};
+
+/* V2 and up boot things. */
+struct linux_bootargs_v2 {
+ const char **bootpath;
+ const char **bootargs;
+ const int *fd_stdin;
+ const int *fd_stdout;
+};
+
+/* The top level PROM vector. */
+struct linux_romvec {
+ /* Version numbers. */
+ unsigned int pv_magic_cookie;
+ unsigned int pv_romvers;
+ unsigned int pv_plugin_revision;
+ unsigned int pv_printrev;
+
+ /* Version 0 memory descriptors. */
+ struct linux_mem_v0 pv_v0mem;
+
+ /* Node operations. */
+ const struct linux_nodeops *pv_nodeops;
+
+ char **pv_bootstr;
+ struct linux_dev_v0_funcs pv_v0devops;
+
+ const char *pv_stdin;
+ const char *pv_stdout;
+#define PROMDEV_KBD 0 /* input from keyboard */
+#define PROMDEV_SCREEN 0 /* output to screen */
+#define PROMDEV_TTYA 1 /* in/out to ttya */
+#define PROMDEV_TTYB 2 /* in/out to ttyb */
+
+ /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
+ int (*pv_getchar)(void);
+ void (*pv_putchar)(int ch);
+
+ /* Non-blocking variants. */
+ int (*pv_nbgetchar)(void);
+ int (*pv_nbputchar)(int ch);
+
+ void (*pv_putstr)(char *str, int len);
+
+ /* Miscellany. */
+ void (*pv_reboot)(char *bootstr);
+ void (*pv_printf)(__const__ char *fmt, ...);
+ void (*pv_abort)(void);
+ __volatile__ unsigned int *pv_ticks;
+ void (*pv_halt)(void);
+ void (**pv_synchook)(void);
+
+ /* Evaluate a forth string, not different proto for V0 and V2->up. */
+ union {
+ void (*v0_eval)(int len, char *str);
+ void (*v2_eval)(char *str, int arg0, int arg1, int arg2, int arg3, int arg4);
+ } pv_fortheval;
+
+ const struct linux_arguments_v0 * const *pv_v0bootargs;
+
+ /* Get ether address. */
+ unsigned int (*pv_enaddr)(int d, char *enaddr);
+
+ struct linux_bootargs_v2 pv_v2bootargs;
+ struct linux_dev_v2_funcs pv_v2devops;
+
+ /* Prom version 3 memory allocation */
+ char * (*v3_memalloc)(char *va, unsigned int size, unsigned int align);
+
+ int filler[14];
+
+ /* This one is sun4c/sun4 only. */
+ void (*pv_setctxt)(int ctxt, char *va, int pmeg);
+
+ /* Prom version 3 Multiprocessor routines. This stuff is crazy.
+ * No joke. Calling these when there is only one cpu probably
+ * crashes the machine, have to test this. :-)
+ */
+
+ /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+ * 'thiscontext' executing at address 'prog_counter'
+ */
+ int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
+ int thiscontext, char *prog_counter);
+
+ /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
+ * until a resume cpu call is made.
+ */
+ int (*v3_cpustop)(unsigned int whichcpu);
+
+ /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+ * resume cpu call is made.
+ */
+ int (*v3_cpuidle)(unsigned int whichcpu);
+
+ /* v3_cpuresume() will resume processor 'whichcpu' executing
+ * starting with whatever 'pc' and 'npc' were left at the
+ * last 'idle' or 'stop' call.
+ */
+ int (*v3_cpuresume)(unsigned int whichcpu);
+};
+
+/* Routines for traversing the prom device tree. */
+struct linux_nodeops {
+ int (*no_nextnode)(int node);
+ int (*no_child)(int node);
+ int (*no_proplen)(int node, const char *name);
+ int (*no_getprop)(int node, const char *name, char *val);
+ int (*no_setprop)(int node, const char *name, char *val, int len);
+ const char * (*no_nextprop)(int node, const char *name);
+};
+
+/* More fun PROM structures for device probing. */
+#define PROMREG_MAX 16
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 15
+
+struct linux_prom_registers {
+ unsigned int which_io; /* is this in OBIO space? */
+ unsigned int phys_addr; /* The physical address of this register */
+ unsigned int reg_size; /* How many bytes does this register take up? */
+};
+
+struct linux_prom_irqs {
+ int pri; /* IRQ priority */
+ int vector; /* This is foobar, what does it do? */
+};
+
+/* Element of the "ranges" vector */
+struct linux_prom_ranges {
+ unsigned int ot_child_space;
+ unsigned int ot_child_base; /* Bus feels this */
+ unsigned int ot_parent_space;
+ unsigned int ot_parent_base; /* CPU looks from here */
+ unsigned int or_size;
+};
+
+/* Ranges and reg properties are a bit different for PCI. */
+struct linux_prom_pci_registers {
+ /*
+ * We don't know what information this field contain.
+ * We guess, PCI device function is in bits 15:8
+ * So, ...
+ */
+ unsigned int which_io; /* Let it be which_io */
+
+ unsigned int phys_hi;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_pci_ranges {
+ unsigned int child_phys_hi; /* Only certain bits are encoded here. */
+ unsigned int child_phys_mid;
+ unsigned int child_phys_lo;
+
+ unsigned int parent_phys_hi;
+ unsigned int parent_phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_pci_assigned_addresses {
+ unsigned int which_io;
+
+ unsigned int phys_hi;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_ebus_ranges {
+ unsigned int child_phys_hi;
+ unsigned int child_phys_lo;
+
+ unsigned int parent_phys_hi;
+ unsigned int parent_phys_mid;
+ unsigned int parent_phys_lo;
+
+ unsigned int size;
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_OPENPROM_H) */
diff --git a/roms/openbios/arch/sparc32/pgtsrmmu.h b/roms/openbios/arch/sparc32/pgtsrmmu.h
new file mode 100644
index 00000000..64dbaa65
--- /dev/null
+++ b/roms/openbios/arch/sparc32/pgtsrmmu.h
@@ -0,0 +1,223 @@
+/*
+ * Taken from kernel for decoupling from <asm/page.h>. --zaitcev
+ *
+ * $Id: pgtsrmmu.h,v 1.2 1999/04/19 01:04:31 zaitcev Exp $
+ * pgtsrmmu.h: SRMMU page table defines and code.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _PGTSRMMU_H
+#define _PGTSRMMU_H
+
+/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#define SRMMU_PMD_SHIFT 18
+#define SRMMU_PMD_SIZE (1UL << SRMMU_PMD_SHIFT)
+#define SRMMU_PMD_MASK (~(SRMMU_PMD_SIZE-1))
+#define SRMMU_PMD_ALIGN(addr) (((addr)+SRMMU_PMD_SIZE-1)&SRMMU_PMD_MASK)
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define SRMMU_PGDIR_SHIFT 24
+#define SRMMU_PGDIR_SIZE (1UL << SRMMU_PGDIR_SHIFT)
+#define SRMMU_PGDIR_MASK (~(SRMMU_PGDIR_SIZE-1))
+#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK)
+
+#define SRMMU_PTRS_PER_PTE 64
+#define SRMMU_PTRS_PER_PMD 64
+#define SRMMU_PTRS_PER_PGD 256
+
+#define SRMMU_PTE_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */
+#define SRMMU_PMD_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */
+#define SRMMU_PGD_TABLE_SIZE 0x400 /* 256 entries, 4 bytes a piece */
+
+#define SRMMU_VMALLOC_START (0xfe300000)
+#define SRMMU_VMALLOC_END ~0x0UL
+
+/* Definition of the values in the ET field of PTD's and PTE's */
+#define SRMMU_ET_MASK 0x3
+#define SRMMU_ET_INVALID 0x0
+#define SRMMU_ET_PTD 0x1
+#define SRMMU_ET_PTE 0x2
+#define SRMMU_ET_REPTE 0x3 /* AIEEE, SuperSparc II reverse endian page! */
+
+/* Physical page extraction from PTP's and PTE's. */
+#define SRMMU_CTX_PMASK 0xfffffff0
+#define SRMMU_PTD_PMASK 0xfffffff0
+#define SRMMU_PTE_PMASK 0xffffff00
+
+/* The pte non-page bits. Some notes:
+ * 1) cache, dirty, valid, and ref are frobbable
+ * for both supervisor and user pages.
+ * 2) exec and write will only give the desired effect
+ * on user pages
+ * 3) use priv and priv_readonly for changing the
+ * characteristics of supervisor ptes
+ */
+#define SRMMU_CACHE 0x80
+#define SRMMU_DIRTY 0x40
+#define SRMMU_REF 0x20
+#define SRMMU_EXEC 0x08
+#define SRMMU_WRITE 0x04
+#define SRMMU_VALID 0x02 /* SRMMU_ET_PTE */
+#define SRMMU_PRIV 0x1c
+#define SRMMU_PRIV_RDONLY 0x18
+
+#define SRMMU_CHG_MASK (0xffffff00 | SRMMU_REF | SRMMU_DIRTY)
+
+/* SRMMU Register addresses in ASI 0x4. These are valid for all
+ * current SRMMU implementations that exist.
+ */
+#define SRMMU_CTRL_REG 0x00000000
+#define SRMMU_CTXTBL_PTR 0x00000100
+#define SRMMU_CTX_REG 0x00000200
+#define SRMMU_FAULT_STATUS 0x00000300
+#define SRMMU_FAULT_ADDR 0x00000400
+
+#ifndef __ASSEMBLY__
+
+/* Accessing the MMU control register. */
+static __inline__ unsigned int srmmu_get_mmureg(void)
+{
+ unsigned int retval;
+ __asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
+ "=r" (retval) :
+ "i" (ASI_M_MMUREGS));
+ return retval;
+}
+
+static __inline__ void srmmu_set_mmureg(unsigned long regval)
+{
+ __asm__ __volatile__("sta %0, [%%g0] %1\n\t" : :
+ "r" (regval), "i" (ASI_M_MMUREGS) : "memory");
+
+}
+
+static __inline__ void srmmu_set_ctable_ptr(unsigned long paddr)
+{
+ paddr = ((paddr >> 4) & SRMMU_CTX_PMASK);
+ __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
+ "r" (paddr), "r" (SRMMU_CTXTBL_PTR),
+ "i" (ASI_M_MMUREGS) :
+ "memory");
+}
+
+static __inline__ unsigned long srmmu_get_ctable_ptr(void)
+{
+ unsigned int retval;
+
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r" (retval) :
+ "r" (SRMMU_CTXTBL_PTR),
+ "i" (ASI_M_MMUREGS));
+ return (retval & SRMMU_CTX_PMASK) << 4;
+}
+
+static __inline__ void srmmu_set_context(int context)
+{
+ __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
+ "r" (context), "r" (SRMMU_CTX_REG),
+ "i" (ASI_M_MMUREGS) : "memory");
+}
+
+static __inline__ int srmmu_get_context(void)
+{
+ register int retval;
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r" (retval) :
+ "r" (SRMMU_CTX_REG),
+ "i" (ASI_M_MMUREGS));
+ return retval;
+}
+
+static __inline__ unsigned int srmmu_get_fstatus(void)
+{
+ unsigned int retval;
+
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r" (retval) :
+ "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS));
+ return retval;
+}
+
+static __inline__ unsigned int srmmu_get_faddr(void)
+{
+ unsigned int retval;
+
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r" (retval) :
+ "r" (SRMMU_FAULT_ADDR), "i" (ASI_M_MMUREGS));
+ return retval;
+}
+
+/* This is guaranteed on all SRMMU's. */
+static __inline__ void srmmu_flush_whole_tlb(void)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+ "r" (0x400), /* Flush entire TLB!! */
+ "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+/* These flush types are not available on all chips... */
+static __inline__ void srmmu_flush_tlb_ctx(void)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+ "r" (0x300), /* Flush TLB ctx.. */
+ "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+static __inline__ void srmmu_flush_tlb_region(unsigned long addr)
+{
+ addr &= SRMMU_PGDIR_MASK;
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+ "r" (addr | 0x200), /* Flush TLB region.. */
+ "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+
+static __inline__ void srmmu_flush_tlb_segment(unsigned long addr)
+{
+ addr &= SRMMU_PMD_MASK;
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+ "r" (addr | 0x100), /* Flush TLB segment.. */
+ "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+static __inline__ void srmmu_flush_tlb_page(unsigned long page)
+{
+ page &= PAGE_MASK;
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+ "r" (page), /* Flush TLB page.. */
+ "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+static __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr)
+{
+ unsigned long retval;
+
+ vaddr &= PAGE_MASK;
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r" (retval) :
+ "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
+
+ return retval;
+}
+
+static __inline__ int
+srmmu_get_pte (unsigned long addr)
+{
+ register unsigned long entry;
+
+ __asm__ __volatile__("\n\tlda [%1] %2,%0\n\t" :
+ "=r" (entry):
+ "r" ((addr & 0xfffff000) | 0x400), "i" (ASI_M_FLUSH_PROBE));
+ return entry;
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_SPARC_PGTSRMMU_H) */
diff --git a/roms/openbios/arch/sparc32/plainboot.c b/roms/openbios/arch/sparc32/plainboot.c
new file mode 100644
index 00000000..08dab2d1
--- /dev/null
+++ b/roms/openbios/arch/sparc32/plainboot.c
@@ -0,0 +1,21 @@
+/* tag: openbios fixed address forth starter
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/sys_info.h"
+#include "multiboot.h"
+
+#define FIXED_DICTSTART 0xfffe0000
+#define FIXED_DICTEND 0xfffeffff
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ info->dict_start=(unsigned long *)FIXED_DICTSTART;
+ info->dict_end=(unsigned long *)FIXED_DICTEND;
+}
diff --git a/roms/openbios/arch/sparc32/psr.h b/roms/openbios/arch/sparc32/psr.h
new file mode 100644
index 00000000..0f6cfabb
--- /dev/null
+++ b/roms/openbios/arch/sparc32/psr.h
@@ -0,0 +1,88 @@
+/* $Id: psr.h,v 1.1 2002/07/12 17:12:03 zaitcev Exp $
+ * psr.h: This file holds the macros for masking off various parts of
+ * the processor status register on the Sparc. This is valid
+ * for Version 8. On the V9 this is renamed to the PSTATE
+ * register and its members are accessed as fields like
+ * PSTATE.PRIV for the current CPU privilege level.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __LINUX_SPARC_PSR_H
+#define __LINUX_SPARC_PSR_H
+
+/* The Sparc PSR fields are laid out as the following:
+ *
+ * ------------------------------------------------------------------------
+ * | impl | vers | icc | resv | EC | EF | PIL | S | PS | ET | CWP |
+ * | 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 |
+ * ------------------------------------------------------------------------
+ */
+#define PSR_CWP 0x0000001f /* current window pointer */
+#define PSR_ET 0x00000020 /* enable traps field */
+#define PSR_PS 0x00000040 /* previous privilege level */
+#define PSR_S 0x00000080 /* current privilege level */
+#define PSR_PIL 0x00000f00 /* processor interrupt level */
+#define PSR_EF 0x00001000 /* enable floating point */
+#define PSR_EC 0x00002000 /* enable co-processor */
+#define PSR_LE 0x00008000 /* SuperSparcII little-endian */
+#define PSR_ICC 0x00f00000 /* integer condition codes */
+#define PSR_C 0x00100000 /* carry bit */
+#define PSR_V 0x00200000 /* overflow bit */
+#define PSR_Z 0x00400000 /* zero bit */
+#define PSR_N 0x00800000 /* negative bit */
+#define PSR_VERS 0x0f000000 /* cpu-version field */
+#define PSR_IMPL 0xf0000000 /* cpu-implementation field */
+
+#ifndef __ASSEMBLY
+/* Get the %psr register. */
+static __inline__ unsigned int get_psr(void)
+{
+ unsigned int psr;
+ __asm__ __volatile__(
+ "rd %%psr, %0\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ : "=r" (psr)
+ : /* no inputs */
+ : "memory");
+
+ return psr;
+}
+
+static __inline__ void put_psr(unsigned int new_psr)
+{
+ __asm__ __volatile__(
+ "wr %0, 0x0, %%psr\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ : /* no outputs */
+ : "r" (new_psr)
+ : "memory", "cc");
+}
+
+/* Get the %fsr register. Be careful, make sure the floating point
+ * enable bit is set in the %psr when you execute this or you will
+ * incur a trap.
+ */
+
+static unsigned int fsr_storage;
+
+static __inline__ unsigned int get_fsr(void)
+{
+ unsigned int fsr = 0;
+
+ __asm__ __volatile__(
+ "st %%fsr, %1\n\t"
+ "ld %1, %0\n\t"
+ : "=r" (fsr)
+ : "m" (fsr_storage));
+
+ return fsr;
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__LINUX_SPARC_PSR_H) */
diff --git a/roms/openbios/arch/sparc32/romvec.c b/roms/openbios/arch/sparc32/romvec.c
new file mode 100644
index 00000000..8757c28f
--- /dev/null
+++ b/roms/openbios/arch/sparc32/romvec.c
@@ -0,0 +1,524 @@
+/*
+ * PROM interface support
+ * Copyright 1996 The Australian National University.
+ * Copyright 1996 Fujitsu Laboratories Limited
+ * Copyright 1999 Pete A. Zaitcev
+ * This software may be distributed under the terms of the Gnu
+ * Public License version 2 or later
+ */
+
+#include <stdarg.h>
+
+#include "openprom.h"
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "drivers/drivers.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+#include "romvec.h"
+
+#ifdef CONFIG_DEBUG_OBP
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+char obp_stdin, obp_stdout;
+const char *obp_stdin_path, *obp_stdout_path;
+
+struct linux_arguments_v0 obp_arg;
+const char *bootpath;
+static const struct linux_arguments_v0 * const obp_argp = &obp_arg;
+
+static void (*sync_hook)(void);
+
+static struct linux_romvec romvec0;
+
+static void doublewalk(__attribute__((unused)) unsigned int ptab1,
+ __attribute__((unused)) unsigned int va)
+{
+}
+
+int obp_nextnode(int node)
+{
+ int peer;
+
+ PUSH(node);
+ fword("peer");
+ peer = POP();
+ DPRINTF("obp_nextnode(0x%x) = 0x%x\n", node, peer);
+
+ return peer;
+}
+
+int obp_child(int node)
+{
+ int child;
+
+ PUSH(node);
+ fword("child");
+ child = POP();
+ DPRINTF("obp_child(0x%x) = 0x%x\n", node, child);
+
+ return child;
+}
+
+int obp_proplen(int node, const char *name)
+{
+ int notfound;
+
+ if (!node) {
+ DPRINTF("obp_proplen(0x0, %s) = -1\n", name);
+ return -1;
+ }
+
+ push_str(name);
+ PUSH(node);
+ fword("get-package-property");
+ notfound = POP();
+
+ if (notfound) {
+ DPRINTF("obp_proplen(0x%x, %s) (not found)\n", node, name);
+
+ return -1;
+ } else {
+ int len;
+
+ len = POP();
+ (void) POP();
+ DPRINTF("obp_proplen(0x%x, %s) = %d\n", node, name, len);
+
+ return len;
+ }
+}
+
+#ifdef CONFIG_DEBUG_OBP
+static int looks_like_string(const char *str, int len)
+{
+ int i;
+ int ret = (str[len-1] == '\0');
+ for (i = 0; i < len-1 && ret; i++)
+ {
+ int ch = str[i] & 0xFF;
+ if (ch < 0x20 || ch > 0x7F)
+ ret = 0;
+ }
+ return ret;
+}
+#endif
+
+int obp_getprop(int node, const char *name, char *value)
+{
+ int notfound, found;
+ int len;
+ const char *str;
+
+ if (!node) {
+ DPRINTF("obp_getprop(0x0, %s) = -1\n", name);
+ return -1;
+ }
+
+ if (!name) {
+ // NULL name means get first property
+ push_str("");
+ PUSH(node);
+ fword("next-property");
+ found = POP();
+ if (found) {
+ len = POP();
+ str = (char *) POP();
+ DPRINTF("obp_getprop(0x%x, NULL) = %s\n", node, str);
+
+ return (int)str;
+ }
+ DPRINTF("obp_getprop(0x%x, NULL) (not found)\n", node);
+
+ return -1;
+ } else {
+ push_str(name);
+ PUSH(node);
+ fword("get-package-property");
+ notfound = POP();
+ }
+ if (notfound) {
+ DPRINTF("obp_getprop(0x%x, %s) (not found)\n", node, name);
+
+ return -1;
+ } else {
+ len = POP();
+ str = (char *) POP();
+ if (len > 0)
+ memcpy(value, str, len);
+ else
+ str = "NULL";
+
+#ifdef CONFIG_DEBUG_OBP
+ if (looks_like_string(str, len)) {
+ DPRINTF("obp_getprop(0x%x, %s) = %s\n", node, name, str);
+ } else {
+ int i;
+ DPRINTF("obp_getprop(0x%x, %s) = ", node, name);
+ for (i = 0; i < len; i++) {
+ DPRINTF("%02x%s", str[i] & 0xFF,
+ (len == 4 || i == len-1) ? "" : " ");
+ }
+ DPRINTF("\n");
+ }
+#endif
+
+ return len;
+ }
+}
+
+const char *obp_nextprop(int node, const char *name)
+{
+ int found;
+
+ if (!name || *name == '\0') {
+ // NULL name means get first property
+ push_str("");
+ name = "NULL";
+ } else {
+ push_str(name);
+ }
+ PUSH(node);
+ fword("next-property");
+ found = POP();
+ if (!found) {
+ DPRINTF("obp_nextprop(0x%x, %s) (not found)\n", node, name);
+
+ return "";
+ } else {
+ char *str;
+
+ POP(); /* len */
+ str = (char *) POP();
+
+ DPRINTF("obp_nextprop(0x%x, %s) = %s\n", node, name, str);
+
+ return str;
+ }
+}
+
+int obp_setprop(__attribute__((unused)) int node,
+ __attribute__((unused)) const char *name,
+ __attribute__((unused)) char *value,
+ __attribute__((unused)) int len)
+{
+ DPRINTF("obp_setprop(0x%x, %s) = %s (%d)\n", node, name, value, len);
+
+ return -1;
+}
+
+static const struct linux_nodeops nodeops0 = {
+ obp_nextnode_handler, /* int (*no_nextnode)(int node); */
+ obp_child_handler, /* int (*no_child)(int node); */
+ obp_proplen_handler, /* int (*no_proplen)(int node, char *name); */
+ obp_getprop_handler, /* int (*no_getprop)(int node,char *name,char *val); */
+ obp_setprop_handler, /* int (*no_setprop)(int node, char *name,
+ char *val, int len); */
+ obp_nextprop_handler /* char * (*no_nextprop)(int node, char *name); */
+};
+
+int obp_nbgetchar(void)
+{
+ return getchar();
+}
+
+int obp_nbputchar(int ch)
+{
+ putchar(ch);
+
+ return 0;
+}
+
+void obp_putstr(char *str, int len)
+{
+ PUSH(pointer2cell(str));
+ PUSH(len);
+ fword("type");
+}
+
+void obp_printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ printk(fmt, ap);
+ va_end(ap);
+}
+
+void obp_reboot(char *str)
+{
+ printk("rebooting (%s)\n", str);
+ *reset_reg = 1;
+ printk("reboot failed\n");
+ for (;;) {}
+}
+
+void obp_abort(void)
+{
+ printk("abort, power off\n");
+ *power_reg = 1;
+ printk("power off failed\n");
+ for (;;) {}
+}
+
+void obp_halt(void)
+{
+ printk("halt, power off\n");
+ *power_reg = 1;
+ printk("power off failed\n");
+ for (;;) {}
+}
+
+int obp_devopen(char *str)
+{
+ int ret;
+
+ push_str(str);
+ fword("open-dev");
+ ret = POP();
+ DPRINTF("obp_devopen(%s) = 0x%x\n", str, ret);
+
+ return ret;
+}
+
+int obp_devclose(int dev_desc)
+{
+ int ret = 1;
+
+ PUSH(dev_desc);
+ fword("close-dev");
+
+ DPRINTF("obp_devclose(0x%x) = %d\n", dev_desc, ret);
+
+ return ret;
+}
+
+int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf)
+{
+ int ret, hi, lo, bs;
+
+ bs = 512;
+ hi = ((uint64_t)offset * bs) >> 32;
+ lo = ((uint64_t)offset * bs) & 0xffffffff;
+
+ ret = obp_devseek(dev_desc, hi, lo);
+
+ ret = obp_devread(dev_desc, buf, num_blks * bs) / bs;
+
+ DPRINTF("obp_rdblkdev(fd 0x%x, num_blks %d, offset %d (hi %d lo %d), buf 0x%x) = %d\n", dev_desc, num_blks, offset, hi, lo, (int)buf, ret);
+
+ return ret;
+}
+
+int obp_devread(int dev_desc, char *buf, int nbytes)
+{
+ int ret;
+
+ PUSH((int)buf);
+ PUSH(nbytes);
+ push_str("read");
+ PUSH(dev_desc);
+ fword("$call-method");
+ ret = POP();
+
+ DPRINTF("obp_devread(fd 0x%x, buf 0x%x, nbytes %d) = %d\n", dev_desc, (int)buf, nbytes, ret);
+
+ return ret;
+}
+
+int obp_devwrite(int dev_desc, char *buf, int nbytes)
+{
+#ifdef CONFIG_DEBUG_OBP_DEVWRITE /* disabled, makes too much noise */
+ int ret;
+#endif
+
+ PUSH((int)buf);
+ PUSH(nbytes);
+ push_str("write");
+ PUSH(dev_desc);
+ fword("$call-method");
+#ifdef CONFIG_DEBUG_OBP_DEVWRITE
+ ret = POP();
+ DPRINTF("obp_devwrite(fd 0x%x, buf %s, nbytes %d) = %d\n", dev_desc, buf, nbytes, ret);
+#else
+ POP();
+#endif
+
+ return nbytes;
+}
+
+int obp_devseek(int dev_desc, int hi, int lo)
+{
+ int ret;
+
+ PUSH(lo);
+ PUSH(hi);
+ push_str("seek");
+ PUSH(dev_desc);
+ fword("$call-method");
+ ret = POP();
+
+ DPRINTF("obp_devseek(fd 0x%x, hi %d, lo %d) = %d\n", dev_desc, hi, lo, ret);
+
+ return ret;
+}
+
+int obp_inst2pkg(int dev_desc)
+{
+ int ret;
+
+ PUSH(dev_desc);
+ fword("ihandle>non-interposed-phandle");
+ ret = POP();
+
+ DPRINTF("obp_inst2pkg(fd 0x%x) = 0x%x\n", dev_desc, ret);
+
+ return ret;
+}
+
+int obp_cpustart(__attribute__((unused))unsigned int whichcpu,
+ __attribute__((unused))int ctxtbl_ptr,
+ __attribute__((unused))int thiscontext,
+ __attribute__((unused))char *prog_counter)
+{
+ int cpu, found;
+ struct linux_prom_registers *smp_ctable = (void *)ctxtbl_ptr;
+
+ DPRINTF("obp_cpustart: cpu %d, ctxptr 0x%x, ctx %d, pc 0x%x\n", whichcpu,
+ smp_ctable->phys_addr, thiscontext, (unsigned int)prog_counter);
+
+ found = obp_getprop(whichcpu, "mid", (char *)&cpu);
+ if (found == -1)
+ return -1;
+ DPRINTF("cpu found, id %d -> cpu %d\n", whichcpu, cpu);
+
+ return start_cpu((unsigned int)prog_counter, ((unsigned int)smp_ctable->phys_addr) >> 4,
+ thiscontext, cpu);
+}
+
+int obp_cpustop(__attribute__((unused)) unsigned int whichcpu)
+{
+ DPRINTF("obp_cpustop: cpu %d\n", whichcpu);
+
+ return 0;
+}
+
+int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu)
+{
+ DPRINTF("obp_cpuidle: cpu %d\n", whichcpu);
+
+ return 0;
+}
+
+int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu)
+{
+ DPRINTF("obp_cpuresume: cpu %d\n", whichcpu);
+
+ return 0;
+}
+
+void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4)
+{
+ int dstacktmp = 0;
+
+ // It seems Solaris passes up to 5 arguments which should be pushed onto the Forth
+ // stack for execution. However the API doesn't provide for a way to specify the number
+ // of arguments actually being passed. Hence we preserve the state of the Forth stack
+ // before, push all the arguments, execute the Forth, then restore the stack to its
+ // previous state. This enables us to have a variable number of arguments and still
+ // preserve stack state between subsequent calls.
+
+ // Preserve stack state
+ dstacktmp = dstackcnt;
+
+ PUSH(arg4);
+ PUSH(arg3);
+ PUSH(arg2);
+ PUSH(arg1);
+ PUSH(arg0);
+
+ DPRINTF("obp_fortheval_v2(%x %x %x %x %x %s)\n", arg4, arg3, arg2, arg1, arg0, str);
+ push_str(str);
+ fword("eval");
+
+ // Restore stack state
+ dstackcnt = dstacktmp;
+}
+
+volatile uint32_t *obp_ticks;
+
+void *
+init_openprom(void)
+{
+ /* Setup the openprom vector. Note that all functions should be invoked
+ via their handler (see call-romvec.S) which acts as a proxy to save
+ the globals and setup the stack correctly */
+
+ // Linux wants a R/W romvec table
+ romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC;
+ romvec0.pv_romvers = 3;
+ romvec0.pv_plugin_revision = 2;
+ romvec0.pv_printrev = 0x20019;
+ romvec0.pv_v0mem.v0_totphys = NULL;
+ romvec0.pv_v0mem.v0_prommap = NULL;
+ romvec0.pv_v0mem.v0_available = NULL;
+ romvec0.pv_nodeops = &nodeops0;
+ romvec0.pv_bootstr = (void *)doublewalk;
+ romvec0.pv_v0devops.v0_devopen = &obp_devopen_handler;
+ romvec0.pv_v0devops.v0_devclose = &obp_devclose_handler;
+ romvec0.pv_v0devops.v0_rdblkdev = &obp_rdblkdev_handler;
+ romvec0.pv_stdin = &obp_stdin;
+ romvec0.pv_stdout = &obp_stdout;
+ romvec0.pv_getchar = obp_nbgetchar_handler;
+ romvec0.pv_putchar = (void (*)(int))obp_nbputchar_handler;
+ romvec0.pv_nbgetchar = obp_nbgetchar_handler;
+ romvec0.pv_nbputchar = obp_nbputchar_handler;
+ romvec0.pv_putstr = obp_putstr_handler;
+ romvec0.pv_reboot = obp_reboot_handler;
+ romvec0.pv_printf = obp_printf_handler;
+ romvec0.pv_abort = obp_abort_handler;
+
+ /* Point to the Forth obp-ticks variable and reset */
+ fword("obp-ticks");
+ obp_ticks = cell2pointer(POP());
+ *obp_ticks = 0;
+ romvec0.pv_ticks = obp_ticks;
+
+ romvec0.pv_halt = obp_halt_handler;
+ romvec0.pv_synchook = &sync_hook;
+ romvec0.pv_v0bootargs = &obp_argp;
+ romvec0.pv_fortheval.v2_eval = obp_fortheval_v2_handler;
+ romvec0.pv_v2devops.v2_inst2pkg = obp_inst2pkg_handler;
+ romvec0.pv_v2devops.v2_dumb_mem_alloc = obp_dumb_memalloc_handler;
+ romvec0.pv_v2devops.v2_dumb_mem_free = obp_dumb_memfree_handler;
+ romvec0.pv_v2devops.v2_dumb_mmap = obp_dumb_mmap_handler;
+ romvec0.pv_v2devops.v2_dumb_munmap = obp_dumb_munmap_handler;
+ romvec0.pv_v2devops.v2_dev_open = obp_devopen_handler;
+ romvec0.pv_v2devops.v2_dev_close = (void (*)(int))obp_devclose_handler;
+ romvec0.pv_v2devops.v2_dev_read = obp_devread_handler;
+ romvec0.pv_v2devops.v2_dev_write = obp_devwrite_handler;
+ romvec0.pv_v2devops.v2_dev_seek = obp_devseek_handler;
+
+ romvec0.pv_v2bootargs.bootpath = &bootpath;
+
+ romvec0.pv_v2bootargs.bootargs = &obp_arg.argv[1];
+
+ /* Point fd_stdin/fd_stdout to the Forth stdin/stdout variables */
+ fword("stdin");
+ romvec0.pv_v2bootargs.fd_stdin = cell2pointer(POP());
+ fword("stdout");
+ romvec0.pv_v2bootargs.fd_stdout = cell2pointer(POP());
+
+ romvec0.v3_memalloc = obp_memalloc_handler;
+
+ romvec0.v3_cpustart = obp_cpustart_handler;
+ romvec0.v3_cpustop = obp_cpustop_handler;
+ romvec0.v3_cpuidle = obp_cpuidle_handler;
+ romvec0.v3_cpuresume = obp_cpuresume_handler;
+
+ return &romvec0;
+}
diff --git a/roms/openbios/arch/sparc32/romvec.h b/roms/openbios/arch/sparc32/romvec.h
new file mode 100644
index 00000000..4375f06f
--- /dev/null
+++ b/roms/openbios/arch/sparc32/romvec.h
@@ -0,0 +1,79 @@
+/*
+ * romvec main C function and handler declarations
+ */
+
+extern volatile uint32_t *obp_ticks;
+void *init_openprom(void);
+
+int obp_devopen(char *str);
+int obp_devopen_handler(char *str);
+int obp_devclose(int dev_desc);
+int obp_devclose_handler(int dev_desc);
+int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf);
+int obp_rdblkdev_handler(int dev_desc, int num_blks, int offset, char *buf);
+int obp_nbgetchar(void);
+int obp_nbgetchar_handler(void);
+int obp_nbputchar(int ch);
+int obp_nbputchar_handler(int ch);
+void obp_putstr(char *str, int len);
+void obp_putstr_handler(char *str, int len);
+void obp_printf(__const__ char *fmt, ...);
+void obp_printf_handler(__const__ char *fmt, ...);
+void obp_reboot(char *str);
+void obp_reboot_handler(char *str);
+void obp_abort(void);
+void obp_abort_handler(void);
+void obp_halt(void);
+void obp_halt_handler(void);
+void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4);
+void obp_fortheval_v2_handler(char *str, int arg0, int arg1, int arg2, int arg3, int arg4);
+int obp_inst2pkg(int dev_desc);
+int obp_inst2pkg_handler(int dev_desc);
+char *obp_dumb_memalloc(char *va, unsigned int size);
+char *obp_dumb_memalloc_handler(char *va, unsigned int size);
+void obp_dumb_memfree(char *va, unsigned size);
+void obp_dumb_memfree_handler(char *va, unsigned size);
+char *obp_dumb_mmap(char *va, int which_io, unsigned int pa, unsigned int size);
+char *obp_dumb_mmap_handler(char *va, int which_io, unsigned int pa, unsigned int size);
+void obp_dumb_munmap(__attribute__((unused)) char *va, __attribute__((unused)) unsigned int size);
+void obp_dumb_munmap_handler(__attribute__((unused)) char *va, __attribute__((unused)) unsigned int size);
+int obp_devread(int dev_desc, char *buf, int nbytes);
+int obp_devread_handler(int dev_desc, char *buf, int nbytes);
+int obp_devwrite(int dev_desc, char *buf, int nbytes);
+int obp_devwrite_handler(int dev_desc, char *buf, int nbytes);
+int obp_devseek(int dev_desc, int hi, int lo);
+int obp_devseek_handler(int dev_desc, int hi, int lo);
+int obp_cpustart(__attribute__((unused))unsigned int whichcpu,
+ __attribute__((unused))int ctxtbl_ptr,
+ __attribute__((unused))int thiscontext,
+ __attribute__((unused))char *prog_counter);
+int obp_cpustart_handler(__attribute__((unused))unsigned int whichcpu,
+ __attribute__((unused))int ctxtbl_ptr,
+ __attribute__((unused))int thiscontext,
+ __attribute__((unused))char *prog_counter);
+int obp_cpustop(__attribute__((unused)) unsigned int whichcpu);
+int obp_cpustop_handler(__attribute__((unused)) unsigned int whichcpu);
+int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu);
+int obp_cpuidle_handler(__attribute__((unused)) unsigned int whichcpu);
+int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu);
+int obp_cpuresume_handler(__attribute__((unused)) unsigned int whichcpu);
+int obp_nextnode(int node);
+int obp_nextnode_handler(int node);
+int obp_child(int node);
+int obp_child_handler(int node);
+int obp_proplen(int node, const char *name);
+int obp_proplen_handler(int node, const char *name);
+int obp_getprop(int node, const char *name, char *value);
+int obp_getprop_handler(int node, const char *name, char *value);
+int obp_setprop(__attribute__((unused)) int node,
+ __attribute__((unused)) const char *name,
+ __attribute__((unused)) char *value,
+ __attribute__((unused)) int len);
+int obp_setprop_handler(__attribute__((unused)) int node,
+ __attribute__((unused)) const char *name,
+ __attribute__((unused)) char *value,
+ __attribute__((unused)) int len);
+const char *obp_nextprop(int node, const char *name);
+const char *obp_nextprop_handler(int node, const char *name);
+char *obp_memalloc(char *va, unsigned int size, unsigned int align);
+char *obp_memalloc_handler(char *va, unsigned int size, unsigned int align);
diff --git a/roms/openbios/arch/sparc32/switch.S b/roms/openbios/arch/sparc32/switch.S
new file mode 100644
index 00000000..d5b1b659
--- /dev/null
+++ b/roms/openbios/arch/sparc32/switch.S
@@ -0,0 +1,154 @@
+#define __ASSEMBLY
+#include "psr.h"
+#include "asm/asi.h"
+#define ASI_BP ASI_M_BYPASS
+#define REGWIN_SZ 0x40
+
+ .globl __switch_context, __switch_context_nosave, __exit_context, halt
+
+ .text
+ .align 4
+
+#define STACKFRAME_SZ 0x60
+
+/* These are just handy. */
+#define _SV save %sp, -STACKFRAME_SZ, %sp
+#define _RS restore
+
+#define FLUSH_ALL_KERNEL_WINDOWS \
+ _SV; _SV; _SV; _SV; _SV; _SV; _SV; \
+ _RS; _RS; _RS; _RS; _RS; _RS; _RS;
+
+/*
+ * Switch execution context
+ * This saves registers in the stack, then
+ * switches the stack, and restores everything from the new stack.
+ * This function takes no argument. New stack pointer is
+ * taken from global variable __context, and old stack pointer
+ * is also saved to __context. This way we can just jump to
+ * this routine to get back to the original context.
+ */
+
+__switch_context:
+ FLUSH_ALL_KERNEL_WINDOWS
+ /* Save everything in stack */
+ st %fp, [%fp + 120 -144]
+ add %fp, -144, %fp
+ st %g1, [%fp + 4]
+ st %g2, [%fp + 8]
+ st %g3, [%fp + 12]
+ st %g4, [%fp + 16]
+ st %g5, [%fp + 20]
+ st %g6, [%fp + 24]
+ st %g7, [%fp + 28]
+
+ st %o0, [%fp + 32]
+ st %o1, [%fp + 36]
+ st %o2, [%fp + 40]
+ st %o3, [%fp + 44]
+ st %o4, [%fp + 48]
+ st %o5, [%fp + 52]
+ st %sp, [%fp + 56]
+ st %o7, [%fp + 60]
+
+ st %l0, [%fp + 64]
+ st %l1, [%fp + 68]
+ st %l2, [%fp + 72]
+ st %l3, [%fp + 76]
+ st %l4, [%fp + 80]
+ st %l5, [%fp + 84]
+ st %l6, [%fp + 88]
+ st %l7, [%fp + 92]
+
+ st %i0, [%fp + 96]
+ st %i1, [%fp + 100]
+ st %i2, [%fp + 104]
+ st %i3, [%fp + 108]
+ st %i4, [%fp + 112]
+ st %i5, [%fp + 116]
+ st %i7, [%fp + 124]
+
+ /* ctx->return_address: Return to caller */
+ st %o7, [%fp + 128]
+
+ /* Interrupts are not allowed... */
+
+ /* Turn on Supervisor, EnableFloating, and all the PIL bits.
+ * Also puts us in register window zero with traps off.
+ */
+#if 0
+ set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
+ wr %g2, 0x0, %psr
+#endif
+ set __context, %g1
+ /* Swap ctx pointer with %fp and jump*/
+ ba __set_context
+ swap [%g1], %fp
+__switch_context_nosave:
+ set __context, %g1
+ /* load %fp from ctx pointer */
+ ld [%g1], %fp
+__set_context:
+ /* Load all registers */
+ /* offset 0: %g0, no need to load */
+ ld [%fp + 4], %g1
+ ld [%fp + 8], %g2
+ ld [%fp + 12], %g3
+ ld [%fp + 16], %g4
+ ld [%fp + 20], %g5
+ ld [%fp + 24], %g6
+ ld [%fp + 28], %g7
+
+ /* offset 32: %o0, loaded from ctx->param */
+ ld [%fp + 36], %o1
+ ld [%fp + 40], %o2
+ ld [%fp + 44], %o3
+ ld [%fp + 48], %o4
+ ld [%fp + 52], %o5
+ ld [%fp + 56], %sp
+ /* offset 60: %o7, loaded from ctx->return_addr */
+
+ ld [%fp + 64], %l0
+ ld [%fp + 68], %l1
+ ld [%fp + 72], %l2
+ ld [%fp + 76], %l3
+ ld [%fp + 80], %l4
+ ld [%fp + 84], %l5
+ ld [%fp + 88], %l6
+ ld [%fp + 92], %l7
+
+ ld [%fp + 96], %i0
+ ld [%fp + 100], %i1
+ ld [%fp + 104], %i2
+ ld [%fp + 108], %i3
+ ld [%fp + 112], %i4
+ ld [%fp + 116], %i5
+ ld [%fp + 124], %i7
+
+ /* ctx->return_addr */
+ ld [%fp + 136], %o7
+
+ /* ctx->param */
+ ld [%fp + 140], %o0
+
+ /* ctx->pc, save %g1 to %y and load to %g1 */
+ mov %g1, %y
+ ld [%fp + 128], %g1
+ /* %fp last */
+ ld [%fp + 120], %fp
+ /* Finally, get the new %pc from %g1 and restore %g1*/
+ jmp %g1
+ mov %y, %g1
+
+ FLUSH_ALL_KERNEL_WINDOWS
+__exit_context:
+ /* Get back to the original context */
+ call __switch_context
+ nop
+
+ /* We get here if the other context attempt to switch to this
+ * dead context. This should not happen. */
+
+halt:
+ b halt
+ nop
diff --git a/roms/openbios/arch/sparc32/sys_info.c b/roms/openbios/arch/sparc32/sys_info.c
new file mode 100644
index 00000000..719537d4
--- /dev/null
+++ b/roms/openbios/arch/sparc32/sys_info.c
@@ -0,0 +1,58 @@
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/elf_boot.h"
+#include "libopenbios/sys_info.h"
+#include "context.h"
+#include "boot.h"
+
+#define printf printk
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+unsigned int qemu_mem_size;
+
+void collect_multiboot_info(struct sys_info *);
+
+void collect_sys_info(struct sys_info *info)
+{
+ int i;
+ unsigned long long total = 0;
+ struct memrange *mmap;
+
+ /* Pick up paramters given by bootloader to us */
+ //info->boot_type = boot_ctx->eax;
+ //info->boot_data = boot_ctx->ebx;
+ info->boot_arg = boot_ctx->param[0];
+ //debug("boot eax = %#lx\n", info->boot_type);
+ //debug("boot ebx = %#lx\n", info->boot_data);
+ info->boot_type = ELF_BHDR_MAGIC;
+ info->boot_data = virt_to_phys(&elf_image_notes);
+ debug("boot arg = %#lx\n", info->boot_arg);
+
+ collect_elfboot_info(info);
+#ifdef CONFIG_LINUXBIOS
+ collect_linuxbios_info(info);
+#endif
+#ifdef CONFIG_IMAGE_ELF_MULTIBOOT
+ collect_multiboot_info(info);
+#endif
+
+ if (!info->memrange) {
+ info->n_memranges = 1;
+ info->memrange = malloc(1 * sizeof(struct memrange));
+ info->memrange[0].base = 0;
+ info->memrange[0].size = qemu_mem_size;
+ }
+
+ debug("\n");
+ mmap=info->memrange;
+ for (i = 0; i < info->n_memranges; i++) {
+ debug("%08lx-", (long)mmap[i].base);
+ debug("%08lx\n", (long)mmap[i].base + (long)mmap[i].size);
+ total += mmap[i].size;
+ }
+ debug("RAM %ld MB\n", (long)total >> 20);
+}
diff --git a/roms/openbios/arch/sparc32/tree.fs b/roms/openbios/arch/sparc32/tree.fs
new file mode 100644
index 00000000..c82bb171
--- /dev/null
+++ b/roms/openbios/arch/sparc32/tree.fs
@@ -0,0 +1,114 @@
+include config.fs
+
+" /" find-device
+ 2 encode-int " #address-cells" property
+ 1 encode-int " #size-cells" property
+
+ " sun4m" encode-string " compatible" property
+ h# 0a21fe80 encode-int " clock-frequency" property
+
+ : encode-unit encode-unit-sbus ;
+ : decode-unit decode-unit-sbus ;
+
+new-device
+ " memory" device-name
+ external
+ : open true ;
+ : close ;
+ \ claim ( phys size align -- base )
+ \ release ( phys size -- )
+finish-device
+
+new-device
+ " virtual-memory" device-name
+ external
+ : open true ;
+ : close ;
+ \ claim ( phys size align -- base )
+ \ release ( phys size -- )
+finish-device
+
+new-device
+ " iommu" device-name
+ 2 encode-int " #address-cells" property
+ 1 encode-int " #size-cells" property
+ h# 1000 encode-int " page-size" property
+ 0 encode-int " cache-coherence?" property
+ external
+ : open ( cr ." opening iommu" cr) true ;
+ : close ;
+ : encode-unit encode-unit-sbus ;
+ : decode-unit decode-unit-sbus ;
+finish-device
+
+" /iommu" find-device
+new-device
+ " sbus" device-name
+ " hierarchical" device-type
+ 2 encode-int " #address-cells" property
+ 1 encode-int " #size-cells" property
+ h# 01443fd0 encode-int " clock-frequency" property
+ h# 1c encode-int " slot-address-bits" property
+ h# 3f encode-int " burst-sizes" property
+ external
+ : open ( cr ." opening SBus" cr) true ;
+ : close ;
+ : encode-unit encode-unit-sbus ;
+ : decode-unit decode-unit-sbus ;
+ : map-in map-in-sbus ;
+ : map-out map-out-sbus ;
+finish-device
+
+[IFDEF] CONFIG_BPP
+" /iommu/sbus" find-device
+new-device
+ " SUNW,bpp" device-name
+ h# 4 encode-int h# 0c800000 encode-int encode+ h# 0000001c encode-int encode+ " reg" property
+ h# 33 encode-int 0 encode-int encode+ " intr" property
+finish-device
+[THEN]
+
+" /iommu/sbus" find-device
+new-device
+ " espdma" device-name
+ external
+ : encode-unit encode-unit-sbus ;
+ : decode-unit decode-unit-sbus ;
+finish-device
+
+" /iommu/sbus" find-device
+new-device
+ " ledma" device-name
+ h# 3f encode-int " burst-sizes" property
+ external
+ : encode-unit encode-unit-sbus ;
+ : decode-unit decode-unit-sbus ;
+finish-device
+
+" /iommu/sbus/ledma" find-device
+new-device
+ " le" device-name
+ " network" device-type
+ h# 7 encode-int " busmaster-regval" property
+ h# 26 encode-int 0 encode-int encode+ " intr" property
+finish-device
+
+\ obio (on-board IO)
+" /" find-device
+new-device
+ " obio" device-name
+ " hierarchical" device-type
+ 2 encode-int " #address-cells" property
+ 1 encode-int " #size-cells" property
+ external
+ : open ( cr ." opening obio" cr) true ;
+ : close ;
+ : encode-unit encode-unit-sbus ;
+ : decode-unit decode-unit-sbus ;
+finish-device
+
+" /options" find-device
+ " disk" encode-string " boot-from" property
+
+" /openprom" find-device
+ 0 0 " aligned-allocator" property
diff --git a/roms/openbios/arch/sparc32/udiv.S b/roms/openbios/arch/sparc32/udiv.S
new file mode 100644
index 00000000..32753418
--- /dev/null
+++ b/roms/openbios/arch/sparc32/udiv.S
@@ -0,0 +1,357 @@
+/* $Id: udiv.S,v 1.4 1996/09/30 02:22:38 davem Exp $
+ * udiv.S: This routine was taken from glibc-1.09 and is covered
+ * by the GNU Library General Public License Version 2.
+ */
+
+
+/* This file is generated from divrem.m4; DO NOT EDIT! */
+/*
+ * Division and remainder, from Appendix E of the Sparc Version 8
+ * Architecture Manual, with fixes from Gordon Irlam.
+ */
+
+/*
+ * Input: dividend and divisor in %o0 and %o1 respectively.
+ *
+ * m4 parameters:
+ * .udiv name of function to generate
+ * div div=div => %o0 / %o1; div=rem => %o0 % %o1
+ * false false=true => signed; false=false => unsigned
+ *
+ * Algorithm parameters:
+ * N how many bits per iteration we try to get (4)
+ * WORDSIZE total number of bits (32)
+ *
+ * Derived constants:
+ * TOPBITS number of bits in the top decade of a number
+ *
+ * Important variables:
+ * Q the partial quotient under development (initially 0)
+ * R the remainder so far, initially the dividend
+ * ITER number of main division loop iterations required;
+ * equal to ceil(log2(quotient) / N). Note that this
+ * is the log base (2^N) of the quotient.
+ * V the current comparand, initially divisor*2^(ITER*N-1)
+ *
+ * Cost:
+ * Current estimate for non-large dividend is
+ * ceil(log2(quotient) / N) * (10 + 7N/2) + C
+ * A large dividend is one greater than 2^(31-TOPBITS) and takes a
+ * different path, as the upper bits of the quotient must be developed
+ * one bit at a time.
+ */
+
+
+ .globl .udiv
+ .globl _Udiv
+.udiv:
+_Udiv: /* needed for export */
+
+ ! Ready to divide. Compute size of quotient; scale comparand.
+ orcc %o1, %g0, %o5
+ bne 1f
+ mov %o0, %o3
+
+ ! Divide by zero trap. If it returns, return 0 (about as
+ ! wrong as possible, but that is what SunOS does...).
+ ta 0x2
+ retl
+ clr %o0
+
+1:
+ cmp %o3, %o5 ! if %o1 exceeds %o0, done
+ blu Lgot_result ! (and algorithm fails otherwise)
+ clr %o2
+
+ sethi %hi(1 << (32 - 4 - 1)), %g1
+
+ cmp %o3, %g1
+ blu Lnot_really_big
+ clr %o4
+
+ ! Here the dividend is >= 2**(31-N) or so. We must be careful here,
+ ! as our usual N-at-a-shot divide step will cause overflow and havoc.
+ ! The number of bits in the result here is N*ITER+SC, where SC <= N.
+ ! Compute ITER in an unorthodox manner: know we need to shift V into
+ ! the top decade: so do not even bother to compare to R.
+ 1:
+ cmp %o5, %g1
+ bgeu 3f
+ mov 1, %g7
+
+ sll %o5, 4, %o5
+
+ b 1b
+ add %o4, 1, %o4
+
+ ! Now compute %g7.
+ 2:
+ addcc %o5, %o5, %o5
+ bcc Lnot_too_big
+ add %g7, 1, %g7
+
+ ! We get here if the %o1 overflowed while shifting.
+ ! This means that %o3 has the high-order bit set.
+ ! Restore %o5 and subtract from %o3.
+ sll %g1, 4, %g1 ! high order bit
+ srl %o5, 1, %o5 ! rest of %o5
+ add %o5, %g1, %o5
+
+ b Ldo_single_div
+ sub %g7, 1, %g7
+
+ Lnot_too_big:
+ 3:
+ cmp %o5, %o3
+ blu 2b
+ nop
+
+ be Ldo_single_div
+ nop
+ /* NB: these are commented out in the V8-Sparc manual as well */
+ /* (I do not understand this) */
+ ! %o5 > %o3: went too far: back up 1 step
+ ! srl %o5, 1, %o5
+ ! dec %g7
+ ! do single-bit divide steps
+ !
+ ! We have to be careful here. We know that %o3 >= %o5, so we can do the
+ ! first divide step without thinking. BUT, the others are conditional,
+ ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high-
+ ! order bit set in the first step, just falling into the regular
+ ! division loop will mess up the first time around.
+ ! So we unroll slightly...
+ Ldo_single_div:
+ subcc %g7, 1, %g7
+ bl Lend_regular_divide
+ nop
+
+ sub %o3, %o5, %o3
+ mov 1, %o2
+
+ b Lend_single_divloop
+ nop
+ Lsingle_divloop:
+ sll %o2, 1, %o2
+ bl 1f
+ srl %o5, 1, %o5
+ ! %o3 >= 0
+ sub %o3, %o5, %o3
+ b 2f
+ add %o2, 1, %o2
+ 1: ! %o3 < 0
+ add %o3, %o5, %o3
+ sub %o2, 1, %o2
+ 2:
+ Lend_single_divloop:
+ subcc %g7, 1, %g7
+ bge Lsingle_divloop
+ tst %o3
+
+ b,a Lend_regular_divide
+
+Lnot_really_big:
+1:
+ sll %o5, 4, %o5
+
+ cmp %o5, %o3
+ bleu 1b
+ addcc %o4, 1, %o4
+
+ be Lgot_result
+ sub %o4, 1, %o4
+
+ tst %o3 ! set up for initial iteration
+Ldivloop:
+ sll %o2, 4, %o2
+ ! depth 1, accumulated bits 0
+ bl L.1.16
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ ! depth 2, accumulated bits 1
+ bl L.2.17
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ ! depth 3, accumulated bits 3
+ bl L.3.19
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ ! depth 4, accumulated bits 7
+ bl L.4.23
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ b 9f
+ add %o2, (7*2+1), %o2
+
+L.4.23:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ b 9f
+ add %o2, (7*2-1), %o2
+
+L.3.19:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ ! depth 4, accumulated bits 5
+ bl L.4.21
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ b 9f
+ add %o2, (5*2+1), %o2
+
+L.4.21:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ b 9f
+ add %o2, (5*2-1), %o2
+
+L.2.17:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ ! depth 3, accumulated bits 1
+ bl L.3.17
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ ! depth 4, accumulated bits 3
+ bl L.4.19
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ b 9f
+ add %o2, (3*2+1), %o2
+
+L.4.19:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ b 9f
+ add %o2, (3*2-1), %o2
+
+L.3.17:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ ! depth 4, accumulated bits 1
+ bl L.4.17
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ b 9f
+ add %o2, (1*2+1), %o2
+
+L.4.17:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ b 9f
+ add %o2, (1*2-1), %o2
+
+L.1.16:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ ! depth 2, accumulated bits -1
+ bl L.2.15
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ ! depth 3, accumulated bits -1
+ bl L.3.15
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ ! depth 4, accumulated bits -1
+ bl L.4.15
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ b 9f
+ add %o2, (-1*2+1), %o2
+
+L.4.15:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ b 9f
+ add %o2, (-1*2-1), %o2
+
+L.3.15:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ ! depth 4, accumulated bits -3
+ bl L.4.13
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ b 9f
+ add %o2, (-3*2+1), %o2
+
+L.4.13:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ b 9f
+ add %o2, (-3*2-1), %o2
+
+L.2.15:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ ! depth 3, accumulated bits -3
+ bl L.3.13
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ ! depth 4, accumulated bits -5
+ bl L.4.11
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ b 9f
+ add %o2, (-5*2+1), %o2
+
+L.4.11:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ b 9f
+ add %o2, (-5*2-1), %o2
+
+L.3.13:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ ! depth 4, accumulated bits -7
+ bl L.4.9
+ srl %o5,1,%o5
+ ! remainder is positive
+ subcc %o3,%o5,%o3
+ b 9f
+ add %o2, (-7*2+1), %o2
+
+L.4.9:
+ ! remainder is negative
+ addcc %o3,%o5,%o3
+ b 9f
+ add %o2, (-7*2-1), %o2
+
+ 9:
+Lend_regular_divide:
+ subcc %o4, 1, %o4
+ bge Ldivloop
+ tst %o3
+
+ bl,a Lgot_result
+ ! non-restoring fixup here (one instruction only!)
+ sub %o2, 1, %o2
+
+Lgot_result:
+
+ retl
+ mov %o2, %o0
+
+ .globl .udiv_patch
+.udiv_patch:
+ wr %g0, 0x0, %y
+ nop
+ nop
+ retl
+ udiv %o0, %o1, %o0
+ nop
diff --git a/roms/openbios/arch/sparc32/vectors.S b/roms/openbios/arch/sparc32/vectors.S
new file mode 100644
index 00000000..e812cecb
--- /dev/null
+++ b/roms/openbios/arch/sparc32/vectors.S
@@ -0,0 +1,254 @@
+/*
+ * <vectors.S>
+ *
+ * Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions.
+ *
+ * Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ */
+
+#define __ASSEMBLY
+#include "psr.h"
+#include "asm/asi.h"
+#define SER_ADDR5 0x71100004
+#define SER_ADDR10 0xf1100004
+
+ .section ".text.vectors", "ax"
+ .align 4 /* Should be 16384, but alignment is handled by the ldscript */
+/* Sparc32 trap table */
+ .globl trap_table, t_zero, t_wovf, t_wunf, __divide_error
+trap_table:
+
+#define WINDOW_SPILL \
+ rd %psr, %l0; rd %wim, %l3; b spill_window_entry; nop;
+
+#define WINDOW_FILL \
+ rd %psr, %l0; rd %wim, %l3; b fill_window_entry; nop;
+
+#define TRAP_DFAULT(lvl) \
+ rd %psr, %l0; rd %wim, %l3; b handle_dfault; mov lvl, %l7;
+
+#define BTRAP(lvl) ba bug; mov lvl, %g1; nop; nop;
+#define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7)
+#define TRAP_ENTRY_INTERRUPT(int_level) \
+ sethi %hi(irq_entry ## int_level), %l7; \
+ or %l7, %lo(irq_entry ## int_level), %l7; \
+ jmp %l7; \
+ nop
+
+t_zero: b entry; nop; nop; nop;
+ BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) BTRAP(0x4)
+t_wovf: WINDOW_SPILL /* Window Overflow */
+t_wunf: WINDOW_FILL /* Window Underflow */
+ BTRAP(0x7)
+ BTRAP(0x8)
+ TRAP_DFAULT(0x9)
+ BTRAP(0xa) BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
+#if 0
+ BAD_TRAP(0x10)
+t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */
+t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */
+t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */
+t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */
+t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */
+t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */
+t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */
+t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */
+t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */
+t_irq10: TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
+t_irq11: TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */
+t_irq12: TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */
+t_irq13: TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
+t_irq14: TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
+t_nmi: BAD_TRAP(0x1f) /* Level 15 (NMI) */
+#else
+ BTRAPS(0x10)
+ BTRAP(0x18) BTRAP(0x19)
+t_irq10: TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */
+ BTRAP(0x1b) BTRAP(0x1c) BTRAP(0x1d)
+t_irq14: TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
+ BTRAP(0x1f)
+#endif
+ BTRAPS(0x20)
+ BTRAP(0x28)
+ TRAP_DFAULT(0x29)
+ BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e) BTRAP(0x2f)
+ BTRAPS(0x30) BTRAPS(0x38)
+ BTRAPS(0x40) BTRAPS(0x48)
+ BTRAPS(0x50) BTRAPS(0x58)
+ BTRAPS(0x60) BTRAPS(0x68)
+ BTRAPS(0x70) BTRAPS(0x78)
+ BTRAPS(0x80) BTRAPS(0x88)
+ BTRAPS(0x90) BTRAPS(0x98)
+ BTRAPS(0xa0) BTRAPS(0xa8)
+ BTRAPS(0xb0) BTRAPS(0xb8)
+ BTRAPS(0xc0) BTRAPS(0xc8)
+ BTRAPS(0xd0) BTRAPS(0xd8)
+ BTRAPS(0xe0) BTRAPS(0xe8)
+ BTRAPS(0xf0) BTRAPS(0xf8)
+
+ .section ".text", "ax"
+ .align 4
+__divide_error:
+bug:
+ /* Dump the exception and its context */
+ ! Set up CPU state
+ rd %psr, %g2
+ andn %g2, PSR_ET, %g2
+ wr %g2, %psr
+ ! Disable mmu, re-enable boot mode
+ set _start, %g3
+ set dump_exception, %g2
+ sub %g2, %g3, %g3
+ set 3 << 13, %g2
+ jmp %g3
+ sta %g2, [%g0] ASI_M_MMUREGS
+
+outstr:
+ /* void outstr (unsigned long port5, unsigned long port10,
+ * const unsigned char *str);
+ * Writes a string on an IO port.
+ */
+1: lduba [%o2] ASI_M_KERNELTXT, %o3
+ cmp %o3, 0
+ be 2f
+ nop
+ stba %o3, [%o0] ASI_M_BYPASS
+ stba %o3, [%o1] ASI_M_CTL
+ b 1b
+ inc %o2
+2: retl
+ nop
+
+outhex:
+ /* void outhex (unsigned long port5, unsigned long port10,
+ * uint32_t value);
+ * Dumps a 32 bits hex number on serial port
+ */
+ mov %o2, %o4
+ set 28, %o3
+ srl %o4, %o3, %o2
+1: and %o2, 0xf, %o2
+ cmp %o2, 9
+ bgt 2f
+ nop
+ b 3f
+ add %o2, '0', %o2
+2: add %o2, 'a' - 10, %o2
+3: stba %o2, [%o0] ASI_M_BYPASS
+ stba %o2, [%o1] ASI_M_CTL
+ subcc %o3, 4, %o3
+ bge 1b
+ srl %o4, %o3, %o2
+ retl
+ nop
+
+ /* void dump_exception ();
+ *
+ * Dump a message when catching an exception
+ */
+dump_exception:
+ set SER_ADDR5 + 2, %o0
+ set SER_ADDR10 + 2, %o1
+ set (_BUG_message_0), %o2
+ call outstr
+ nop
+
+ call outhex
+ mov %g1, %o2
+
+ set (_BUG_message_1), %o2
+ call outstr
+ nop
+
+ call outhex
+ mov %l1, %o2
+
+ set (_BUG_message_2), %o2
+ call outstr
+ nop
+
+ call outhex
+ mov %l2, %o2
+
+ set (_BUG_message_3), %o2
+ call outstr
+ nop
+_forever:
+ /* Loop forever */
+ b _forever ;
+ nop
+
+irq_entry10:
+ sethi %hi(counter_regs), %l7
+ ld [%l7 + %lo(counter_regs)], %l7
+ sethi 0x10000, %l6
+ ld [%l7 + %l6], %g0
+ jmp %l1
+ rett %l2
+
+irq_entry14:
+ sethi %hi(counter_regs), %l7
+ ld [%l7 + %lo(counter_regs)], %l7
+ ld [%l7], %g0
+ sethi %hi(obp_ticks), %l7
+ ld [%l7 + %lo(obp_ticks)], %l7
+ ld [%l7], %l6
+ add %l6, 10, %l6
+ st %l6, [%l7]
+ jmp %l1
+ rett %l2
+
+/* Register window handlers */
+#include "wof.S"
+#include "wuf.S"
+
+/* Data fault handler */
+ .data
+ .align 4
+ .global ignore_dfault
+
+ignore_dfault:
+ .word 0
+
+ .text
+ .align 4
+
+handle_dfault:
+ /* If ignore_dfault is 0, fall through to normal exception handler */
+ sethi %hi(ignore_dfault), %l4
+ ld [%l4 + %lo(ignore_dfault)], %l4
+ tst %l4
+ bz,a bug
+ mov %l7, %g1
+
+ /* Otherwise skip the faulting instruction and return */
+ jmp %l2
+ rett %l2 + 4
+
+
+ .section .rodata
+_BUG_message_0:
+ .string "Unhandled Exception 0x"
+_BUG_message_1:
+ .string "\r\nPC = 0x"
+_BUG_message_2:
+ .string " NPC = 0x"
+_BUG_message_3:
+ .string "\r\nStopping execution\r\n"
diff --git a/roms/openbios/arch/sparc32/wof.S b/roms/openbios/arch/sparc32/wof.S
new file mode 100644
index 00000000..8d6bb731
--- /dev/null
+++ b/roms/openbios/arch/sparc32/wof.S
@@ -0,0 +1,133 @@
+/*
+ * Proll takes this from Sparclinux kernel, ruthlessly truncated
+ * because we have no user windows.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ */
+
+// #include <asm/winmacro.h>
+// #include <asm/asmmacro.h>
+
+/* Reg_window offsets */
+#define RW_L0 0x00
+#define RW_L1 0x04
+#define RW_L2 0x08
+#define RW_L3 0x0c
+#define RW_L4 0x10
+#define RW_L5 0x14
+#define RW_L6 0x18
+#define RW_L7 0x1c
+#define RW_I0 0x20
+#define RW_I1 0x24
+#define RW_I2 0x28
+#define RW_I3 0x2c
+#define RW_I4 0x30
+#define RW_I5 0x34
+#define RW_I6 0x38
+#define RW_I7 0x3c
+
+/* Store the register window onto the 8-byte aligned area starting
+ * at %reg. It might be %sp, it might not, we don't care.
+ */
+#define STORE_WINDOW(reg) \
+ std %l0, [%reg + RW_L0]; \
+ std %l2, [%reg + RW_L2]; \
+ std %l4, [%reg + RW_L4]; \
+ std %l6, [%reg + RW_L6]; \
+ std %i0, [%reg + RW_I0]; \
+ std %i2, [%reg + RW_I2]; \
+ std %i4, [%reg + RW_I4]; \
+ std %i6, [%reg + RW_I6];
+
+/* We define macro's for registers which have a fixed
+ * meaning throughout this entire routine. The 'T' in
+ * the comments mean that the register can only be
+ * accessed when in the 'trap' window, 'G' means
+ * accessible in any window. Do not change these registers
+ * after they have been set, until you are ready to return
+ * from the trap.
+ */
+#define t_psr l0 /* %psr at trap time T */
+#define t_pc l1 /* PC for trap return T */
+#define t_npc l2 /* NPC for trap return T */
+#define t_wim l3 /* %wim at trap time T */
+#define saved_g5 l5 /* Global save register T */
+#define saved_g6 l6 /* Global save register T */
+
+/* Now registers whose values can change within the handler. */
+#define twin_tmp l4 /* Temp reg, only usable in trap window T */
+#define glob_tmp g5 /* Global temporary reg, usable anywhere G */
+
+ .text
+ .align 4
+
+ /* BEGINNING OF PATCH INSTRUCTIONS */
+ /* On a 7-window Sparc the boot code patches spnwin_*
+ * instructions with the following ones.
+ */
+ .globl spnwin_patch1_7win, spnwin_patch2_7win, spnwin_patch3_7win
+spnwin_patch1_7win: sll %t_wim, 6, %glob_tmp
+spnwin_patch2_7win: and %glob_tmp, 0x7f, %glob_tmp
+spnwin_patch3_7win: and %twin_tmp, 0x7f, %twin_tmp
+ /* END OF PATCH INSTRUCTIONS */
+
+ /* The trap entry point has done the following:
+ *
+ * rd %psr, %l0
+ * rd %wim, %l3
+ * b spill_window_entry
+ * nop
+ */
+
+ .globl spill_window_entry
+ .globl spnwin_patch1, spnwin_patch2
+spill_window_entry:
+ /* LOCATION: Trap Window */
+
+ mov %g5, %saved_g5 ! save away global temp register
+ mov %g6, %saved_g6 ! save away 'current' ptr register
+
+ /* Compute what the new %wim will be if we save the
+ * window properly in this trap handler.
+ *
+ * newwim = ((%wim>>1) | (%wim<<(nwindows - 1)));
+ */
+ srl %t_wim, 0x1, %twin_tmp
+spnwin_patch1: sll %t_wim, 7, %glob_tmp
+ or %glob_tmp, %twin_tmp, %glob_tmp
+spnwin_patch2: and %glob_tmp, 0xff, %glob_tmp
+
+ /* Save into the window which must be saved and do it.
+ */
+ save %g0, %g0, %g0 ! save into the window to stash away
+ wr %glob_tmp, 0x0, %wim ! set new %wim, this is safe now
+
+ /* LOCATION: Window to be saved */
+
+ STORE_WINDOW(sp) ! stash the window
+ restore %g0, %g0, %g0 ! go back into trap window
+
+ /* LOCATION: Trap window */
+ mov %saved_g5, %g5 ! restore %glob_tmp
+ mov %saved_g6, %g6 ! restore %curptr
+ wr %t_psr, 0x0, %psr ! restore condition codes in %psr
+ nop; nop; nop ! waste some time
+ jmp %t_pc ! Return from trap
+ rett %t_npc ! we are done
diff --git a/roms/openbios/arch/sparc32/wuf.S b/roms/openbios/arch/sparc32/wuf.S
new file mode 100644
index 00000000..853fc732
--- /dev/null
+++ b/roms/openbios/arch/sparc32/wuf.S
@@ -0,0 +1,154 @@
+/*
+ * Window fill (underflow) trap, based on code from Sparclinux.
+ *
+ * Copyright (C) 1995 David S. Miller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+// #include <psr.h>
+// #include <asi.h>
+
+/* Reg_window offsets */
+#define RW_L0 0x00
+#define RW_L1 0x04
+#define RW_L2 0x08
+#define RW_L3 0x0c
+#define RW_L4 0x10
+#define RW_L5 0x14
+#define RW_L6 0x18
+#define RW_L7 0x1c
+#define RW_I0 0x20
+#define RW_I1 0x24
+#define RW_I2 0x28
+#define RW_I3 0x2c
+#define RW_I4 0x30
+#define RW_I5 0x34
+#define RW_I6 0x38
+#define RW_I7 0x3c
+
+/* Load a register window from the area beginning at %reg. */
+#define LOAD_WINDOW(reg) \
+ ldd [%reg + RW_L0], %l0; \
+ ldd [%reg + RW_L2], %l2; \
+ ldd [%reg + RW_L4], %l4; \
+ ldd [%reg + RW_L6], %l6; \
+ ldd [%reg + RW_I0], %i0; \
+ ldd [%reg + RW_I2], %i2; \
+ ldd [%reg + RW_I4], %i4; \
+ ldd [%reg + RW_I6], %i6;
+
+#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
+
+/* Just like the overflow handler we define macros for registers
+ * with fixed meanings in this routine.
+ */
+#define t_psr l0
+#define t_pc l1
+#define t_npc l2
+#define t_wim l3
+/* Don't touch the above registers or else you die horribly... */
+
+/* Now macros for the available scratch registers in this routine. */
+#define twin_tmp1 l4
+#define twin_tmp2 l5
+
+ .text
+ .align 4
+
+ /* The trap entry point has executed the following:
+ *
+ * rd %psr, %l0
+ * rd %wim, %l3
+ * b fill_window_entry
+ * andcc %l0, PSR_PS, %g0
+ */
+
+ /* To get an idea of what has just happened to cause this
+ * trap take a look at this diagram:
+ *
+ * 1 2 3 4 <-- Window number
+ * ----------
+ * T O W I <-- Symbolic name
+ *
+ * O == the window that execution was in when
+ * the restore was attempted
+ *
+ * T == the trap itself has save'd us into this
+ * window
+ *
+ * W == this window is the one which is now invalid
+ * and must be made valid plus loaded from the
+ * stack
+ *
+ * I == this window will be the invalid one when we
+ * are done and return from trap if successful
+ */
+
+ /* BEGINNING OF PATCH INSTRUCTIONS */
+
+ /* On 7-window Sparc the boot code patches fnwin_patch1
+ * with the following instruction.
+ */
+ .globl fnwin_patch1_7win, fnwin_patch2_7win
+fnwin_patch1_7win: srl %t_wim, 6, %twin_tmp2
+fnwin_patch2_7win: and %twin_tmp1, 0x7f, %twin_tmp1
+ /* END OF PATCH INSTRUCTIONS */
+
+
+ .globl fill_window_entry, fnwin_patch1, fnwin_patch2
+fill_window_entry:
+ /* LOCATION: Window 'T' */
+
+ /* Compute what the new %wim is going to be if we retrieve
+ * the proper window off of the stack.
+ */
+ sll %t_wim, 1, %twin_tmp1
+fnwin_patch1: srl %t_wim, 7, %twin_tmp2
+ or %twin_tmp1, %twin_tmp2, %twin_tmp1
+fnwin_patch2: and %twin_tmp1, 0xff, %twin_tmp1
+
+ wr %twin_tmp1, 0x0, %wim /* Make window 'I' invalid */
+
+ restore %g0, %g0, %g0 /* Restore to window 'O' */
+
+ /* Trapped from kernel, we trust that the kernel does not
+ * 'over restore' sorta speak and just grab the window
+ * from the stack and return. Easy enough.
+ */
+ /* LOCATION: Window 'O' */
+
+ restore %g0, %g0, %g0
+ WRITE_PAUSE
+
+ /* LOCATION: Window 'W' */
+
+ LOAD_WINDOW(sp) /* Load it up */
+
+ /* Spin the wheel... */
+ save %g0, %g0, %g0
+ save %g0, %g0, %g0
+ /* I'd like to buy a vowel please... */
+
+ /* LOCATION: Window 'T' */
+
+ /* Now preserve the condition codes in %psr, pause, and
+ * return from trap. This is the simplest case of all.
+ */
+ wr %t_psr, 0x0, %psr
+ WRITE_PAUSE
+
+ jmp %t_pc
+ rett %t_npc
diff --git a/roms/openbios/arch/sparc64/boot.c b/roms/openbios/arch/sparc64/boot.c
new file mode 100644
index 00000000..5107be6c
--- /dev/null
+++ b/roms/openbios/arch/sparc64/boot.c
@@ -0,0 +1,130 @@
+/*
+ *
+ */
+#undef BOOTSTRAP
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+
+uint64_t kernel_image;
+uint64_t kernel_size;
+uint64_t qemu_cmdline;
+uint64_t cmdline_size;
+char boot_device;
+
+extern int sparc64_of_client_interface( int *params );
+
+
+void go(void)
+{
+ ucell address, type, size;
+ int image_retval = 0;
+
+ /* Get the entry point and the type (see forth/debugging/client.fs) */
+ feval("saved-program-state >sps.entry @");
+ address = POP();
+ feval("saved-program-state >sps.file-type @");
+ type = POP();
+ feval("saved-program-state >sps.file-size @");
+ size = POP();
+
+ printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type);
+
+ switch (type) {
+ case 0x0:
+ /* Start ELF boot image */
+ image_retval = start_elf(address, (uint64_t)&elf_boot_notes);
+ break;
+
+ case 0x1:
+ /* Start ELF image */
+ image_retval = start_client_image(address, (uint64_t)&sparc64_of_client_interface);
+ break;
+
+ case 0x5:
+ /* Start a.out image */
+ image_retval = start_client_image(address, (uint64_t)&sparc64_of_client_interface);
+ break;
+
+ case 0x10:
+ /* Start Fcode image */
+ printk("Evaluating FCode...\n");
+ PUSH(address);
+ PUSH(1);
+ fword("byte-load");
+ image_retval = 0;
+ break;
+
+ case 0x11:
+ /* Start Forth image */
+ PUSH(address);
+ PUSH(size);
+ fword("eval2");
+ image_retval = 0;
+ break;
+ }
+
+ printk("Image returned with return value %#x\n", image_retval);
+}
+
+/* ( path len -- path len ) */
+
+void boot(void)
+{
+ char *path, *param;
+
+ /* Copy the incoming path */
+ fword("2dup");
+ path = pop_fstr_copy();
+
+ /* Boot preloaded kernel */
+ if (kernel_size) {
+ void (*entry)(unsigned long p1, unsigned long p2, unsigned long p3,
+ unsigned long p4, unsigned long p5);
+
+ printk("[sparc64] Kernel already loaded\n");
+ entry = (void *) (unsigned long)kernel_image;
+ entry(0, 0, 0, 0, (unsigned long)&sparc64_of_client_interface);
+ }
+
+ /* Invoke Linux directly -- probably not supported */
+ if(!path) {
+ /* No path specified, so grab defaults from /chosen */
+ push_str("bootpath");
+ push_str("/chosen");
+ fword("(find-dev)");
+ POP();
+ fword("get-package-property");
+ POP();
+ /* Update our local copy of path as well as the one on the stack */
+ fword("2dup");
+ path = pop_fstr_copy();
+ }
+
+ if (path) {
+ param = strchr(path, ' ');
+ if(param) {
+ *param = '\0';
+ param++;
+ } else if (cmdline_size) {
+ param = (char *)qemu_cmdline;
+ } else {
+ push_str("boot-args");
+ push_str("/options");
+ fword("(find-dev)");
+ POP();
+ fword("get-package-property");
+ POP();
+ param = pop_fstr_copy();
+ }
+
+ /* Invoke platform-specific Linux loader */
+ linux_load(&sys_info, path, param);
+
+ free(path);
+ }
+}
diff --git a/roms/openbios/arch/sparc64/boot.h b/roms/openbios/arch/sparc64/boot.h
new file mode 100644
index 00000000..3ab05e0a
--- /dev/null
+++ b/roms/openbios/arch/sparc64/boot.h
@@ -0,0 +1,35 @@
+/* tag: openbios loader prototypes for sparc64
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+// linux_load.c
+int linux_load(struct sys_info *info, const char *file, const char *cmdline);
+
+// context.c
+extern struct context * volatile __context;
+uint64_t start_elf(uint64_t entry_point, uint64_t param);
+uint64_t start_client_image(uint64_t entry_point, uint64_t cif_handler);
+
+// boot.c
+extern uint64_t kernel_image;
+extern uint64_t kernel_size;
+extern uint64_t qemu_cmdline;
+extern uint64_t cmdline_size;
+extern char boot_device;
+extern void boot(void);
+extern void go(void);
+
+// sys_info.c
+extern uint64_t qemu_mem_size;
+extern void collect_sys_info(struct sys_info *info);
+
+// console.c
+void ob_su_init(uint64_t base, uint64_t offset, int intr);
+void cls(void);
+
+// lib.c
+void ob_mmu_init(const char *cpuname, uint64_t ram_size);
diff --git a/roms/openbios/arch/sparc64/build.xml b/roms/openbios/arch/sparc64/build.xml
new file mode 100644
index 00000000..3a1cd346
--- /dev/null
+++ b/roms/openbios/arch/sparc64/build.xml
@@ -0,0 +1,72 @@
+<build condition="SPARC64">
+
+ <dictionary name="openbios-sparc64" init="openbios">
+ <object source="tree.fs" target="forth"/>
+ <object source="init.fs" target="forth"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <library name="sparc64" type="static" target="target">
+ <object source="openbios.c"/>
+ <object source="console.c"/>
+ <object source="lib.c"/>
+ <object source="boot.c"/>
+ <object source="context.c"/>
+ <object source="switch.S"/>
+ <object source="linux_load.c"/>
+ <object source="sys_info.c"/>
+ <object source="ofmem_sparc64.c"/>
+ <object source="entry.S"/>
+ <object source="vectors.S"/>
+ <object source="call-client.S"/>
+ </library>
+
+ <executable name="openbios-plain.elf" target="target" condition="IMAGE_ELF">
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -T $(SRCDIR)/arch/sparc64/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-plain.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="plainboot.c"/>
+ <external-object source="libsparc64.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+ <!-- HACK ALERT -->
+
+ <executable name="target/include/static-dict.h" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <rule><![CDATA[
+ $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule>
+ <external-object source="openbios-sparc64.dict"/>
+ </executable>
+
+ <executable name="target/arch/sparc64/builtin.o" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <rule><![CDATA[ $(SRCDIR)/arch/sparc64/builtin.c $(ODIR)/target/include/static-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/sparc64/builtin.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+ <!-- END OF HACK ALERT -->
+
+ <executable name="openbios-builtin.elf" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <!-- We use -N to reduce the file size by 1M -->
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/sparc64/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-builtin.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <external-object source="target/arch/sparc64/builtin.o"/>
+ <external-object source="libsparc64.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+</build>
diff --git a/roms/openbios/arch/sparc64/builtin.c b/roms/openbios/arch/sparc64/builtin.c
new file mode 100644
index 00000000..864da797
--- /dev/null
+++ b/roms/openbios/arch/sparc64/builtin.c
@@ -0,0 +1,33 @@
+/* tag: openbios forth starter for builtin dictionary for sparc64
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "asm/types.h"
+#include "libopenbios/sys_info.h"
+
+/*
+ * wrap an array around the hex'ed dictionary file
+ */
+
+/* 512K for the dictionary */
+#define DICTIONARY_SIZE (512 * 1024 / sizeof(ucell))
+#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary))
+
+static ucell forth_dictionary[DICTIONARY_SIZE] = {
+#include "static-dict.h"
+};
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ info->dict_start=(unsigned long *)forth_dictionary;
+ info->dict_end = (unsigned long *)FORTH_DICTIONARY_END;
+ info->dict_last = (ucell *)((unsigned char *)forth_dictionary +
+ FORTH_DICTIONARY_LAST);
+ info->dict_limit = sizeof(forth_dictionary);
+}
diff --git a/roms/openbios/arch/sparc64/call-client.S b/roms/openbios/arch/sparc64/call-client.S
new file mode 100644
index 00000000..f365e3cb
--- /dev/null
+++ b/roms/openbios/arch/sparc64/call-client.S
@@ -0,0 +1,236 @@
+ .globl sparc64_of_client_interface, client_tba
+
+
+/*
+ * SAVE_WINDOW_STATE and RESTORE_WINDOW_STATE are used to ensure
+ * that the CPU window state is preserved across CIF calls. This is
+ * to workaround a *BSD restriction that window fill/spill traps must
+ * be minimised during trap table takeover, and likely emulates the
+ * behaviour of OBP.
+ */
+
+#define SAVE_WINDOW_STATE(type) \
+ setx client_window, %g6, %g1; \
+ rdpr %cwp, %g7; \
+ stx %g7, [%g1]; \
+ rdpr %cansave, %g7; \
+ stx %g7, [%g1 + 0x8]; \
+ rdpr %canrestore, %g7; \
+ stx %g7, [%g1 + 0x10]; \
+ rdpr %otherwin, %g7; \
+ stx %g7, [%g1 + 0x18]; \
+ rdpr %wstate, %g7; \
+ stx %g7, [%g1 + 0x20]; \
+ rdpr %cleanwin, %g7; \
+ stx %g7, [%g1 + 0x28]; \
+ \
+ stx %o0, [%g1 + 0x30]; \
+ stx %o1, [%g1 + 0x38]; \
+ stx %o2, [%g1 + 0x40]; \
+ stx %o3, [%g1 + 0x48]; \
+ stx %o4, [%g1 + 0x50]; \
+ stx %o5, [%g1 + 0x58]; \
+ stx %o6, [%g1 + 0x60]; \
+ stx %o7, [%g1 + 0x68]; \
+ \
+ rdpr %pstate, %g7; \
+ stx %g7, [%g1 + 0x70]; \
+ rd %y, %g7; \
+ stx %g7, [%g1 + 0x78]; \
+ rd %fprs, %g7; \
+ stx %g7, [%g1 + 0x80]; \
+ \
+ /* Now iterate through all of the windows saving all l and i registers */ \
+ add %g1, 0x90, %g5; \
+ \
+ /* Get the number of windows in %g6 */ \
+ rdpr %ver, %g6; \
+ and %g6, 0xf, %g6; \
+ inc %g6; \
+ \
+save_cpu_window_##type: \
+ deccc %g6; \
+ wrpr %g6, %cwp; \
+ stx %l0, [%g5]; \
+ stx %l1, [%g5 + 0x8]; \
+ stx %l2, [%g5 + 0x10]; \
+ stx %l3, [%g5 + 0x18]; \
+ stx %l4, [%g5 + 0x20]; \
+ stx %l5, [%g5 + 0x28]; \
+ stx %l6, [%g5 + 0x30]; \
+ stx %l7, [%g5 + 0x38]; \
+ stx %i0, [%g5 + 0x40]; \
+ stx %i1, [%g5 + 0x48]; \
+ stx %i2, [%g5 + 0x50]; \
+ stx %i3, [%g5 + 0x58]; \
+ stx %i4, [%g5 + 0x60]; \
+ stx %i5, [%g5 + 0x68]; \
+ stx %i6, [%g5 + 0x70]; \
+ stx %i7, [%g5 + 0x78]; \
+ bne save_cpu_window_##type; \
+ add %g5, 0x80, %g5; \
+ \
+ /* For 8 windows with 16 registers to save in the window, memory required \
+ is 16*8*8 = 0x400 bytes */ \
+ \
+ /* Now we should be in window 0 so update the other window registers */ \
+ rdpr %ver, %g6; \
+ and %g6, 0xf, %g6; \
+ dec %g6; \
+ wrpr %g6, %cansave; \
+ \
+ wrpr %g0, %cleanwin; \
+ wrpr %g0, %canrestore; \
+ wrpr %g0, %otherwin;
+
+
+#define RESTORE_WINDOW_STATE(type) \
+ setx client_window, %g6, %g1; \
+ \
+ /* Get the number of windows in %g6 */ \
+ rdpr %ver, %g6; \
+ and %g6, 0xf, %g6; \
+ inc %g6; \
+ \
+ /* Now iterate through all of the windows restoring all l and i registers */ \
+ add %g1, 0x90, %g5; \
+ \
+restore_cpu_window_##type: \
+ deccc %g6; \
+ wrpr %g6, %cwp; \
+ ldx [%g5], %l0; \
+ ldx [%g5 + 0x8], %l1; \
+ ldx [%g5 + 0x10], %l2; \
+ ldx [%g5 + 0x18], %l3; \
+ ldx [%g5 + 0x20], %l4; \
+ ldx [%g5 + 0x28], %l5; \
+ ldx [%g5 + 0x30], %l6; \
+ ldx [%g5 + 0x38], %l7; \
+ ldx [%g5 + 0x40], %i0; \
+ ldx [%g5 + 0x48], %i1; \
+ ldx [%g5 + 0x50], %i2; \
+ ldx [%g5 + 0x58], %i3; \
+ ldx [%g5 + 0x60], %i4; \
+ ldx [%g5 + 0x68], %i5; \
+ ldx [%g5 + 0x70], %i6; \
+ ldx [%g5 + 0x78], %i7; \
+ bne restore_cpu_window_##type; \
+ add %g5, 0x80, %g5; \
+ \
+ /* Restore the window registers to their original value */ \
+ ldx [%g1], %g7; \
+ wrpr %g7, %cwp; \
+ ldx [%g1 + 0x8], %g7; \
+ wrpr %g7, %cansave; \
+ ldx [%g1 + 0x10], %g7; \
+ wrpr %g7, %canrestore; \
+ ldx [%g1 + 0x18], %g7; \
+ wrpr %g7, %otherwin; \
+ ldx [%g1 + 0x20], %g7; \
+ wrpr %g7, %wstate; \
+ ldx [%g1 + 0x28], %g7; \
+ wrpr %g7, %cleanwin; \
+ \
+ ldx [%g1 + 0x30], %o0; \
+ ldx [%g1 + 0x38], %o1; \
+ ldx [%g1 + 0x40], %o2; \
+ ldx [%g1 + 0x48], %o3; \
+ ldx [%g1 + 0x50], %o4; \
+ ldx [%g1 + 0x58], %o5; \
+ ldx [%g1 + 0x60], %o6; \
+ ldx [%g1 + 0x68], %o7; \
+ \
+ ldx [%g1 + 0x70], %g7; \
+ wrpr %g7, %pstate; \
+ ldx [%g1 + 0x78], %g7; \
+ wr %g7, 0, %y; \
+ ldx [%g1 + 0x80], %g7; \
+ wr %g7, 0, %fprs
+
+
+ .data
+ .align 8
+
+ .skip 16384
+openbios_stack:
+
+client_stack:
+ .xword 0
+client_tba:
+ .xword 0
+client_window:
+ .skip 2048
+
+
+ .text
+ .align 4
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .register %g6, #scratch
+ .register %g7, #scratch
+/*
+ make some more space on stack since linux kernel only provides 128 bytes
+ without memory to spill registers (used by gcc in -O0 mode)
+*/
+
+sparc64_of_client_interface:
+
+ /* Save globals on callers stack */
+ add %sp, -56, %sp
+
+ stx %g1, [%sp + 2047 + 0]
+ stx %g2, [%sp + 2047 + 8]
+ stx %g3, [%sp + 2047 + 16]
+ stx %g4, [%sp + 2047 + 24]
+ stx %g5, [%sp + 2047 + 32]
+ stx %g6, [%sp + 2047 + 40]
+ stx %g7, [%sp + 2047 + 48]
+
+ /* Save client trap table */
+ setx client_tba, %g6, %g7
+ rdpr %tba, %g6
+ stx %g6, [%g7]
+
+ /* Save existing stack */
+ setx client_stack, %g6, %g7
+ stx %sp, [%g7]
+
+ /* Save windows */
+ SAVE_WINDOW_STATE(cif)
+
+ /* Move to OpenBIOS stack */
+ setx openbios_stack - 2047 - 192, %g6, %g7
+ mov %g7, %sp
+
+ /* Call client inteface */
+ call of_client_interface
+ ldx [%g1 + 0x30], %o0
+
+ setx client_window, %g6, %g1
+ stx %o0, [%g1 + 0x30]
+
+ /* Restore windows */
+ RESTORE_WINDOW_STATE(cif)
+
+ /* Restore stack */
+ setx client_stack, %g6, %g7
+ ldx [%g7], %sp
+
+ /* Restore client trap table */
+ setx client_tba, %g6, %g7
+ ldx [%g7], %g6
+ wrpr %g6, %tba
+
+ /* Restore globals */
+ ldx [%sp + 2047 + 0], %g1
+ ldx [%sp + 2047 + 8], %g2
+ ldx [%sp + 2047 + 16], %g3
+ ldx [%sp + 2047 + 24], %g4
+ ldx [%sp + 2047 + 32], %g5
+ ldx [%sp + 2047 + 40], %g6
+ ldx [%sp + 2047 + 48], %g7
+
+ add %sp, 56, %sp
+
+ jmp %o7+8
+ nop
diff --git a/roms/openbios/arch/sparc64/console.c b/roms/openbios/arch/sparc64/console.c
new file mode 100644
index 00000000..6ab5cba4
--- /dev/null
+++ b/roms/openbios/arch/sparc64/console.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "kernel/kernel.h"
+#include "drivers/drivers.h"
+#include "libopenbios/fontdata.h"
+#include "openbios.h"
+#include "libc/vsprintf.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+
+/* ******************************************************************
+ * simple polling video/keyboard console functions
+ * ****************************************************************** */
+
+#ifdef CONFIG_DEBUG_CONSOLE
+/* ******************************************************************
+ * common functions, implementing simple concurrent console
+ * ****************************************************************** */
+
+static int arch_putchar(int c)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ uart_putchar(c);
+#endif
+ return c;
+}
+
+static int arch_availchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return 1;
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ if (pc_kbd_dataready())
+ return 1;
+#endif
+ return 0;
+}
+
+static int arch_getchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return (uart_getchar(CONFIG_SERIAL_PORT));
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ if (pc_kbd_dataready())
+ return (pc_kbd_readdata());
+#endif
+ return 0;
+}
+
+struct _console_ops arch_console_ops = {
+ .putchar = arch_putchar,
+ .availchar = arch_availchar,
+ .getchar = arch_getchar
+};
+
+#endif // CONFIG_DEBUG_CONSOLE
diff --git a/roms/openbios/arch/sparc64/const.h b/roms/openbios/arch/sparc64/const.h
new file mode 100644
index 00000000..8ad902b2
--- /dev/null
+++ b/roms/openbios/arch/sparc64/const.h
@@ -0,0 +1,19 @@
+/* const.h: Macros for dealing with constants. */
+
+#ifndef _SPARC64_CONST_H
+#define _SPARC64_CONST_H
+
+/* Some constant macros are used in both assembler and
+ * C code. Therefore we cannot annotate them always with
+ * 'UL' and other type specificers unilaterally. We
+ * use the following macros to deal with this.
+ */
+
+#ifdef __ASSEMBLY__
+#define _AC(X,Y) X
+#else
+#define _AC(X,Y) (X##Y)
+#endif
+
+
+#endif /* !(_SPARC64_CONST_H) */
diff --git a/roms/openbios/arch/sparc64/context.c b/roms/openbios/arch/sparc64/context.c
new file mode 100644
index 00000000..2e766895
--- /dev/null
+++ b/roms/openbios/arch/sparc64/context.c
@@ -0,0 +1,129 @@
+/*
+ * context switching
+ * 2003-10 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "context.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+#include "openbios.h"
+
+#define MAIN_STACK_SIZE 16384
+#define IMAGE_STACK_SIZE 4096*4
+
+#define debug printk
+
+static void start_main(void); /* forward decl. */
+void __exit_context(void); /* assembly routine */
+
+/*
+ * Main context structure
+ * It is placed at the bottom of our stack, and loaded by assembly routine
+ * to start us up.
+ */
+static struct context main_ctx = {
+ .regs[REG_SP] = (uint64_t) &_estack - STACK_BIAS - 96,
+ .pc = (uint64_t) start_main,
+ .npc = (uint64_t) start_main + 4,
+ .return_addr = (uint64_t) __exit_context,
+};
+
+/* This is used by assembly routine to load/store the context which
+ * it is to switch/switched. */
+struct context * volatile __context = &main_ctx;
+
+/* Stack for loaded ELF image */
+static uint8_t image_stack[IMAGE_STACK_SIZE];
+
+/* Pointer to startup context (physical address) */
+unsigned long __boot_ctx;
+
+/*
+ * Main starter
+ * This is the C function that runs first.
+ */
+static void start_main(void)
+{
+ /* Save startup context, so we can refer to it later.
+ * We have to keep it in physical address since we will relocate. */
+ __boot_ctx = virt_to_phys(__context);
+
+ /* Start the real fun */
+ openbios();
+
+ /* Returning from here should jump to __exit_context */
+ __context = boot_ctx;
+}
+
+static uint64_t ALIGN_SIZE(uint64_t x, uint64_t a)
+{
+ return (x + a - 1) & ~(a-1);
+}
+
+/* Setup a new context using the given stack.
+ */
+struct context *
+init_context(uint8_t *stack, uint64_t stack_size, int num_params)
+{
+ struct context *ctx;
+ uint8_t *stack_top = stack + stack_size;
+
+ ctx = (struct context *)
+ (stack_top - ALIGN_SIZE(sizeof(*ctx) + num_params*sizeof(uint64_t), sizeof(uint64_t)));
+ memset(ctx, 0, sizeof(*ctx));
+
+ /* Fill in reasonable default for flat memory model */
+ ctx->regs[REG_SP] = virt_to_phys(stack_top - STACK_BIAS - 192);
+ ctx->return_addr = virt_to_phys(__exit_context);
+
+ return ctx;
+}
+
+/* Switch to another context. */
+struct context *switch_to(struct context *ctx)
+{
+ struct context *save, *ret;
+
+ debug("switching to new context: entry point %#llx stack 0x%016llx\n", ctx->pc, ctx->regs[REG_SP]);
+ save = __context;
+ __context = ctx;
+ //asm ("pushl %cs; call __switch_context");
+ asm ("call __switch_context_nosave; nop");
+ ret = __context;
+ __context = save;
+ return ret;
+}
+
+/* Start ELF Boot image */
+uint64_t start_elf(uint64_t entry_point, uint64_t param)
+{
+ struct context *ctx;
+
+ ctx = init_context(image_stack, sizeof image_stack, 1);
+ ctx->pc = entry_point;
+ ctx->param[0] = param;
+ //ctx->eax = 0xe1fb007;
+ //ctx->ebx = param;
+
+ ctx = switch_to(ctx);
+ //return ctx->eax;
+ return 0;
+}
+
+/* Start client image */
+uint64_t start_client_image(uint64_t entry_point, uint64_t cif_handler)
+{
+ struct context *ctx;
+
+ ctx = init_context(image_stack, sizeof image_stack, 0);
+ ctx->pc = entry_point;
+ ctx->npc = entry_point+4;
+ ctx->regs[REG_O0] = 0;
+ ctx->regs[REG_O0+4] = cif_handler;
+
+ ctx = switch_to(ctx);
+
+ return 0;
+}
diff --git a/roms/openbios/arch/sparc64/context.h b/roms/openbios/arch/sparc64/context.h
new file mode 100644
index 00000000..2756fa15
--- /dev/null
+++ b/roms/openbios/arch/sparc64/context.h
@@ -0,0 +1,33 @@
+#ifndef SPARC64_CONTEXT_H
+#define SPARC64_CONTEXT_H
+
+#define STACK_BIAS 2047
+
+struct context {
+ /* General registers */
+ uint64_t regs[32];
+ uint64_t pc;
+ uint64_t npc;
+#define REG_O0 8
+#define REG_SP 14
+#define SP_LOC(ctx) (&(ctx)->regs[REG_SP])
+ /* Flags */
+ /* Optional stack contents */
+ uint64_t return_addr;
+ uint64_t param[0];
+};
+
+/* Create a new context in the given stack */
+struct context *
+init_context(uint8_t *stack, uint64_t stack_size, int num_param);
+
+/* Switch context */
+struct context *switch_to(struct context *);
+
+/* Holds physical address of boot context */
+extern unsigned long __boot_ctx;
+
+/* This can always be safely used to refer to the boot context */
+#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx))
+
+#endif /* SPARC64_CONTEXT_H */
diff --git a/roms/openbios/arch/sparc64/entry.S b/roms/openbios/arch/sparc64/entry.S
new file mode 100644
index 00000000..d03128af
--- /dev/null
+++ b/roms/openbios/arch/sparc64/entry.S
@@ -0,0 +1,287 @@
+/**
+ ** Standalone startup code for Linux PROM emulator.
+ ** Copyright 1999 Pete A. Zaitcev
+ ** This code is licensed under GNU General Public License.
+ **/
+/*
+ * $Id: head.S,v 1.12 2002/07/23 05:47:09 zaitcev Exp $
+ */
+
+#define __ASSEMBLY__
+#include <asm/asi.h>
+#include "pstate.h"
+#include "lsu.h"
+#define NO_QEMU_PROTOS
+#define NO_OPENBIOS_PROTOS
+#include "arch/common/fw_cfg.h"
+
+#define PROM_ADDR 0x1fff0000000
+#define CFG_ADDR 0x1fe02000510
+#define HZ 1 * 1000 * 1000
+#define TICK_INT_DIS 0x8000000000000000
+
+ .globl entry, _entry
+
+ .section ".text", "ax"
+ .align 8
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .register %g6, #scratch
+ .register %g7, #scratch
+
+/*
+ * Entry point
+ * We start execution from here.
+ */
+_entry:
+entry:
+ ! Set up CPU state
+ wrpr %g0, PSTATE_PRIV, %pstate
+ wr %g0, 0, %fprs
+ wrpr %g0, 0x0, %tl
+
+ ! Extract NWINDOWS from %ver
+ rdpr %ver, %g1
+ and %g1, 0xf, %g1
+ dec %g1
+ wrpr %g1, 0, %cleanwin
+ wrpr %g1, 0, %cansave
+ wrpr %g0, 0, %canrestore
+ wrpr %g0, 0, %otherwin
+ wrpr %g0, 0, %wstate
+ ! disable timer now
+ setx TICK_INT_DIS, %g2, %g1
+ wr %g1, 0, %tick_cmpr
+
+ ! Disable I/D MMUs and caches
+ stxa %g0, [%g0] ASI_LSU_CONTROL
+
+ ! Check signature "QEMU"
+ setx CFG_ADDR, %g2, %g5
+ mov FW_CFG_SIGNATURE, %g2
+ stha %g2, [%g5] ASI_PHYS_BYPASS_EC_E_L
+ inc %g5
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2
+ cmp %g2, 'Q'
+ bne bad_conf
+ nop
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2
+ cmp %g2, 'E'
+ bne bad_conf
+ nop
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2
+ cmp %g2, 'M'
+ bne bad_conf
+ nop
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2
+ cmp %g2, 'U'
+ bne bad_conf
+ nop
+
+ ! Clear ITLB
+ mov 6 << 3, %g1
+ stxa %g0, [%g1] ASI_IMMU
+ stxa %g0, [%g1] ASI_DMMU
+ mov 63 << 3, %g1
+1: stxa %g0, [%g1] ASI_ITLB_DATA_ACCESS
+ subcc %g1, 1 << 3, %g1
+ bpos 1b
+ nop
+
+ ! Clear DTLB
+ mov 63 << 3, %g1
+1: stxa %g0, [%g1] ASI_DTLB_DATA_ACCESS
+ subcc %g1, 1 << 3, %g1
+ bpos 1b
+ nop
+
+ ! Get memory size from configuration device
+ ! NB: little endian format
+ mov FW_CFG_RAM_SIZE, %g2
+ dec %g5
+ stha %g2, [%g5] ASI_PHYS_BYPASS_EC_E_L
+ inc %g5
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g4
+
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+ sllx %g3, 8, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+ sllx %g3, 16, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+ sllx %g3, 24, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+ sllx %g3, 32, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+ sllx %g3, 40, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+ sllx %g3, 48, %g3
+ or %g3, %g4, %g4
+
+ lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3
+ sllx %g3, 56, %g3
+ or %g3, %g4, %g1
+ ! %g1 contains end of memory
+
+ setx _end, %g7, %g3
+ set 0x7ffff, %g2
+ add %g3, %g2, %g3
+ andn %g3, %g2, %g3
+ setx _data, %g7, %g2
+ sub %g3, %g2, %g2
+ sub %g1, %g2, %g2 ! %g2 = start of private memory
+ mov %g2, %l0
+
+ ! setup .data & .bss
+ setx _data, %g7, %g4
+ sub %g3, %g4, %g5
+ srlx %g5, 19, %g6 ! %g6 = # of 512k .bss pages
+ set 0xc0000000, %g3
+ sllx %g3, 32, %g3
+ or %g3, 0x76, %g3
+ ! valid, 512k, locked, cacheable(I/E/C), priv, writable
+ set 48, %g7
+1: stxa %g4, [%g7] ASI_DMMU ! vaddr = _data + N * 0x80000, ctx=0
+ or %g2, %g3, %g5
+ ! paddr = start_mem + N * 0x80000
+ stxa %g5, [%g0] ASI_DTLB_DATA_IN
+ set 0x80000, %g5
+ add %g2, %g5, %g2
+ add %g4, %g5, %g4
+ deccc %g6
+ bne 1b
+ nop
+
+ ! setup .rodata, also make .text readable
+ setx _data, %g7, %g5
+ setx _start, %g7, %g4
+ sub %g5, %g4, %g5
+ srlx %g5, 19, %g6 ! %g6 = # of 512k .rodata pages
+ set 48, %g7
+ set 0x80000, %g5
+ setx PROM_ADDR, %l1, %l2
+1: stxa %g4, [%g7] ASI_DMMU ! vaddr = _rodata, ctx=0
+ set 0xc0000000, %g3
+ sllx %g3, 32, %g3
+ or %g3, 0x74, %g3
+ or %l2, %g3, %g3
+ ! valid, 512k, locked, cacheable(I/E/C), priv
+ ! paddr = _rodata + N * 0x10000
+ stxa %g3, [%g0] ASI_DTLB_DATA_IN
+ add %g4, %g5, %g4
+ deccc %g6
+ bne 1b
+ add %l2, %g5, %l2
+
+ membar #Sync
+
+ setx _start, %g7, %g4
+ setx _rodata, %g7, %g5
+ sub %g5, %g4, %g5
+ set 0x7ffff, %g7
+ add %g5, %g7, %g5 ! round to 512k
+ srlx %g5, 19, %g6 ! %g6 = # of 512k .text pages
+ set 0x80000, %g5
+ set 48, %g7
+ setx PROM_ADDR, %l1, %l2
+1: stxa %g4, [%g7] ASI_IMMU ! vaddr = _start, ctx=0
+ set 0xc0000000, %g3
+ sllx %g3, 32, %g3
+ or %g3, 0x74, %g3
+ or %l2, %g3, %g3
+ ! valid, 512k, locked, cacheable(I/E/C), priv
+ ! paddr = _start + N * 0x80000
+ stxa %g3, [%g0] ASI_ITLB_DATA_IN
+ add %g4, %g5, %g4
+ deccc %g6
+ bne 1b
+ add %l2, %g5, %l2
+
+ flush %g4
+
+ mov %g1, %g3
+
+ set 8, %g2
+ sta %g0, [%g2] ASI_DMMU ! set primary ctx=0
+
+ ! Enable I/D MMUs and caches
+ setx lowmem, %g2, %g1
+ set LSU_CONTROL_DM|LSU_CONTROL_IM|LSU_CONTROL_DC|LSU_CONTROL_IC, %g2
+ jmp %g1
+ stxa %g2, [%g0] ASI_LSU_CONTROL
+
+lowmem:
+ /* Copy the DATA section from ROM. */
+ setx _data - 8, %o7, %o0 ! First address of DATA
+ setx _bss, %o7, %o1 ! Last address of DATA
+ setx _start, %o7, %o2
+ sub %o0, %o2, %o2 ! _data - _start
+ setx PROM_ADDR, %o7, %o3
+ add %o3, %o2, %o2 ! PROM_ADDR + (_data - _start)
+ ba 2f
+ nop
+1:
+ ldxa [%o2] ASI_PHYS_BYPASS_EC_E, %g1
+ stx %g1, [%o0]
+2:
+ add %o2, 0x8, %o2
+ subcc %o0, %o1, %g0
+ bl 1b
+ add %o0, 0x8, %o0
+
+ /* Zero out our BSS section. */
+ setx _bss - 8, %o7, %o0 ! First address of BSS
+ setx _end - 8, %o7, %o1 ! Last address of BSS
+ ba 2f
+ nop
+1:
+ stx %g0, [%o0]
+2:
+ subcc %o0, %o1, %g0
+ bl 1b
+ add %o0, 0x8, %o0
+
+ setx trap_table, %g2, %g1
+ wrpr %g1, %tba
+
+ setx qemu_mem_size, %g7, %g1
+ stx %g3, [%g1]
+
+ setx _data, %g7, %g1 ! Store va->pa conversion factor
+ sub %g1, %l0, %g2
+ setx va_shift, %g7, %g1
+ stx %g2, [%g1]
+
+ /* Finally, turn on traps so that we can call c-code. */
+ wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
+
+ ! 100 Hz timer
+ setx TICK_INT_DIS, %g2, %g1
+ rd %tick, %g2
+ andn %g2, %g1, %g2
+ set HZ, %g1
+ add %g1, %g2, %g1
+ wr %g1, 0, %tick_cmpr
+
+ /* Switch to our main context.
+ * Main context is statically defined in C.
+ */
+
+ call __switch_context_nosave
+ nop
+
+ /* We get here when the main context switches back to
+ * the boot context.
+ */
+bad_conf:
+ b bad_conf
+ nop
diff --git a/roms/openbios/arch/sparc64/init.fs b/roms/openbios/arch/sparc64/init.fs
new file mode 100644
index 00000000..eb6c9da5
--- /dev/null
+++ b/roms/openbios/arch/sparc64/init.fs
@@ -0,0 +1,61 @@
+\ va>tte-data defer MMU virtual to physical address hook for Solaris
+\ We need to make sure this is in the global wordlist
+active-package 0 active-package!
+defer va>tte-data
+0 to va>tte-data
+active-package!
+
+:noname
+ ." Type 'help' for detailed information" cr
+ \ ." boot secondary slave cdrom: " cr
+ \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr
+ ; DIAG-initializer
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+:noname
+ set-defaults
+; PREPOST-initializer
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " memory" " /memory" preopen
+
+; SYSTEM-initializer
+
+\ use the tty interface if available
+: activate-tty-interface
+ " /packages/terminal-emulator" find-dev if drop
+ then
+;
+
+device-end
+
+: rmap@ ( virt -- rmentry )
+ drop 0
+ ;
+
+\ Load VGA FCode driver blob
+[IFDEF] CONFIG_DRIVER_VGA
+ -1 value vga-driver-fcode
+ " QEMU,VGA.bin" $encode-file to vga-driver-fcode
+[THEN]
diff --git a/roms/openbios/arch/sparc64/ldscript b/roms/openbios/arch/sparc64/ldscript
new file mode 100644
index 00000000..54288e82
--- /dev/null
+++ b/roms/openbios/arch/sparc64/ldscript
@@ -0,0 +1,67 @@
+OUTPUT_FORMAT(elf64-sparc)
+OUTPUT_ARCH(sparc:v9)
+
+/* QEMU ELF loader can't handle very complex files, so we put ELFBoot
+info to rodata and put initctx to data.*/
+
+ENTRY(trap_table)
+
+/* Initial load address
+ */
+BASE_ADDR = 0x00000000ffd00000;
+
+/* 16KB stack */
+STACK_SIZE = 16384;
+IOMEM_SIZE = 256 * 1024 + 768 * 1024;
+
+SECTIONS
+{
+ . = BASE_ADDR;
+
+ /* Start of the program.
+ * Now the version string is in the note, we must include it
+ * in the program. Otherwise we lose the string after relocation. */
+ _start = .;
+
+ /* Normal sections */
+ .text ALIGN(524288): {
+ *(.text.vectors)
+ *(.text)
+ *(.text.*)
+ }
+ .rodata ALIGN(524288): {
+ _rodata = .;
+ sound_drivers_start = .;
+ *(.rodata.sound_drivers)
+ sound_drivers_end = .;
+ *(.rodata)
+ *(.rodata.*)
+ *(.note.ELFBoot)
+ }
+ .data ALIGN(524288): {
+ _data = .;
+ *(.data)
+ *(.data.*)
+ }
+
+ .bss ALIGN(4096): {
+ _bss = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+
+ _stack = .;
+ . += STACK_SIZE;
+ . = ALIGN(16);
+ _estack = .;
+ }
+
+ . = ALIGN(4096);
+ _end = .;
+ _iomem = _end + IOMEM_SIZE;
+
+ /* We discard .note sections other than .note.ELFBoot,
+ * because some versions of GCC generates useless ones. */
+
+ /DISCARD/ : { *(.comment*) *(.note.*) }
+}
diff --git a/roms/openbios/arch/sparc64/lib.c b/roms/openbios/arch/sparc64/lib.c
new file mode 100644
index 00000000..e9101af5
--- /dev/null
+++ b/roms/openbios/arch/sparc64/lib.c
@@ -0,0 +1,508 @@
+/* lib.c
+ * tag: simple function library
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libc/vsprintf.h"
+#include "libopenbios/bindings.h"
+#include "spitfire.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+
+#include "arch/sparc64/ofmem_sparc64.h"
+
+/* Format a string and print it on the screen, just like the libc
+ * function printf.
+ */
+int printk( const char *fmt, ... )
+{
+ char *p, buf[512];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ )
+ putchar(*p);
+ return i;
+}
+
+/* Private functions for mapping between physical/virtual addresses */
+phys_addr_t
+va2pa(unsigned long va)
+{
+ if ((va >= (unsigned long)&_start) &&
+ (va < (unsigned long)&_end))
+ return va - va_shift;
+ else
+ return va;
+}
+
+unsigned long
+pa2va(phys_addr_t pa)
+{
+ if ((pa + va_shift >= (unsigned long)&_start) &&
+ (pa + va_shift < (unsigned long)&_end))
+ return pa + va_shift;
+ else
+ return pa;
+}
+
+void *malloc(int size)
+{
+ return ofmem_malloc(size);
+}
+
+void* realloc( void *ptr, size_t size )
+{
+ return ofmem_realloc(ptr, size);
+}
+
+void free(void *ptr)
+{
+ ofmem_free(ptr);
+}
+
+static void
+mmu_open(void)
+{
+ RET(-1);
+}
+
+static void
+mmu_close(void)
+{
+}
+
+void ofmem_walk_boot_map(translation_entry_cb cb)
+{
+ unsigned long phys, virt, size, mode, data, mask;
+ unsigned int i;
+
+ for (i = 0; i < 64; i++) {
+ data = spitfire_get_dtlb_data(i);
+ if (data & SPITFIRE_TTE_VALID) {
+ switch ((data >> 61) & 3) {
+ default:
+ case 0x0: /* 8k */
+ mask = 0xffffffffffffe000ULL;
+ size = PAGE_SIZE_8K;
+ break;
+ case 0x1: /* 64k */
+ mask = 0xffffffffffff0000ULL;
+ size = PAGE_SIZE_64K;
+ break;
+ case 0x2: /* 512k */
+ mask = 0xfffffffffff80000ULL;
+ size = PAGE_SIZE_512K;
+ break;
+ case 0x3: /* 4M */
+ mask = 0xffffffffffc00000ULL;
+ size = PAGE_SIZE_4M;
+ break;
+ }
+
+ virt = spitfire_get_dtlb_tag(i);
+ virt &= mask;
+
+ /* extract 41bit physical address */
+ phys = data & 0x000001fffffff000ULL;
+ phys &= mask;
+
+ mode = data & 0xfff;
+
+ cb(phys, virt, size, mode);
+ }
+ }
+}
+
+/*
+ 3.6.5 translate
+ ( virt -- false | phys.lo ... phys.hi mode true )
+*/
+static void
+mmu_translate(void)
+{
+ ucell virt, mode;
+ phys_addr_t phys;
+
+ virt = POP();
+
+ phys = ofmem_translate(virt, &mode);
+
+ if (phys != -1UL) {
+ PUSH(phys & 0xffffffff);
+ PUSH(phys >> 32);
+ PUSH(mode);
+ PUSH(-1);
+ }
+ else {
+ PUSH(0);
+ }
+}
+
+/*
+ * D5.3 pgmap@ ( va -- tte )
+ */
+static void
+pgmap_fetch(void)
+{
+ unsigned long va, tte_data;
+
+ va = POP();
+
+ tte_data = find_tte(va);
+ if (tte_data == -1)
+ goto error;
+
+ /* return tte_data */
+ PUSH(tte_data);
+ return;
+
+error:
+ /* If we get here, there was no entry */
+ PUSH(0);
+}
+
+/*
+ ( index tte_data vaddr -- ? )
+*/
+static void
+dtlb_load(void)
+{
+ unsigned long vaddr, tte_data, idx;
+
+ vaddr = POP();
+ tte_data = POP();
+ idx = POP();
+ dtlb_load3(vaddr, tte_data, idx);
+}
+
+/* MMU D-TLB miss handler */
+void
+dtlb_miss_handler(void)
+{
+ unsigned long faultva, tte_data = 0;
+
+ /* Grab fault address from MMU and round to nearest 8k page */
+ faultva = dtlb_faultva();
+ faultva >>= 13;
+ faultva <<= 13;
+
+ /* If a valid va>tte-data routine has been set, invoke that Forth xt instead */
+ if (va2ttedata && *va2ttedata != 0) {
+
+ /* va>tte-data ( addr cnum -- false | tte-data true ) */
+ PUSH(faultva);
+ PUSH(0);
+ enterforth(*va2ttedata);
+
+ /* Check the result first... */
+ tte_data = POP();
+ if (!tte_data) {
+ bug();
+ } else {
+ /* Grab the real data */
+ tte_data = POP();
+ }
+ } else {
+ /* Search the ofmem linked list for this virtual address */
+ tte_data = find_tte(faultva);
+ }
+
+ if (tte_data) {
+ /* Update MMU */
+ dtlb_load2(faultva, tte_data);
+ } else {
+ /* If we got here, there was no translation so fail */
+ bug();
+ }
+
+}
+
+/*
+ ( index tte_data vaddr -- ? )
+*/
+static void
+itlb_load(void)
+{
+ unsigned long vaddr, tte_data, idx;
+
+ vaddr = POP();
+ tte_data = POP();
+ idx = POP();
+ itlb_load3(vaddr, tte_data, idx);
+}
+
+/* MMU I-TLB miss handler */
+void
+itlb_miss_handler(void)
+{
+ unsigned long faultva, tte_data = 0;
+
+ /* Grab fault address from MMU and round to nearest 8k page */
+ faultva = itlb_faultva();
+ faultva >>= 13;
+ faultva <<= 13;
+
+ /* If a valid va>tte-data routine has been set, invoke that Forth xt instead */
+ if (va2ttedata && *va2ttedata != 0) {
+
+ /* va>tte-data ( addr cnum -- false | tte-data true ) */
+ PUSH(faultva);
+ PUSH(0);
+ enterforth(*va2ttedata);
+
+ /* Check the result first... */
+ tte_data = POP();
+ if (!tte_data) {
+ bug();
+ } else {
+ /* Grab the real data */
+ tte_data = POP();
+ }
+ } else {
+ /* Search the ofmem linked list for this virtual address */
+ tte_data = find_tte(faultva);
+ }
+
+ if (tte_data) {
+ /* Update MMU */
+ itlb_load2(faultva, tte_data);
+ } else {
+ /* If we got here, there was no translation so fail */
+ bug();
+ }
+}
+
+/*
+ 3.6.5 map
+ ( phys.lo ... phys.hi virt size mode -- )
+*/
+static void
+mmu_map(void)
+{
+ ucell virt, size, mode;
+ phys_addr_t phys;
+
+ mode = POP();
+ size = POP();
+ virt = POP();
+ phys = POP();
+ phys <<= 32;
+ phys |= POP();
+
+ ofmem_map(phys, virt, size, mode);
+}
+
+/*
+ 3.6.5 unmap
+ ( virt size -- )
+*/
+static void
+mmu_unmap(void)
+{
+ ucell virt, size;
+
+ size = POP();
+ virt = POP();
+ ofmem_unmap(virt, size);
+}
+
+/*
+ 3.6.5 claim
+ ( virt size align -- base )
+*/
+static void
+mmu_claim(void)
+{
+ ucell virt=-1UL, size, align;
+
+ align = POP();
+ size = POP();
+ if (!align) {
+ virt = POP();
+ }
+
+ virt = ofmem_claim_virt(virt, size, align);
+
+ PUSH(virt);
+}
+
+/*
+ 3.6.5 release
+ ( virt size -- )
+*/
+static void
+mmu_release(void)
+{
+ ucell virt, size;
+
+ size = POP();
+ virt = POP();
+
+ ofmem_release_virt(virt, size);
+}
+
+/* ( phys size align --- base ) */
+static void
+mem_claim( void )
+{
+ ucell size, align;
+ phys_addr_t phys=-1UL;
+
+ align = POP();
+ size = POP();
+ if (!align) {
+ phys = POP();
+ phys <<= 32;
+ phys |= POP();
+ }
+
+ phys = ofmem_claim_phys(phys, size, align);
+
+ PUSH(phys & 0xffffffffUL);
+ PUSH(phys >> 32);
+}
+
+/* ( phys size --- ) */
+static void
+mem_release( void )
+{
+ phys_addr_t phys;
+ ucell size;
+
+ size = POP();
+ phys = POP();
+ phys <<= 32;
+ phys |= POP();
+
+ ofmem_release_phys(phys, size);
+}
+
+/* ( name-cstr phys size align --- phys ) */
+static void
+mem_retain ( void )
+{
+ ucell size, align;
+ phys_addr_t phys=-1UL;
+
+ align = POP();
+ size = POP();
+ if (!align) {
+ phys = POP();
+ phys <<= 32;
+ phys |= POP();
+ }
+
+ /* Currently do nothing with the name */
+ POP();
+
+ phys = ofmem_retain(phys, size, align);
+
+ PUSH(phys & 0xffffffffUL);
+ PUSH(phys >> 32);
+}
+
+/* ( virt size align -- baseaddr|-1 ) */
+static void
+ciface_claim( void )
+{
+ ucell align = POP();
+ ucell size = POP();
+ ucell virt = POP();
+ ucell ret = ofmem_claim( virt, size, align );
+
+ /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
+ PUSH( ret );
+}
+
+/* ( virt size -- ) */
+static void
+ciface_release( void )
+{
+ ucell size = POP();
+ ucell virt = POP();
+ ofmem_release(virt, size);
+}
+
+DECLARE_NODE(memory, INSTALL_OPEN, 0, "/memory");
+
+NODE_METHODS( memory ) = {
+ { "claim", mem_claim },
+ { "release", mem_release },
+ { "SUNW,retain", mem_retain },
+};
+
+DECLARE_NODE(mmu, INSTALL_OPEN, 0, "/virtual-memory");
+
+NODE_METHODS(mmu) = {
+ { "open", mmu_open },
+ { "close", mmu_close },
+ { "translate", mmu_translate },
+ { "SUNW,dtlb-load", dtlb_load },
+ { "SUNW,itlb-load", itlb_load },
+ { "map", mmu_map },
+ { "unmap", mmu_unmap },
+ { "claim", mmu_claim },
+ { "release", mmu_release },
+};
+
+void ob_mmu_init(const char *cpuname, uint64_t ram_size)
+{
+ /* memory node */
+ REGISTER_NODE_METHODS(memory, "/memory");
+
+ /* MMU node */
+ REGISTER_NODE_METHODS(mmu, "/virtual-memory");
+
+ ofmem_register(find_dev("/memory"), find_dev("/virtual-memory"));
+
+ push_str("/chosen");
+ fword("find-device");
+
+ push_str("/virtual-memory");
+ fword("open-dev");
+ fword("encode-int");
+ push_str("mmu");
+ fword("property");
+
+ push_str("/memory");
+ fword("find-device");
+
+ /* All memory: 0 to RAM_size */
+ PUSH(0);
+ fword("encode-int");
+ PUSH(0);
+ fword("encode-int");
+ fword("encode+");
+ PUSH((int)(ram_size >> 32));
+ fword("encode-int");
+ fword("encode+");
+ PUSH((int)(ram_size & 0xffffffff));
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ push_str("/openprom/client-services");
+ fword("find-device");
+ bind_func("cif-claim", ciface_claim);
+ bind_func("cif-release", ciface_release);
+
+ /* Other MMU functions */
+ PUSH(0);
+ fword("active-package!");
+ bind_func("pgmap@", pgmap_fetch);
+
+ /* Find address of va2ttedata defer word contents for MMU miss handlers */
+ va2ttedata = (ucell *)findword("va>tte-data");
+ va2ttedata++;
+}
diff --git a/roms/openbios/arch/sparc64/linux_load.c b/roms/openbios/arch/sparc64/linux_load.c
new file mode 100644
index 00000000..e3afc2db
--- /dev/null
+++ b/roms/openbios/arch/sparc64/linux_load.c
@@ -0,0 +1,653 @@
+/*
+ * Linux/i386 loader
+ * Supports bzImage, zImage and Image format.
+ *
+ * Based on work by Steve Gehlbach.
+ * Portions are taken from mkelfImage.
+ *
+ * 2003-09 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/sys_info.h"
+#include "context.h"
+#include "libc/diskio.h"
+#include "boot.h"
+
+#define printf printk
+#define debug printk
+#define strtoull_with_suffix strtol
+
+#define LINUX_PARAM_LOC 0x90000
+#define COMMAND_LINE_LOC 0x91000
+#define GDT_LOC 0x92000
+#define STACK_LOC 0x93000
+
+#define E820MAX 32 /* number of entries in E820MAP */
+struct e820entry {
+ unsigned long long addr; /* start of memory segment */
+ unsigned long long size; /* size of memory segment */
+ unsigned long type; /* type of memory segment */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
+#define E820_NVS 4
+};
+
+/* The header of Linux/i386 kernel */
+struct linux_header {
+ uint8_t reserved1[0x1f1]; /* 0x000 */
+ uint8_t setup_sects; /* 0x1f1 */
+ uint16_t root_flags; /* 0x1f2 */
+ uint8_t reserved2[6]; /* 0x1f4 */
+ uint16_t vid_mode; /* 0x1fa */
+ uint16_t root_dev; /* 0x1fc */
+ uint16_t boot_sector_magic; /* 0x1fe */
+ /* 2.00+ */
+ uint8_t reserved3[2]; /* 0x200 */
+ uint8_t header_magic[4]; /* 0x202 */
+ uint16_t protocol_version; /* 0x206 */
+ uint32_t realmode_swtch; /* 0x208 */
+ uint16_t start_sys; /* 0x20c */
+ uint16_t kver_addr; /* 0x20e */
+ uint8_t type_of_loader; /* 0x210 */
+ uint8_t loadflags; /* 0x211 */
+ uint16_t setup_move_size; /* 0x212 */
+ uint32_t code32_start; /* 0x214 */
+ uint32_t ramdisk_image; /* 0x218 */
+ uint32_t ramdisk_size; /* 0x21c */
+ uint8_t reserved4[4]; /* 0x220 */
+ /* 2.01+ */
+ uint16_t heap_end_ptr; /* 0x224 */
+ uint8_t reserved5[2]; /* 0x226 */
+ /* 2.02+ */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ /* 2.03+ */
+ uint32_t initrd_addr_max; /* 0x22c */
+} __attribute__ ((packed));
+
+
+/* Paramters passed to 32-bit part of Linux
+ * This is another view of the structure above.. */
+struct linux_params {
+ uint8_t orig_x; /* 0x00 */
+ uint8_t orig_y; /* 0x01 */
+ uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */
+ uint16_t orig_video_page; /* 0x04 */
+ uint8_t orig_video_mode; /* 0x06 */
+ uint8_t orig_video_cols; /* 0x07 */
+ uint16_t unused2; /* 0x08 */
+ uint16_t orig_video_ega_bx; /* 0x0a */
+ uint16_t unused3; /* 0x0c */
+ uint8_t orig_video_lines; /* 0x0e */
+ uint8_t orig_video_isVGA; /* 0x0f */
+ uint16_t orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ uint16_t lfb_width; /* 0x12 */
+ uint16_t lfb_height; /* 0x14 */
+ uint16_t lfb_depth; /* 0x16 */
+ uint32_t lfb_base; /* 0x18 */
+ uint32_t lfb_size; /* 0x1c */
+ uint16_t cl_magic; /* 0x20 */
+#define CL_MAGIC_VALUE 0xA33F
+ uint16_t cl_offset; /* 0x22 */
+ uint16_t lfb_linelength; /* 0x24 */
+ uint8_t red_size; /* 0x26 */
+ uint8_t red_pos; /* 0x27 */
+ uint8_t green_size; /* 0x28 */
+ uint8_t green_pos; /* 0x29 */
+ uint8_t blue_size; /* 0x2a */
+ uint8_t blue_pos; /* 0x2b */
+ uint8_t rsvd_size; /* 0x2c */
+ uint8_t rsvd_pos; /* 0x2d */
+ uint16_t vesapm_seg; /* 0x2e */
+ uint16_t vesapm_off; /* 0x30 */
+ uint16_t pages; /* 0x32 */
+ uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */
+
+ //struct apm_bios_info apm_bios_info; /* 0x40 */
+ uint8_t apm_bios_info[0x40];
+ //struct drive_info_struct drive_info; /* 0x80 */
+ uint8_t drive_info[0x20];
+ //struct sys_desc_table sys_desc_table; /* 0xa0 */
+ uint8_t sys_desc_table[0x140];
+ uint32_t alt_mem_k; /* 0x1e0 */
+ uint8_t reserved5[4]; /* 0x1e4 */
+ uint8_t e820_map_nr; /* 0x1e8 */
+ uint8_t reserved6[9]; /* 0x1e9 */
+ uint16_t mount_root_rdonly; /* 0x1f2 */
+ uint8_t reserved7[4]; /* 0x1f4 */
+ uint16_t ramdisk_flags; /* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+ uint8_t reserved8[2]; /* 0x1fa */
+ uint16_t orig_root_dev; /* 0x1fc */
+ uint8_t reserved9[1]; /* 0x1fe */
+ uint8_t aux_device_info; /* 0x1ff */
+ uint8_t reserved10[2]; /* 0x200 */
+ uint8_t param_block_signature[4]; /* 0x202 */
+ uint16_t param_block_version; /* 0x206 */
+ uint8_t reserved11[8]; /* 0x208 */
+ uint8_t loader_type; /* 0x210 */
+#define LOADER_TYPE_LOADLIN 1
+#define LOADER_TYPE_BOOTSECT_LOADER 2
+#define LOADER_TYPE_SYSLINUX 3
+#define LOADER_TYPE_ETHERBOOT 4
+#define LOADER_TYPE_KERNEL 5
+ uint8_t loader_flags; /* 0x211 */
+ uint8_t reserved12[2]; /* 0x212 */
+ uint32_t kernel_start; /* 0x214 */
+ uint32_t initrd_start; /* 0x218 */
+ uint32_t initrd_size; /* 0x21c */
+ uint8_t reserved12_5[8]; /* 0x220 */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ uint8_t reserved13[164]; /* 0x22c */
+ struct e820entry e820_map[E820MAX]; /* 0x2d0 */
+ uint8_t reserved16[688]; /* 0x550 */
+#define COMMAND_LINE_SIZE 256
+ /* Command line is copied here by 32-bit i386/kernel/head.S.
+ * So I will follow the boot protocol, rather than putting it
+ * directly here. --ts1 */
+ uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */
+ uint8_t reserved17[1792]; /* 0x900 - 0x1000 */
+};
+
+static uint64_t forced_memsize;
+static int fd;
+
+static unsigned long file_size(void)
+{
+ long long fpos, fsize;
+
+ /* Save current position */
+ fpos = tell(fd);
+
+ /* Go to end of file and get position */
+ seek_io(fd, -1);
+ fsize = tell(fd);
+
+ /* Go back to old position */
+ seek_io(fd, 0);
+ seek_io(fd, fpos);
+
+ return fsize;
+}
+
+/* Load the first part the file and check if it's Linux */
+static uint32_t load_linux_header(struct linux_header *hdr)
+{
+ int load_high;
+ uint32_t kern_addr;
+
+ if (read_io(fd, hdr, sizeof *hdr) != sizeof *hdr) {
+ debug("Can't read Linux header\n");
+ return 0;
+ }
+ if (hdr->boot_sector_magic != 0xaa55) {
+ debug("Not a Linux kernel image\n");
+ return 0;
+ }
+
+ /* Linux is found. Print some information */
+ if (memcmp(hdr->header_magic, "HdrS", 4) != 0) {
+ /* This may be floppy disk image or something.
+ * Perform a simple (incomplete) sanity check. */
+ if (hdr->setup_sects >= 16
+ || file_size() - (hdr->setup_sects<<9) >= 512<<10) {
+ debug("This looks like a bootdisk image but not like Linux...\n");
+ return 0;
+ }
+
+ printf("Possible very old Linux");
+ /* This kernel does not even have a protocol version.
+ * Force the value. */
+ hdr->protocol_version = 0; /* pre-2.00 */
+ } else
+ printf("Found Linux");
+ if (hdr->protocol_version >= 0x200 && hdr->kver_addr) {
+ char kver[256];
+ seek_io(fd, hdr->kver_addr + 0x200);
+ if (read_io(fd, kver, sizeof kver) != 0) {
+ kver[255] = 0;
+ printf(" version %s", kver);
+ }
+ }
+ debug(" (protocol %#x)", hdr->protocol_version);
+ load_high = 0;
+ if (hdr->protocol_version >= 0x200) {
+ debug(" (loadflags %#x)", hdr->loadflags);
+ load_high = hdr->loadflags & 1;
+ }
+ if (load_high) {
+ printf(" bzImage");
+ kern_addr = 0x100000;
+ } else {
+ printf(" zImage or Image");
+ kern_addr = 0x1000;
+ }
+ printf(".\n");
+
+ return kern_addr;
+}
+
+/* Set up parameters for 32-bit kernel */
+static void
+init_linux_params(struct linux_params *params, struct linux_header *hdr)
+{
+ debug("Setting up paramters at %#lx\n", virt_to_phys(params));
+ memset(params, 0, sizeof *params);
+
+ /* Copy some useful values from header */
+ params->mount_root_rdonly = hdr->root_flags;
+ params->orig_root_dev = hdr->root_dev;
+
+ /* Video parameters.
+ * This assumes we have VGA in standard 80x25 text mode,
+ * just like our vga.c does.
+ * Cursor position is filled later to allow some more printf's. */
+ params->orig_video_mode = 3;
+ params->orig_video_cols = 80;
+ params->orig_video_lines = 25;
+ params->orig_video_isVGA = 1;
+ params->orig_video_points = 16;
+
+ params->loader_type = 0xff; /* Unregistered Linux loader */
+}
+
+/* Memory map */
+static void
+set_memory_size(struct linux_params *params, struct sys_info *info)
+{
+ int i;
+ uint64_t end;
+ uint32_t ramtop = 0;
+ struct e820entry *linux_map;
+ struct memrange *filo_map;
+
+ linux_map = params->e820_map;
+ filo_map = info->memrange;
+ for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) {
+ if (i < E820MAX) {
+ /* Convert to BIOS e820 style */
+ linux_map->addr = filo_map->base;
+ linux_map->size = filo_map->size;
+ linux_map->type = E820_RAM;
+ debug("%016Lx - %016Lx\n", linux_map->addr,
+ linux_map->addr + linux_map->size);
+ params->e820_map_nr = i+1;
+ }
+
+ /* Find out top of RAM. XXX This ignores hole above 1MB */
+ end = filo_map->base + filo_map->size;
+ if (end < (1ULL << 32)) { /* don't count memory above 4GB */
+ if (end > ramtop)
+ ramtop = (uint32_t) end;
+ }
+ }
+ debug("ramtop=%#x\n", ramtop);
+ /* Size of memory above 1MB in KB */
+ params->alt_mem_k = (ramtop - (1<<20)) >> 10;
+ /* old style, 64MB max */
+ if (ramtop >= (64<<20))
+ params->ext_mem_k = (63<<10);
+ else
+ params->ext_mem_k = params->alt_mem_k;
+ debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k);
+}
+
+/*
+ * Parse command line
+ * Some parameters, like initrd=<file>, are not passed to kernel,
+ * we are responsible to process them.
+ * Parameters for kernel are copied to kern_cmdline. Returns name of initrd.
+ */
+static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline)
+{
+ const char *start, *sep, *end, *val;
+ char name[64];
+ unsigned long len;
+ int k_len;
+ int to_kern;
+ char *initrd = NULL;
+ int toolong = 0;
+
+ forced_memsize = 0;
+
+ if (!orig_cmdline) {
+ *kern_cmdline = '\0';
+ return NULL;
+ }
+
+ k_len = 0;
+ debug("original command line: \"%s\"\n", orig_cmdline);
+ debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline));
+
+ start = orig_cmdline;
+ while (*start == ' ')
+ start++;
+ while (*start) {
+ end = strchr(start, ' ');
+ if (!end)
+ end = start + strlen(start);
+ sep = strchr(start, '=');
+ if (!sep || sep > end)
+ sep = end;
+ len = sep - start;
+ if (len >= sizeof(name))
+ len = sizeof(name) - 1;
+ memcpy(name, start, len);
+ name[len] = 0;
+
+ if (*sep == '=') {
+ val = sep + 1;
+ len = end - val;
+ } else {
+ val = NULL;
+ len = 0;
+ }
+
+ /* Only initrd= and mem= are handled here. vga= is not,
+ * which I believe is a paramter to the realmode part of Linux,
+ * which we don't execute. */
+ if (strcmp(name, "initrd") == 0) {
+ if (!val)
+ printf("Missing filename to initrd parameter\n");
+ else {
+ initrd = malloc(len + 1);
+ memcpy(initrd, val, len);
+ initrd[len] = 0;
+ debug("initrd=%s\n", initrd);
+ }
+ /* Don't pass this to kernel */
+ to_kern = 0;
+ } else if (strcmp(name, "mem") == 0) {
+ if (!val)
+ printf("Missing value for mem parameter\n");
+ else {
+ forced_memsize = strtoull_with_suffix(val, (char**)&val, 0);
+ if (forced_memsize == 0)
+ printf("Invalid mem option, ignored\n");
+ if (val != end) {
+ printf("Garbage after mem=<size>, ignored\n");
+ forced_memsize = 0;
+ }
+ debug("mem=%llu\n", (unsigned long long)forced_memsize);
+ }
+ /* mem= is for both loader and kernel */
+ to_kern = 1;
+ } else
+ to_kern = 1;
+
+ if (to_kern) {
+ /* Copy to kernel command line buffer */
+ if (k_len != 0)
+ kern_cmdline[k_len++] = ' '; /* put separator */
+ len = end - start;
+ if (k_len + len >= COMMAND_LINE_SIZE) {
+ len = COMMAND_LINE_SIZE - k_len - 1;
+ if (!toolong) {
+ printf("Kernel command line is too long; truncated to "
+ "%d bytes\n", COMMAND_LINE_SIZE-1);
+ toolong = 1;
+ }
+ }
+ memcpy(kern_cmdline + k_len, start, len);
+ k_len += len;
+ }
+
+ start = end;
+ while (*start == ' ')
+ start++;
+ }
+ kern_cmdline[k_len] = 0;
+ debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline);
+
+ return initrd;
+}
+
+/* Set command line location */
+static void set_command_line_loc(struct linux_params *params,
+ struct linux_header *hdr)
+{
+ if (hdr->protocol_version >= 0x202) {
+ /* new style */
+ params->cmd_line_ptr = COMMAND_LINE_LOC;
+ } else {
+ /* old style */
+ params->cl_magic = CL_MAGIC_VALUE;
+ params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC;
+ }
+}
+
+/* Load 32-bit part of kernel */
+static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr)
+{
+ uint32_t kern_offset, kern_size;
+
+ if (hdr->setup_sects == 0)
+ hdr->setup_sects = 4;
+ kern_offset = (hdr->setup_sects + 1) * 512;
+ seek_io(fd, kern_offset);
+ kern_size = file_size() - kern_offset;
+ debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size);
+
+#if 0
+ if (using_devsize) {
+ printf("Attempt to load up to end of device as kernel; "
+ "specify the image size\n");
+ return 0;
+ }
+#endif
+
+ printf("Loading kernel... ");
+ if ((uint32_t)read_io(fd, phys_to_virt(kern_addr), kern_size) != kern_size) {
+ printf("Can't read kernel\n");
+ return 0;
+ }
+ printf("ok\n");
+
+ return kern_size;
+}
+
+static int load_initrd(struct linux_header *hdr, uint32_t kern_end,
+ struct linux_params *params, const char *initrd_file)
+{
+ uint32_t max;
+ uint32_t start, end, size;
+ uint64_t forced;
+
+ fd = open_io(initrd_file);
+ if (fd == -1) {
+ printf("Can't open initrd: %s\n", initrd_file);
+ return -1;
+ }
+
+#if 0
+ if (using_devsize) {
+ printf("Attempt to load up to end of device as initrd; "
+ "specify the image size\n");
+ return -1;
+ }
+#endif
+
+ size = file_size();
+
+
+ /* Find out the kernel's restriction on how high the initrd can be
+ * placed */
+ if (hdr->protocol_version >= 0x203)
+ max = hdr->initrd_addr_max;
+ else
+ max = 0x38000000; /* Hardcoded value for older kernels */
+
+ /* FILO itself is at the top of RAM. (relocated)
+ * So, try putting initrd just below us. */
+ end = virt_to_phys(_start);
+ if (end > max)
+ end = max;
+
+ /* If "mem=" option is given, we have to put the initrd within
+ * the specified range. */
+ if (forced_memsize) {
+ forced = forced_memsize;
+ if (forced > max)
+ forced = max;
+ /* If the "mem=" is lower, it's easy */
+ if (forced <= end)
+ end = forced;
+ else {
+ /* Otherwise, see if we can put it above us */
+ if (virt_to_phys(_end) + size <= forced)
+ end = forced; /* Ok */
+ }
+ }
+
+ start = end - size;
+ start &= ~0xfff; /* page align */
+ end = start + size;
+
+ debug("start=%#x end=%#x\n", start, end);
+
+ if (start < kern_end) {
+ printf("Initrd is too big to fit in memory\n");
+ return -1;
+ }
+
+ printf("Loading initrd... ");
+ if ((uint32_t)read_io(fd, phys_to_virt(start), size) != size) {
+ printf("Can't read initrd\n");
+ return -1;
+ }
+ printf("ok\n");
+
+ params->initrd_start = start;
+ params->initrd_size = size;
+
+ close_io(fd);
+
+ return 0;
+}
+
+static void hardware_setup(void)
+{
+ /* Disable nmi */
+ outb(0x80, 0x70);
+
+ /* Make sure any coprocessor is properly reset.. */
+ outb(0, 0xf0);
+ outb(0, 0xf1);
+
+ /* we're getting screwed again and again by this problem of the 8259.
+ * so we're going to leave this lying around for inclusion into
+ * crt0.S on an as-needed basis.
+ *
+ * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
+ * we put them right after the intel-reserved hardware interrupts, at
+ * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
+ * messed this up with the original PC, and they haven't been able to
+ * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
+ * which is used for the internal hardware interrupts as well. We just
+ * have to reprogram the 8259's, and it isn't fun.
+ */
+
+ outb(0x11, 0x20); /* initialization sequence to 8259A-1 */
+ outb(0x11, 0xA0); /* and to 8259A-2 */
+
+ outb(0x20, 0x21); /* start of hardware int's (0x20) */
+ outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */
+
+ outb(0x04, 0x21); /* 8259-1 is master */
+ outb(0x02, 0xA1); /* 8259-2 is slave */
+
+ outb(0x01, 0x21); /* 8086 mode for both */
+ outb(0x01, 0xA1);
+
+ outb(0xFF, 0xA1); /* mask off all interrupts for now */
+ outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */
+}
+
+/* Start Linux */
+static int start_linux(uint32_t kern_addr)
+{
+ struct context *ctx;
+ //extern int cursor_x, cursor_y;
+
+ ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
+
+ /* Entry point */
+ ctx->pc = kern_addr;
+ ctx->npc = kern_addr + 4;
+
+ debug("pc=%#x\n", kern_addr);
+ printf("Jumping to entry point...\n");
+
+#ifdef VGA_CONSOLE
+ /* Update VGA cursor position.
+ * This must be here because the printf changes the value! */
+ params->orig_x = cursor_x;
+ params->orig_y = cursor_y;
+#endif
+
+ /* Go... */
+ ctx = switch_to(ctx);
+
+ /* It's impossible but... */
+ printf("Returned with o0=%#llx\n", ctx->regs[REG_O0]);
+
+ return ctx->regs[REG_O0];
+}
+
+int linux_load(struct sys_info *info, const char *file, const char *cmdline)
+{
+ struct linux_header hdr;
+ struct linux_params *params;
+ uint32_t kern_addr, kern_size;
+ char *initrd_file = NULL;
+
+ fd = open_io(file);
+ if (fd == -1)
+ return -1;
+
+ kern_addr = load_linux_header(&hdr);
+ if (kern_addr == 0) {
+ close_io(fd);
+ return LOADER_NOT_SUPPORT;
+ }
+
+ debug("[sparc64] Booting kernel '%s' ", file);
+ if (cmdline)
+ debug("with parameters '%s'\n", cmdline);
+ else
+ debug("without parameters.\n");
+
+ params = phys_to_virt(LINUX_PARAM_LOC);
+ init_linux_params(params, &hdr);
+ set_memory_size(params, info);
+ initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
+ set_command_line_loc(params, &hdr);
+
+ kern_size = load_linux_kernel(&hdr, kern_addr);
+ if (kern_size == 0) {
+ if (initrd_file)
+ free(initrd_file);
+ return -1;
+ }
+
+ if (initrd_file) {
+ if (load_initrd(&hdr, kern_addr+kern_size, params, initrd_file)
+ != 0) {
+ free(initrd_file);
+ return -1;
+ }
+ free(initrd_file);
+ }
+
+ hardware_setup();
+
+ start_linux(kern_addr);
+ return 0;
+}
diff --git a/roms/openbios/arch/sparc64/lsu.h b/roms/openbios/arch/sparc64/lsu.h
new file mode 100644
index 00000000..d85c33f2
--- /dev/null
+++ b/roms/openbios/arch/sparc64/lsu.h
@@ -0,0 +1,20 @@
+/* $Id: lsu.h,v 1.2 1997/04/04 00:50:22 davem Exp $ */
+#ifndef _SPARC64_LSU_H
+#define _SPARC64_LSU_H
+
+#include "const.h"
+
+/* LSU Control Register */
+#define LSU_CONTROL_PM _AC(0x000001fe00000000,UL) /* Phys-watchpoint byte mask*/
+#define LSU_CONTROL_VM _AC(0x00000001fe000000,UL) /* Virt-watchpoint byte mask*/
+#define LSU_CONTROL_PR _AC(0x0000000001000000,UL) /* Phys-rd watchpoint enable*/
+#define LSU_CONTROL_PW _AC(0x0000000000800000,UL) /* Phys-wr watchpoint enable*/
+#define LSU_CONTROL_VR _AC(0x0000000000400000,UL) /* Virt-rd watchpoint enable*/
+#define LSU_CONTROL_VW _AC(0x0000000000200000,UL) /* Virt-wr watchpoint enable*/
+#define LSU_CONTROL_FM _AC(0x00000000000ffff0,UL) /* Parity mask enables. */
+#define LSU_CONTROL_DM _AC(0x0000000000000008,UL) /* Data MMU enable. */
+#define LSU_CONTROL_IM _AC(0x0000000000000004,UL) /* Instruction MMU enable. */
+#define LSU_CONTROL_DC _AC(0x0000000000000002,UL) /* Data cache enable. */
+#define LSU_CONTROL_IC _AC(0x0000000000000001,UL) /* Instruction cache enable.*/
+
+#endif /* !(_SPARC64_LSU_H) */
diff --git a/roms/openbios/arch/sparc64/multiboot.c b/roms/openbios/arch/sparc64/multiboot.c
new file mode 100644
index 00000000..8514ca0a
--- /dev/null
+++ b/roms/openbios/arch/sparc64/multiboot.c
@@ -0,0 +1,125 @@
+/* Support for Multiboot */
+
+#include "config.h"
+#include "asm/io.h"
+#include "libopenbios/sys_info.h"
+#include "multiboot.h"
+
+#define printf printk
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+struct mbheader {
+ unsigned int magic, flags, checksum;
+};
+const struct mbheader multiboot_header
+ __attribute__((section (".hdr"))) =
+{
+ MULTIBOOT_HEADER_MAGIC,
+ MULTIBOOT_HEADER_FLAGS,
+ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+};
+
+/* Multiboot information structure, provided by loader to us */
+
+struct multiboot_mmap {
+ unsigned entry_size;
+ unsigned base_lo, base_hi;
+ unsigned size_lo, size_hi;
+ unsigned type;
+};
+
+#define MULTIBOOT_MEM_VALID 0x01
+#define MULTIBOOT_BOOT_DEV_VALID 0x02
+#define MULTIBOOT_CMDLINE_VALID 0x04
+#define MULTIBOOT_MODS_VALID 0x08
+#define MULTIBOOT_AOUT_SYMS_VALID 0x10
+#define MULTIBOOT_ELF_SYMS_VALID 0x20
+#define MULTIBOOT_MMAP_VALID 0x40
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ struct multiboot_info *mbinfo;
+ struct multiboot_mmap *mbmem;
+ unsigned mbcount, mbaddr;
+ unsigned int i;
+ struct memrange *mmap;
+ int mmap_count;
+ module_t *mod;
+
+ if (info->boot_type != 0x2BADB002)
+ return;
+
+ debug("Using Multiboot information at %#lx\n", info->boot_data);
+
+ mbinfo = phys_to_virt(info->boot_data);
+
+ if (mbinfo->mods_count != 1) {
+ printf("Multiboot: no dictionary\n");
+ return;
+ }
+
+ mod = (module_t *) mbinfo->mods_addr;
+ info->dict_start=(unsigned long *)mod->mod_start;
+ info->dict_end=(unsigned long *)mod->mod_end;
+
+ if (mbinfo->flags & MULTIBOOT_MMAP_VALID) {
+ /* convert mmap records */
+ mbmem = phys_to_virt(mbinfo->mmap_addr);
+ mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4);
+ mmap = malloc(mbcount * sizeof(struct memrange));
+ mmap_count = 0;
+ mbaddr = mbinfo->mmap_addr;
+ for (i = 0; i < mbcount; i++) {
+ mbmem = phys_to_virt(mbaddr);
+ debug("%08x%08x %08x%08x (%d)\n",
+ mbmem->base_hi,
+ mbmem->base_lo,
+ mbmem->size_hi,
+ mbmem->size_lo,
+ mbmem->type);
+ if (mbmem->type == 1) { /* Only normal RAM */
+ mmap[mmap_count].base = mbmem->base_lo
+ + (((unsigned long long) mbmem->base_hi) << 32);
+ mmap[mmap_count].size = mbmem->size_lo
+ + (((unsigned long long) mbmem->size_hi) << 32);
+ mmap_count++;
+ }
+ mbaddr += mbmem->entry_size + 4;
+ if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length)
+ break;
+ }
+ /* simple sanity check - there should be at least 2 RAM segments
+ * (base 640k and extended) */
+ if (mmap_count >= 2)
+ goto got_it;
+
+ printf("Multiboot mmap is broken\n");
+ free(mmap);
+ /* fall back to mem_lower/mem_upper */
+ }
+
+ if (mbinfo->flags & MULTIBOOT_MEM_VALID) {
+ /* use mem_lower and mem_upper */
+ mmap_count = 2;
+ mmap = malloc(2 * sizeof(*mmap));
+ mmap[0].base = 0;
+ mmap[0].size = mbinfo->mem_lower << 10;
+ mmap[1].base = 1 << 20; /* 1MB */
+ mmap[1].size = mbinfo->mem_upper << 10;
+ goto got_it;
+ }
+
+ printf("Can't get memory information from Multiboot\n");
+ return;
+
+got_it:
+ info->memrange = mmap;
+ info->n_memranges = mmap_count;
+
+ return;
+}
diff --git a/roms/openbios/arch/sparc64/multiboot.h b/roms/openbios/arch/sparc64/multiboot.h
new file mode 100644
index 00000000..17cf202e
--- /dev/null
+++ b/roms/openbios/arch/sparc64/multiboot.h
@@ -0,0 +1,96 @@
+/* multiboot.h
+ * tag: header for multiboot
+ *
+ * Copyright (C) 2003-2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+/* magic number for multiboot header */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* flags for multiboot header */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* magic number passed by multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (8KB). */
+#define STACK_SIZE 0x2000
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* We don't want these declarations in boot.S */
+
+/* multiboot header */
+typedef struct multiboot_header {
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* symbol table for a.out */
+typedef struct aout_symbol_table {
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* section header table for ELF */
+typedef struct elf_section_header_table {
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* multiboot information */
+typedef struct multiboot_info {
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+} multiboot_info_t;
+
+/* module structure */
+typedef struct module {
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map {
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+#endif /* ! ASM */
diff --git a/roms/openbios/arch/sparc64/ofmem_sparc64.c b/roms/openbios/arch/sparc64/ofmem_sparc64.c
new file mode 100644
index 00000000..bdfaf563
--- /dev/null
+++ b/roms/openbios/arch/sparc64/ofmem_sparc64.c
@@ -0,0 +1,381 @@
+/*
+ * <ofmem_sparc64.c>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "arch/sparc64/ofmem_sparc64.h"
+#include "spitfire.h"
+
+#define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8))
+
+#define MEMSIZE (128 * 1024)
+static union {
+ char memory[MEMSIZE];
+ ofmem_t ofmem;
+} s_ofmem_data;
+
+#define OFMEM (&s_ofmem_data.ofmem)
+#define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE)
+
+static retain_t s_retained;
+translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans;
+
+ucell *va2ttedata = 0;
+extern uint64_t qemu_mem_size;
+
+static inline size_t ALIGN_SIZE(size_t x, size_t a)
+{
+ return (x + a - 1) & ~(a-1);
+}
+
+static ucell get_heap_top( void )
+{
+ return (ucell)TOP_OF_RAM;
+}
+
+ofmem_t* ofmem_arch_get_private(void)
+{
+ return OFMEM;
+}
+
+void* ofmem_arch_get_malloc_base(void)
+{
+ return OF_MALLOC_BASE;
+}
+
+ucell ofmem_arch_get_heap_top(void)
+{
+ return get_heap_top();
+}
+
+ucell ofmem_arch_get_virt_top(void)
+{
+ return (ucell)TOP_OF_RAM;
+}
+
+ucell ofmem_arch_get_iomem_base(void)
+{
+ /* Currently unused */
+ return 0;
+}
+
+ucell ofmem_arch_get_iomem_top(void)
+{
+ /* Currently unused */
+ return 0;
+}
+
+retain_t *ofmem_arch_get_retained(void)
+{
+ return (&s_retained);
+}
+
+int ofmem_arch_get_translation_entry_size(void)
+{
+ /* Return size of a single MMU package translation property entry in cells */
+ return 3;
+}
+
+void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t)
+{
+ /* Generate translation property entry for SPARC. While there is no
+ formal documentation for this, both Linux kernel and OpenSolaris sources
+ expect a translation property entry to have the following layout:
+
+ virtual address
+ length
+ mode (valid TTE for start of translation region)
+ */
+
+ transentry[0] = t->virt;
+ transentry[1] = t->size;
+ transentry[2] = t->phys | t->mode | SPITFIRE_TTE_VALID;
+}
+
+/* Return the size of a memory available entry given the phandle in cells */
+int ofmem_arch_get_available_entry_size(phandle_t ph)
+{
+ if (ph == s_phandle_memory) {
+ return 1 + ofmem_arch_get_physaddr_cellsize();
+ } else {
+ return 1 + 1;
+ }
+}
+
+/* Generate memory available property entry for Sparc64 */
+void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size)
+{
+ int i = 0;
+
+ if (ph == s_phandle_memory) {
+ i += ofmem_arch_encode_physaddr(availentry, start);
+ } else {
+ availentry[i++] = start;
+ }
+
+ availentry[i] = size;
+}
+
+/* Unmap a set of pages */
+void ofmem_arch_unmap_pages(ucell virt, ucell size)
+{
+ ucell va;
+
+ /* align address to 8k */
+ virt &= ~PAGE_MASK_8K;
+
+ /* align size to 8k */
+ size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K;
+
+ for (va = virt; va < virt + size; va += PAGE_SIZE_8K) {
+ itlb_demap(va);
+ dtlb_demap(va);
+ }
+}
+
+/* Map a set of pages */
+void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode)
+{
+ unsigned long tte_data, currsize;
+
+ /* Install locked tlb entries now */
+ if (mode & SPITFIRE_TTE_LOCKED) {
+
+ /* aligned to 8k page */
+ size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K;
+
+ while (size > 0) {
+ currsize = size;
+ if (currsize >= PAGE_SIZE_4M &&
+ (virt & PAGE_MASK_4M) == 0 &&
+ (phys & PAGE_MASK_4M) == 0) {
+ currsize = PAGE_SIZE_4M;
+ tte_data = 6ULL << 60;
+ } else if (currsize >= PAGE_SIZE_512K &&
+ (virt & PAGE_MASK_512K) == 0 &&
+ (phys & PAGE_MASK_512K) == 0) {
+ currsize = PAGE_SIZE_512K;
+ tte_data = 4ULL << 60;
+ } else if (currsize >= PAGE_SIZE_64K &&
+ (virt & PAGE_MASK_64K) == 0 &&
+ (phys & PAGE_MASK_64K) == 0) {
+ currsize = PAGE_SIZE_64K;
+ tte_data = 2ULL << 60;
+ } else {
+ currsize = PAGE_SIZE_8K;
+ tte_data = 0;
+ }
+
+ tte_data |= phys | mode | SPITFIRE_TTE_VALID;
+
+ itlb_load2(virt, tte_data);
+ dtlb_load2(virt, tte_data);
+
+ size -= currsize;
+ phys += currsize;
+ virt += currsize;
+ }
+ }
+}
+
+/************************************************************************/
+/* misc */
+/************************************************************************/
+
+int ofmem_arch_get_physaddr_cellsize(void)
+{
+ return 1;
+}
+
+int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value)
+{
+ p[0] = value;
+ return 1;
+}
+
+ucell ofmem_arch_default_translation_mode( phys_addr_t phys )
+{
+ /* Writable, cacheable */
+ /* Privileged and not locked */
+ return SPITFIRE_TTE_CP | SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE | SPITFIRE_TTE_PRIVILEGED;
+}
+
+ucell ofmem_arch_io_translation_mode( phys_addr_t phys )
+{
+ /* Writable, privileged and not locked */
+ return SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE | SPITFIRE_TTE_PRIVILEGED;
+}
+
+/* Architecture-specific OFMEM helpers */
+unsigned long
+find_tte(unsigned long va)
+{
+ translation_t *t = *g_ofmem_translations;
+ unsigned long tte_data;
+
+ /* Search the ofmem linked list for this virtual address */
+ while (t != NULL) {
+ /* Find the correct range */
+ if (va >= t->virt && va < (t->virt + t->size)) {
+
+ /* valid tte, 8k size */
+ tte_data = SPITFIRE_TTE_VALID;
+
+ /* mix in phys address mode */
+ tte_data |= t->mode;
+
+ /* mix in page physical address = t->phys + offset */
+ tte_data |= t->phys + (va - t->virt);
+
+ /* return tte_data */
+ return tte_data;
+ }
+ t = t->next;
+ }
+
+ /* Couldn't find tte */
+ return -1;
+}
+
+/* ITLB handlers */
+void
+itlb_load2(unsigned long vaddr, unsigned long tte_data)
+{
+ asm("stxa %0, [%1] %2\n"
+ "stxa %3, [%%g0] %4\n"
+ : : "r" (vaddr), "r" (48), "i" (ASI_IMMU),
+ "r" (tte_data), "i" (ASI_ITLB_DATA_IN));
+}
+
+void
+itlb_load3(unsigned long vaddr, unsigned long tte_data,
+ unsigned long tte_index)
+{
+ asm("stxa %0, [%1] %2\n"
+ "stxa %3, [%4] %5\n"
+ : : "r" (vaddr), "r" (48), "i" (ASI_IMMU),
+ "r" (tte_data), "r" (tte_index << 3), "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+unsigned long
+itlb_faultva(void)
+{
+ unsigned long faultva;
+
+ asm("ldxa [%1] %2, %0\n"
+ : "=r" (faultva)
+ : "r" (48), "i" (ASI_IMMU));
+
+ return faultva;
+}
+
+void
+itlb_demap(unsigned long vaddr)
+{
+ asm("stxa %0, [%0] %1\n"
+ : : "r" (vaddr), "i" (ASI_IMMU_DEMAP));
+}
+
+/* DTLB handlers */
+void
+dtlb_load2(unsigned long vaddr, unsigned long tte_data)
+{
+ asm("stxa %0, [%1] %2\n"
+ "stxa %3, [%%g0] %4\n"
+ : : "r" (vaddr), "r" (48), "i" (ASI_DMMU),
+ "r" (tte_data), "i" (ASI_DTLB_DATA_IN));
+}
+
+void
+dtlb_load3(unsigned long vaddr, unsigned long tte_data,
+ unsigned long tte_index)
+{
+ asm("stxa %0, [%1] %2\n"
+ "stxa %3, [%4] %5\n"
+ : : "r" (vaddr), "r" (48), "i" (ASI_DMMU),
+ "r" (tte_data), "r" (tte_index << 3), "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+unsigned long
+dtlb_faultva(void)
+{
+ unsigned long faultva;
+
+ asm("ldxa [%1] %2, %0\n"
+ : "=r" (faultva)
+ : "r" (48), "i" (ASI_DMMU));
+
+ return faultva;
+}
+
+void
+dtlb_demap(unsigned long vaddr)
+{
+ asm("stxa %0, [%0] %1\n"
+ : : "r" (vaddr), "i" (ASI_DMMU_DEMAP));
+}
+
+/************************************************************************/
+/* init / cleanup */
+/************************************************************************/
+
+static int remap_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode )
+{
+ ofmem_claim_phys(phys, size, 0);
+ ofmem_claim_virt(virt, size, 0);
+ ofmem_map_page_range(phys, virt, size, mode);
+ if (!(mode & SPITFIRE_TTE_LOCKED)) {
+ OFMEM_TRACE("remap_page_range clearing translation " FMT_ucellx
+ " -> " FMT_ucellx " " FMT_ucellx " mode " FMT_ucellx "\n",
+ virt, phys, size, mode );
+ ofmem_arch_unmap_pages(virt, size);
+ }
+ return 0;
+}
+
+#define RETAIN_MAGIC 0x1100220033004400
+
+void ofmem_init( void )
+{
+ retain_t *retained = ofmem_arch_get_retained();
+ int i;
+
+ memset(&s_ofmem_data, 0, sizeof(s_ofmem_data));
+ s_ofmem_data.ofmem.ramsize = qemu_mem_size;
+
+ /* inherit translations set up by entry.S */
+ ofmem_walk_boot_map(remap_page_range);
+
+ /* Map the memory */
+ ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, 0x800000, 0x36);
+
+ if (!(retained->magic == RETAIN_MAGIC)) {
+ OFMEM_TRACE("ofmem_init: no retained magic found, creating\n");
+ retained->magic = RETAIN_MAGIC;
+ retained->numentries = 0;
+ } else {
+ OFMEM_TRACE("ofmem_init: retained magic found, total %lld mappings\n", retained->numentries);
+
+ /* Mark physical addresses as used so they are not reallocated */
+ for (i = 0; i < retained->numentries; i++) {
+ ofmem_claim_phys(retained->retain_phys_range[i].start,
+ retained->retain_phys_range[i].size, 0);
+ }
+
+ /* Reset retained area for next reset */
+ retained->magic = RETAIN_MAGIC;
+ retained->numentries = 0;
+ }
+}
diff --git a/roms/openbios/arch/sparc64/openbios.c b/roms/openbios/arch/sparc64/openbios.c
new file mode 100644
index 00000000..4557f7f9
--- /dev/null
+++ b/roms/openbios/arch/sparc64/openbios.c
@@ -0,0 +1,664 @@
+/* tag: openbios forth environment, executable code
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "drivers/drivers.h"
+#include "dict.h"
+#include "arch/common/nvram.h"
+#include "packages/nvram.h"
+#include "libopenbios/sys_info.h"
+#include "openbios.h"
+#include "drivers/pci.h"
+#include "asm/pci.h"
+#include "boot.h"
+#include "../../drivers/timer.h" // XXX
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+#include "arch/sparc64/ofmem_sparc64.h"
+#include "spitfire.h"
+
+#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
+#define APB_SPECIAL_BASE 0x1fe00000000ULL
+#define APB_MEM_BASE 0x1ff00000000ULL
+
+#define MEMORY_SIZE (512*1024) /* 512K ram for hosted system */
+
+// XXX
+#define NVRAM_BASE 0x2000
+#define NVRAM_SIZE 0x2000
+#define NVRAM_IDPROM 0x1fd8
+#define NVRAM_IDPROM_SIZE 32
+#define NVRAM_OB_START (0)
+#define NVRAM_OB_SIZE ((NVRAM_IDPROM - NVRAM_OB_START) & ~15)
+
+static uint8_t idprom[NVRAM_IDPROM_SIZE];
+
+struct hwdef {
+ pci_arch_t pci;
+ uint16_t machine_id_low, machine_id_high;
+};
+
+static const struct hwdef hwdefs[] = {
+ {
+ .pci = {
+ .name = "SUNW,sabre",
+ .vendor_id = PCI_VENDOR_ID_SUN,
+ .device_id = PCI_DEVICE_ID_SUN_SABRE,
+ .cfg_addr = APB_SPECIAL_BASE + 0x1000000ULL, // PCI bus configuration space
+ .cfg_data = APB_MEM_BASE, // PCI bus memory space
+ .cfg_base = APB_SPECIAL_BASE,
+ .cfg_len = 0x2000000,
+ .host_pci_base = APB_MEM_BASE,
+ .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */
+ .mem_len = 0x10000000,
+ .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space
+ .io_len = 0x10000,
+ .irqs = { 0, 1, 2, 3 },
+ },
+ .machine_id_low = 0,
+ .machine_id_high = 255,
+ },
+};
+
+struct cpudef {
+ unsigned long iu_version;
+ const char *name;
+ unsigned long ecache_associativity;
+ unsigned long ecache_line_size;
+ unsigned long ecache_size;
+ unsigned long num_dtlb_entries;
+ unsigned long dcache_associativity;
+ unsigned long dcache_line_size;
+ unsigned long dcache_size;
+ unsigned long num_itlb_entries;
+ unsigned long icache_associativity;
+ unsigned long icache_line_size;
+ unsigned long icache_size;
+};
+
+/*
+ ( addr -- ? )
+*/
+
+extern volatile uint64_t client_tba;
+
+static void
+set_trap_table(void)
+{
+ unsigned long addr;
+
+ addr = POP();
+
+ /* Update client_tba to be updated on CIF exit */
+ client_tba = addr;
+}
+
+/* Reset control register is defined in 17.2.7.3 of US IIi User Manual */
+static void
+sparc64_reset_all(void)
+{
+ unsigned long addr = 0x1fe0000f020ULL;
+ unsigned long val = 1 << 29;
+
+ asm("stxa %0, [%1] 0x15\n\t"
+ : : "r" (val), "r" (addr) : "memory");
+}
+
+/* PCI Target Address Space Register (see UltraSPARC IIi User's Manual
+ section 19.3.0.4) */
+#define PBM_PCI_TARGET_AS 0x2028
+#define PBM_PCI_TARGET_AS_CD_ENABLE 0x40
+
+static void
+sparc64_set_tas_register(unsigned long val)
+{
+ unsigned long addr = APB_SPECIAL_BASE + PBM_PCI_TARGET_AS;
+
+ asm("stxa %0, [%1] 0x15\n\t"
+ : : "r" (val), "r" (addr) : "memory");
+}
+
+static void cpu_generic_init(const struct cpudef *cpu, uint32_t clock_frequency)
+{
+ unsigned long iu_version;
+
+ push_str("/");
+ fword("find-device");
+
+ fword("new-device");
+
+ push_str(cpu->name);
+ fword("device-name");
+
+ push_str("cpu");
+ fword("device-type");
+
+ asm("rdpr %%ver, %0\n"
+ : "=r"(iu_version) :);
+
+ PUSH((iu_version >> 48) & 0xff);
+ fword("encode-int");
+ push_str("manufacturer#");
+ fword("property");
+
+ PUSH((iu_version >> 32) & 0xff);
+ fword("encode-int");
+ push_str("implementation#");
+ fword("property");
+
+ PUSH((iu_version >> 24) & 0xff);
+ fword("encode-int");
+ push_str("mask#");
+ fword("property");
+
+ PUSH(9);
+ fword("encode-int");
+ push_str("sparc-version");
+ fword("property");
+
+ PUSH(0);
+ fword("encode-int");
+ push_str("cpuid");
+ fword("property");
+
+ PUSH(0);
+ fword("encode-int");
+ push_str("upa-portid");
+ fword("property");
+
+ PUSH(clock_frequency);
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+
+ PUSH(cpu->ecache_associativity);
+ fword("encode-int");
+ push_str("ecache-associativity");
+ fword("property");
+
+ PUSH(cpu->ecache_line_size);
+ fword("encode-int");
+ push_str("ecache-line-size");
+ fword("property");
+
+ PUSH(cpu->ecache_size);
+ fword("encode-int");
+ push_str("ecache-size");
+ fword("property");
+
+ PUSH(cpu->dcache_associativity);
+ fword("encode-int");
+ push_str("dcache-associativity");
+ fword("property");
+
+ PUSH(cpu->dcache_line_size);
+ fword("encode-int");
+ push_str("dcache-line-size");
+ fword("property");
+
+ PUSH(cpu->dcache_size);
+ fword("encode-int");
+ push_str("dcache-size");
+ fword("property");
+
+ PUSH(cpu->icache_associativity);
+ fword("encode-int");
+ push_str("icache-associativity");
+ fword("property");
+
+ PUSH(cpu->ecache_line_size);
+ fword("encode-int");
+ push_str("icache-line-size");
+ fword("property");
+
+ PUSH(cpu->ecache_size);
+ fword("encode-int");
+ push_str("icache-size");
+ fword("property");
+
+ PUSH(cpu->num_itlb_entries);
+ fword("encode-int");
+ push_str("#itlb-entries");
+ fword("property");
+
+ PUSH(cpu->num_dtlb_entries);
+ fword("encode-int");
+ push_str("#dtlb-entries");
+ fword("property");
+
+ fword("finish-device");
+
+ // Trap table
+ push_str("/openprom/client-services");
+ fword("find-device");
+ bind_func("SUNW,set-trap-table", set_trap_table);
+
+ // Reset
+ bind_func("sparc64-reset-all", sparc64_reset_all);
+ push_str("' sparc64-reset-all to reset-all");
+ fword("eval");
+}
+
+static const struct cpudef sparc_defs[] = {
+ {
+ .iu_version = (0x04ULL << 48) | (0x02ULL << 32),
+ .name = "FJSV,GP",
+ },
+ {
+ .iu_version = (0x04ULL << 48) | (0x03ULL << 32),
+ .name = "FJSV,GPUSK",
+ },
+ {
+ .iu_version = (0x04ULL << 48) | (0x04ULL << 32),
+ .name = "FJSV,GPUSC",
+ },
+ {
+ .iu_version = (0x04ULL << 48) | (0x05ULL << 32),
+ .name = "FJSV,GPUZC",
+ },
+ {
+ .iu_version = (0x17ULL << 48) | (0x10ULL << 32),
+ .name = "SUNW,UltraSPARC",
+ .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x100000,
+ .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000,
+ .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000,
+ .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40,
+ },
+ {
+ .iu_version = (0x17ULL << 48) | (0x11ULL << 32),
+ .name = "SUNW,UltraSPARC-II",
+ .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x100000,
+ .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000,
+ .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000,
+ .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40,
+ },
+ {
+ .iu_version = (0x17ULL << 48) | (0x12ULL << 32),
+ .name = "SUNW,UltraSPARC-IIi",
+ .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x40000,
+ .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000,
+ .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000,
+ .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40,
+ },
+ {
+ .iu_version = (0x17ULL << 48) | (0x13ULL << 32),
+ .name = "SUNW,UltraSPARC-IIe",
+ },
+ {
+ .iu_version = (0x3eULL << 48) | (0x14ULL << 32),
+ .name = "SUNW,UltraSPARC-III",
+ },
+ {
+ .iu_version = (0x3eULL << 48) | (0x15ULL << 32),
+ .name = "SUNW,UltraSPARC-III+",
+ },
+ {
+ .iu_version = (0x3eULL << 48) | (0x16ULL << 32),
+ .name = "SUNW,UltraSPARC-IIIi",
+ },
+ {
+ .iu_version = (0x3eULL << 48) | (0x18ULL << 32),
+ .name = "SUNW,UltraSPARC-IV",
+ },
+ {
+ .iu_version = (0x3eULL << 48) | (0x19ULL << 32),
+ .name = "SUNW,UltraSPARC-IV+",
+ },
+ {
+ .iu_version = (0x3eULL << 48) | (0x22ULL << 32),
+ .name = "SUNW,UltraSPARC-IIIi+",
+ },
+ {
+ .iu_version = (0x3eULL << 48) | (0x23ULL << 32),
+ .name = "SUNW,UltraSPARC-T1",
+ },
+ {
+ .iu_version = (0x3eULL << 48) | (0x24ULL << 32),
+ .name = "SUNW,UltraSPARC-T2",
+ },
+ {
+ .iu_version = (0x22ULL << 48) | (0x10ULL << 32),
+ .name = "SUNW,UltraSPARC",
+ },
+};
+
+static const struct cpudef *
+id_cpu(void)
+{
+ unsigned long iu_version;
+ unsigned int i;
+
+ asm("rdpr %%ver, %0\n"
+ : "=r"(iu_version) :);
+ iu_version &= 0xffffffff00000000ULL;
+
+ for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) {
+ if (iu_version == sparc_defs[i].iu_version)
+ return &sparc_defs[i];
+ }
+ printk("Unknown cpu (psr %lx), freezing!\n", iu_version);
+ for (;;);
+}
+
+static void nvram_read(uint16_t offset, char *buf, unsigned int nbytes)
+{
+ unsigned int i;
+
+ for (i = 0; i < nbytes; i++) {
+ buf[i] = inb(NVRAM_BASE + offset + i);
+ }
+}
+
+static void nvram_write(uint16_t offset, const char *buf, unsigned int nbytes)
+{
+ unsigned int i;
+
+ for (i = 0; i < nbytes; i++) {
+ outb(buf[i], NVRAM_BASE + offset + i);
+ }
+}
+
+static uint8_t qemu_uuid[16];
+
+void arch_nvram_get(char *data)
+{
+ char *obio_cmdline;
+ uint32_t size = 0;
+ const struct cpudef *cpu;
+ char buf[256];
+ uint32_t temp;
+ uint64_t ram_size;
+ uint32_t clock_frequency;
+ uint16_t machine_id;
+ const char *stdin_path, *stdout_path;
+
+ fw_cfg_init();
+
+ fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
+ buf[4] = '\0';
+
+ printk("Configuration device id %s", buf);
+
+ temp = fw_cfg_read_i32(FW_CFG_ID);
+ machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
+
+ printk(" version %d machine id %d\n", temp, machine_id);
+
+ if (temp != 1) {
+ printk("Incompatible configuration device version, freezing\n");
+ for(;;);
+ }
+
+ kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
+ if (kernel_size)
+ kernel_image = fw_cfg_read_i64(FW_CFG_KERNEL_ADDR);
+
+ size = fw_cfg_read_i32(FW_CFG_CMDLINE_SIZE);
+ if (size) {
+ obio_cmdline = (char *)malloc(size + 1);
+ fw_cfg_read(FW_CFG_CMDLINE_DATA, obio_cmdline, size);
+ obio_cmdline[size] = '\0';
+ } else {
+ obio_cmdline = strdup("");
+ }
+ qemu_cmdline = (uint64_t)obio_cmdline;
+ cmdline_size = size;
+ boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
+
+ if (kernel_size)
+ printk("kernel addr %llx size %llx\n", kernel_image, kernel_size);
+ if (size)
+ printk("kernel cmdline %s\n", obio_cmdline);
+
+ nvram_read(NVRAM_OB_START, data, NVRAM_OB_SIZE);
+
+ temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
+
+ printk("CPUs: %x", temp);
+
+ clock_frequency = 100000000;
+
+ cpu = id_cpu();
+ //cpu->initfn();
+ cpu_generic_init(cpu, clock_frequency);
+ printk(" x %s\n", cpu->name);
+
+ // Add /uuid
+ fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
+
+ printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
+ qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
+ qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
+ qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
+ qemu_uuid[15]);
+
+ push_str("/");
+ fword("find-device");
+
+ PUSH((long)&qemu_uuid);
+ PUSH(16);
+ fword("encode-bytes");
+ push_str("uuid");
+ fword("property");
+
+ // Add /idprom
+ nvram_read(NVRAM_IDPROM, (char *)idprom, NVRAM_IDPROM_SIZE);
+
+ PUSH((long)&idprom);
+ PUSH(32);
+ fword("encode-bytes");
+ push_str("idprom");
+ fword("property");
+
+ PUSH(500 * 1000 * 1000);
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+
+ ram_size = fw_cfg_read_i64(FW_CFG_RAM_SIZE);
+
+ ob_mmu_init(cpu->name, ram_size);
+
+ /* Setup nvram variables */
+ push_str("/options");
+ fword("find-device");
+
+ switch (boot_device) {
+ case 'a':
+ push_str("/obio/SUNW,fdtwo");
+ break;
+ case 'c':
+ push_str("disk:a");
+ break;
+ default:
+ case 'd':
+ push_str("cdrom:f cdrom");
+ break;
+ case 'n':
+ push_str("net");
+ break;
+ }
+
+ fword("encode-string");
+ push_str("boot-device");
+ fword("property");
+
+ push_str(obio_cmdline);
+ fword("encode-string");
+ push_str("boot-file");
+ fword("property");
+
+ /* Set up other properties */
+ push_str("/chosen");
+ fword("find-device");
+
+ if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) {
+ stdin_path = stdout_path = "ttya";
+ } else {
+ stdin_path = "keyboard";
+ stdout_path = "screen";
+ }
+
+ push_str(stdin_path);
+ push_str("input-device");
+ fword("$setenv");
+
+ push_str(stdout_path);
+ push_str("output-device");
+ fword("$setenv");
+}
+
+void arch_nvram_put(char *data)
+{
+ nvram_write(0, data, NVRAM_OB_SIZE);
+}
+
+int arch_nvram_size(void)
+{
+ return NVRAM_OB_SIZE;
+}
+
+void setup_timers(void)
+{
+}
+
+void udelay(unsigned int usecs)
+{
+ volatile int i;
+
+ for (i = 0; i < usecs * 100; i++);
+}
+
+static void init_memory(void)
+{
+ phys_addr_t phys;
+ ucell virt;
+
+ /* Claim the memory from OFMEM (align to 512K so we only take 1 TLB slot) */
+ phys = ofmem_claim_phys(-1, MEMORY_SIZE, PAGE_SIZE_512K);
+ if (!phys)
+ printk("panic: not enough physical memory on host system.\n");
+
+ virt = ofmem_claim_virt(-1, MEMORY_SIZE, PAGE_SIZE_512K);
+ if (!virt)
+ printk("panic: not enough virtual memory on host system.\n");
+
+ /* Generate the mapping (and lock translation into the TLBs) */
+ ofmem_map(phys, virt, MEMORY_SIZE, ofmem_arch_default_translation_mode(phys) | SPITFIRE_TTE_LOCKED);
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator
+ */
+
+ PUSH(virt);
+ PUSH(virt + MEMORY_SIZE);
+}
+
+extern volatile uint64_t *obp_ticks_pointer;
+
+static void
+arch_init( void )
+{
+ openbios_init();
+ modules_init();
+#ifdef CONFIG_DRIVER_PCI
+ ob_pci_init();
+
+ /* Set TAS register to match the virtual-dma properties
+ set during sabre configure */
+ sparc64_set_tas_register(PBM_PCI_TARGET_AS_CD_ENABLE);
+#endif
+ nvconf_init();
+ device_end();
+
+ /* Point to the Forth obp-ticks variable */
+ fword("obp-ticks");
+ obp_ticks_pointer = cell2pointer(POP());
+
+ bind_func("platform-boot", boot );
+ bind_func("(go)", go);
+}
+
+unsigned long isa_io_base;
+
+extern struct _console_ops arch_console_ops;
+
+int openbios(void)
+{
+ unsigned int i;
+ uint16_t machine_id;
+ const struct hwdef *hwdef = NULL;
+
+
+ for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
+ isa_io_base = hwdefs[i].pci.io_base;
+ machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
+ if (hwdefs[i].machine_id_low <= machine_id &&
+ hwdefs[i].machine_id_high >= machine_id) {
+ hwdef = &hwdefs[i];
+ arch = &hwdefs[i].pci;
+ break;
+ }
+ }
+ if (!hwdef)
+ for(;;); // Internal inconsistency, hang
+
+#ifdef CONFIG_DEBUG_CONSOLE
+ init_console(arch_console_ops);
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED);
+#endif
+ printk("OpenBIOS for Sparc64\n");
+#endif
+
+ ofmem_init();
+
+ collect_sys_info(&sys_info);
+
+ dict = (unsigned char *)sys_info.dict_start;
+ dicthead = (cell)sys_info.dict_end;
+ last = sys_info.dict_last;
+ dictlimit = sys_info.dict_limit;
+
+ forth_init();
+
+#ifdef CONFIG_DEBUG_BOOT
+ printk("forth started.\n");
+ printk("initializing memory...");
+#endif
+
+ init_memory();
+
+#ifdef CONFIG_DEBUG_BOOT
+ printk("done\n");
+#endif
+
+ PUSH_xt( bind_noname_func(arch_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+
+ if (!PC) {
+ printk("panic: no dictionary entry point.\n");
+ return -1;
+ }
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("done (%d bytes).\n", dicthead);
+ printk("Jumping to dictionary...\n");
+#endif
+
+ enterforth((xt_t)PC);
+ printk("falling off...\n");
+ free(dict);
+ return 0;
+}
diff --git a/roms/openbios/arch/sparc64/openbios.h b/roms/openbios/arch/sparc64/openbios.h
new file mode 100644
index 00000000..2146300d
--- /dev/null
+++ b/roms/openbios/arch/sparc64/openbios.h
@@ -0,0 +1,27 @@
+/*
+ * Creation Date: <2004/01/15 16:14:05 samuel>
+ * Time-stamp: <2004/01/15 16:14:05 samuel>
+ *
+ * <openbios.h>
+ *
+ *
+ *
+ * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_OPENBIOS
+#define _H_OPENBIOS
+
+int openbios(void);
+
+/* console.c */
+#ifdef CONFIG_DEBUG_CONSOLE
+extern void video_init(void);
+#endif
+
+#endif /* _H_OPENBIOS */
diff --git a/roms/openbios/arch/sparc64/openprom.h b/roms/openbios/arch/sparc64/openprom.h
new file mode 100644
index 00000000..0a336901
--- /dev/null
+++ b/roms/openbios/arch/sparc64/openprom.h
@@ -0,0 +1,281 @@
+/* $Id: openprom.h,v 1.9 2001/03/16 10:22:02 davem Exp $ */
+#ifndef __SPARC64_OPENPROM_H
+#define __SPARC64_OPENPROM_H
+
+/* openprom.h: Prom structures and defines for access to the OPENBOOT
+ * prom routines and data areas.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __ASSEMBLY__
+/* V0 prom device operations. */
+struct linux_dev_v0_funcs {
+ int (*v0_devopen)(char *device_str);
+ int (*v0_devclose)(int dev_desc);
+ int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
+};
+
+/* V2 and later prom device operations. */
+struct linux_dev_v2_funcs {
+ int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
+ char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
+ void (*v2_dumb_mem_free)(char *va, unsigned sz);
+
+ /* To map devices into virtual I/O space. */
+ char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
+ void (*v2_dumb_munmap)(char *virta, unsigned size);
+
+ int (*v2_dev_open)(char *devpath);
+ void (*v2_dev_close)(int d);
+ int (*v2_dev_read)(int d, char *buf, int nbytes);
+ int (*v2_dev_write)(int d, char *buf, int nbytes);
+ int (*v2_dev_seek)(int d, int hi, int lo);
+
+ /* Never issued (multistage load support) */
+ void (*v2_wheee2)(void);
+ void (*v2_wheee3)(void);
+};
+
+struct linux_mlist_v0 {
+ struct linux_mlist_v0 *theres_more;
+ unsigned start_adr;
+ unsigned num_bytes;
+};
+
+struct linux_mem_v0 {
+ struct linux_mlist_v0 **v0_totphys;
+ struct linux_mlist_v0 **v0_prommap;
+ struct linux_mlist_v0 **v0_available; /* What we can use */
+};
+
+/* Arguments sent to the kernel from the boot prompt. */
+struct linux_arguments_v0 {
+ char *argv[8];
+ char args[100];
+ char boot_dev[2];
+ int boot_dev_ctrl;
+ int boot_dev_unit;
+ int dev_partition;
+ char *kernel_file_name;
+ void *aieee1; /* XXX */
+};
+
+/* V2 and up boot things. */
+struct linux_bootargs_v2 {
+ char **bootpath;
+ char **bootargs;
+ int *fd_stdin;
+ int *fd_stdout;
+};
+
+/* The top level PROM vector. */
+struct linux_romvec {
+ /* Version numbers. */
+ unsigned int pv_magic_cookie;
+ unsigned int pv_romvers;
+ unsigned int pv_plugin_revision;
+ unsigned int pv_printrev;
+
+ /* Version 0 memory descriptors. */
+ struct linux_mem_v0 pv_v0mem;
+
+ /* Node operations. */
+ struct linux_nodeops *pv_nodeops;
+
+ char **pv_bootstr;
+ struct linux_dev_v0_funcs pv_v0devops;
+
+ char *pv_stdin;
+ char *pv_stdout;
+#define PROMDEV_KBD 0 /* input from keyboard */
+#define PROMDEV_SCREEN 0 /* output to screen */
+#define PROMDEV_TTYA 1 /* in/out to ttya */
+#define PROMDEV_TTYB 2 /* in/out to ttyb */
+
+ /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
+ int (*pv_getchar)(void);
+ void (*pv_putchar)(int ch);
+
+ /* Non-blocking variants. */
+ int (*pv_nbgetchar)(void);
+ int (*pv_nbputchar)(int ch);
+
+ void (*pv_putstr)(char *str, int len);
+
+ /* Miscellany. */
+ void (*pv_reboot)(char *bootstr);
+ void (*pv_printf)(__const__ char *fmt, ...);
+ void (*pv_abort)(void);
+ __volatile__ int *pv_ticks;
+ void (*pv_halt)(void);
+ void (**pv_synchook)(void);
+
+ /* Evaluate a forth string, not different proto for V0 and V2->up. */
+ union {
+ void (*v0_eval)(int len, char *str);
+ void (*v2_eval)(char *str);
+ } pv_fortheval;
+
+ struct linux_arguments_v0 **pv_v0bootargs;
+
+ /* Get ether address. */
+ unsigned int (*pv_enaddr)(int d, char *enaddr);
+
+ struct linux_bootargs_v2 pv_v2bootargs;
+ struct linux_dev_v2_funcs pv_v2devops;
+
+ int filler[15];
+
+ /* This one is sun4c/sun4 only. */
+ void (*pv_setctxt)(int ctxt, char *va, int pmeg);
+
+ /* Prom version 3 Multiprocessor routines. This stuff is crazy.
+ * No joke. Calling these when there is only one cpu probably
+ * crashes the machine, have to test this. :-)
+ */
+
+ /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+ * 'thiscontext' executing at address 'prog_counter'
+ */
+ int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
+ int thiscontext, char *prog_counter);
+
+ /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
+ * until a resume cpu call is made.
+ */
+ int (*v3_cpustop)(unsigned int whichcpu);
+
+ /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+ * resume cpu call is made.
+ */
+ int (*v3_cpuidle)(unsigned int whichcpu);
+
+ /* v3_cpuresume() will resume processor 'whichcpu' executing
+ * starting with whatever 'pc' and 'npc' were left at the
+ * last 'idle' or 'stop' call.
+ */
+ int (*v3_cpuresume)(unsigned int whichcpu);
+};
+
+/* Routines for traversing the prom device tree. */
+struct linux_nodeops {
+ int (*no_nextnode)(int node);
+ int (*no_child)(int node);
+ int (*no_proplen)(int node, char *name);
+ int (*no_getprop)(int node, char *name, char *val);
+ int (*no_setprop)(int node, char *name, char *val, int len);
+ char * (*no_nextprop)(int node, char *name);
+};
+
+/* More fun PROM structures for device probing. */
+#define PROMREG_MAX 16
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 15
+
+struct linux_prom_registers {
+ unsigned which_io; /* hi part of physical address */
+ unsigned phys_addr; /* The physical address of this register */
+ int reg_size; /* How many bytes does this register take up? */
+};
+
+struct linux_prom64_registers {
+ long phys_addr;
+ long reg_size;
+};
+
+struct linux_prom_irqs {
+ int pri; /* IRQ priority */
+ int vector; /* This is foobar, what does it do? */
+};
+
+/* Element of the "ranges" vector */
+struct linux_prom_ranges {
+ unsigned int ot_child_space;
+ unsigned int ot_child_base; /* Bus feels this */
+ unsigned int ot_parent_space;
+ unsigned int ot_parent_base; /* CPU looks from here */
+ unsigned int or_size;
+};
+
+struct linux_prom64_ranges {
+ unsigned long ot_child_base; /* Bus feels this */
+ unsigned long ot_parent_base; /* CPU looks from here */
+ unsigned long or_size;
+};
+
+/* Ranges and reg properties are a bit different for PCI. */
+struct linux_prom_pci_registers {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_pci_ranges {
+ unsigned int child_phys_hi; /* Only certain bits are encoded here. */
+ unsigned int child_phys_mid;
+ unsigned int child_phys_lo;
+
+ unsigned int parent_phys_hi;
+ unsigned int parent_phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_pci_intmap {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int interrupt;
+
+ int cnode;
+ unsigned int cinterrupt;
+};
+
+struct linux_prom_pci_intmask {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+ unsigned int interrupt;
+};
+
+struct linux_prom_ebus_ranges {
+ unsigned int child_phys_hi;
+ unsigned int child_phys_lo;
+
+ unsigned int parent_phys_hi;
+ unsigned int parent_phys_mid;
+ unsigned int parent_phys_lo;
+
+ unsigned int size;
+};
+
+struct linux_prom_ebus_intmap {
+ unsigned int phys_hi;
+ unsigned int phys_lo;
+
+ unsigned int interrupt;
+
+ int cnode;
+ unsigned int cinterrupt;
+};
+
+struct linux_prom_ebus_intmask {
+ unsigned int phys_hi;
+ unsigned int phys_lo;
+ unsigned int interrupt;
+};
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_OPENPROM_H) */
diff --git a/roms/openbios/arch/sparc64/plainboot.c b/roms/openbios/arch/sparc64/plainboot.c
new file mode 100644
index 00000000..08dab2d1
--- /dev/null
+++ b/roms/openbios/arch/sparc64/plainboot.c
@@ -0,0 +1,21 @@
+/* tag: openbios fixed address forth starter
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/sys_info.h"
+#include "multiboot.h"
+
+#define FIXED_DICTSTART 0xfffe0000
+#define FIXED_DICTEND 0xfffeffff
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ info->dict_start=(unsigned long *)FIXED_DICTSTART;
+ info->dict_end=(unsigned long *)FIXED_DICTEND;
+}
diff --git a/roms/openbios/arch/sparc64/pstate.h b/roms/openbios/arch/sparc64/pstate.h
new file mode 100644
index 00000000..f32d6f7d
--- /dev/null
+++ b/roms/openbios/arch/sparc64/pstate.h
@@ -0,0 +1,90 @@
+/* $Id: pstate.h,v 1.6 1997/06/25 07:39:45 jj Exp $ */
+#ifndef _SPARC64_PSTATE_H
+#define _SPARC64_PSTATE_H
+
+#include "const.h"
+
+/* The V9 PSTATE Register (with SpitFire extensions).
+ *
+ * -----------------------------------------------------------------------
+ * | Resv | IG | MG | CLE | TLE | MM | RED | PEF | AM | PRIV | IE | AG |
+ * -----------------------------------------------------------------------
+ * 63 12 11 10 9 8 7 6 5 4 3 2 1 0
+ */
+#define PSTATE_IG _AC(0x0000000000000800,UL) /* Interrupt Globals. */
+#define PSTATE_MG _AC(0x0000000000000400,UL) /* MMU Globals. */
+#define PSTATE_CLE _AC(0x0000000000000200,UL) /* Current Little Endian.*/
+#define PSTATE_TLE _AC(0x0000000000000100,UL) /* Trap Little Endian. */
+#define PSTATE_MM _AC(0x00000000000000c0,UL) /* Memory Model. */
+#define PSTATE_TSO _AC(0x0000000000000000,UL) /* MM: TotalStoreOrder */
+#define PSTATE_PSO _AC(0x0000000000000040,UL) /* MM: PartialStoreOrder */
+#define PSTATE_RMO _AC(0x0000000000000080,UL) /* MM: RelaxedMemoryOrder*/
+#define PSTATE_RED _AC(0x0000000000000020,UL) /* Reset Error Debug. */
+#define PSTATE_PEF _AC(0x0000000000000010,UL) /* Floating Point Enable.*/
+#define PSTATE_AM _AC(0x0000000000000008,UL) /* Address Mask. */
+#define PSTATE_PRIV _AC(0x0000000000000004,UL) /* Privilege. */
+#define PSTATE_IE _AC(0x0000000000000002,UL) /* Interrupt Enable. */
+#define PSTATE_AG _AC(0x0000000000000001,UL) /* Alternate Globals. */
+
+/* The V9 TSTATE Register (with SpitFire and Linux extensions).
+ *
+ * ---------------------------------------------------------------
+ * | Resv | CCR | ASI | %pil | PSTATE | Resv | CWP |
+ * ---------------------------------------------------------------
+ * 63 40 39 32 31 24 23 20 19 8 7 5 4 0
+ */
+#define TSTATE_CCR _AC(0x000000ff00000000,UL) /* Condition Codes. */
+#define TSTATE_XCC _AC(0x000000f000000000,UL) /* Condition Codes. */
+#define TSTATE_XNEG _AC(0x0000008000000000,UL) /* %xcc Negative. */
+#define TSTATE_XZERO _AC(0x0000004000000000,UL) /* %xcc Zero. */
+#define TSTATE_XOVFL _AC(0x0000002000000000,UL) /* %xcc Overflow. */
+#define TSTATE_XCARRY _AC(0x0000001000000000,UL) /* %xcc Carry. */
+#define TSTATE_ICC _AC(0x0000000f00000000,UL) /* Condition Codes. */
+#define TSTATE_INEG _AC(0x0000000800000000,UL) /* %icc Negative. */
+#define TSTATE_IZERO _AC(0x0000000400000000,UL) /* %icc Zero. */
+#define TSTATE_IOVFL _AC(0x0000000200000000,UL) /* %icc Overflow. */
+#define TSTATE_ICARRY _AC(0x0000000100000000,UL) /* %icc Carry. */
+#define TSTATE_ASI _AC(0x00000000ff000000,UL) /* AddrSpace ID. */
+#define TSTATE_PIL _AC(0x0000000000f00000,UL) /* %pil (Linux traps)*/
+#define TSTATE_PSTATE _AC(0x00000000000fff00,UL) /* PSTATE. */
+#define TSTATE_IG _AC(0x0000000000080000,UL) /* Interrupt Globals.*/
+#define TSTATE_MG _AC(0x0000000000040000,UL) /* MMU Globals. */
+#define TSTATE_CLE _AC(0x0000000000020000,UL) /* CurrLittleEndian. */
+#define TSTATE_TLE _AC(0x0000000000010000,UL) /* TrapLittleEndian. */
+#define TSTATE_MM _AC(0x000000000000c000,UL) /* Memory Model. */
+#define TSTATE_TSO _AC(0x0000000000000000,UL) /* MM: TSO */
+#define TSTATE_PSO _AC(0x0000000000004000,UL) /* MM: PSO */
+#define TSTATE_RMO _AC(0x0000000000008000,UL) /* MM: RMO */
+#define TSTATE_RED _AC(0x0000000000002000,UL) /* Reset Error Debug.*/
+#define TSTATE_PEF _AC(0x0000000000001000,UL) /* FPU Enable. */
+#define TSTATE_AM _AC(0x0000000000000800,UL) /* Address Mask. */
+#define TSTATE_PRIV _AC(0x0000000000000400,UL) /* Privilege. */
+#define TSTATE_IE _AC(0x0000000000000200,UL) /* Interrupt Enable. */
+#define TSTATE_AG _AC(0x0000000000000100,UL) /* Alternate Globals.*/
+#define TSTATE_CWP _AC(0x000000000000001f,UL) /* Curr Win-Pointer. */
+
+/* Floating-Point Registers State Register.
+ *
+ * --------------------------------
+ * | Resv | FEF | DU | DL |
+ * --------------------------------
+ * 63 3 2 1 0
+ */
+#define FPRS_FEF _AC(0x0000000000000004,UL) /* FPU Enable. */
+#define FPRS_DU _AC(0x0000000000000002,UL) /* Dirty Upper. */
+#define FPRS_DL _AC(0x0000000000000001,UL) /* Dirty Lower. */
+
+/* Version Register.
+ *
+ * ------------------------------------------------------
+ * | MANUF | IMPL | MASK | Resv | MAXTL | Resv | MAXWIN |
+ * ------------------------------------------------------
+ * 63 48 47 32 31 24 23 16 15 8 7 5 4 0
+ */
+#define VERS_MANUF _AC(0xffff000000000000,UL) /* Manufacturer. */
+#define VERS_IMPL _AC(0x0000ffff00000000,UL) /* Implementation. */
+#define VERS_MASK _AC(0x00000000ff000000,UL) /* Mask Set Revision.*/
+#define VERS_MAXTL _AC(0x000000000000ff00,UL) /* Max Trap Level. */
+#define VERS_MAXWIN _AC(0x000000000000001f,UL) /* Max RegWindow Idx.*/
+
+#endif /* !(_SPARC64_PSTATE_H) */
diff --git a/roms/openbios/arch/sparc64/spitfire.h b/roms/openbios/arch/sparc64/spitfire.h
new file mode 100644
index 00000000..4a951b1f
--- /dev/null
+++ b/roms/openbios/arch/sparc64/spitfire.h
@@ -0,0 +1,510 @@
+/* $Id: spitfire.h,v 1.18 2001/11/29 16:42:10 kanoj Exp $
+ * spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC64_SPITFIRE_H
+#define _SPARC64_SPITFIRE_H
+
+#include <asm/asi.h>
+
+/* The following register addresses are accessible via ASI_DMMU
+ * and ASI_IMMU, that is there is a distinct and unique copy of
+ * each these registers for each TLB.
+ */
+#define TSB_TAG_TARGET 0x0000000000000000 /* All chips */
+#define TLB_SFSR 0x0000000000000018 /* All chips */
+#define TSB_REG 0x0000000000000028 /* All chips */
+#define TLB_TAG_ACCESS 0x0000000000000030 /* All chips */
+#define VIRT_WATCHPOINT 0x0000000000000038 /* All chips */
+#define PHYS_WATCHPOINT 0x0000000000000040 /* All chips */
+#define TSB_EXTENSION_P 0x0000000000000048 /* Ultra-III and later */
+#define TSB_EXTENSION_S 0x0000000000000050 /* Ultra-III and later, D-TLB only */
+#define TSB_EXTENSION_N 0x0000000000000058 /* Ultra-III and later */
+#define TLB_TAG_ACCESS_EXT 0x0000000000000060 /* Ultra-III+ and later */
+
+/* These registers only exist as one entity, and are accessed
+ * via ASI_DMMU only.
+ */
+#define PRIMARY_CONTEXT 0x0000000000000008
+#define SECONDARY_CONTEXT 0x0000000000000010
+#define DMMU_SFAR 0x0000000000000020
+#define VIRT_WATCHPOINT 0x0000000000000038
+#define PHYS_WATCHPOINT 0x0000000000000040
+
+#define SPITFIRE_HIGHEST_LOCKED_TLBENT (64 - 1)
+
+/* translation table entry bits */
+#define SPITFIRE_TTE_WRITABLE 0x02
+#define SPITFIRE_TTE_PRIVILEGED 0x04
+#define SPITFIRE_TTE_CV 0x10
+#define SPITFIRE_TTE_CP 0x20
+#define SPITFIRE_TTE_LOCKED 0x40
+#define SPITFIRE_TTE_VALID 0x8000000000000000ULL
+
+#ifndef __ASSEMBLY__
+
+enum ultra_tlb_layout {
+ spitfire = 0,
+ cheetah = 1,
+ cheetah_plus = 2,
+};
+
+extern enum ultra_tlb_layout tlb_type;
+
+#define CHEETAH_HIGHEST_LOCKED_TLBENT (16 - 1)
+
+#define L1DCACHE_SIZE 0x4000
+
+#define sparc64_highest_locked_tlbent() \
+ (tlb_type == spitfire ? \
+ SPITFIRE_HIGHEST_LOCKED_TLBENT : \
+ CHEETAH_HIGHEST_LOCKED_TLBENT)
+
+static __inline__ unsigned long spitfire_get_isfsr(void)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (ret)
+ : "r" (TLB_SFSR), "i" (ASI_IMMU));
+ return ret;
+}
+
+static __inline__ unsigned long spitfire_get_dsfsr(void)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (ret)
+ : "r" (TLB_SFSR), "i" (ASI_DMMU));
+ return ret;
+}
+
+static __inline__ unsigned long spitfire_get_sfar(void)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (ret)
+ : "r" (DMMU_SFAR), "i" (ASI_DMMU));
+ return ret;
+}
+
+static __inline__ void spitfire_put_isfsr(unsigned long sfsr)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (sfsr), "r" (TLB_SFSR), "i" (ASI_IMMU));
+}
+
+static __inline__ void spitfire_put_dsfsr(unsigned long sfsr)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (sfsr), "r" (TLB_SFSR), "i" (ASI_DMMU));
+}
+
+static __inline__ unsigned long spitfire_get_primary_context(void)
+{
+ unsigned long ctx;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (ctx)
+ : "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+ return ctx;
+}
+
+static __inline__ void spitfire_set_primary_context(unsigned long ctx)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (ctx & 0x3ff),
+ "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
+ __asm__ __volatile__ ("membar #Sync" : : : "memory");
+}
+
+static __inline__ unsigned long spitfire_get_secondary_context(void)
+{
+ unsigned long ctx;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (ctx)
+ : "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU));
+ return ctx;
+}
+
+static __inline__ void spitfire_set_secondary_context(unsigned long ctx)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (ctx & 0x3ff),
+ "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU));
+ __asm__ __volatile__ ("membar #Sync" : : : "memory");
+}
+
+/* The data cache is write through, so this just invalidates the
+ * specified line.
+ */
+static __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG));
+ __asm__ __volatile__ ("membar #Sync" : : : "memory");
+}
+
+/* The instruction cache lines are flushed with this, but note that
+ * this does not flush the pipeline. It is possible for a line to
+ * get flushed but stale instructions to still be in the pipeline,
+ * a flush instruction (to any address) is sufficient to handle
+ * this issue after the line is invalidated.
+ */
+static __inline__ void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
+}
+
+static __inline__ unsigned long spitfire_get_dtlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS));
+
+ /* Clear TTE diag bits. */
+ data &= ~0x0003fe0000000000UL;
+
+ return data;
+}
+
+static __inline__ unsigned long spitfire_get_dtlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" (entry << 3), "i" (ASI_DTLB_TAG_READ));
+ return tag;
+}
+
+static __inline__ void spitfire_put_dtlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data), "r" (entry << 3),
+ "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static __inline__ unsigned long spitfire_get_itlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS));
+
+ /* Clear TTE diag bits. */
+ data &= ~0x0003fe0000000000UL;
+
+ return data;
+}
+
+static __inline__ unsigned long spitfire_get_itlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" (entry << 3), "i" (ASI_ITLB_TAG_READ));
+ return tag;
+}
+
+static __inline__ void spitfire_put_itlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data), "r" (entry << 3),
+ "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+/* Spitfire hardware assisted TLB flushes. */
+
+/* Context level flushes. */
+static __inline__ void spitfire_flush_dtlb_primary_context(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x40), "i" (ASI_DMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_itlb_primary_context(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x40), "i" (ASI_IMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_dtlb_secondary_context(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x50), "i" (ASI_DMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_itlb_secondary_context(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x50), "i" (ASI_IMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_dtlb_nucleus_context(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x60), "i" (ASI_DMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_itlb_nucleus_context(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x60), "i" (ASI_IMMU_DEMAP));
+}
+
+/* Page level flushes. */
+static __inline__ void spitfire_flush_dtlb_primary_page(unsigned long page)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (page), "i" (ASI_DMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_itlb_primary_page(unsigned long page)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (page), "i" (ASI_IMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_dtlb_secondary_page(unsigned long page)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (page | 0x10), "i" (ASI_DMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_itlb_secondary_page(unsigned long page)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (page | 0x10), "i" (ASI_IMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_dtlb_nucleus_page(unsigned long page)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
+}
+
+static __inline__ void spitfire_flush_itlb_nucleus_page(unsigned long page)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (page | 0x20), "i" (ASI_IMMU_DEMAP));
+}
+
+/* Cheetah has "all non-locked" tlb flushes. */
+static __inline__ void cheetah_flush_dtlb_all(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x80), "i" (ASI_DMMU_DEMAP));
+}
+
+static __inline__ void cheetah_flush_itlb_all(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x80), "i" (ASI_IMMU_DEMAP));
+}
+
+/* Cheetah has a 4-tlb layout so direct access is a bit different.
+ * The first two TLBs are fully assosciative, hold 16 entries, and are
+ * used only for locked and >8K sized translations. One exists for
+ * data accesses and one for instruction accesses.
+ *
+ * The third TLB is for data accesses to 8K non-locked translations, is
+ * 2 way assosciative, and holds 512 entries. The fourth TLB is for
+ * instruction accesses to 8K non-locked translations, is 2 way
+ * assosciative, and holds 128 entries.
+ *
+ * Cheetah has some bug where bogus data can be returned from
+ * ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes
+ * the problem for me. -DaveM
+ */
+static __inline__ unsigned long cheetah_get_ldtlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
+ "ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_DTLB_DATA_ACCESS));
+
+ return data;
+}
+
+static __inline__ unsigned long cheetah_get_litlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
+ "ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_DATA_ACCESS));
+
+ return data;
+}
+
+static __inline__ unsigned long cheetah_get_ldtlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_DTLB_TAG_READ));
+
+ return tag;
+}
+
+static __inline__ unsigned long cheetah_get_litlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_TAG_READ));
+
+ return tag;
+}
+
+static __inline__ void cheetah_put_ldtlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data),
+ "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static __inline__ void cheetah_put_litlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data),
+ "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+static __inline__ unsigned long cheetah_get_dtlb_data(int entry, int tlb)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
+ "ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
+
+ return data;
+}
+
+static __inline__ unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
+ return tag;
+}
+
+static __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data),
+ "r" ((tlb << 16) | (entry << 3)),
+ "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static __inline__ unsigned long cheetah_get_itlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
+ "ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" ((2 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_DATA_ACCESS));
+
+ return data;
+}
+
+static __inline__ unsigned long cheetah_get_itlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ));
+ return tag;
+}
+
+static __inline__ void cheetah_put_itlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data), "r" ((2 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_SPARC64_SPITFIRE_H) */
diff --git a/roms/openbios/arch/sparc64/switch.S b/roms/openbios/arch/sparc64/switch.S
new file mode 100644
index 00000000..d2cc7bed
--- /dev/null
+++ b/roms/openbios/arch/sparc64/switch.S
@@ -0,0 +1,124 @@
+#include "pstate.h"
+#include <asm/asi.h>
+#define ASI_BP ASI_M_BYPASS
+#define REGWIN_SZ 0x40
+
+ .globl __switch_context, __switch_context_nosave, __exit_context, halt
+
+ .text
+ .align 4
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .register %g6, #scratch
+ .register %g7, #scratch
+
+/*
+ * Switch execution context
+ * This saves registers in the stack, then
+ * switches the stack, and restores everything from the new stack.
+ * This function takes no argument. New stack pointer is
+ * taken from global variable __context, and old stack pointer
+ * is also saved to __context. This way we can just jump to
+ * this routine to get back to the original context.
+ */
+
+/* XXX: totally bogus for sparc, need to save and restore all windows */
+__switch_context:
+
+ /* make sure caller's windows are on caller's stack */
+ flushw;
+
+ /* Save everything in current stack */
+
+ setx __context, %g2, %g1
+ stx %g3, [%g1 + 24]
+ stx %g4, [%g1 + 32]
+ stx %g5, [%g1 + 40]
+ stx %g6, [%g1 + 48]
+ stx %g7, [%g1 + 56]
+
+ stx %o0, [%g1 + 64]
+ stx %o1, [%g1 + 72]
+ stx %o2, [%g1 + 80]
+ stx %o3, [%g1 + 88]
+ stx %o4, [%g1 + 96]
+ stx %o5, [%g1 + 104]
+ stx %o6, [%g1 + 112]
+ stx %o7, [%g1 + 120]
+
+ stx %l0, [%g1 + 128]
+ stx %l1, [%g1 + 136]
+ stx %l2, [%g1 + 144]
+ stx %l3, [%g1 + 152]
+ stx %l4, [%g1 + 160]
+ stx %l5, [%g1 + 168]
+ stx %l6, [%g1 + 176]
+ stx %l7, [%g1 + 184]
+
+ stx %i0, [%g1 + 192]
+ stx %i1, [%g1 + 200]
+ stx %i2, [%g1 + 208]
+ stx %i3, [%g1 + 216]
+ stx %i4, [%g1 + 224]
+ stx %i5, [%g1 + 232]
+ stx %i6, [%g1 + 240]
+ stx %i7, [%g1 + 248]
+
+__switch_context_nosave:
+ /* Interrupts are not allowed... */
+ /* make sure caller's windows are on caller's stack */
+ flushw
+ /* Load all registers
+ */
+ setx __context, %g2, %g1
+ ldx [%g1], %g1
+ ldx [%g1 + 16], %g2
+ ldx [%g1 + 24], %g3
+ ldx [%g1 + 32], %g4
+ ldx [%g1 + 40], %g5
+ ldx [%g1 + 48], %g6
+ ldx [%g1 + 56], %g7
+
+ ldx [%g1 + 64], %o0
+ ldx [%g1 + 72], %o1
+ ldx [%g1 + 80], %o2
+ ldx [%g1 + 88], %o3
+ ldx [%g1 + 96], %o4
+ ldx [%g1 + 104], %o5
+ ldx [%g1 + 112], %o6
+ ldx [%g1 + 120], %o7
+
+ ldx [%g1 + 128], %l0
+ ldx [%g1 + 136], %l1
+ ldx [%g1 + 144], %l2
+ ldx [%g1 + 152], %l3
+ ldx [%g1 + 160], %l4
+ ldx [%g1 + 168], %l5
+ ldx [%g1 + 176], %l6
+ ldx [%g1 + 184], %l7
+
+ ldx [%g1 + 192], %i0
+ ldx [%g1 + 200], %i1
+ ldx [%g1 + 208], %i2
+ ldx [%g1 + 216], %i3
+ ldx [%g1 + 224], %i4
+ ldx [%g1 + 232], %i5
+ ldx [%g1 + 240], %i6
+ ldx [%g1 + 248], %i7
+
+ ldx [%g1 + 256], %g1
+ /* Finally, load new %pc */
+ jmp %g1
+ clr %g1
+
+__exit_context:
+ /* Get back to the original context */
+ call __switch_context
+ nop
+
+ /* We get here if the other context attempt to switch to this
+ * dead context. This should not happen. */
+
+halt:
+ b halt
+ nop
diff --git a/roms/openbios/arch/sparc64/sys_info.c b/roms/openbios/arch/sparc64/sys_info.c
new file mode 100644
index 00000000..f70aa027
--- /dev/null
+++ b/roms/openbios/arch/sparc64/sys_info.c
@@ -0,0 +1,59 @@
+#include "config.h"
+#include "kernel/kernel.h"
+#include "arch/common/elf_boot.h"
+#include "libopenbios/sys_info.h"
+#include "context.h"
+#include "boot.h"
+
+#define printf printk
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+uint64_t qemu_mem_size;
+unsigned long va_shift;
+
+void collect_multiboot_info(struct sys_info *);
+
+void collect_sys_info(struct sys_info *info)
+{
+ int i;
+ unsigned long long total = 0;
+ struct memrange *mmap;
+
+ /* Pick up paramters given by bootloader to us */
+ //info->boot_type = boot_ctx->eax;
+ //info->boot_data = boot_ctx->ebx;
+ info->boot_arg = boot_ctx->param[0];
+ //debug("boot eax = %#lx\n", info->boot_type);
+ //debug("boot ebx = %#lx\n", info->boot_data);
+ info->boot_type = ELF_BHDR_MAGIC;
+ info->boot_data = virt_to_phys(&elf_image_notes);
+ debug("boot arg = %#lx\n", info->boot_arg);
+
+ collect_elfboot_info(info);
+#ifdef CONFIG_LINUXBIOS
+ collect_linuxbios_info(info);
+#endif
+#ifdef CONFIG_IMAGE_ELF_MULTIBOOT
+ collect_multiboot_info(info);
+#endif
+
+ if (!info->memrange) {
+ info->n_memranges = 1;
+ info->memrange = malloc(1 * sizeof(struct memrange));
+ info->memrange[0].base = 0;
+ info->memrange[0].size = qemu_mem_size;
+ }
+
+ debug("\n");
+ mmap=info->memrange;
+ for (i = 0; i < info->n_memranges; i++) {
+ debug("%08lx-", (long)mmap[i].base);
+ debug("%08lx\n", (long)mmap[i].base + (long)mmap[i].size);
+ total += mmap[i].size;
+ }
+ debug("RAM %ld MB\n", (long)total >> 20);
+}
diff --git a/roms/openbios/arch/sparc64/tree.fs b/roms/openbios/arch/sparc64/tree.fs
new file mode 100644
index 00000000..e034b593
--- /dev/null
+++ b/roms/openbios/arch/sparc64/tree.fs
@@ -0,0 +1,49 @@
+include config.fs
+
+\ -------------------------------------------------------------------------
+\ UPA encode/decode unit
+\ -------------------------------------------------------------------------
+
+: decode-unit-upa ( str len -- id lun )
+ ascii , left-split
+ ( addr-R len-R addr-L len-L )
+ parse-hex
+ -rot parse-hex
+ swap
+;
+
+: encode-unit-upa ( id lun -- str len)
+ swap
+ pocket tohexstr
+ " ," pocket tmpstrcat >r
+ rot pocket tohexstr r> tmpstrcat drop
+;
+
+" /" find-device
+ 2 encode-int " #address-cells" property
+ 2 encode-int " #size-cells" property
+ " sun4u" encode-string " compatible" property
+
+ : encode-unit encode-unit-upa ;
+ : decode-unit decode-unit-upa ;
+
+new-device
+ " memory" device-name
+ " memory" device-type
+ external
+ : open true ;
+ : close ;
+ \ see arch/sparc64/lib.c for methods
+finish-device
+
+new-device
+ " virtual-memory" device-name
+ external
+ \ see arch/sparc64/lib.c for methods
+finish-device
+
+" /options" find-device
+ " disk" encode-string " boot-from" property
+
+" /openprom" find-device
+ " OBP 3.10.24 1999/01/01 01:01" encode-string " version" property
diff --git a/roms/openbios/arch/sparc64/vectors.S b/roms/openbios/arch/sparc64/vectors.S
new file mode 100644
index 00000000..927c1cdc
--- /dev/null
+++ b/roms/openbios/arch/sparc64/vectors.S
@@ -0,0 +1,765 @@
+/*
+ * <vectors.S>
+ *
+ * Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions.
+ *
+ * Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ */
+
+#define __ASSEMBLY__
+#include "pstate.h"
+#include <asm/asi.h>
+#define ASI_BP ASI_PHYS_BYPASS_EC_E
+#define PROM_ADDR 0x1fff0000000
+#define SER_ADDR 0x1fe020003f8
+#define TICK_INT_DIS 0x8000000000000000
+#define TICK_INTERVAL 1*1000*1000
+
+ .section ".text.vectors", "ax"
+ .align 16384
+/* Sparc64 trap table */
+ .globl trap_table, __divide_error, softint_irq, softint_irq_tl1
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .register %g6, #scratch
+ .register %g7, #scratch
+trap_table:
+#define SPILL_WINDOW \
+ btst 1, %sp; \
+ be spill_32bit; \
+ nop; \
+ stx %l0, [%sp + STACK_BIAS + 0x00]; \
+ stx %l1, [%sp + STACK_BIAS + 0x08]; \
+ stx %l2, [%sp + STACK_BIAS + 0x10]; \
+ stx %l3, [%sp + STACK_BIAS + 0x18]; \
+ stx %l4, [%sp + STACK_BIAS + 0x20]; \
+ stx %l5, [%sp + STACK_BIAS + 0x28]; \
+ stx %l6, [%sp + STACK_BIAS + 0x30]; \
+ stx %l7, [%sp + STACK_BIAS + 0x38]; \
+ stx %i0, [%sp + STACK_BIAS + 0x40]; \
+ stx %i1, [%sp + STACK_BIAS + 0x48]; \
+ stx %i2, [%sp + STACK_BIAS + 0x50]; \
+ stx %i3, [%sp + STACK_BIAS + 0x58]; \
+ stx %i4, [%sp + STACK_BIAS + 0x60]; \
+ stx %i5, [%sp + STACK_BIAS + 0x68]; \
+ stx %i6, [%sp + STACK_BIAS + 0x70]; \
+ stx %i7, [%sp + STACK_BIAS + 0x78]; \
+ saved; retry; nop; nop; nop; nop; nop; nop; \
+ nop; nop; nop; nop; nop;
+
+#define FILL_WINDOW \
+ btst 1, %sp; \
+ be fill_32bit; \
+ nop; \
+ ldx [%sp + STACK_BIAS + 0x00], %l0; \
+ ldx [%sp + STACK_BIAS + 0x08], %l1; \
+ ldx [%sp + STACK_BIAS + 0x10], %l2; \
+ ldx [%sp + STACK_BIAS + 0x18], %l3; \
+ ldx [%sp + STACK_BIAS + 0x20], %l4; \
+ ldx [%sp + STACK_BIAS + 0x28], %l5; \
+ ldx [%sp + STACK_BIAS + 0x30], %l6; \
+ ldx [%sp + STACK_BIAS + 0x38], %l7; \
+ ldx [%sp + STACK_BIAS + 0x40], %i0; \
+ ldx [%sp + STACK_BIAS + 0x48], %i1; \
+ ldx [%sp + STACK_BIAS + 0x50], %i2; \
+ ldx [%sp + STACK_BIAS + 0x58], %i3; \
+ ldx [%sp + STACK_BIAS + 0x60], %i4; \
+ ldx [%sp + STACK_BIAS + 0x68], %i5; \
+ ldx [%sp + STACK_BIAS + 0x70], %i6; \
+ ldx [%sp + STACK_BIAS + 0x78], %i7; \
+ restored; retry; nop; nop; nop; nop; nop; nop; \
+ nop; nop; nop; nop; nop;
+
+#define CLEAN_WINDOW \
+ rdpr %cleanwin, %l0; add %l0, 1, %l0; \
+ wrpr %l0, 0x0, %cleanwin; \
+ clr %o0; clr %o1; clr %o2; clr %o3; \
+ clr %o4; clr %o5; clr %o6; clr %o7; \
+ clr %l0; clr %l1; clr %l2; clr %l3; \
+ clr %l4; clr %l5; clr %l6; clr %l7; \
+ retry; \
+ nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
+
+#define TRAP_IRQ(routine, level) \
+ ba routine; mov level, %g1; nop; nop; nop; nop; nop; nop;
+#define BTRAP(lvl) \
+ ba bug; mov lvl, %g1; nop; nop; nop; nop; nop; nop;
+#define BTRAPTL1(lvl) BTRAP(lvl)
+#define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7)
+#define BTRAPS4(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3)
+#define TRAP_HANDLER(routine) ba routine; nop; nop; nop; nop; nop; nop; nop;
+
+#define STACK_BIAS 2047
+ .globl sparc64_ttable_tl0, sparc64_ttable_tl1
+sparc64_ttable_tl0:
+ ba entry; nop; nop; nop; nop; nop; nop; nop;! XXX remove
+ ba entry; nop; nop; nop; nop; nop; nop; nop;! Power-on reset
+ ba entry; nop; nop; nop; nop; nop; nop; nop;! Watchdog reset
+ ba entry; nop; nop; nop; nop; nop; nop; nop;! External reset
+ ba entry; nop; nop; nop; nop; nop; nop; nop;! Software reset
+ ba entry; nop; nop; nop; nop; nop; nop; nop;! RED state
+ BTRAP(0x06) BTRAP(0x07) BTRAPS(0x08)
+ BTRAPS(0x10) BTRAPS(0x18)
+ BTRAP(0x20) BTRAP(0x21) BTRAP(0x22) BTRAP(0x23)
+ CLEAN_WINDOW ! 24-27
+ BTRAPS(0x28)
+ BTRAPS(0x30) BTRAPS(0x38)
+ BTRAP(0x40) BTRAP(0x41) BTRAP(0x42) BTRAP(0x43)
+tl0_irq4: TRAP_IRQ(handler_irq, 4)
+tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6)
+tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8)
+tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10)
+tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
+tl0_irq13: TRAP_IRQ(handler_irq, 13)
+tl0_irq14: TRAP_IRQ(softint_irq, 14)
+tl0_irq15: TRAP_IRQ(handler_irq, 15)
+ BTRAPS(0x50) BTRAPS(0x58)
+ BTRAPS4(0x60)
+ TRAP_HANDLER(reload_IMMU_tlb) ! 0x64 : instruction_access_MMU_miss
+ TRAP_HANDLER(reload_IMMU_tlb) ! 0x65 : instruction_access_MMU_miss
+ TRAP_HANDLER(reload_IMMU_tlb) ! 0x66 : instruction_access_MMU_miss
+ TRAP_HANDLER(reload_IMMU_tlb) ! 0x67 : instruction_access_MMU_miss
+ TRAP_HANDLER(reload_DMMU_tlb) ! 0x68 : data_access_MMU_miss
+ TRAP_HANDLER(reload_DMMU_tlb) ! 0x69 : data_access_MMU_miss
+ TRAP_HANDLER(reload_DMMU_tlb) ! 0x6A : data_access_MMU_miss
+ TRAP_HANDLER(reload_DMMU_tlb) ! 0x6B : data_access_MMU_miss
+ BTRAPS4(0x6C) ! data_access_protection
+ BTRAPS(0x70) BTRAPS(0x78)
+tl0_s0n: SPILL_WINDOW
+tl0_s1n: SPILL_WINDOW
+tl0_s2n: SPILL_WINDOW
+tl0_s3n: SPILL_WINDOW
+tl0_s4n: SPILL_WINDOW
+tl0_s5n: SPILL_WINDOW
+tl0_s6n: SPILL_WINDOW
+tl0_s7n: SPILL_WINDOW
+tl0_s0o: SPILL_WINDOW
+tl0_s1o: SPILL_WINDOW
+tl0_s2o: SPILL_WINDOW
+tl0_s3o: SPILL_WINDOW
+tl0_s4o: SPILL_WINDOW
+tl0_s5o: SPILL_WINDOW
+tl0_s6o: SPILL_WINDOW
+tl0_s7o: SPILL_WINDOW
+tl0_f0n: FILL_WINDOW
+tl0_f1n: FILL_WINDOW
+tl0_f2n: FILL_WINDOW
+tl0_f3n: FILL_WINDOW
+tl0_f4n: FILL_WINDOW
+tl0_f5n: FILL_WINDOW
+tl0_f6n: FILL_WINDOW
+tl0_f7n: FILL_WINDOW
+tl0_f0o: FILL_WINDOW
+tl0_f1o: FILL_WINDOW
+tl0_f2o: FILL_WINDOW
+tl0_f3o: FILL_WINDOW
+tl0_f4o: FILL_WINDOW
+tl0_f5o: FILL_WINDOW
+tl0_f6o: FILL_WINDOW
+tl0_f7o: FILL_WINDOW
+tl0_resv100: BTRAPS(0x100) BTRAPS(0x108)
+tl0_resv110: BTRAPS(0x110) BTRAPS(0x118)
+tl0_resv120: BTRAPS(0x120) BTRAPS(0x128)
+tl0_resv130: BTRAPS(0x130) BTRAPS(0x138)
+tl0_resv140: BTRAPS(0x140) BTRAPS(0x148)
+tl0_resv150: BTRAPS(0x150) BTRAPS(0x158)
+tl0_resv160: BTRAPS(0x160) BTRAPS(0x168)
+tl0_resv170: BTRAPS(0x170) BTRAPS(0x178)
+tl0_resv180: BTRAPS(0x180) BTRAPS(0x188)
+tl0_resv190: BTRAPS(0x190) BTRAPS(0x198)
+tl0_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8)
+tl0_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8)
+tl0_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8)
+tl0_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8)
+tl0_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8)
+tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8)
+
+#undef BTRAPS
+#define BTRAPS(x) BTRAPTL1(x) BTRAPTL1(x+1) BTRAPTL1(x+2) BTRAPTL1(x+3) BTRAPTL1(x+4) BTRAPTL1(x+5) BTRAPTL1(x+6) BTRAPTL1(x+7)
+
+#define SKIP_IRQ(routine, level) \
+ retry; nop; nop; nop; nop; nop; nop; nop;
+
+sparc64_ttable_tl1:
+ BTRAPS(0x00) BTRAPS(0x08)
+ BTRAPS(0x10) BTRAPS(0x18)
+ BTRAPTL1(0x20) BTRAPTL1(0x21) BTRAPTL1(0x22) BTRAPTL1(0x23)
+ CLEAN_WINDOW ! 24-27
+ BTRAPS(0x28)
+ BTRAPS(0x30) BTRAPS(0x38)
+ BTRAPTL1(0x40) BTRAPTL1(0x41) BTRAPTL1(0x42) BTRAPTL1(0x43)
+tl1_irq4: TRAP_IRQ(handler_irq, 4)
+tl1_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6)
+tl1_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8)
+tl1_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10)
+tl1_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
+tl1_irq13: TRAP_IRQ(handler_irq, 13)
+tl1_irq14: SKIP_IRQ(softint_irq, 14)
+tl1_irq15: TRAP_IRQ(handler_irq, 15)
+ BTRAPS(0x50) BTRAPS(0x58)
+ BTRAPS4(0x60)
+ TRAP_HANDLER(reload_IMMU_tlb) ! 0x64 : instruction_access_MMU_miss
+ TRAP_HANDLER(reload_IMMU_tlb) ! 0x65 : instruction_access_MMU_miss
+ TRAP_HANDLER(reload_IMMU_tlb) ! 0x66 : instruction_access_MMU_miss
+ TRAP_HANDLER(reload_IMMU_tlb) ! 0x67 : instruction_access_MMU_miss
+ TRAP_HANDLER(reload_DMMU_tlb) ! 0x68 : data_access_MMU_miss
+ TRAP_HANDLER(reload_DMMU_tlb) ! 0x69 : data_access_MMU_miss
+ TRAP_HANDLER(reload_DMMU_tlb) ! 0x6A : data_access_MMU_miss
+ TRAP_HANDLER(reload_DMMU_tlb) ! 0x6B : data_access_MMU_miss
+ BTRAPS4(0x6C) ! data_access_protection
+ BTRAPS(0x70) BTRAPS(0x78)
+tl1_s0n: SPILL_WINDOW
+tl1_s1n: SPILL_WINDOW
+tl1_s2n: SPILL_WINDOW
+tl1_s3n: SPILL_WINDOW
+tl1_s4n: SPILL_WINDOW
+tl1_s5n: SPILL_WINDOW
+tl1_s6n: SPILL_WINDOW
+tl1_s7n: SPILL_WINDOW
+tl1_s0o: SPILL_WINDOW
+tl1_s1o: SPILL_WINDOW
+tl1_s2o: SPILL_WINDOW
+tl1_s3o: SPILL_WINDOW
+tl1_s4o: SPILL_WINDOW
+tl1_s5o: SPILL_WINDOW
+tl1_s6o: SPILL_WINDOW
+tl1_s7o: SPILL_WINDOW
+tl1_f0n: FILL_WINDOW
+tl1_f1n: FILL_WINDOW
+tl1_f2n: FILL_WINDOW
+tl1_f3n: FILL_WINDOW
+tl1_f4n: FILL_WINDOW
+tl1_f5n: FILL_WINDOW
+tl1_f6n: FILL_WINDOW
+tl1_f7n: FILL_WINDOW
+tl1_f0o: FILL_WINDOW
+tl1_f1o: FILL_WINDOW
+tl1_f2o: FILL_WINDOW
+tl1_f3o: FILL_WINDOW
+tl1_f4o: FILL_WINDOW
+tl1_f5o: FILL_WINDOW
+tl1_f6o: FILL_WINDOW
+tl1_f7o: FILL_WINDOW
+tl1_resv100: BTRAPS(0x100) BTRAPS(0x108)
+tl1_resv110: BTRAPS(0x110) BTRAPS(0x118)
+tl1_resv120: BTRAPS(0x120) BTRAPS(0x128)
+tl1_resv130: BTRAPS(0x130) BTRAPS(0x138)
+tl1_resv140: BTRAPS(0x140) BTRAPS(0x148)
+tl1_resv150: BTRAPS(0x150) BTRAPS(0x158)
+tl1_resv160: BTRAPS(0x160) BTRAPS(0x168)
+tl1_resv170: BTRAPS(0x170) BTRAPS(0x178)
+tl1_resv180: BTRAPS(0x180) BTRAPS(0x188)
+tl1_resv190: BTRAPS(0x190) BTRAPS(0x198)
+tl1_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8)
+tl1_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8)
+tl1_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8)
+tl1_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8)
+tl1_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8)
+tl1_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8)
+
+ .section ".data"
+ .align 8
+ .globl tlb_handler_stack_top, tlb_handler_stack_pointer, obp_ticks_pointer
+
+ ! Stack for the tlb MMU trap handlers
+tlb_handler_stack_bottom:
+ .skip 8192
+tlb_handler_stack_top:
+ .skip 8
+
+ ! MMU trap handler stack pointer
+tlb_handler_stack_pointer:
+ .xword tlb_handler_stack_top
+
+ ! Pointer to current tick value
+obp_ticks_pointer:
+ .xword 0
+
+ .section ".text", "ax"
+
+spill_32bit:
+ srl %sp, 0, %sp
+ stw %l0, [%sp + 0x00]
+ stw %l1, [%sp + 0x04]
+ stw %l2, [%sp + 0x08]
+ stw %l3, [%sp + 0x0c]
+ stw %l4, [%sp + 0x10]
+ stw %l5, [%sp + 0x14]
+ stw %l6, [%sp + 0x18]
+ stw %l7, [%sp + 0x1c]
+ stw %i0, [%sp + 0x20]
+ stw %i1, [%sp + 0x24]
+ stw %i2, [%sp + 0x28]
+ stw %i3, [%sp + 0x2c]
+ stw %i4, [%sp + 0x30]
+ stw %i5, [%sp + 0x34]
+ stw %i6, [%sp + 0x38]
+ stw %i7, [%sp + 0x3c]
+ saved
+ retry
+
+fill_32bit:
+ srl %sp, 0, %sp
+ lduw [%sp + 0x00], %l0
+ lduw [%sp + 0x04], %l1
+ lduw [%sp + 0x08], %l2
+ lduw [%sp + 0x0c], %l3
+ lduw [%sp + 0x10], %l4
+ lduw [%sp + 0x14], %l5
+ lduw [%sp + 0x18], %l6
+ lduw [%sp + 0x1c], %l7
+ lduw [%sp + 0x20], %i0
+ lduw [%sp + 0x24], %i1
+ lduw [%sp + 0x28], %i2
+ lduw [%sp + 0x2c], %i3
+ lduw [%sp + 0x30], %i4
+ lduw [%sp + 0x34], %i5
+ lduw [%sp + 0x38], %i6
+ lduw [%sp + 0x3c], %i7
+ restored
+ retry
+
+/*
+ * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch
+ * to C to occur within the MMU I/D TLB miss handlers.
+ *
+ * Because these handlers are called on a TLB miss, we cannot use flushw to store
+ * processor window state on the stack, as the memory areas used by each window's
+ * stack pointer may not be in the TLB, causing recursive TLB miss traps.
+ *
+ * For this reason, we save window state by manually rotating the window registers
+ * and saving their contents (along with other vital registers) into a special
+ * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and
+ * so won't cause issues with trap recursion.
+ *
+ * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow
+ * window fill/spill traps if required), switch to our safe tlb_handler_stack and
+ * invoke the miss handler.
+ */
+
+#define SAVE_CPU_STATE(type) \
+ /* Set up our exception stack pointer in %g1 */ \
+ setx tlb_handler_stack_pointer, %g7, %g6; \
+ ldx [%g6], %g1; \
+ add %g1, -0x510, %g1; \
+ \
+ /* First save the various state registers */ \
+ rdpr %cwp, %g7; \
+ stx %g7, [%g1]; \
+ rdpr %cansave, %g7; \
+ stx %g7, [%g1 + 0x8]; \
+ rdpr %canrestore, %g7; \
+ stx %g7, [%g1 + 0x10]; \
+ rdpr %otherwin, %g7; \
+ stx %g7, [%g1 + 0x18]; \
+ rdpr %wstate, %g7; \
+ stx %g7, [%g1 + 0x20]; \
+ rdpr %cleanwin, %g7; \
+ stx %g7, [%g1 + 0x28]; \
+ rdpr %pstate, %g7; \
+ stx %g7, [%g1 + 0x30]; \
+ \
+ rd %y, %g7; \
+ stx %g7, [%g1 + 0x38]; \
+ rd %fprs, %g7; \
+ stx %g7, [%g1 + 0x40]; \
+ \
+ rdpr %tl, %g7; \
+ stx %g7, [%g1 + 0x48]; \
+ \
+ /* Trap state */ \
+ add %g1, 0x50, %g5; \
+ mov 4, %g6; \
+ \
+save_trap_state_##type: \
+ deccc %g6; \
+ wrpr %g6, %tl; \
+ rdpr %tpc, %g7; \
+ stx %g7, [%g5]; \
+ rdpr %tnpc, %g7; \
+ stx %g7, [%g5 + 0x8]; \
+ rdpr %tstate, %g7; \
+ stx %g7, [%g5 + 0x10]; \
+ rdpr %tt, %g7; \
+ stx %g7, [%g5 + 0x18]; \
+ bne save_trap_state_##type; \
+ add %g5, 0x20, %g5; \
+ \
+ /* For 4 trap levels with 4 registers, memory required is
+ 4*8*4 = 0x80 bytes */ \
+ \
+ /* Save the o registers */ \
+ stx %o0, [%g1 + 0xd0]; \
+ stx %o1, [%g1 + 0xd8]; \
+ stx %o2, [%g1 + 0xe0]; \
+ stx %o3, [%g1 + 0xe8]; \
+ stx %o4, [%g1 + 0xf0]; \
+ stx %o5, [%g1 + 0xf8]; \
+ stx %o6, [%g1 + 0x100]; \
+ stx %o7, [%g1 + 0x108]; \
+ \
+ /* Now iterate through all of the windows saving all l and i registers */ \
+ add %g1, 0x110, %g5; \
+ \
+ /* Get the number of windows in %g6 */ \
+ rdpr %ver, %g6; \
+ and %g6, 0xf, %g6; \
+ inc %g6; \
+ \
+save_cpu_window_##type: \
+ deccc %g6; \
+ wrpr %g6, %cwp; \
+ stx %l0, [%g5]; \
+ stx %l1, [%g5 + 0x8]; \
+ stx %l2, [%g5 + 0x10]; \
+ stx %l3, [%g5 + 0x18]; \
+ stx %l4, [%g5 + 0x20]; \
+ stx %l5, [%g5 + 0x28]; \
+ stx %l6, [%g5 + 0x30]; \
+ stx %l7, [%g5 + 0x38]; \
+ stx %i0, [%g5 + 0x40]; \
+ stx %i1, [%g5 + 0x48]; \
+ stx %i2, [%g5 + 0x50]; \
+ stx %i3, [%g5 + 0x58]; \
+ stx %i4, [%g5 + 0x60]; \
+ stx %i5, [%g5 + 0x68]; \
+ stx %i6, [%g5 + 0x70]; \
+ stx %i7, [%g5 + 0x78]; \
+ bne save_cpu_window_##type; \
+ add %g5, 0x80, %g5; \
+ \
+ /* For 8 windows with 16 registers to save in the window, memory required
+ is 16*8*8 = 0x400 bytes */ \
+ \
+ /* Now we should be in window 0 so update the other window registers */ \
+ rdpr %ver, %g6; \
+ and %g6, 0xf, %g6; \
+ dec %g6; \
+ wrpr %g6, %cansave; \
+ \
+ wrpr %g0, %cleanwin; \
+ wrpr %g0, %canrestore; \
+ wrpr %g0, %otherwin; \
+ \
+ /* Update our exception stack pointer */ \
+ setx tlb_handler_stack_pointer, %g7, %g6; \
+ stx %g1, [%g6];
+
+
+#define RESTORE_CPU_STATE(type) \
+ /* Set up our exception stack pointer in %g1 */ \
+ setx tlb_handler_stack_pointer, %g7, %g6; \
+ ldx [%g6], %g1; \
+ \
+ /* Get the number of windows in %g6 */ \
+ rdpr %ver, %g6; \
+ and %g6, 0xf, %g6; \
+ inc %g6; \
+ \
+ /* Now iterate through all of the windows restoring all l and i registers */ \
+ add %g1, 0x110, %g5; \
+ \
+restore_cpu_window_##type: \
+ deccc %g6; \
+ wrpr %g6, %cwp; \
+ ldx [%g5], %l0; \
+ ldx [%g5 + 0x8], %l1; \
+ ldx [%g5 + 0x10], %l2; \
+ ldx [%g5 + 0x18], %l3; \
+ ldx [%g5 + 0x20], %l4; \
+ ldx [%g5 + 0x28], %l5; \
+ ldx [%g5 + 0x30], %l6; \
+ ldx [%g5 + 0x38], %l7; \
+ ldx [%g5 + 0x40], %i0; \
+ ldx [%g5 + 0x48], %i1; \
+ ldx [%g5 + 0x50], %i2; \
+ ldx [%g5 + 0x58], %i3; \
+ ldx [%g5 + 0x60], %i4; \
+ ldx [%g5 + 0x68], %i5; \
+ ldx [%g5 + 0x70], %i6; \
+ ldx [%g5 + 0x78], %i7; \
+ bne restore_cpu_window_##type; \
+ add %g5, 0x80, %g5; \
+ \
+ /* Restore the window registers to their original value */ \
+ ldx [%g1], %g7; \
+ wrpr %g7, %cwp; \
+ ldx [%g1 + 0x8], %g7; \
+ wrpr %g7, %cansave; \
+ ldx [%g1 + 0x10], %g7; \
+ wrpr %g7, %canrestore; \
+ ldx [%g1 + 0x18], %g7; \
+ wrpr %g7, %otherwin; \
+ ldx [%g1 + 0x20], %g7; \
+ wrpr %g7, %wstate; \
+ ldx [%g1 + 0x28], %g7; \
+ wrpr %g7, %cleanwin; \
+ ldx [%g1 + 0x30], %g7; \
+ wrpr %g7, %pstate; \
+ \
+ /* Restore the o registers */ \
+ ldx [%g1 + 0xd0], %o0; \
+ ldx [%g1 + 0xd8], %o1; \
+ ldx [%g1 + 0xe0], %o2; \
+ ldx [%g1 + 0xe8], %o3; \
+ ldx [%g1 + 0xf0], %o4; \
+ ldx [%g1 + 0xf8], %o5; \
+ ldx [%g1 + 0x100], %o6; \
+ ldx [%g1 + 0x108], %o7; \
+ \
+ /* Restore the trap state */ \
+ add %g1, 0x50, %g5; \
+ mov 4, %g6; \
+ \
+restore_trap_state_##type: \
+ deccc %g6; \
+ wrpr %g6, %tl; \
+ ldx [%g5], %g7; \
+ wrpr %g7, %tpc; \
+ ldx [%g5 + 0x8], %g7; \
+ wrpr %g7, %tnpc; \
+ ldx [%g5 + 0x10], %g7; \
+ wrpr %g7, %tstate; \
+ ldx [%g5 + 0x18], %g7; \
+ wrpr %g7, %tt; \
+ bne restore_trap_state_##type; \
+ add %g5, 0x20, %g5; \
+ \
+ ldx [%g1 + 0x38], %g7; \
+ wr %g7, 0, %y; \
+ ldx [%g1 + 0x40], %g7; \
+ wr %g7, 0, %fprs; \
+ ldx [%g1 + 0x48], %g7; \
+ wrpr %g7, %tl; \
+ \
+ /* Restore exception stack pointer to previous value */ \
+ setx tlb_handler_stack_pointer, %g7, %g6; \
+ add %g1, 0x510, %g1; \
+ stx %g1, [%g6];
+
+
+ .globl reload_DMMU_tlb, reload_IMMU_tlb, bug
+
+reload_DMMU_tlb:
+
+ SAVE_CPU_STATE(dtlb)
+
+ /* Switch to TLB locked stack space (note we add an additional 192 bytes required for
+ gcc to save its arguments when building with -O0) */
+ add %g1, -STACK_BIAS - 192, %sp
+
+ /* Enable interrupts for window spill/fill traps */
+ rdpr %pstate, %g7
+ or %g7, PSTATE_IE, %g7
+ wrpr %g7, %pstate
+
+ call dtlb_miss_handler
+ nop
+
+ /* Disable interrupts */
+ rdpr %pstate, %g7
+ andn %g7, PSTATE_IE, %g7
+ wrpr %g7, %pstate
+
+ RESTORE_CPU_STATE(dtlb)
+
+ retry
+
+reload_IMMU_tlb:
+
+ SAVE_CPU_STATE(itlb)
+
+ /* Switch to TLB locked stack space (note we add an additional 192 bytes required for
+ gcc to save its arguments when building with -O0) */
+ add %g1, -STACK_BIAS - 192, %sp
+
+ /* Enable interrupts for window spill/fill traps */
+ rdpr %pstate, %g7
+ or %g7, PSTATE_IE, %g7
+ wrpr %g7, %pstate
+
+ call itlb_miss_handler
+ nop
+
+ /* Disable interrupts */
+ rdpr %pstate, %g7
+ andn %g7, PSTATE_IE, %g7
+ wrpr %g7, %pstate
+
+ RESTORE_CPU_STATE(itlb)
+
+ retry
+
+softint_irq_tl1:
+softint_irq:
+ mov 1, %g2
+ /* clear tick interrupt */
+ wr %g2, 0x0, %clear_softint
+ sll %g2, %g1, %g2
+ sra %g2, 0, %g2
+ /* clear softint interrupt */
+ wr %g2, 0x0, %clear_softint
+
+ setx TICK_INT_DIS, %g2, %g1
+ rd %tick, %g2
+ and %g1, %g2, %g1
+ brnz,pn %g1, tick_compare_disabled
+ nop
+
+ /* update tick value if pointer set */
+ setx obp_ticks_pointer, %g3, %g1
+ ldx [%g1], %g3
+ brz %g3, tick_rearm
+ nop
+
+ ldx [%g3], %g1
+ add %g1, 10, %g1 ! 100Hz = 10ms
+ stx %g1, [%g3]
+
+tick_rearm:
+ set TICK_INTERVAL, %g1
+ add %g1, %g2, %g1
+ wr %g1, 0, %tick_cmpr
+tick_compare_disabled:
+ retry
+
+handler_irq:
+__divide_error:
+bug:
+ /* Dump the exception and its context */
+ ! Set up CPU state
+ ! Don't change the global register set or we lose %g1 (exception level)
+ rdpr %pstate, %g2
+ or %g2, PSTATE_PRIV, %g2
+ wrpr %g2, %pstate
+ wr %g0, 0, %fprs
+
+ ! Jump to ROM ...
+ setx _start, %g2, %g3
+ setx highmem, %g2, %g4
+ sub %g4, %g3, %g4
+ setx PROM_ADDR, %g2, %g3
+ add %g4, %g3, %g3
+ jmp %g3
+ ! ... while disabling I/D MMUs and caches
+ stxa %g0, [%g0] ASI_LSU_CONTROL
+
+highmem:
+ ! Extract NWINDOWS from %ver
+ rdpr %ver, %g2
+ and %g2, 0xf, %g2
+ wrpr %g2, 0, %cleanwin
+ wrpr %g2, 0, %cansave
+ wrpr %g0, 0, %canrestore
+ wrpr %g0, 0, %otherwin
+ wrpr %g0, 0, %wstate
+
+ b dump_exception
+ nop
+
+outstr:
+ /* void outstr (unsigned long port, const unsigned char *str);
+ * Writes a string on an IO port.
+ */
+1: ldub [%o1], %o3
+ cmp %o3, 0
+ be 2f
+ nop
+ stba %o3, [%o0] ASI_BP
+ b 1b
+ inc %o1
+2: retl
+ nop
+
+outdigit:
+ /* void outdigit (unsigned long port, uint8_t digit);
+ * Dumps a single digit on serial port.
+ */
+ add %o1, '0', %o1
+ retl
+ stba %o1, [%o0] ASI_BP
+
+outhex:
+ /* void outhex (unsigned long port, uint64_t value);
+ * Dumps a 64 bits hex number on serial port
+ */
+ mov %o1, %o2
+ set 60, %o3
+ srlx %o2, %o3, %o1
+1: and %o1, 0xf, %o1
+ cmp %o1, 9
+ bgt 2f
+ nop
+ b 3f
+ add %o1, '0', %o1
+2: add %o1, 'a' - 10, %o1
+3: stba %o1, [%o0] ASI_BP
+ subcc %o3, 4, %o3
+ bge 1b
+ srlx %o2, %o3, %o1
+ retl
+ nop
+
+ /* void dump_exception ();
+ *
+ * Dump a message when catching an exception
+ */
+dump_exception:
+ setx SER_ADDR, %o3, %o0
+ set _start, %g3
+ set (_BUG_message_0), %o1
+ sub %o1, %g3, %g4
+ setx PROM_ADDR, %g2, %g3
+ add %g4, %g3, %g3
+ call outstr
+ mov %g3, %o1
+
+ call outhex
+ mov %g1, %o1
+
+ call outstr
+ add %g3, (_BUG_message_1 - _BUG_message_0), %o1
+
+ call outhex
+ rdpr %tpc, %o1
+
+ call outstr
+ add %g3, (_BUG_message_2 - _BUG_message_0), %o1
+
+ call outhex
+ rdpr %tnpc, %o1
+
+ call outstr
+ add %g3, (_BUG_message_3 - _BUG_message_0), %o1
+
+_forever:
+ /* Loop forever */
+ b _forever ;
+ nop
+
+ .section .rodata
+_BUG_message_0:
+ .string "Unhandled Exception 0x"
+_BUG_message_1:
+ .string "\nPC = 0x"
+_BUG_message_2:
+ .string " NPC = 0x"
+_BUG_message_3:
+ .string "\nStopping execution\n"
diff --git a/roms/openbios/arch/unix/Kconfig b/roms/openbios/arch/unix/Kconfig
new file mode 100644
index 00000000..8faafc0a
--- /dev/null
+++ b/roms/openbios/arch/unix/Kconfig
@@ -0,0 +1,18 @@
+
+config HOST_UNIX
+ bool "Build Hosted Unix binary"
+ default y
+ help
+ Build a version of the OpenBIOS kernel that runs in a
+ Unix-like operating system.
+
+config UNIX_QT
+ depends HOST_UNIX
+ bool "QT frontend for Unix binary"
+ default n
+ help
+ Enable this option if you wish to add a graphical user
+ interface to the openbios hosted unix binary. This option
+ needs the QT library installed.
+
+source "arch/unix/plugins/Kconfig"
diff --git a/roms/openbios/arch/unix/Makefile b/roms/openbios/arch/unix/Makefile
new file mode 100644
index 00000000..a8c6565e
--- /dev/null
+++ b/roms/openbios/arch/unix/Makefile
@@ -0,0 +1,29 @@
+#
+
+include ../../config/Makefile.top
+
+SUBDIRS-$(CONFIG_PLUGINS) = plugins
+SUBDIRS-$(CONFIG_UNIX_QT) = gui_qt
+
+DICTIONARIES = unix
+unix-SRC = tree.fs $(ARCHDICT_SRC)
+
+PROGRAMS = unix
+
+unix-OBJS = $(unix-y)
+unix-y += blk.o
+unix-y += boot.o
+unix-y += unix.o
+unix-y += $(KOBJS)
+unix-y += $(MODULE_LIBS) $(FS_LIBS) $(DRIVER_LIBS) $(LIBC_LIBS)
+unix-$(CONFIG_PLUGINS) += plugins.o
+
+unix-LDFLAGS = $(unix-LDFLAGS-$(CONFIG_PLUGINS))
+unix-LDFLAGS-y = -rdynamic $(LIBDL_LDFLAGS)
+unix-LDFLAGS-n =
+unix-LDADD =
+
+INCLUDES = -I../../kernel -I../../kernel/include -DBOOTSTRAP
+
+include $(rules)/Rules.forth
+include $(rules)/Rules.make
diff --git a/roms/openbios/arch/unix/blk.c b/roms/openbios/arch/unix/blk.c
new file mode 100644
index 00000000..d0f5c6a4
--- /dev/null
+++ b/roms/openbios/arch/unix/blk.c
@@ -0,0 +1,115 @@
+/*
+ * <arch/unix/blk.c>
+ *
+ * block device emulation for unix hosts
+ *
+ * Copyright (C) 2004 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "blk.h"
+
+typedef struct {
+ int unit;
+ int channel;
+} blk_data_t;
+
+
+DECLARE_NODE( blk, INSTALL_OPEN, sizeof(blk_data_t), "+/unix/block/disk" );
+
+static void
+blk_open( blk_data_t *pb )
+{
+ phandle_t ph;
+
+ fword("my-unit");
+
+ pb->unit = POP();
+ pb->channel = 0; /* FIXME */
+
+ selfword("open-deblocker");
+
+ /* interpose disk-label */
+ ph = find_dev("/packages/disk-label");
+ fword("my-args");
+ PUSH_ph( ph );
+ fword("interpose");
+
+ /* printk("osi-blk: open %d\n", pb->unit ); */
+
+ PUSH( -1 );
+}
+
+static void
+blk_close( __attribute__((unused)) blk_data_t *pb )
+{
+ selfword("close-deblocker");
+}
+
+
+/* ( buf blk nblks -- actual ) */
+static void
+blk_read_blocks( blk_data_t *pb )
+{
+ cell i, n = POP();
+ cell blk = POP();
+ char *dest = (char*)POP();
+
+ // printk("blk_read_blocks %x block=%d n=%d\n", (ucell)dest, blk, n );
+
+ for( i=0; i<n; ) {
+ char buf[4096];
+ ucell m = MIN( n-i, sizeof(buf)/512 );
+
+ if( read_from_disk(pb->channel, pb->unit, blk+i, (ucell)buf, m*512) < 0 ) {
+ printk("read_from_disk: error\n");
+ RET(0);
+ }
+ memcpy( dest, buf, m * 512 );
+ i += m;
+ dest += m * 512;
+ }
+ PUSH( n );
+}
+
+/* ( -- bs ) */
+static void
+blk_block_size( __attribute__((unused)) blk_data_t *pb )
+{
+ PUSH( 512 );
+}
+
+/* ( -- maxbytes ) */
+static void
+blk_max_transfer( __attribute__((unused)) blk_data_t *pb )
+{
+ PUSH( 1024*1024 );
+}
+
+static void
+blk_initialize( __attribute__((unused)) blk_data_t *pb )
+{
+ fword("is-deblocker");
+}
+
+
+NODE_METHODS( blk ) = {
+ { NULL, blk_initialize },
+ { "open", blk_open },
+ { "close", blk_close },
+ { "read-blocks", blk_read_blocks },
+ { "block-size", blk_block_size },
+ { "max-transfer", blk_max_transfer},
+};
+
+void
+blk_init( void )
+{
+ REGISTER_NODE( blk );
+}
diff --git a/roms/openbios/arch/unix/blk.h b/roms/openbios/arch/unix/blk.h
new file mode 100644
index 00000000..aa3b9656
--- /dev/null
+++ b/roms/openbios/arch/unix/blk.h
@@ -0,0 +1,8 @@
+
+#ifndef _H_BLK
+#define _H_BLK
+
+extern void blk_init( void );
+extern int read_from_disk( int channel, int unit, int blk, unsigned long mphys, int size );
+
+#endif /* _H_BLK */
diff --git a/roms/openbios/arch/unix/boot.c b/roms/openbios/arch/unix/boot.c
new file mode 100644
index 00000000..f4a29428
--- /dev/null
+++ b/roms/openbios/arch/unix/boot.c
@@ -0,0 +1,84 @@
+/*
+ *
+ */
+#undef BOOTSTRAP
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elf_load.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+
+void boot(void);
+void *load_elf(char *spec);
+
+void
+*load_elf(char *spec)
+{
+#if 0
+ int fd;
+ void *entry=NULL;
+ int i, lszz_offs, elf_offs;
+ char buf[128]; // , *addr;
+ Elf_ehdr ehdr;
+ Elf_phdr *phdr;
+ size_t s;
+
+ if( (fd=open_io(spec)) == -1 )
+ return NULL;
+
+ if( (elf_offs=find_elf(fd)) < 0 ) {
+ printk("----> %s is not an ELF image\n", buf );
+ return NULL;
+ }
+
+ if( !(phdr=elf_readhdrs(fd, 0, &ehdr)) ) {
+ printk("elf32_readhdrs failed\n");
+ return NULL;
+ }
+
+ (unsigned long long *)entry = ehdr.e_entry;
+
+ lszz_offs = elf_offs;
+ for( i=0; i<ehdr.e_phnum; i++ ) {
+ s = MIN( phdr[i].p_filesz, phdr[i].p_memsz );
+ seek_io( fd, elf_offs + phdr[i].p_offset );
+ /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n",
+ phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset,
+ phdr[i].p_vaddr ); */
+ if( phdr[i].p_vaddr != phdr[i].p_paddr )
+ printk("WARNING: ELF segment virtual addr != physical addr\n");
+ lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz );
+ if( !s )
+ continue;
+
+ printk("ELF ROM-section loaded at %08lX (size %08lX)\n",
+ (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz);
+ }
+ free( phdr );
+ return entry;
+#else
+ return NULL;
+#endif
+}
+
+void
+boot( void )
+{
+ char *path;
+ void *entry;
+
+ /* Copy the incoming path */
+ fword("2dup");
+ path = pop_fstr_copy();
+
+ if(!path) {
+ printk("[unix] Booting default not supported.\n");
+ return;
+ }
+ printk("[unix] Booting '%s'\n",path);
+ entry=load_elf(path);
+ if(entry)
+ printk("successfully loaded client at %llx.\n", (unsigned long long)(ucell)entry);
+ else
+ printk("failed.\n");
+}
diff --git a/roms/openbios/arch/unix/build.xml b/roms/openbios/arch/unix/build.xml
new file mode 100644
index 00000000..bc0cf9e7
--- /dev/null
+++ b/roms/openbios/arch/unix/build.xml
@@ -0,0 +1,23 @@
+<build condition="HOST_UNIX">
+
+ <dictionary name="openbios-unix" init="openbios" target="forth">
+ <object source="tree.fs"/>
+ </dictionary>
+
+ <executable name="openbios-unix" target="target">
+ <rule>
+ $(call quiet-command,$(CC) $(CFLAGS) -rdynamic $(LIBDL_LDFLAGS) -o $@ $^," LINK $(TARGET_DIR)$@")
+ </rule>
+ <object source="unix.c" flags="-DBOOTSTRAP"/>
+ <object source="boot.c" flags="-DBOOTSTRAP"/>
+ <object source="blk.c" flags="-DBOOTSTRAP"/>
+ <object source="plugins.c" flags="-DBOOTSTRAP" condition="PLUGINS"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="liblibc.a"/>
+ </executable>
+
+</build>
diff --git a/roms/openbios/arch/unix/gui_qt/Makefile b/roms/openbios/arch/unix/gui_qt/Makefile
new file mode 100644
index 00000000..20eb1580
--- /dev/null
+++ b/roms/openbios/arch/unix/gui_qt/Makefile
@@ -0,0 +1,42 @@
+#
+# Makefile of QT user interface for OpenBIOS
+#
+# (C) 2004 Stefan Reinauer <stepan@openbios.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2
+#
+
+include ../../../config/Makefile.top
+
+XTARGETS = qt
+
+qt-OBJS = $(obj-y)
+obj-y += gui_qt.o
+
+QMAKE = qmake
+UIDIR = $(shell pwd )
+TOPDIR = $(shell cd $(top_srcdir) ; pwd)
+ABSOINC = $(shell cd $(ARCHINCLUDES) 2> /dev/null ; pwd )
+
+export UIDIR TOPDIR ABSOINC
+
+$(ODIR)/makefile.qmake: gui-qt.pro Makefile
+ @echo "ODIR: $(ODIR)"
+ @test -d $(ODIR) || $(INSTALL) -d $(ODIR)
+ @test -d $(ODIR)/qbuild || $(INSTALL) -d $(ODIR)/qbuild
+ @install -m 644 gui-qt.pro $(ODIR)/
+ cd $(ODIR) ; $(QMAKE) -o makefile.qmake
+
+$(ODIR)/libgui_qt.a: $(ODIR)/makefile.qmake $(wildcard *.cpp)
+ cd $(ODIR) ; $(MAKE) -f makefile.qmake
+ @ln -f $(ODIR)/qbuild/libgui_qt.a $@
+
+clean-local:
+ @rm -f $(ODIR)/makefile.qmake
+ @rm -rf $(QBUILDDIR)
+
+INCLUDES = -I$(top_srcdir)/include -DBOOTSTRAP
+
+include $(rules)/Rules.make
diff --git a/roms/openbios/arch/unix/gui_qt/gui-qt.cpp b/roms/openbios/arch/unix/gui_qt/gui-qt.cpp
new file mode 100644
index 00000000..24c08428
--- /dev/null
+++ b/roms/openbios/arch/unix/gui_qt/gui-qt.cpp
@@ -0,0 +1,128 @@
+/* tag: qt user interface fb class
+ *
+ * Copyright (C) 2003-2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "gui-qt.h"
+#include "logo.xpm"
+
+#include <iostream>
+
+static const int sizex=640;
+static const int sizey=480;
+static const int depth=8;
+
+static unsigned char color[256][3]={
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0xaa },
+ { 0x00, 0xaa, 0x00 },
+ { 0x00, 0xaa, 0xaa },
+ { 0xaa, 0x00, 0x00 },
+ { 0xaa, 0x00, 0xaa },
+ { 0xaa, 0x55, 0x00 },
+ { 0xaa, 0xaa, 0xaa },
+ { 0x55, 0x55, 0x55 },
+ { 0x55, 0x55, 0xff },
+ { 0x55, 0xff, 0x55 },
+ { 0x55, 0xff, 0xff },
+ { 0xff, 0x55, 0x55 },
+ { 0xff, 0x55, 0xff },
+ { 0xff, 0xff, 0x55 },
+ { 0xff, 0xff, 0xff },
+};
+
+FrameBufferWidget::FrameBufferWidget(QWidget *parent, const char * name)
+: QWidget(parent, name, Qt::WType_TopLevel)
+{
+ setCaption ("OpenBIOS");
+ setIcon(QPixmap(logo));
+
+ QPopupMenu *file = new QPopupMenu (this);
+
+ file->insertItem( "E&xit", this, SLOT(quit()), CTRL+Key_Q );
+
+ QPopupMenu *help = new QPopupMenu( this );
+ help->insertItem("&About OpenBIOS", this, SLOT(about()), CTRL+Key_H );
+ help->insertItem( "About &Qt", this, SLOT(aboutQt()) );
+
+ menu = new QMenuBar( this );
+ Q_CHECK_PTR( menu );
+ menu->insertItem( "&File", file );
+ menu->insertSeparator();
+ menu->insertItem( "&Help", help );
+ menu->setSeparator( QMenuBar::InWindowsStyle );
+
+ setFixedSize(sizex,sizey+menu->heightForWidth(sizex));
+
+ buffer.create(sizex, sizey, depth, 256);
+
+ for (int i=16; i < 256; i++) {
+ color[i][0]=i;
+ color[i][1]=i;
+ color[i][2]=i;
+ }
+
+ for (int i=0; i< 256; i++)
+ buffer.setColor(i, qRgb(color[i][0], color[i][1], color[i][2]));
+
+ buffer.fill( 0 );
+
+ updatetimer=new QTimer(this);
+ connect( updatetimer, SIGNAL(timeout()), this, SLOT(update()) );
+ updatetimer->start(200,FALSE);
+
+ setMouseTracking( TRUE );
+}
+
+unsigned char * FrameBufferWidget::getFrameBuffer(void)
+{
+ return buffer.bits();
+}
+
+void FrameBufferWidget::paintEvent ( QPaintEvent * )
+{
+ QPainter p( this );
+ p.drawImage(0,menu->heightForWidth(sizex),buffer, 0,0, sizex, sizey);
+}
+
+void FrameBufferWidget::about()
+{
+ QMessageBox::about( this, "About OpenBIOS",
+ " Welcome to OpenBIOS 1.01\n"
+ " IEEE 1275-1994 Open Firmware implementation\n\n"
+ "written by Stefan Reinauer <stepan@openbios.org>\n\n"
+ " http://www.openbios.org/\n");
+}
+
+void FrameBufferWidget::aboutQt()
+{
+ QMessageBox::aboutQt( this, "OpenBIOS" );
+}
+
+void FrameBufferWidget::quit()
+{
+ extern volatile int gui_running;
+ extern volatile int runforth;
+
+ gui_running=0;
+ interruptforth=1;
+
+ qApp->quit();
+}
+
+void FrameBufferWidget::update()
+{
+ QPainter p( this );
+ p.drawImage(0,menu->heightForWidth(sizex),buffer, 0,0, sizex, sizey);
+}
+
+void FrameBufferWidget::keyPressEvent(QKeyEvent * e)
+{
+ int a=e->ascii();
+ if (a) {
+ std::cout << " key '" << e->text() << "' pressed" << std::endl;
+ }
+}
diff --git a/roms/openbios/arch/unix/gui_qt/gui-qt.h b/roms/openbios/arch/unix/gui_qt/gui-qt.h
new file mode 100644
index 00000000..202619f7
--- /dev/null
+++ b/roms/openbios/arch/unix/gui_qt/gui-qt.h
@@ -0,0 +1,44 @@
+/* tag: qt user interface fb class description
+ *
+ * Copyright (C) 2003-2004 Stefan Reinauer <stepan@openbios.org>
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __framebufferwidget_h
+#define __framebufferwidget_h
+
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <qmenubar.h>
+#include <qpopupmenu.h>
+#include <qmessagebox.h>
+#include <qstatusbar.h>
+#include <qtimer.h>
+
+class FrameBufferWidget : public QWidget {
+ Q_OBJECT
+ public:
+ FrameBufferWidget(QWidget *parent=0, const char *name=0);
+ unsigned char *getFrameBuffer(void);
+
+ public slots:
+ void quit();
+ void about();
+ void aboutQt();
+ void update();
+
+ private:
+ QImage buffer;
+ QMenuBar *menu;
+ QStatusBar *status;
+ QTimer *updatetimer;
+ void paintEvent ( QPaintEvent * );
+ protected:
+ void keyPressEvent(QKeyEvent * e);
+};
+
+#endif
diff --git a/roms/openbios/arch/unix/gui_qt/gui-qt.pro b/roms/openbios/arch/unix/gui_qt/gui-qt.pro
new file mode 100644
index 00000000..f58baecf
--- /dev/null
+++ b/roms/openbios/arch/unix/gui_qt/gui-qt.pro
@@ -0,0 +1,18 @@
+# tag: qmake project file for OpenBIOS QT user interface
+#
+# Copyright (C) 2003-2004 Stefan Reinauer <stepan@openbios.org>
+#
+# See the file "COPYING" for further information about
+# the copyright and warranty status of this work.
+#
+
+TEMPLATE = lib
+CONFIG += qt thread warn_on release staticlib
+LIBS =
+INCLUDEPATH = qbuild $(ABSOINC) $(TOPDIR)/include
+DESTDIR = qbuild
+OBJECTS_DIR = qbuild
+MOC_DIR = qbuild
+TARGET = gui_qt
+HEADERS = $(UIDIR)/gui-qt.h
+SOURCES = $(UIDIR)/gui-qt.cpp $(UIDIR)/qt-main.cpp
diff --git a/roms/openbios/arch/unix/gui_qt/logo.xpm b/roms/openbios/arch/unix/gui_qt/logo.xpm
new file mode 100644
index 00000000..9e2ac60b
--- /dev/null
+++ b/roms/openbios/arch/unix/gui_qt/logo.xpm
@@ -0,0 +1,132 @@
+/* This logo was created by Stephan Lau,
+ * created to xpm by Stefan Reinauer
+ */
+static char *logo[] = {
+/* columns rows colors chars-per-pixel */
+"300 80 44 1",
+" c #010101",
+". c #070709",
+"X c #0B0B0B",
+"o c #0F0F11",
+"O c #121212",
+"+ c #1B1B1B",
+"@ c #1F1F21",
+"# c #232323",
+"$ c #262628",
+"% c #2B2B2C",
+"& c #2E2E30",
+"* c #333333",
+"= c #373739",
+"- c #3B3B3B",
+"; c #434343",
+": c #464648",
+"> c #4B4B4B",
+", c #4E4E50",
+"< c #535353",
+"1 c #5B5B5B",
+"2 c #5E5E60",
+"3 c #646464",
+"4 c #666668",
+"5 c #6B6B6B",
+"6 c #747474",
+"7 c #767678",
+"8 c #7B7B7B",
+"9 c #838383",
+"0 c #8A8A8A",
+"q c #939394",
+"w c #979799",
+"e c #9B9B9B",
+"r c #A3A3A3",
+"t c #ABABAB",
+"y c #B4B4B4",
+"u c #BBBBBB",
+"i c #C3C3C3",
+"p c #CBCBCB",
+"a c #D3D3D3",
+"s c #DBDBDB",
+"d c #E3E3E3",
+"f c #EBEBEB",
+"g c #F3F3F3",
+"h c #FEFEFE",
+/* pixels */
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfdssaapuuuytteeewq0009998867666555555555555565666778899000qwwerttyyuuppassdfghhhhhhhhhhgfgggghhhgfgfghhhhggffghhhhggffghhhhgfggghhhhgfggghhhhgfgfghhhhfgfgghhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdsapuytrwq0986555554455555555555555555555555555555555555555555555555555555555555555555555555556790qertyiuuuafhhhfpiishhhhfipidhhhhfiiidhhhhdiiifhhhhsiiifhhhhsiipghhhhaiipghhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfdaiuttq0976555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558iuue5579wuuuuiasfduuishhhhduuudhhhhduuudhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdaittw086555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558yuur55549uuiw55569uuutyiadsuuudhhhhsuuudhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfapyrw975555555555555555555555555555555555555555555555555555555555555555555555555555555554555555555555555555554455555555555555555555558uuue54559uuuw55559uuuq55550uiutypafduuufhhhhsuuufhhhhsuuufhhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdautw965555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555679qqerttuuppaasdddffgghghhhhhhhhhghhggfduuupaappuuuuyeq090uuuq55559uyi05555quuuuadghsuuufhhhhauuufhhhhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfsite0655555555555555555555555555555555555555555555555555555555555555555555555455555555555555555690wrtiiaddghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfuuuahhhhfuuushhhhfuuuaaiittuuuq55550uuu95560tuuudhhhhsuuughhhhauuufhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhgsite955555555555555555555555555455555555555555555555555555555555555555555555555545555555555570wryiadfhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhguuuahhhhfuuuahhhhfuuushhhhduuudfsaiuuuuq5555qiuu99etipuuifhhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaut0655555555555555555555555555555555555555555555556555555555555555555555555555555555554559qruisfhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdsdfhhhhgdddfhhhhfddsfhhhhgdddfhhhhfddsffspyteeq755559qetisfhgfdddghhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgsir065555555555555555555555555555455555555555555555554555555555555555555555555555555555580rupsghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsuudhhhhhhhhhhhhfuuphhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgspyt085555560tudghhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaue9555555555555555554<----=---=---==-==<555555---:3:--=--=-*--==--<55555545<;------==->135890phhhhhy009tfq0009009090909wshhhhhhg<;;:;;;:<9fhhhhhhhf$ rhhhhhs3# ;phhhhhhhf0# Owghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdpue0655559wuaghhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgsue855555455555555555555:O. *5455- *. &44555>O 6ghhh+ 5O ehghhh9 . Xighhhhh9 -gfggf3 +sddffd8O rddffffffffgffffgffffffffggffffffffgffffgffdaute09868eusghhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfpr955555555555555555555555% .%=************& +2555o +=************% +3343% X-<3568888787884. ;dggq. O19888888888888, 8fgghsO . 1fggghsO ysdfiO 9ttuu> . 1rtuyuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuuuuuuiiuuuut06449rpdhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhduw85555555555555555555555555* .,111<1111111111< #113- #<<111111111111< #123- Xtssaaaaaaaaaaaaa <sdf@ Otaaaaasaaaaaaaae 9sdgg, =sdggh< 2ipa0 7etr# <etttuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuighfauw857wudhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhfie7555555555555555555555554555: =1<<<<<<<<<<<<<<& -<<3X X<<><<<<1,,<<<<<& ;7e8 9apiiiiiipiiiiii6 0ia9 8uuuiipipiiiiiii> oyisdt X%% 2iadgy Xrty6 @69& X90e; *3% 49wttuuuuuuuuuuuuuuuuuuuuuuuuuuuyuyyyuuyuuuuuuuuuuihhhhhhgayw86eifhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhar8555555555555555555555555555543. +<,>>>,>><>>>>,,:. O;:<& -:;>>><>,,<><>,:. $eytO -puuyuuuuuuuuuiutX %rytO *ytrtyuuiuuuuuuu9 1ruis%. 108- . 8tisd% <qw9X #tre> *59, -86* O47qetuuuuuuuuuuuuuuuuuuuuuuuuuuuiasddsaiuuuuuuuuuuighhhhhhhhhgatq9tahhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhgiq55555555555555555555555555555555- ;>:>:,<<<,<<<<<<# . %-;: . O:;;;>>,<<>,,<38; 5qr3 eutttuuiiiipiiii1 5wr< qreeryuiipiiipii$ X0wru8 O976& +9wya0 O999O qeq9O >3< +751. &159wtyuuuuuuuuuuuuuuuuuuuuuuuuisfhhhhhhgdpuuuuuiuuihhhhhhhhhhhhhhdierighhhhhhh",
+"hhhhhhhhhhhhhhhhhfi05555555555555555555555555555555552 #>;;:,,<<<11<11<> +--;+ ;;--;><<1116qtpy -009 ,ttrrtuppaaaaaaay -q09 ;ewqrtupaaaaaaap9 10qrtX .3754X . >60tuX 387% 3w09: +3<O. 153% O:159wtyuuuuiuuuuuuuuuuuuuuuuuuaghhhhhhhhhhhdiuuuuuuighhhhhhhhhhhhhhhhfaupghhhhh",
+"hhhhhhhhhhhhhhhhiq55555555555555555555555555555555555+ X;:;;><<112311212+ .---& $;-;;><138eusddd- X000% oerrrtuaadsdddddd- o090$ Xwqqetypadddsddsao .%q9qr3 $856- +160t5 $761 X9097X ;1& &54< *;159wtyuuuuuuuuuuuuuuuuuuuuuushhhhhhhhhhhhhhdpyuuuuihhhhhhhhhhhhhhhhhhhhgsdhhhh",
+"hhhhhhhhhhhhhhsr555555545555555555555555555555555555, %;;-:><123333535> %---O .;--;;<5wifgfgfgt 1w04 2ewerupsffgffggft 1w05 1wqqeyasffgfgggg9 7q0wq 6665 ,360w 666O <999= %32. . <31+. +>>160rtuuuuuuuuuuuuuuuuuuuuuyshhhhhhhhhhhhhhhhfuuuuuighhhhhhhhhhhhhhhhhhhhhhhghh",
+"hhhhhhhhhhhhhi05555555555555555555555555555555555555o .X;;-::<1335555454X X:--$ &:--,6rsfghhghgh# Orq0O <<<<156999090999# +rqqO +qqqetisgghhghhha >rqqe* >867# *358e* >76; #9994 . .44- o2<>++++O>><48qrtuuuuuuuuuuuuiuuuuuuuuphhhhhhhhhhhhhhhhhhsyuiuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhu65555555555555555555555555555555555555- *;-->>1355555554- *;--. O;-<5rpdfhhhhhhh9 7rq< 6eq, 5w0wtisdgghhhhhh< Oqwqw8 X7773 X45608 X666. 3779% ;55X. %<1356651<<369etyuuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhhhhhgpyuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhi755555555555555555555555555555555555553. +;--;><2555555553. O:--$ *16qtiafhghhhhhgO *rq9X @,>:><356787888787653rq9X %wqqryadfghhhhhhy 3rqqrO <669O >569q+ <66* =8781 O953 &<24698533359qryuuuuuuuuuuuiuuuuuuuuuphhhhhhhhhhhhhhhhhhhhsyuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhs955555555555555555555555555555555555555% -;;;><1335555555$ -;;* %9wweypdfhhhhhhh4 eeq- 90990rtupaaaaaaaapiutee- 9qqerusfhhhhhhhh# +twqr1 @868= $867q1 @873 o5689O 166; &<36999865690etyyuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhhhhhhhfiuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhy55555555555555555555555555555555555555< #;--:,<3355555551 #;;-+ Xqwqetisfhghhhhhp 1eq7 >q999qrtuuipipuippuytrr8 :wqqruadfhhhhhhh9 6ewweX 363% #6689qX 276# >769, $867* +13800q9999qrtyuuuuuuuuuuuuuuuuuuuuuufhhhhhhhhhhhhhhhhhhhhhpuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhh955555555555555555555555555555555555555@ .:-;;:<1335555554+ .;:-* 1wqqrupfghhhhhhh; Oeeq$ ..q0990qrtuuuuuuuuuuuuttr& XqqqetpdfghhhhhhfO *tewe> %8869q< *76< O6687X 4669$ .X159qeeeqqqrryuuuuuuuuuuuuuuuuuuuiuuighhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhh55555555555555555555555555555555555555: $;-;;,<335555554: $:-2+ +qqqeyidgghhhhhhr 1rq3 1q000rryuipiiipiiiiiuuu7 1wqwtuadghhhhhhh6 qwww0 =20979q9 X566X <679= . -8680- . >69errtrrrtyyuuuuuuuuuuuuuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhh95555555555555555555555555555555555555O X:--;><2355555553O O:162 3eqerusdghhhhhhf# $tqqO +qqqwrtipaaaaaaaaaaaaapp+ Oeqqetpsgghhhhhhs >ewqr&. ;q0998qe* >86; #7685 O6680e1 *50ettyyyyyuuuuuuuuuuuuuuuuuuuuuuuuuhhhhhhhhhhhhhhhhhhhhhhpuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhht655555555555555555555555555555555555: %;-;:<1335555555& .:500X +eqerypsghhhhhhh6 Oqeq3 1qqwryiasddddddddddddsd7 8wqqtuafghhhhhhh; Oreqw7 -999qw7. +665X 4679@ :789wt6 O50etyyuuuuuuuuuuuuuuuuuuuuuuuuuiuuughhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhs955555555555555555555555555555555555% --;;>1135555553- ,0eq> =wqerisfghhhhhf9 8rwq- 9qqetpsdffgfgffgfdttgfa *rqqryadghhhhhhhq 4rqwrO *-@ 79qeu+ ,76* . *7681 O8680ruy X49etyuuuuuuuuuuuuuuuuuuuuiuuuuuuuuudhhhhhhhhhhhhhhhhhhhhgiuuuhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhu65555555555555555555555555555555554# .4eew9 X Oqteww= #dgg; 9wqwtisfghhhhhhfX Xewqe3 %63< @70ey5 #961 X6678X 3679ruip& 48wryuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuphhhhhhhhhhhhhhhhhhhhduuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhu7555555555555555554555555555555545,@X . .+>qyrre& X8O O-7utreer9=X ufg5 +ewqruadghhhhhhf; >eqweX . 451> -6qyyO 366# ;769< $769wtpaa3 O36qrtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuighhhhhhhhhhhhhhhhhhhpyuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhp95455555555555555555555555555555331:;---;><1111111117tutre8 1q999wtipaaasssaaaiutrrrruyrq09qruiasasasasassssddddaitrwetisfhghhhhhhgfautewr; -654% o56eu< =86: . O8687 6669ruada4 @160ryuuuuuuuuuuuuuuuuuuiuuuuuuuuuuuuahhhhhhhhhhhhhhhhhhsuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhde555555555555555555555555555555331,;---;;,<<<<<1<<8tutrtt+ Or099qwtuipppppppiiuytrtyiiiteq0qryupppppppppppppssdspurreriafghhhhhhhhgdaueee8 X665< ;38e9 X765X 1679% >669wyadfd5 *150rtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuushhghhhhhhhhhhhhhgiyuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhiq555555555555555555555555555533<<:;-;;>>,>,>,,,6ttyttt3 5q9990rttuuuuuuyuuyyttyupaapurewertyyuuuuuuuuuuuipasaputttypsgghhhhhhhggsautrt* ,667# .+159e* >86;. $6695 .8680tisfgd3 X:160rtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhgiuiuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhfi055555555555555555555555555332<>>:;:>>>,<>,>6tuuuiiuX *eq00wrryyuuuuyuuuuuyuiiasdsaputrtttuuyuyuuuuyyuupaassaiuyupsfghhhhhhhhhgdaiuy6 O967< 146q3 O865 5679O ,769wuafggfX #:150rtuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuuuushhhhhhhhhhhhfiuuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhfiq5555555555555555555554555431<<<,<<<<<<<15tippppa<. 0wqqetyippppppppppippaasdfgfdsapiipipppppppppppppaadddsaapasfghhhhhhhhhggfsapi+ 1678O -5589+ 176% -679, +85O rgg0 X-,36qrtuuuuuuuuuuuuiuuuuuuuuuuuuuuuuiuuuuupfghhhhhhhfauuuuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhat85555555555555555555555433221111111113tsssssdr >eqqetupaasaaasaasssasddfgggggfdssasassaassasaasssddffffddddfgghhhhhhhhhhhgfdd8 $878> X55601 $761 X5788o 37- -dfd@ &>,39qryuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuypsdffdspuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhfiw6555555555555555555555333332322331efffdffs+ qqwetiadfffdfddfffdfffffgghhhgggfffdfdffdfdfdfdfdfffggfggfggghhhhhhhhhhhhggggp 6666 >6699 676+ >679- =73 .yss8 .O,,159etyuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyuyuuuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhfiw7545555555555555555555545353350dgggghg4 -rqqruadfggghghhggghgghhhhhhhhhhghghhghgghghghghghghhhhhhhhghghhhhhhhhhhhhhhhg< ;669& +666q* -76, . O8686 X66$ <uiuO . -><57qryuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuughhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdir955555555555555555555555555uhhhhhhhgfsuteqrtpdfhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhu X7764 . 15696 .766# . <679$. <7< oqty- %<<149etyuuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsue85555455555555555555559dhhhhhhhgfauteeriadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh* >865X -667q# >765 668= =86% -0q1 +4357qtiasdddddddddddddddsdddddddsddddddsddddddddddddsddddddddddddshhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfaue755555555555555555ehhhhhhhhgdautrtuadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhq ;-% +76703 O868: . >>% +975 %2* X6669wuadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsit06553555555555phhhhhhhggfaiuuupsfghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfO . +76680X 3869- . %986> . . X5877qtpsgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaur065455555dhhhhhhhhgfdaapadfghghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh6 . -8767q> *7699* . . -0989; +98669qusfggfffghhhhgfffghhhhgfffghhhhgdfdghhhhgfffghhhhgfffghhhhdfffghhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgspte955fhhhhhhhhggfddddfghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs . O3987800 5760e4 O3099997 X;996136qpdfhfuuuahhhhduuushhhhduuudhhhhduuufhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfahhhhhhhhhhggffggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh- X%>688780r& ,869qry< #;89999qwr3o O=58887559rdghhguuushhhhfuuishhhhduuudhhhhduuufhhhhsuuufhhhhauuufhhhhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdauq841<15566890ryupute9880ruuur3<;1156889qrtyyr41>,145670979qyfgghfuuuahhhhfuuushhhhdiuudhhhhduuudhhhhsuuufhhhhauiughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhggdptq8433356789qrupaaite990ruppitq85345790wtypiitw84335680qe0qrugghhfuuushhhhfuuushhhhduuudhhhhsuuudhhhhauuufhhhhsuuufhhhhpuuighhhhhhhhhhhhhghhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhg7-&508666880qrtipssaiyeqqrtpsspue076699qetipsaaurq866790ettwrtphhhhfuuuahhhhfuuudhhhhduuudhhhhduuidhhhhsuuufhhhhauuifsfhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhg9O550eqq0qwertuisdffsauyttupsddsayrqqqqrtupaddfdpureq0qeryiprtyahhhhfuuushhhhfuuushhhhfuuudhhhhduuudhhhhsuuufhhhhauuug;0hhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh;8saiuuttuyuipaddgggfsaiiiasffgfaaiytyuupaddgggfdpuuyyuupadauuuahhhhfiuiahhhhfiuudhhhhduuidhhhhduuufhhhhsiiufhhhhauuug>0hhpiuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhO ysaaaOt3 4dggp% %usssu& *ifssaaaasdffghOpggsOtaat- -ufggXahhpOfggOp7 .5fgfgghhhgggf9 6gggOphhhXigg9 6gggX 9gggi* *pghhO; 4@+dhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhp*4tgffdf %&er phh+;yu&&gfg+:uu*%hgffddfffghhh uhgd tdd@%yy:+hhh uhhu hhh **tr ahhhhhhhhhhh 0uut<hhh uhhf uhh 0uut<hhhp*4uufhhh$;uu**hhh *0 7*0hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh:9hhgghg 3ggh<shh uhhu hgh uhhu hghggghgghhhh<5hhwOggg uhhy hhh thhu hhh 4hhh<shhhhhhhhhhh4 5uhhhhh<5hheOhhh4 5uhhhhhh;0hhhhhh uhhu hhh uu h;0hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh00phhhhhhhhhhhhhhh90phhhhhhhhhhhhhhh00phhhhhhhhhhhhhh:0hhhhhh uhhhhhhh *;;* hhh *;;* hhhhhhhhhhhhht fh@9hhh uhhu hhh;9hhu hhh uhhhhhhhhhhhhhhhghu< *phhhr fh#0hhhhu< *phhhh;0hhhhhh &>;* hhh uu h>9hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 0hhhhhhhhhhhhhhh 0hhhhhhhhhhhhhhh 0hhhhhhhhhhhhhh;0hhhhhh uhhhhhhh 40900hhh 40900hhhhhhhhhhhhhh@0r fhhh uhhu hhh;0hht hhh uhhhhhhhhhhhhhhhhhhhs<#hhhh#0t fhhhhhhs<#hhhh;0hhuhhh 39000hhh uy h9>hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh00phhhhhhhhhhhhhhh90phhhhhhhhhhhhhhh00phhhhhhhhhhhhhh;9hhhhhh uhhhhhhh@<uuuphhh@1uuuphhhhghhhhhhhhh0O#5hhhh*%uu*&hhh<<u4 hhh uhhhhhhhhhhhhhhhh<tuu0Ohhhh0O#4hhhh<ruu0Ohhhh1<u9 uhh@1uuuphhh uu h0;hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<0hhhhhhXphhhhhhhs;. Xhhhs> Ohhhhhhhhhhhhhhg3 shhhhp; ;ahhha+ ;wOhhhXahhhhhhhhhhhhhhhh6 Owhhhhf4 shhhh6 Oqhhhhp$ 6hhhs; OhhhXpaOh0<hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhh3;hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh4;hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh09 uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhh09 uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<:5hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<:4hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
+};
diff --git a/roms/openbios/arch/unix/gui_qt/qt-main.cpp b/roms/openbios/arch/unix/gui_qt/qt-main.cpp
new file mode 100644
index 00000000..8311fe63
--- /dev/null
+++ b/roms/openbios/arch/unix/gui_qt/qt-main.cpp
@@ -0,0 +1,97 @@
+/* tag: openbios qt user interface
+ *
+ * Copyright (C) 2003-2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+
+extern "C" {
+#include <pthread.h>
+#include <unistd.h>
+#include "unix/plugins.h"
+#include "unix/plugin_pci.h"
+}
+#include "gui-qt.h"
+
+#define DEBUG
+
+volatile unsigned char * fb=0;
+volatile int gui_running=0;
+
+typedef struct {
+ int argc;
+ char **argv;
+} threaddata;
+
+void *gui_thread(void *ptr)
+{
+ threaddata *td=(threaddata *)ptr;
+
+ QApplication a(td->argc, td->argv);
+ FrameBufferWidget w;
+
+ a.setMainWidget(&w);
+ w.show();
+
+ fb=w.getFrameBuffer();
+
+ gui_running=-1;
+ a.exec();
+ gui_running=0;
+
+ return 0;
+}
+
+extern "C" {
+extern int plugin_qt_init(void);
+int plugin_qt_init(void)
+{
+ pthread_t mythread;
+ char *args[]={ "plugin_qt" };
+ threaddata mytd = { 1, args };
+
+#ifdef DEBUG
+ printf("Initializing \"framebuffer\" plugin...");
+#endif
+ pthread_create(&mythread, NULL, gui_thread, &mytd);
+ while (!fb)
+ usleep(20);
+
+#if 0
+
+ /* now we have the framebuffer start address.
+ * updating pci config space to reflect this
+ */
+#if (BITS > 32)
+ *(u32 *)(pci_config_space+0x14)=(u32)((unsigned long)fb>>32);
+#else
+ *(u32 *)(pci_config_space+0x14)=0;
+#endif
+ *(u32 *)(pci_config_space+0x10)=(u32)((unsigned long)fb&0xffffffff);
+
+ /* next is to write the rom address. We write that at a random
+ * address in pci config space for now.
+ */
+#if (BITS > 32)
+ *(u32 *)(pci_config_space+0x34)=(u32)((unsigned long)qt_fcode>>32);
+#else
+ *(u32 *)(pci_config_space+0x34)=0;
+#endif
+ *(u32 *)(pci_config_space+0x30)=(u32)((unsigned long)qt_fcode&0xffffffff);
+
+ /* FIXME: we need to put the fcode image for this
+ * device to the rom resource, once it exists
+ */
+
+ /* register pci device to be available to beginagain */
+ pci_register_device(0, 2, 0, pci_config_space);
+#endif
+#ifdef DEBUG
+ printf("done.\n");
+#endif
+ return 0;
+}
+
+}
diff --git a/roms/openbios/arch/unix/plugins.c b/roms/openbios/arch/unix/plugins.c
new file mode 100644
index 00000000..855454b0
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins.c
@@ -0,0 +1,197 @@
+/* tag: plugin interface for openbios forth kernel
+ *
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "sysinclude.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#include "unix/plugins.h"
+
+unsigned char *plugindir = "/usr/share/OpenBIOS/plugins";
+#define PLUGINDIR plugindir
+#define PATHSIZE 256
+
+#define CONFIG_DEBUG_PLUGINS
+
+typedef struct iorange iorange_t;
+struct iorange {
+ const char *name;
+ unsigned int start;
+ unsigned int end;
+ io_ops_t *ops;
+ iorange_t *next;
+};
+
+static iorange_t *ioranges = NULL;
+
+typedef struct plugin plugin_t;
+struct plugin {
+ const char *name;
+ plugin_t *next;
+};
+
+static plugin_t *plugins = NULL;
+
+io_ops_t *find_iorange(u32 reg)
+{
+ iorange_t *range = ioranges;
+ while (range) {
+ if (range->start <= reg && range->end >= reg)
+ return range->ops;
+ range = range->next;
+ }
+ return NULL;
+}
+
+int register_iorange(const char *name, io_ops_t * ops, unsigned int rstart,
+ unsigned int rend)
+{
+ iorange_t *newrange;
+
+ /* intersection check */
+ newrange = ioranges;
+ while (newrange) {
+ int fail = 0;
+ /* new section swallows old section */
+ if (newrange->start >= rstart && newrange->end <= rend)
+ fail = -1;
+ /* new section start or end point are within range */
+ if (newrange->start <= rstart && newrange->end >= rstart)
+ fail = -1;
+ if (newrange->start <= rend && newrange->end >= rend)
+ fail = -1;
+ if (fail) {
+ printf("Error: overlapping IO regions: %s and %s\n",
+ newrange->name, name);
+ return -1;
+ }
+ newrange = newrange->next;
+ }
+
+ newrange = malloc(sizeof(iorange_t));
+
+ newrange->name = name;
+ newrange->ops = ops;
+ newrange->start = rstart;
+ newrange->end = rend;
+ newrange->next = ioranges;
+
+ ioranges = newrange;
+
+ return 0;
+}
+
+int is_loaded(const char *plugin_name)
+{
+ plugin_t *p = plugins;
+ while (p) {
+ if (!strcmp(plugin_name, p->name))
+ return -1;
+ p = p->next;
+ }
+ return 0;
+}
+
+int load_plugin(const char *plugin_name)
+{
+ void *handle;
+ char *error;
+ char path[PATHSIZE];
+
+ int (*init_plugin) (void);
+ char **deps;
+ char **plugin_info;
+ plugin_t *p;
+
+ if (is_loaded(plugin_name)) {
+ printf("Plugin %s already loaded.\n", plugin_name);
+ return 0;
+ }
+
+ strncpy(path, PLUGINDIR, PATHSIZE);
+ strncat(path, "/plugin_", PATHSIZE);
+ strncat(path, plugin_name, PATHSIZE);
+ strncat(path, ".so", PATHSIZE);
+
+#if DEBUG
+ printf("Opening plugin %s\n", path);
+#endif
+
+ handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
+ if (!handle) {
+ error = dlerror();
+ printf("Error: Could not open plugin \"%s\": %s\n",
+ plugin_name, error);
+ exit(1);
+ }
+#ifdef CONFIG_DEBUG_PLUGINS
+ plugin_info = dlsym(handle, "plugin_author");
+ if ((error = dlerror()) == NULL)
+ printf("Plugin %s author: %s\n", plugin_name, *plugin_info);
+ plugin_info = dlsym(handle, "plugin_license");
+ if ((error = dlerror()) == NULL)
+ printf("Plugin %s license: %s\n", plugin_name, *plugin_info);
+ plugin_info = dlsym(handle, "plugin_description");
+ if ((error = dlerror()) == NULL)
+ printf("Plugin %s descr.: %s\n", plugin_name, *plugin_info);
+#endif
+ p = malloc(sizeof(plugin_t));
+ p->next = plugins;
+ p->name = plugin_name;
+ plugins = p;
+
+ deps = dlsym(handle, "plugin_deps");
+ if ((error = dlerror()) != NULL)
+ deps = NULL;
+
+
+ strncpy(path, "plugin_", PATHSIZE);
+ strncat(path, plugin_name, PATHSIZE);
+ strncat(path, "_init", PATHSIZE);
+
+ init_plugin = dlsym(handle, path);
+ if ((error = dlerror()) != NULL) {
+ printf("error: %s\n", error);
+ exit(1);
+ }
+
+ if (deps) {
+ int i = 0;
+ char *walk = deps[0];
+#ifdef CONFIG_DEBUG_PLUGINS
+ printf("\nPlugin %s dependencies:", plugin_name);
+#endif
+ while (walk) {
+ printf(" %s", walk);
+ if (!is_loaded(walk)) {
+#ifdef CONFIG_DEBUG_PLUGINS
+ printf("(loading)\n");
+#endif
+ load_plugin(walk);
+ }
+#ifdef CONFIG_DEBUG_PLUGINS
+ else {
+ printf("(loaded)");
+ }
+#endif
+ walk = deps[++i];
+ }
+ }
+
+ printf("\n");
+#if DEBUG
+ printf("Initializing module:\n");
+#endif
+
+ return init_plugin();
+
+ // We don't dlclose the handle here since
+ // we want to keep our symbols for later use.
+}
diff --git a/roms/openbios/arch/unix/plugins/Kconfig b/roms/openbios/arch/unix/plugins/Kconfig
new file mode 100644
index 00000000..43237bf9
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/Kconfig
@@ -0,0 +1,16 @@
+config PLUGINS
+ depends HOST_UNIX
+ bool "Plugin system (obsolete)"
+ default n
+
+config PLUGIN_PCI
+ depends HOST_UNIX && PLUGINS
+ bool "PCI Emulation"
+ default n
+
+config PLUGIN_QT
+ bool "QT Display Emulation"
+ depends HOST_UNIX && PLUGINS && PLUGIN_PCI
+ default n
+ help
+ This plugin needs qt installed. Disable if you don't have qt.
diff --git a/roms/openbios/arch/unix/plugins/Makefile b/roms/openbios/arch/unix/plugins/Makefile
new file mode 100644
index 00000000..c6b9a651
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/Makefile
@@ -0,0 +1,13 @@
+
+include ../../../config/Makefile.top
+
+SUBDIRS-$(CONFIG_PLUGIN_PCI) += plugin_pci
+SUBDIRS-$(CONFIG_PLUGIN_QT) += plugin_qt
+
+PROGRAMS = # loader
+loader-OBJS = loader.o
+loader-LDFLAGS = -dynamic $(LIBDL_LDFLAGS)
+
+INCLUDES = -DBOOTSTRAP
+
+include $(rules)/Rules.make
diff --git a/roms/openbios/arch/unix/plugins/Rules.plugin b/roms/openbios/arch/unix/plugins/Rules.plugin
new file mode 100644
index 00000000..9e9b6255
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/Rules.plugin
@@ -0,0 +1,15 @@
+# -*- makefile -*-
+
+INCLUDES = -I$(top_srcdir)/include -DBOOTSTRAP
+CFLAGS = -fPIC
+
+%.so: %.o
+ $(CC) -shared $(CFLAGS) $(filter %.o,$^) -o $@
+
+THISDIR := $(notdir $(shell pwd))
+
+all-local: $(addprefix $(ODIR)/../,$(PLUGINS))
+
+$(ODIR)/../%.so: $(ODIR)/%.so
+ install -d ../$(ODIR)
+ ln -f "../$(THISDIR)"/$< $@
diff --git a/roms/openbios/arch/unix/plugins/loader.c b/roms/openbios/arch/unix/plugins/loader.c
new file mode 100644
index 00000000..d3781de7
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/loader.c
@@ -0,0 +1,209 @@
+/* tag: openbios plugin loader
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+/* This is a simple plugin loader. OpenBIOS duplicates some
+ * of this code in kernel/arch/unix/plugins.c. This code is
+ * here for reference and simple testing.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <unistd.h> // sleep
+
+#include "unix/plugins.h"
+
+#define PLUGINDIR "/usr/share/OpenBIOS/plugins"
+#define PATHSIZE 256
+
+#define DEBUG_PLUGINS
+
+typedef struct iorange iorange_t;
+struct iorange {
+ const char *name;
+ unsigned int start;
+ unsigned int end;
+ io_ops_t *ops;
+ iorange_t *next;
+};
+
+iorange_t *ioranges = NULL;
+
+typedef struct plugin plugin_t;
+struct plugin {
+ const char *name;
+ plugin_t *next;
+};
+
+plugin_t *plugins = NULL;
+
+int register_iorange(const char *name, io_ops_t * ops, unsigned int rstart,
+ unsigned int rend)
+{
+ iorange_t *newrange;
+
+ /* intersection check */
+ newrange = ioranges;
+ while (newrange) {
+ int fail = 0;
+ /* new section swallows old section */
+ if (newrange->start >= rstart && newrange->end <= rend)
+ fail = -1;
+ /* new section start or end point are within range */
+ if (newrange->start <= rstart && newrange->end >= rstart)
+ fail = -1;
+ if (newrange->start <= rend && newrange->end >= rend)
+ fail = -1;
+ if (fail) {
+ printf("Error: overlapping IO regions: %s and %s\n",
+ newrange->name, name);
+ return -1;
+ }
+ newrange = newrange->next;
+ }
+
+ newrange = malloc(sizeof(iorange_t));
+
+ newrange->name = name;
+ newrange->ops = ops;
+ newrange->start = rstart;
+ newrange->end = rend;
+ newrange->next = ioranges;
+
+ ioranges = newrange;
+
+ return 0;
+}
+
+int is_loaded(const char *plugin_name)
+{
+ plugin_t *p = plugins;
+ while (p) {
+ if (!strcmp(plugin_name, p->name))
+ return -1;
+ p = p->next;
+ }
+ return 0;
+}
+
+int load_plugin(const char *plugin_name)
+{
+ void *handle;
+ char *error;
+ char path[PATHSIZE];
+
+ int (*init_plugin) (void);
+ char **deps;
+ char **plugin_info;
+ plugin_t *p;
+
+ if (is_loaded(plugin_name)) {
+ printf("Plugin %s already loaded.\n", plugin_name);
+ return 0;
+ }
+
+ strncpy(path, PLUGINDIR, PATHSIZE);
+ strncat(path, "/plugin_", PATHSIZE);
+ strncat(path, plugin_name, PATHSIZE);
+ strncat(path, ".so", PATHSIZE);
+
+#if DEBUG
+ printf("Opening plugin %s\n", path);
+#endif
+
+ handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL);
+ if (!handle) {
+ error = dlerror();
+ printf("Error: Could not open plugin \"%s\": %s\n",
+ plugin_name, error);
+ exit(1);
+ }
+#ifdef DEBUG_PLUGINS
+ plugin_info = dlsym(handle, "plugin_author");
+ if ((error = dlerror()) == NULL)
+ printf("Plugin %s author: %s\n", plugin_name, *plugin_info);
+ plugin_info = dlsym(handle, "plugin_license");
+ if ((error = dlerror()) == NULL)
+ printf("Plugin %s license: %s\n", plugin_name, *plugin_info);
+ plugin_info = dlsym(handle, "plugin_description");
+ if ((error = dlerror()) == NULL)
+ printf("Plugin %s descr.: %s\n", plugin_name, *plugin_info);
+#endif
+ p = malloc(sizeof(plugin_t));
+ p->next = plugins;
+ p->name = plugin_name;
+ plugins = p;
+
+ deps = dlsym(handle, "plugin_deps");
+ if ((error = dlerror()) != NULL)
+ deps = NULL;
+
+
+ strncpy(path, "plugin_", PATHSIZE);
+ strncat(path, plugin_name, PATHSIZE);
+ strncat(path, "_init", PATHSIZE);
+
+ init_plugin = dlsym(handle, path);
+ if ((error = dlerror()) != NULL) {
+ printf("error: %s\n", error);
+ exit(1);
+ }
+
+ if (deps) {
+ int i = 0;
+ char *walk = deps[0];
+#ifdef DEBUG_PLUGINS
+ printf("\nPlugin %s dependencies:", plugin_name);
+#endif
+ while (walk) {
+ printf(" %s", walk);
+ if (!is_loaded(walk)) {
+#ifdef DEBUG_PLUGINS
+ printf("(loading)\n");
+#endif
+ load_plugin(walk);
+ }
+#ifdef DEBUG_PLUGINS
+ else {
+ printf("(loaded)");
+ }
+#endif
+ walk = deps[++i];
+ }
+ }
+
+ printf("\n");
+#if DEBUG
+ printf("Initializing module:\n");
+#endif
+
+ return init_plugin();
+
+ // We don't dlclose the handle here since
+ // we want to keep our symbols for later use.
+}
+
+int main(void)
+{
+ iorange_t *r;
+
+ // load_plugin("kbd");
+ // load_plugin("pci");
+ load_plugin("qt");
+
+ printf("\nRegistered IO Ranges:\n");
+ r = ioranges;
+ while (r) {
+ printf(" %s: %x-%x\n", r->name, r->start, r->end);
+ r = r->next;
+ }
+
+ sleep(10);
+ return 0;
+}
diff --git a/roms/openbios/arch/unix/plugins/plugin_pci/Makefile b/roms/openbios/arch/unix/plugins/plugin_pci/Makefile
new file mode 100644
index 00000000..e46a6cda
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_pci/Makefile
@@ -0,0 +1,7 @@
+
+include ../../../../config/Makefile.top
+
+PLUGINS = plugin_pci.so
+
+include ../Rules.plugin
+include $(rules)/Rules.make
diff --git a/roms/openbios/arch/unix/plugins/plugin_pci/Makefile.old b/roms/openbios/arch/unix/plugins/plugin_pci/Makefile.old
new file mode 100644
index 00000000..10d0555d
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_pci/Makefile.old
@@ -0,0 +1,21 @@
+# tag: Makefile for OpenBIOS PCI plugin
+#
+# Copyright (C) 2003 Stefan Reinauer
+#
+# See the file "COPYING" for further information about
+# the copyright and warranty status of this work.
+#
+
+PLUGIN_SOURCES = plugin_pci.c
+PLUGIN_NAME = plugin_pci.so
+
+INCLUDES := -I$(TOPDIR)/include -I$(BUILDDIR) -I..
+VPATH := $(VPATH):.
+
+all: $(PLUGIN_NAME)
+
+$(PLUGIN_NAME): $(PLUGIN_SOURCES)
+ $(CC) -shared -Wall -Os -fPIC $(INCLUDES) $< -o $(BUILDDIR)/$@
+
+clean:
+ rm -f plugin_*.so
diff --git a/roms/openbios/arch/unix/plugins/plugin_pci/plugin_pci.c b/roms/openbios/arch/unix/plugins/plugin_pci/plugin_pci.c
new file mode 100644
index 00000000..586ea2aa
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_pci/plugin_pci.c
@@ -0,0 +1,221 @@
+/* tag: openbios pci plugin
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "unix/plugins.h"
+#include "unix/plugin_pci.h"
+
+#define DEBUG
+
+u32 pci_conf_addr = 0;
+pci_dev_t *pci_devices = NULL;
+
+static pci_dev_t *find_device(u32 conf_addr)
+{
+ pci_dev_t *devs = pci_devices;
+ unsigned bus = (conf_addr >> 16) & 0xff;
+ unsigned dev = (conf_addr >> 11) & 0x1f;
+ unsigned fn = (conf_addr >> 8) & 0x7;
+
+ // printf("Looking for device %x\n",conf_addr);
+
+ while (devs) {
+ if (devs->bus == bus && devs->dev == dev && devs->fn == fn)
+ return devs;
+ devs = devs->next;
+ }
+ return NULL;
+}
+
+/*
+ * IO functions. These manage all the magic of providing a PCI
+ * compatible interface to OpenBIOS' unix version of the kernel.
+ */
+
+static u8 pci_inb(u32 reg)
+{
+ u32 basereg = (reg & 0xfffc);
+ u32 basepos = (reg & 0x03);
+ pci_dev_t *dev;
+
+ if (basereg == 0xcf8) {
+ return (pci_conf_addr >> (basepos << 3));
+ }
+
+ /* still here? so we're 0xCFC */
+ dev = find_device(pci_conf_addr);
+ if (!dev || !dev->config)
+ return 0xff;
+
+ return dev->config[(pci_conf_addr + basepos) & 0xff];
+}
+
+static u16 pci_inw(u32 reg)
+{
+ u32 basereg = (reg & 0xfffc);
+ u32 basepos = (reg & 0x02);
+ pci_dev_t *dev;
+
+ if (basereg == 0xcf8) {
+ return (pci_conf_addr >> (basepos << 3));
+ }
+
+ /* still here? so we're 0xCFC */
+ dev = find_device(pci_conf_addr);
+ if (!dev || !dev->config)
+ return 0xffff;
+
+ return *(u16 *) (dev->config + ((pci_conf_addr + basepos) & 0xff));
+}
+
+static u32 pci_inl(u32 reg)
+{
+ u32 basereg = (reg & 0xfffc);
+ pci_dev_t *dev;
+
+ if (basereg == 0xcf8) {
+ return pci_conf_addr;
+ }
+
+ /* still here? so we're 0xCFC */
+ dev = find_device(pci_conf_addr);
+ if (!dev || !dev->config)
+ return 0xffffffff;
+
+ return *(u32 *) (dev->config + (pci_conf_addr & 0xff));
+}
+
+static void pci_outb(u32 reg, u8 val)
+{
+ u32 basereg = (reg & 0xfffc);
+ u32 basepos = (reg & 0x03);
+ pci_dev_t *dev;
+
+ if (basereg == 0xcf8) {
+ pci_conf_addr &= (~(0xff << (basepos << 3)));
+ pci_conf_addr |= (val << (basepos << 3));
+ return;
+ }
+
+ /* still here? so we're 0xCFC */
+ dev = find_device(pci_conf_addr);
+ if (!dev || !dev->config)
+ return;
+
+ dev->config[pci_conf_addr & 0xff] = val;
+}
+
+static void pci_outw(u32 reg, u16 val)
+{
+ u32 basereg = (reg & 0xfffc);
+ u32 basepos = (reg & 0x02);
+ pci_dev_t *dev;
+
+ if (basereg == 0xcf8) {
+ pci_conf_addr &= (~(0xffff << (basepos << 3)));
+ pci_conf_addr |= (val << (basepos << 3));
+ return;
+ }
+
+ /* still here? so we're 0xCFC */
+ dev = find_device(pci_conf_addr);
+ if (!dev || !dev->config)
+ return;
+
+ *(u16 *) (dev->config + (pci_conf_addr & 0xff)) = val;
+}
+
+static void pci_outl(u32 reg, u32 val)
+{
+ u32 basereg = (reg & 0xfffc);
+ pci_dev_t *dev;
+
+ if (basereg == 0xcf8) {
+ pci_conf_addr = val;
+ return;
+ }
+
+ /* still here? so we're 0xCFC */
+ dev = find_device(pci_conf_addr);
+ if (!dev || !dev->config)
+ return;
+
+ *(u32 *) (dev->config + (pci_conf_addr & 0xff)) = val;
+}
+
+static io_ops_t pci_io_ops = {
+ inb:pci_inb,
+ inw:pci_inw,
+ inl:pci_inl,
+ outb:pci_outb,
+ outw:pci_outw,
+ outl:pci_outl
+};
+
+/*
+ * Functions visible to modules depending on this module.
+ */
+
+int pci_register_device(unsigned bus, unsigned dev, unsigned fn,
+ u8 * config)
+{
+ pci_dev_t *newdev;
+ u32 caddr = (1 << 31) | (bus << 16) | (dev << 11) | (fn << 8);
+
+ if (find_device(caddr)) {
+ printf("Error: pci device %02x:%02x.%01x already exists\n",
+ bus, dev, fn);
+ return -1;
+ }
+
+ newdev = malloc(sizeof(pci_dev_t));
+
+ if (!newdev) {
+ printf("Out of memory\n");
+ return -1;
+ }
+
+ newdev->bus = bus;
+ newdev->dev = dev;
+ newdev->fn = fn;
+ newdev->config = config;
+ newdev->next = pci_devices;
+
+ pci_devices = newdev;
+
+ return 0;
+}
+
+/*
+ * Initialization is really simple. We just grab the
+ * PCI conf1 io range for our emulation functions.
+ */
+extern int plugin_pci_init( void );
+
+int plugin_pci_init(void)
+{
+#ifdef DEBUG
+ printf("Plugin \"pci\" initializing... ");
+#endif
+ register_iorange("pci", &pci_io_ops, 0xcf8, 0xcff);
+#ifdef DEBUG
+ printf("done.\n");
+#endif
+ return 0;
+}
+
+/* plugin meta information available for the plugin loader */
+PLUGIN_AUTHOR ("Stefan Reinauer <stepan@openbios.org>")
+PLUGIN_DESCRIPTION ("Generic PCI Device Emulation")
+PLUGIN_LICENSE ("GPL v2")
+
+/* This plugin has no dependencies. Otherwise the following
+ * macro would be uncommented:
+ * PLUGIN_DEPENDENCIES ("this", "that")
+ */
diff --git a/roms/openbios/arch/unix/plugins/plugin_qt/Makefile b/roms/openbios/arch/unix/plugins/plugin_qt/Makefile
new file mode 100644
index 00000000..371dc2f0
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_qt/Makefile
@@ -0,0 +1,37 @@
+
+include ../../../../config/Makefile.top
+
+PLUGINS = plugin_qt.so
+
+QMAKE = qmake
+PLUGINDIR = $(shell cd .. ; pwd )
+TOPDIR = $(shell cd $(top_srcdir) ; pwd)
+ABSOINC = $(shell cd $(ARCHINCLUDES) 2> /dev/null ; pwd )
+
+export PLUGINDIR TOPDIR ABSOINC
+
+qt_rom.fc: qt_rom.fs
+ $(TOKE) -v qt_rom.fs
+
+fcode.h: qt_rom.fc
+ @echo "static const u8 qt_fcode[] = {" > $@
+ @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \
+ | sed 's/0x ,//g' >> $@
+ @echo "};" >> $@
+
+$(ODIR)/makefile.qmake: plugin_qt.pro Makefile
+ @test -d $(ODIR) || $(INSTALL) -d $(ODIR)
+ @test -d $(ODIR)/qbuild || $(INSTALL) -d $(ODIR)/qbuild
+ @cp plugin_qt.pro $(ODIR)/
+ cd $(ODIR) ; $(QMAKE) -o makefile.qmake
+
+$(ODIR)/plugin_qt.so: fcode.h $(ODIR)/makefile.qmake $(wildcard *.cpp)
+ cd $(ODIR) ; $(MAKE) -f makefile.qmake
+ @ln -f $(ODIR)/qbuild/plugin_qt.so $@
+
+clean-local:
+ @rm -f $(ODIR)/makefile.qmake
+ @rm -rf $(QBUILDDIR) $(ODIR)/*.fc $(ODIR)/fcode.h
+
+include ../Rules.plugin
+include $(rules)/Rules.make
diff --git a/roms/openbios/arch/unix/plugins/plugin_qt/logo.xpm b/roms/openbios/arch/unix/plugins/plugin_qt/logo.xpm
new file mode 100644
index 00000000..9e2ac60b
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_qt/logo.xpm
@@ -0,0 +1,132 @@
+/* This logo was created by Stephan Lau,
+ * created to xpm by Stefan Reinauer
+ */
+static char *logo[] = {
+/* columns rows colors chars-per-pixel */
+"300 80 44 1",
+" c #010101",
+". c #070709",
+"X c #0B0B0B",
+"o c #0F0F11",
+"O c #121212",
+"+ c #1B1B1B",
+"@ c #1F1F21",
+"# c #232323",
+"$ c #262628",
+"% c #2B2B2C",
+"& c #2E2E30",
+"* c #333333",
+"= c #373739",
+"- c #3B3B3B",
+"; c #434343",
+": c #464648",
+"> c #4B4B4B",
+", c #4E4E50",
+"< c #535353",
+"1 c #5B5B5B",
+"2 c #5E5E60",
+"3 c #646464",
+"4 c #666668",
+"5 c #6B6B6B",
+"6 c #747474",
+"7 c #767678",
+"8 c #7B7B7B",
+"9 c #838383",
+"0 c #8A8A8A",
+"q c #939394",
+"w c #979799",
+"e c #9B9B9B",
+"r c #A3A3A3",
+"t c #ABABAB",
+"y c #B4B4B4",
+"u c #BBBBBB",
+"i c #C3C3C3",
+"p c #CBCBCB",
+"a c #D3D3D3",
+"s c #DBDBDB",
+"d c #E3E3E3",
+"f c #EBEBEB",
+"g c #F3F3F3",
+"h c #FEFEFE",
+/* pixels */
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfdssaapuuuytteeewq0009998867666555555555555565666778899000qwwerttyyuuppassdfghhhhhhhhhhgfgggghhhgfgfghhhhggffghhhhggffghhhhgfggghhhhgfggghhhhgfgfghhhhfgfgghhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdsapuytrwq0986555554455555555555555555555555555555555555555555555555555555555555555555555555556790qertyiuuuafhhhfpiishhhhfipidhhhhfiiidhhhhdiiifhhhhsiiifhhhhsiipghhhhaiipghhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfdaiuttq0976555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558iuue5579wuuuuiasfduuishhhhduuudhhhhduuudhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdaittw086555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558yuur55549uuiw55569uuutyiadsuuudhhhhsuuudhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfapyrw975555555555555555555555555555555555555555555555555555555555555555555555555555555554555555555555555555554455555555555555555555558uuue54559uuuw55559uuuq55550uiutypafduuufhhhhsuuufhhhhsuuufhhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdautw965555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555679qqerttuuppaasdddffgghghhhhhhhhhghhggfduuupaappuuuuyeq090uuuq55559uyi05555quuuuadghsuuufhhhhauuufhhhhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfsite0655555555555555555555555555555555555555555555555555555555555555555555555455555555555555555690wrtiiaddghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfuuuahhhhfuuushhhhfuuuaaiittuuuq55550uuu95560tuuudhhhhsuuughhhhauuufhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhgsite955555555555555555555555555455555555555555555555555555555555555555555555555545555555555570wryiadfhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhguuuahhhhfuuuahhhhfuuushhhhduuudfsaiuuuuq5555qiuu99etipuuifhhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaut0655555555555555555555555555555555555555555555556555555555555555555555555555555555554559qruisfhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdsdfhhhhgdddfhhhhfddsfhhhhgdddfhhhhfddsffspyteeq755559qetisfhgfdddghhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgsir065555555555555555555555555555455555555555555555554555555555555555555555555555555555580rupsghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsuudhhhhhhhhhhhhfuuphhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgspyt085555560tudghhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaue9555555555555555554<----=---=---==-==<555555---:3:--=--=-*--==--<55555545<;------==->135890phhhhhy009tfq0009009090909wshhhhhhg<;;:;;;:<9fhhhhhhhf$ rhhhhhs3# ;phhhhhhhf0# Owghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdpue0655559wuaghhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgsue855555455555555555555:O. *5455- *. &44555>O 6ghhh+ 5O ehghhh9 . Xighhhhh9 -gfggf3 +sddffd8O rddffffffffgffffgffffffffggffffffffgffffgffdaute09868eusghhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfpr955555555555555555555555% .%=************& +2555o +=************% +3343% X-<3568888787884. ;dggq. O19888888888888, 8fgghsO . 1fggghsO ysdfiO 9ttuu> . 1rtuyuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuuuuuuiiuuuut06449rpdhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhduw85555555555555555555555555* .,111<1111111111< #113- #<<111111111111< #123- Xtssaaaaaaaaaaaaa <sdf@ Otaaaaasaaaaaaaae 9sdgg, =sdggh< 2ipa0 7etr# <etttuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuighfauw857wudhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhfie7555555555555555555555554555: =1<<<<<<<<<<<<<<& -<<3X X<<><<<<1,,<<<<<& ;7e8 9apiiiiiipiiiiii6 0ia9 8uuuiipipiiiiiii> oyisdt X%% 2iadgy Xrty6 @69& X90e; *3% 49wttuuuuuuuuuuuuuuuuuuuuuuuuuuuyuyyyuuyuuuuuuuuuuihhhhhhgayw86eifhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhar8555555555555555555555555555543. +<,>>>,>><>>>>,,:. O;:<& -:;>>><>,,<><>,:. $eytO -puuyuuuuuuuuuiutX %rytO *ytrtyuuiuuuuuuu9 1ruis%. 108- . 8tisd% <qw9X #tre> *59, -86* O47qetuuuuuuuuuuuuuuuuuuuuuuuuuuuiasddsaiuuuuuuuuuuighhhhhhhhhgatq9tahhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhgiq55555555555555555555555555555555- ;>:>:,<<<,<<<<<<# . %-;: . O:;;;>>,<<>,,<38; 5qr3 eutttuuiiiipiiii1 5wr< qreeryuiipiiipii$ X0wru8 O976& +9wya0 O999O qeq9O >3< +751. &159wtyuuuuuuuuuuuuuuuuuuuuuuuuisfhhhhhhgdpuuuuuiuuihhhhhhhhhhhhhhdierighhhhhhh",
+"hhhhhhhhhhhhhhhhhfi05555555555555555555555555555555552 #>;;:,,<<<11<11<> +--;+ ;;--;><<1116qtpy -009 ,ttrrtuppaaaaaaay -q09 ;ewqrtupaaaaaaap9 10qrtX .3754X . >60tuX 387% 3w09: +3<O. 153% O:159wtyuuuuiuuuuuuuuuuuuuuuuuuaghhhhhhhhhhhdiuuuuuuighhhhhhhhhhhhhhhhfaupghhhhh",
+"hhhhhhhhhhhhhhhhiq55555555555555555555555555555555555+ X;:;;><<112311212+ .---& $;-;;><138eusddd- X000% oerrrtuaadsdddddd- o090$ Xwqqetypadddsddsao .%q9qr3 $856- +160t5 $761 X9097X ;1& &54< *;159wtyuuuuuuuuuuuuuuuuuuuuuushhhhhhhhhhhhhhdpyuuuuihhhhhhhhhhhhhhhhhhhhgsdhhhh",
+"hhhhhhhhhhhhhhsr555555545555555555555555555555555555, %;;-:><123333535> %---O .;--;;<5wifgfgfgt 1w04 2ewerupsffgffggft 1w05 1wqqeyasffgfgggg9 7q0wq 6665 ,360w 666O <999= %32. . <31+. +>>160rtuuuuuuuuuuuuuuuuuuuuuyshhhhhhhhhhhhhhhhfuuuuuighhhhhhhhhhhhhhhhhhhhhhhghh",
+"hhhhhhhhhhhhhi05555555555555555555555555555555555555o .X;;-::<1335555454X X:--$ &:--,6rsfghhghgh# Orq0O <<<<156999090999# +rqqO +qqqetisgghhghhha >rqqe* >867# *358e* >76; #9994 . .44- o2<>++++O>><48qrtuuuuuuuuuuuuiuuuuuuuuphhhhhhhhhhhhhhhhhhsyuiuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhu65555555555555555555555555555555555555- *;-->>1355555554- *;--. O;-<5rpdfhhhhhhh9 7rq< 6eq, 5w0wtisdgghhhhhh< Oqwqw8 X7773 X45608 X666. 3779% ;55X. %<1356651<<369etyuuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhhhhhgpyuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhi755555555555555555555555555555555555553. +;--;><2555555553. O:--$ *16qtiafhghhhhhgO *rq9X @,>:><356787888787653rq9X %wqqryadfghhhhhhy 3rqqrO <669O >569q+ <66* =8781 O953 &<24698533359qryuuuuuuuuuuuiuuuuuuuuuphhhhhhhhhhhhhhhhhhhhsyuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhs955555555555555555555555555555555555555% -;;;><1335555555$ -;;* %9wweypdfhhhhhhh4 eeq- 90990rtupaaaaaaaapiutee- 9qqerusfhhhhhhhh# +twqr1 @868= $867q1 @873 o5689O 166; &<36999865690etyyuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhhhhhhhfiuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhy55555555555555555555555555555555555555< #;--:,<3355555551 #;;-+ Xqwqetisfhghhhhhp 1eq7 >q999qrtuuipipuippuytrr8 :wqqruadfhhhhhhh9 6ewweX 363% #6689qX 276# >769, $867* +13800q9999qrtyuuuuuuuuuuuuuuuuuuuuuufhhhhhhhhhhhhhhhhhhhhhpuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhh955555555555555555555555555555555555555@ .:-;;:<1335555554+ .;:-* 1wqqrupfghhhhhhh; Oeeq$ ..q0990qrtuuuuuuuuuuuuttr& XqqqetpdfghhhhhhfO *tewe> %8869q< *76< O6687X 4669$ .X159qeeeqqqrryuuuuuuuuuuuuuuuuuuuiuuighhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhh55555555555555555555555555555555555555: $;-;;,<335555554: $:-2+ +qqqeyidgghhhhhhr 1rq3 1q000rryuipiiipiiiiiuuu7 1wqwtuadghhhhhhh6 qwww0 =20979q9 X566X <679= . -8680- . >69errtrrrtyyuuuuuuuuuuuuuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhh95555555555555555555555555555555555555O X:--;><2355555553O O:162 3eqerusdghhhhhhf# $tqqO +qqqwrtipaaaaaaaaaaaaapp+ Oeqqetpsgghhhhhhs >ewqr&. ;q0998qe* >86; #7685 O6680e1 *50ettyyyyyuuuuuuuuuuuuuuuuuuuuuuuuuhhhhhhhhhhhhhhhhhhhhhhpuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhht655555555555555555555555555555555555: %;-;:<1335555555& .:500X +eqerypsghhhhhhh6 Oqeq3 1qqwryiasddddddddddddsd7 8wqqtuafghhhhhhh; Oreqw7 -999qw7. +665X 4679@ :789wt6 O50etyyuuuuuuuuuuuuuuuuuuuuuuuuuiuuughhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhs955555555555555555555555555555555555% --;;>1135555553- ,0eq> =wqerisfghhhhhf9 8rwq- 9qqetpsdffgfgffgfdttgfa *rqqryadghhhhhhhq 4rqwrO *-@ 79qeu+ ,76* . *7681 O8680ruy X49etyuuuuuuuuuuuuuuuuuuuuiuuuuuuuuudhhhhhhhhhhhhhhhhhhhhgiuuuhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhu65555555555555555555555555555555554# .4eew9 X Oqteww= #dgg; 9wqwtisfghhhhhhfX Xewqe3 %63< @70ey5 #961 X6678X 3679ruip& 48wryuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuphhhhhhhhhhhhhhhhhhhhduuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhu7555555555555555554555555555555545,@X . .+>qyrre& X8O O-7utreer9=X ufg5 +ewqruadghhhhhhf; >eqweX . 451> -6qyyO 366# ;769< $769wtpaa3 O36qrtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuighhhhhhhhhhhhhhhhhhhpyuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhp95455555555555555555555555555555331:;---;><1111111117tutre8 1q999wtipaaasssaaaiutrrrruyrq09qruiasasasasassssddddaitrwetisfhghhhhhhgfautewr; -654% o56eu< =86: . O8687 6669ruada4 @160ryuuuuuuuuuuuuuuuuuuiuuuuuuuuuuuuahhhhhhhhhhhhhhhhhhsuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhde555555555555555555555555555555331,;---;;,<<<<<1<<8tutrtt+ Or099qwtuipppppppiiuytrtyiiiteq0qryupppppppppppppssdspurreriafghhhhhhhhgdaueee8 X665< ;38e9 X765X 1679% >669wyadfd5 *150rtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuushhghhhhhhhhhhhhhgiyuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhiq555555555555555555555555555533<<:;-;;>>,>,>,,,6ttyttt3 5q9990rttuuuuuuyuuyyttyupaapurewertyyuuuuuuuuuuuipasaputttypsgghhhhhhhggsautrt* ,667# .+159e* >86;. $6695 .8680tisfgd3 X:160rtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhgiuiuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhfi055555555555555555555555555332<>>:;:>>>,<>,>6tuuuiiuX *eq00wrryyuuuuyuuuuuyuiiasdsaputrtttuuyuyuuuuyyuupaassaiuyupsfghhhhhhhhhgdaiuy6 O967< 146q3 O865 5679O ,769wuafggfX #:150rtuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuuuushhhhhhhhhhhhfiuuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhfiq5555555555555555555554555431<<<,<<<<<<<15tippppa<. 0wqqetyippppppppppippaasdfgfdsapiipipppppppppppppaadddsaapasfghhhhhhhhhggfsapi+ 1678O -5589+ 176% -679, +85O rgg0 X-,36qrtuuuuuuuuuuuuiuuuuuuuuuuuuuuuuiuuuuupfghhhhhhhfauuuuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhat85555555555555555555555433221111111113tsssssdr >eqqetupaasaaasaasssasddfgggggfdssasassaassasaasssddffffddddfgghhhhhhhhhhhgfdd8 $878> X55601 $761 X5788o 37- -dfd@ &>,39qryuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuypsdffdspuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhfiw6555555555555555555555333332322331efffdffs+ qqwetiadfffdfddfffdfffffgghhhgggfffdfdffdfdfdfdfdfffggfggfggghhhhhhhhhhhhggggp 6666 >6699 676+ >679- =73 .yss8 .O,,159etyuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyuyuuuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhfiw7545555555555555555555545353350dgggghg4 -rqqruadfggghghhggghgghhhhhhhhhhghghhghgghghghghghghhhhhhhhghghhhhhhhhhhhhhhhg< ;669& +666q* -76, . O8686 X66$ <uiuO . -><57qryuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuughhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdir955555555555555555555555555uhhhhhhhgfsuteqrtpdfhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhu X7764 . 15696 .766# . <679$. <7< oqty- %<<149etyuuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsue85555455555555555555559dhhhhhhhgfauteeriadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh* >865X -667q# >765 668= =86% -0q1 +4357qtiasdddddddddddddddsdddddddsddddddsddddddddddddsddddddddddddshhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfaue755555555555555555ehhhhhhhhgdautrtuadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhq ;-% +76703 O868: . >>% +975 %2* X6669wuadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsit06553555555555phhhhhhhggfaiuuupsfghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfO . +76680X 3869- . %986> . . X5877qtpsgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaur065455555dhhhhhhhhgfdaapadfghghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh6 . -8767q> *7699* . . -0989; +98669qusfggfffghhhhgfffghhhhgfffghhhhgdfdghhhhgfffghhhhgfffghhhhdfffghhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgspte955fhhhhhhhhggfddddfghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs . O3987800 5760e4 O3099997 X;996136qpdfhfuuuahhhhduuushhhhduuudhhhhduuufhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfahhhhhhhhhhggffggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh- X%>688780r& ,869qry< #;89999qwr3o O=58887559rdghhguuushhhhfuuishhhhduuudhhhhduuufhhhhsuuufhhhhauuufhhhhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdauq841<15566890ryupute9880ruuur3<;1156889qrtyyr41>,145670979qyfgghfuuuahhhhfuuushhhhdiuudhhhhduuudhhhhsuuufhhhhauiughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhggdptq8433356789qrupaaite990ruppitq85345790wtypiitw84335680qe0qrugghhfuuushhhhfuuushhhhduuudhhhhsuuudhhhhauuufhhhhsuuufhhhhpuuighhhhhhhhhhhhhghhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhg7-&508666880qrtipssaiyeqqrtpsspue076699qetipsaaurq866790ettwrtphhhhfuuuahhhhfuuudhhhhduuudhhhhduuidhhhhsuuufhhhhauuifsfhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhg9O550eqq0qwertuisdffsauyttupsddsayrqqqqrtupaddfdpureq0qeryiprtyahhhhfuuushhhhfuuushhhhfuuudhhhhduuudhhhhsuuufhhhhauuug;0hhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh;8saiuuttuyuipaddgggfsaiiiasffgfaaiytyuupaddgggfdpuuyyuupadauuuahhhhfiuiahhhhfiuudhhhhduuidhhhhduuufhhhhsiiufhhhhauuug>0hhpiuughhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhO ysaaaOt3 4dggp% %usssu& *ifssaaaasdffghOpggsOtaat- -ufggXahhpOfggOp7 .5fgfgghhhgggf9 6gggOphhhXigg9 6gggX 9gggi* *pghhO; 4@+dhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhp*4tgffdf %&er phh+;yu&&gfg+:uu*%hgffddfffghhh uhgd tdd@%yy:+hhh uhhu hhh **tr ahhhhhhhhhhh 0uut<hhh uhhf uhh 0uut<hhhp*4uufhhh$;uu**hhh *0 7*0hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh:9hhgghg 3ggh<shh uhhu hgh uhhu hghggghgghhhh<5hhwOggg uhhy hhh thhu hhh 4hhh<shhhhhhhhhhh4 5uhhhhh<5hheOhhh4 5uhhhhhh;0hhhhhh uhhu hhh uu h;0hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh00phhhhhhhhhhhhhhh90phhhhhhhhhhhhhhh00phhhhhhhhhhhhhh:0hhhhhh uhhhhhhh *;;* hhh *;;* hhhhhhhhhhhhht fh@9hhh uhhu hhh;9hhu hhh uhhhhhhhhhhhhhhhghu< *phhhr fh#0hhhhu< *phhhh;0hhhhhh &>;* hhh uu h>9hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 0hhhhhhhhhhhhhhh 0hhhhhhhhhhhhhhh 0hhhhhhhhhhhhhh;0hhhhhh uhhhhhhh 40900hhh 40900hhhhhhhhhhhhhh@0r fhhh uhhu hhh;0hht hhh uhhhhhhhhhhhhhhhhhhhs<#hhhh#0t fhhhhhhs<#hhhh;0hhuhhh 39000hhh uy h9>hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh00phhhhhhhhhhhhhhh90phhhhhhhhhhhhhhh00phhhhhhhhhhhhhh;9hhhhhh uhhhhhhh@<uuuphhh@1uuuphhhhghhhhhhhhh0O#5hhhh*%uu*&hhh<<u4 hhh uhhhhhhhhhhhhhhhh<tuu0Ohhhh0O#4hhhh<ruu0Ohhhh1<u9 uhh@1uuuphhh uu h0;hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<0hhhhhhXphhhhhhhs;. Xhhhs> Ohhhhhhhhhhhhhhg3 shhhhp; ;ahhha+ ;wOhhhXahhhhhhhhhhhhhhhh6 Owhhhhf4 shhhh6 Oqhhhhp$ 6hhhs; OhhhXpaOh0<hhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhh3;hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh4;hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh09 uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhh09 uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<:5hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<:4hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
+"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
+};
diff --git a/roms/openbios/arch/unix/plugins/plugin_qt/pciconfig.h b/roms/openbios/arch/unix/plugins/plugin_qt/pciconfig.h
new file mode 100644
index 00000000..88b0e1aa
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_qt/pciconfig.h
@@ -0,0 +1,42 @@
+/* tag: pci config space dump for qt plugin's pci device.
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+static unsigned char pci_config_space[256]={
+ 0x02, 0x10, 0x36, 0x43, 0x87, 0x02, 0xb0, 0x02,
+ 0x00, 0x00, 0x00, 0x03, 0x10, 0x42, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0xf0, 0x01, 0xb0, 0x00, 0x00,
+ 0x00, 0x00, 0x50, 0xe8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x34, 0x17, 0x0a, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x34, 0x17, 0x0a, 0x10,
+ 0x01, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x50, 0x20, 0x00, 0x07, 0x02, 0x00, 0x2f,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
diff --git a/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.cpp b/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.cpp
new file mode 100644
index 00000000..07234dc0
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.cpp
@@ -0,0 +1,128 @@
+/* tag: qt plugin framebuffer class
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "plugin_qt.h"
+#include "logo.xpm"
+
+#include <iostream>
+
+static const int sizex=640;
+static const int sizey=480;
+static const int depth=8;
+
+static unsigned char color[256][3]={
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0xaa },
+ { 0x00, 0xaa, 0x00 },
+ { 0x00, 0xaa, 0xaa },
+ { 0xaa, 0x00, 0x00 },
+ { 0xaa, 0x00, 0xaa },
+ { 0xaa, 0x55, 0x00 },
+ { 0xaa, 0xaa, 0xaa },
+ { 0x55, 0x55, 0x55 },
+ { 0x55, 0x55, 0xff },
+ { 0x55, 0xff, 0x55 },
+ { 0x55, 0xff, 0xff },
+ { 0xff, 0x55, 0x55 },
+ { 0xff, 0x55, 0xff },
+ { 0xff, 0xff, 0x55 },
+ { 0xff, 0xff, 0xff },
+};
+
+FrameBufferWidget::FrameBufferWidget(QWidget *parent, const char * name)
+: QWidget(parent, name, Qt::WType_TopLevel)
+{
+ setCaption ("OpenBIOS");
+ setIcon(QPixmap(logo));
+
+ QPopupMenu *file = new QPopupMenu (this);
+
+ file->insertItem( "E&xit", this, SLOT(quit()), CTRL+Key_Q );
+
+ QPopupMenu *help = new QPopupMenu( this );
+ help->insertItem("&About OpenBIOS", this, SLOT(about()), CTRL+Key_H );
+ help->insertItem( "About &Qt", this, SLOT(aboutQt()) );
+
+ menu = new QMenuBar( this );
+ Q_CHECK_PTR( menu );
+ menu->insertItem( "&File", file );
+ menu->insertSeparator();
+ menu->insertItem( "&Help", help );
+ menu->setSeparator( QMenuBar::InWindowsStyle );
+
+ setFixedSize(sizex,sizey+menu->heightForWidth(sizex));
+
+ buffer.create(sizex, sizey, depth, 256);
+
+ for (int i=16; i < 256; i++) {
+ color[i][0]=i;
+ color[i][1]=i;
+ color[i][2]=i;
+ }
+
+ for (int i=0; i< 256; i++)
+ buffer.setColor(i, qRgb(color[i][0], color[i][1], color[i][2]));
+
+ buffer.fill( 0 );
+
+ updatetimer=new QTimer(this);
+ connect( updatetimer, SIGNAL(timeout()), this, SLOT(update()) );
+ updatetimer->start(200,FALSE);
+
+ setMouseTracking( TRUE );
+}
+
+unsigned char * FrameBufferWidget::getFrameBuffer(void)
+{
+ return buffer.bits();
+}
+
+void FrameBufferWidget::paintEvent ( QPaintEvent * )
+{
+ QPainter p( this );
+ p.drawImage(0,menu->heightForWidth(sizex),buffer, 0,0, sizex, sizey);
+}
+
+void FrameBufferWidget::about()
+{
+ QMessageBox::about( this, "About OpenBIOS",
+ " Welcome to OpenBIOS 1.01\n"
+ " IEEE 1275-1994 Open Firmware implementation\n\n"
+ "written by Stefan Reinauer <stepan@openbios.org>\n\n"
+ " http://www.openbios.org/\n");
+}
+
+void FrameBufferWidget::aboutQt()
+{
+ QMessageBox::aboutQt( this, "OpenBIOS" );
+}
+
+void FrameBufferWidget::quit()
+{
+ extern volatile int gui_running;
+ extern volatile int interruptforth;
+
+ gui_running=0;
+ interruptforth=1;
+
+ qApp->quit();
+}
+
+void FrameBufferWidget::update()
+{
+ QPainter p( this );
+ p.drawImage(0,menu->heightForWidth(sizex),buffer, 0,0, sizex, sizey);
+}
+
+void FrameBufferWidget::keyPressEvent(QKeyEvent * e)
+{
+ int a=e->ascii();
+ if (a) {
+ std::cout << " key '" << e->text() << "' pressed" << std::endl;
+ }
+}
diff --git a/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.h b/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.h
new file mode 100644
index 00000000..a1ed76fe
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.h
@@ -0,0 +1,44 @@
+/* tag: qt plugin framebuffer class description
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __framebufferwidget_h
+#define __framebufferwidget_h
+
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <qmenubar.h>
+#include <qpopupmenu.h>
+#include <qmessagebox.h>
+#include <qstatusbar.h>
+#include <qtimer.h>
+
+class FrameBufferWidget : public QWidget {
+ Q_OBJECT
+ public:
+ FrameBufferWidget(QWidget *parent=0, const char *name=0);
+ unsigned char *getFrameBuffer(void);
+
+ public slots:
+ void quit();
+ void about();
+ void aboutQt();
+ void update();
+
+ private:
+ QImage buffer;
+ QMenuBar *menu;
+ QStatusBar *status;
+ QTimer *updatetimer;
+ void paintEvent ( QPaintEvent * );
+ protected:
+ void keyPressEvent(QKeyEvent * e);
+};
+
+#endif
diff --git a/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.pro b/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.pro
new file mode 100644
index 00000000..96accd36
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.pro
@@ -0,0 +1,18 @@
+# tag: qmake project file for OpenBIOS QT plugin
+#
+# Copyright (C) 2003 Stefan Reinauer
+#
+# See the file "COPYING" for further information about
+# the copyright and warranty status of this work.
+#
+
+TEMPLATE = app
+CONFIG += qt thread warn_on release
+LIBS = -shared
+INCLUDEPATH = qbuild $(ABSOINC) $(TOPDIR)/include $(PLUGINDIR)/plugin_pci
+DESTDIR = qbuild
+OBJECTS_DIR = qbuild
+MOC_DIR = qbuild
+TARGET = plugin_qt.so
+HEADERS = $(PLUGINDIR)/plugin_qt/plugin_qt.h
+SOURCES = $(PLUGINDIR)/plugin_qt/plugin_qt.cpp $(PLUGINDIR)/plugin_qt/qt_main.cpp
diff --git a/roms/openbios/arch/unix/plugins/plugin_qt/qt_main.cpp b/roms/openbios/arch/unix/plugins/plugin_qt/qt_main.cpp
new file mode 100644
index 00000000..ea558d31
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_qt/qt_main.cpp
@@ -0,0 +1,102 @@
+/* tag: openbios qt plugin skeleton
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+
+extern "C" {
+#include <pthread.h>
+#include <unistd.h>
+#include "unix/plugins.h"
+#include "unix/plugin_pci.h"
+}
+#include "plugin_qt.h"
+#include "pciconfig.h"
+#include "fcode.h"
+
+#define DEBUG
+
+volatile unsigned char * fb=0;
+volatile int gui_running=0;
+
+typedef struct {
+ int argc;
+ char **argv;
+} threaddata;
+
+void *gui_thread(void *ptr)
+{
+ threaddata *td=(threaddata *)ptr;
+
+ QApplication a(td->argc, td->argv);
+ FrameBufferWidget w;
+
+ a.setMainWidget(&w);
+ w.show();
+
+ fb=w.getFrameBuffer();
+
+ gui_running=-1;
+ a.exec();
+ gui_running=0;
+
+ return 0;
+}
+
+extern "C" {
+extern int plugin_qt_init(void);
+int plugin_qt_init(void)
+{
+ pthread_t mythread;
+ char *args[]={ "plugin_qt" };
+ threaddata mytd = { 1, args };
+
+#ifdef DEBUG
+ printf("Initializing \"framebuffer\" plugin...");
+#endif
+ pthread_create(&mythread, NULL, gui_thread, &mytd);
+ while (!fb)
+ usleep(20);
+
+ /* now we have the framebuffer start address.
+ * updating pci config space to reflect this
+ */
+#if (BITS > 32)
+ *(u32 *)(pci_config_space+0x14)=(u32)((unsigned long)fb>>32);
+#else
+ *(u32 *)(pci_config_space+0x14)=0;
+#endif
+ *(u32 *)(pci_config_space+0x10)=(u32)((unsigned long)fb&0xffffffff);
+
+ /* next is to write the rom address. We write that at a random
+ * address in pci config space for now.
+ */
+#if (BITS > 32)
+ *(u32 *)(pci_config_space+0x34)=(u32)((unsigned long)qt_fcode>>32);
+#else
+ *(u32 *)(pci_config_space+0x34)=0;
+#endif
+ *(u32 *)(pci_config_space+0x30)=(u32)((unsigned long)qt_fcode&0xffffffff);
+
+ /* FIXME: we need to put the fcode image for this
+ * device to the rom resource, once it exists
+ */
+
+ /* register pci device to be available to beginagain */
+ pci_register_device(0, 2, 0, pci_config_space);
+
+#ifdef DEBUG
+ printf("done.\n");
+#endif
+ return 0;
+}
+
+PLUGIN_AUTHOR("Stefan Reinauer <stepan@openbios.org>")
+PLUGIN_DESCRIPTION("QT gui plugin emulating framebuffer device")
+PLUGIN_LICENSE("GPL v2")
+PLUGIN_DEPENDENCIES("pci")
+
+}
diff --git a/roms/openbios/arch/unix/plugins/plugin_qt/qt_rom.fs b/roms/openbios/arch/unix/plugins/plugin_qt/qt_rom.fs
new file mode 100644
index 00000000..1879c365
--- /dev/null
+++ b/roms/openbios/arch/unix/plugins/plugin_qt/qt_rom.fs
@@ -0,0 +1,85 @@
+\ tag: Property management
+\
+\ this code implements an IEEE 1275-1994 fcode driver
+\ for the OpenBIOS qt interface
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+hex
+
+tokenizer[ 1002 4336 0300 23 ]tokenizer ( -- vid did classid revision )
+
+pci-revision
+
+pci-header
+
+fcode-version2
+headers
+
+" dev /pci" evaluate
+new-device
+
+ " ATY,QTEMU" device-name
+ " display" device-type
+
+ " iso8859-1" encode-string
+ " character-set" property
+
+ true encode-int
+ " iso6429-1983-colors" property
+
+ : qt-open
+ \ [..]
+ ." opening framebuffer device." cr
+ 10 10 " pci-l@" evaluate
+ /n 8 = if
+ 10 14 " pci-l@" evaluate
+ 20 << or
+ then
+ ." framebuffer pointer is at 0x" dup . cr
+ to frame-buffer-adr
+ default-font set-font
+ d# 640 d# 480 d# 80 d# 30 fb8-install
+ true
+ ;
+
+ : qt-close
+ ." QT Interface closed." cr
+ 0 to frame-buffer-adr
+ ;
+
+ : qt-selftest
+ ." QT Interface selftest" cr
+ 0
+ ;
+
+ ['] qt-open is-install
+ ['] qt-close is-remove
+ ['] qt-selftest is-selftest
+
+ external
+
+\ the following words will be defined by fb8-install
+\
+
+\ : open ( -- true )
+\ ;
+
+\ : write ( addr len -- actual )
+\ ;
+
+\ : draw-logo ( line# addr width height -- )
+\ ;
+
+\ : restore ( -- )
+\ ;
+
+finish-device
+
+fcode-end
+
+pci-end
diff --git a/roms/openbios/arch/unix/tree.fs b/roms/openbios/arch/unix/tree.fs
new file mode 100644
index 00000000..a7529b00
--- /dev/null
+++ b/roms/openbios/arch/unix/tree.fs
@@ -0,0 +1,116 @@
+:noname
+ ." Type 'help' for detailed information" cr
+ ; DIAG-initializer
+
+" /" find-device
+
+new-device
+ " memory" device-name
+ \ 12230 encode-int " reg" property
+ external
+ : open true ;
+ : close ;
+ \ claim ( phys size align -- base )
+ \ release ( phys size -- )
+finish-device
+
+new-device
+ " cpus" device-name
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+ : decode-unit parse-hex ;
+
+finish-device
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+;
+
+:noname
+ set-defaults
+; SYSTEM-initializer
+
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " memory" " /memory" preopen
+ " mmu" " /cpus/@0" preopen
+ " stdout" " /builtin/console" preopen
+ " stdin" " /builtin/console" preopen
+ device-end
+; SYSTEM-initializer
+
+\ use the tty interface if available
+:noname
+ " /builtin/console" find-dev if drop
+ " /builtin/console" " input-device" $setenv
+ " /builtin/console" " output-device" $setenv
+ then
+; SYSTEM-initializer
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+dev /
+
+\ node suitable for non-PCI devices
+new-device
+ " unix" device-name
+ 0 encode-int " #address-cells" property
+ 0 encode-int " #size-cells" property
+
+ external
+ : open true ;
+ : close ;
+
+\ block device node
+new-device
+ " block" device-name
+ " unix-block" device-type
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+ : decode-unit parse-hex ;
+
+\ testnode
+\ new-device
+\ " kappa" device-name
+\
+\ 1 encode-int " reg" property
+\ external
+\ : open true ;
+\ : close ;
+\ finish-device
+
+finish-device
+finish-device
+
+dev /aliases
+" /unix/block/disk" encode-string " hd" property
+
+device-end
diff --git a/roms/openbios/arch/unix/unix.c b/roms/openbios/arch/unix/unix.c
new file mode 100644
index 00000000..1f628eb7
--- /dev/null
+++ b/roms/openbios/arch/unix/unix.c
@@ -0,0 +1,611 @@
+/* tag: hosted forth environment, executable code
+ *
+ * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#define __USE_LARGEFILE64
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+
+#ifdef __GLIBC__
+#define _GNU_SOURCE
+#include <getopt.h>
+#endif
+
+#include "sysinclude.h"
+#include "mconfig.h"
+#include "config.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+#include "kernel/stack.h"
+#include "arch/unix/plugins.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "libopenbios/openbios.h"
+#include "openbios-version.h"
+
+#include "blk.h"
+#include "libopenbios/ofmem.h"
+
+#define MEMORY_SIZE (4*1024*1024) /* 4M ram for hosted system */
+#define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */
+
+#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS==64)
+#define lseek lseek64
+#define __LFS O_LARGEFILE
+#else
+#define __LFS 0
+#endif
+
+/* prototypes */
+static void exit_terminal(void);
+void boot(void);
+
+unsigned long virt_offset = 0;
+
+/* local variables */
+
+static ucell *memory;
+
+static int diskemu;
+
+static int segfault = 0;
+static int verbose = 0;
+
+#if defined(CONFIG_PPC) || defined(CONFIG_SPARC64)
+unsigned long isa_io_base;
+#endif
+
+int errno_int; /* implement for fs drivers, needed to build on Mac OS X */
+
+ucell ofmem_claim(ucell addr, ucell size, ucell align)
+{
+ return 0;
+}
+
+#ifdef CONFIG_PPC
+extern void flush_icache_range(char *start, char *stop);
+
+void flush_icache_range(char *start, char *stop)
+{
+}
+#endif
+
+#ifdef CONFIG_PPC
+/* Expose system level is_machine helpers to make generic code easier */
+
+#include "drivers/drivers.h"
+int is_apple(void)
+{
+ return 0;
+}
+
+int is_oldworld(void)
+{
+ return 0;
+}
+
+int is_newworld(void)
+{
+ return 0;
+}
+#endif
+
+#if 0
+static void write_dictionary(char *filename)
+{
+ FILE *f;
+ xt_t initxt;
+
+ initxt = findword("initialize-of");
+ if (!initxt)
+ printk("warning: dictionary needs word called initialize-of\n");
+
+ f = fopen(filename, "w");
+ if (!f) {
+ printk("panic: can't open dictionary.\n");
+ exit_terminal();
+ exit(1);
+ }
+
+ fwrite(DICTID, 16, 1, f);
+ fwrite(dict, dicthead, 1, f);
+
+ /* Write start address and last to relocate on load */
+ fwrite(&dict, sizeof(ucell), 1, f);
+ fwrite(&last, sizeof(ucell), 1, f);
+
+ fclose(f);
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("wrote dictionary to file %s.\n", filename);
+#endif
+}
+#endif
+
+static ucell read_dictionary(char *fil)
+{
+ int ilen;
+ ucell ret;
+ char *mem;
+ FILE *f;
+ struct stat finfo;
+
+ if (stat(fil, &finfo))
+ return 0;
+
+ ilen = finfo.st_size;
+
+ if ((mem = malloc(ilen)) == NULL) {
+ printk("panic: not enough memory.\n");
+ exit_terminal();
+ exit(1);
+ }
+
+ f = fopen(fil, "r");
+ if (!f) {
+ printk("panic: can't open dictionary.\n");
+ exit_terminal();
+ exit(1);
+ }
+
+ if (fread(mem, ilen, 1, f) != 1) {
+ printk("panic: can't read dictionary.\n");
+ fclose(f);
+ exit_terminal();
+ exit(1);
+ }
+ fclose(f);
+
+ ret = load_dictionary(mem, ilen);
+
+ free(mem);
+ return ret;
+}
+
+
+/*
+ * functions used by primitives
+ */
+
+static int unix_availchar(void)
+{
+ int tmp = getc(stdin);
+ if (tmp != EOF) {
+ ungetc(tmp, stdin);
+ return -1;
+ }
+ return 0;
+}
+
+static int unix_putchar(int c)
+{
+ putc(c, stdout);
+ return c;
+}
+
+static int unix_getchar(void)
+{
+ return getc(stdin);
+}
+
+static struct _console_ops unix_console_ops = {
+ .putchar = unix_putchar,
+ .availchar = unix_availchar,
+ .getchar = unix_getchar
+};
+
+u8 inb(u32 reg)
+{
+#ifdef CONFIG_PLUGINS
+ io_ops_t *ior = find_iorange(reg);
+ if (ior)
+ return ior->inb(reg);
+#endif
+
+ printk("TRAP: io byte read @0x%x", reg);
+ return 0xff;
+}
+
+u16 inw(u32 reg)
+{
+#ifdef CONFIG_PLUGINS
+ io_ops_t *ior = find_iorange(reg);
+ if (ior)
+ return ior->inw(reg);
+#endif
+
+ printk("TRAP: io word read @0x%x", reg);
+ return 0xffff;
+}
+
+u32 inl(u32 reg)
+{
+#ifdef CONFIG_PLUGINS
+ io_ops_t *ior = find_iorange(reg);
+ if (ior)
+ return ior->inl(reg);
+#endif
+
+ printk("TRAP: io long read @0x%x", reg);
+ return 0xffffffff;
+}
+
+void outb(u32 reg, u8 val)
+{
+#ifdef CONFIG_PLUGINS
+ io_ops_t *ior = find_iorange(reg);
+ if (ior) {
+ ior->outb(reg, val);
+ return;
+ }
+#endif
+
+ printk("TRAP: io byte write 0x%x -> 0x%x", val, reg);
+}
+
+void outw(u32 reg, u16 val)
+{
+#ifdef CONFIG_PLUGINS
+ io_ops_t *ior = find_iorange(reg);
+ if (ior) {
+ ior->outw(reg, val);
+ return;
+ }
+#endif
+ printk("TRAP: io word write 0x%x -> 0x%x", val, reg);
+}
+
+void outl(u32 reg, u32 val)
+{
+#ifdef CONFIG_PLUGINS
+ io_ops_t *ior = find_iorange(reg);
+ if (ior) {
+ ior->outl(reg, val);
+ return;
+ }
+#endif
+ printk("TRAP: io long write 0x%x -> 0x%x", val, reg);
+}
+
+/*
+ * terminal initialization and cleanup.
+ */
+
+static struct termios saved_termios;
+
+static void init_terminal(void)
+{
+ struct termios termios;
+
+ tcgetattr(0, &saved_termios);
+ tcgetattr(0, &termios);
+ termios.c_lflag &= ~(ICANON | ECHO);
+ termios.c_cc[VMIN] = 1;
+ termios.c_cc[VTIME] = 3; // 300 ms
+ tcsetattr(0, 0, &termios);
+}
+
+static void exit_terminal(void)
+{
+ tcsetattr(0, 0, &saved_termios);
+}
+
+/*
+ * segmentation fault handler. linux specific?
+ */
+
+static void
+segv_handler(int signo __attribute__ ((unused)),
+ siginfo_t * si, void *context __attribute__ ((unused)))
+{
+ static int count = 0;
+ ucell addr = 0xdeadbeef;
+
+ if (count) {
+ printk("Died while dumping forth dictionary core.\n");
+ goto out;
+ }
+
+ count++;
+
+ if (PC >= (ucell) dict && PC <= (ucell) dict + dicthead)
+ addr = *(ucell *) PC;
+
+ printk("panic: segmentation violation at %x\n", (ucell)si->si_addr);
+ printk("dict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n",
+ (ucell)dict, (ucell)dict + dicthead, dicthead, PC, PC - (ucell) dict);
+ printk("dstackcnt=%d rstackcnt=%d instruction=%x\n",
+ dstackcnt, rstackcnt, addr);
+
+#ifdef CONFIG_DEBUG_DSTACK
+ printdstack();
+#endif
+#ifdef CONFIG_DEBUG_RSTACK
+ printrstack();
+#endif
+#if 0
+ printk("Writing dictionary core file\n");
+ write_dictionary("forth.dict.core");
+#endif
+
+ out:
+ exit_terminal();
+ exit(1);
+}
+
+/*
+ * Interrupt handler. linux specific?
+ * Restore terminal state on ctrl-C.
+ */
+
+static void
+int_handler(int signo __attribute__ ((unused)),
+ siginfo_t * si __attribute__ ((unused)),
+ void *context __attribute__ ((unused)))
+{
+ printk("\n");
+ exit_terminal();
+ exit(1);
+}
+
+/*
+ * allocate memory and prepare engine for memory management.
+ */
+
+static void init_memory(void)
+{
+ memory = malloc(MEMORY_SIZE);
+ if (!memory) {
+ printk("panic: not enough memory on host system.\n");
+ exit_terminal();
+ exit(1);
+ }
+
+ memset (memory, 0, MEMORY_SIZE);
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator
+ */
+
+ PUSH((ucell) memory);
+ PUSH((ucell) memory + MEMORY_SIZE);
+}
+
+void exception(__attribute__((unused)) cell no)
+{
+ /*
+ * this is a noop since the dictionary has to take care
+ * itself of errors it generates outside of the bootstrap
+ */
+}
+
+static void
+arch_init( void )
+{
+ openbios_init();
+ modules_init();
+ if(diskemu!=-1)
+ blk_init();
+
+ device_end();
+ bind_func("platform-boot", boot);
+}
+
+int
+read_from_disk( int channel, int unit, int blk, unsigned long mphys, int size )
+{
+ // channels and units not supported yet.
+ unsigned char *buf=(unsigned char *)mphys;
+
+ if(diskemu==-1)
+ return -1;
+
+ //printk("read: ch=%d, unit=%d, blk=%ld, phys=%lx, size=%d\n",
+ // channel, unit, blk, mphys, size);
+
+ lseek(diskemu, (ducell)blk*512, SEEK_SET);
+ read(diskemu, buf, size);
+
+ return 0;
+}
+
+/*
+ * main loop
+ */
+
+#define BANNER "OpenBIOS core. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\
+ "This software comes with absolutely no warranty. "\
+ "All rights reserved.\n\n"
+
+
+#define USAGE "usage: %s [options] [dictionary file|source file]\n\n"
+
+int main(int argc, char *argv[])
+{
+ struct sigaction sa;
+#if 0
+ unsigned char *dictname = NULL;
+#endif
+ int c;
+
+ const char *optstring = "VvhsD:P:p:f:?";
+
+ while (1) {
+#ifdef __GLIBC__
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"version", 0, NULL, 'V'},
+ {"verbose", 0, NULL, 'v'},
+ {"help", 0, NULL, 'h'},
+// {"dictionary", 1, NULL, 'D'},
+ {"segfault", 0, NULL, 's'},
+#ifdef CONFIG_PLUGINS
+ {"plugin-path", 1, NULL, 'P'},
+ {"plugin", 1, NULL, 'p'},
+#endif
+ {"file", 1, NULL, 'f'}
+ };
+
+ c = getopt_long(argc, argv, optstring, long_options,
+ &option_index);
+#else
+ c = getopt(argc, argv, optstring);
+#endif
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'V':
+ printk(BANNER "Version " OPENBIOS_VERSION_STR "\n");
+ return 0;
+ case 'h':
+ case '?':
+ printk(BANNER "Version " OPENBIOS_VERSION_STR "\n"
+ USAGE, argv[0]);
+ return 0;
+ case 'v':
+ verbose = 1;
+ break;
+ case 's':
+ segfault = 1;
+ break;
+#if 0
+ case 'D':
+ printk("Dumping final dictionary to '%s'\n", optarg);
+ dictname = optarg;
+ break;
+#endif
+#ifdef CONFIG_PLUGINS
+ case 'P':
+ printk("Plugin search path is now '%s'\n", optarg);
+ plugindir = optarg;
+ break;
+ case 'p':
+ printk("Loading plugin %s\n", optarg);
+ load_plugin(optarg);
+ break;
+#endif
+ case 'f':
+ diskemu=open(optarg, O_RDONLY|__LFS);
+ if(diskemu!=-1)
+ printk("Using %s as harddisk.\n", optarg);
+ else
+ printk("%s not found. no harddisk node.\n",
+ optarg);
+ break;
+ default:
+ return 1;
+ }
+ }
+
+ if (argc < optind + 1) {
+ printk(USAGE, argv[0]);
+ return 1;
+ }
+
+ /* Initialise console */
+ init_console(unix_console_ops);
+
+ if ((dict = (unsigned char *) malloc(DICTIONARY_SIZE)) == NULL) {
+ printk("panic: not enough memory.\n");
+ return 1;
+ }
+
+ dictlimit = DICTIONARY_SIZE;
+ memset(dict, 0, DICTIONARY_SIZE);
+
+ if (!segfault) {
+ if (verbose)
+ printk("Installing SIGSEGV handler...");
+
+ sa.sa_sigaction = segv_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sigaction(SIGSEGV, &sa, NULL);
+
+ if (verbose)
+ printk("done.\n");
+ }
+
+ /* set terminal to do non blocking reads */
+ init_terminal();
+
+ if (verbose)
+ printk("Installing SIGINT handler...");
+
+ sa.sa_sigaction = int_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sigaction(SIGINT, &sa, NULL);
+
+ if (verbose)
+ printk("done.\n");
+
+ read_dictionary(argv[optind]);
+ forth_init();
+
+ PUSH_xt( bind_noname_func(arch_init) );
+ fword("PREPOST-initializer");
+
+ PC = (cell)findword("initialize-of");
+ if (PC) {
+ if (verbose) {
+ if (optind + 1 != argc)
+ printk("Warning: only first dictionary used.\n");
+
+ printk("dictionary loaded (%d bytes).\n", dicthead);
+ printk("Initializing memory...");
+ }
+ init_memory();
+
+ if (verbose) {
+ printk("done\n");
+
+ printk("Jumping to dictionary...");
+ }
+
+ enterforth((xt_t)PC);
+#if 0
+ if (dictname != NULL)
+ write_dictionary(dictname);
+#endif
+
+ free(memory);
+
+ } else { /* input file is not a dictionary */
+ printk("not supported.\n");
+ }
+
+ exit_terminal();
+ if (diskemu!=-1)
+ close(diskemu);
+
+ free(dict);
+ return 0;
+}
+
+#undef printk
+int
+printk( const char *fmt, ... )
+{
+ int i;
+
+ va_list args;
+ va_start( args, fmt );
+ i = vprintf(fmt, args );
+ va_end( args );
+ return i;
+}
diff --git a/roms/openbios/arch/x86/Kconfig b/roms/openbios/arch/x86/Kconfig
new file mode 100644
index 00000000..eac95828
--- /dev/null
+++ b/roms/openbios/arch/x86/Kconfig
@@ -0,0 +1,47 @@
+mainmenu "OpenBIOS Configuration"
+
+config X86
+ bool
+ default y
+ help
+ Building for X86 hardware.
+
+config LITTLE_ENDIAN
+ bool
+ default y
+ help
+ X86 is little endian
+
+menu "Kernel binaries (x86)"
+
+config IMAGE_ELF
+ bool "ELF image (for LinuxBIOS)"
+ default y
+ help
+ Build a simple elf image that can be used with LinuxBIOS
+ This image will be called openbios.elf
+
+config IMAGE_ELF_EMBEDDED
+ bool "ELF image with embedded dictionary"
+ default y
+ help
+ Build an elf image with embedded dictionary. This image
+ can easily be used with etherboot.
+ The image filename is openbios.full
+
+config IMAGE_ELF_MULTIBOOT
+ bool "Multiboot image"
+ default y
+ help
+ Build a multiboot image for booting with grub
+
+endmenu
+
+menu "Build hosted UNIX Binary"
+source "arch/unix/Kconfig"
+endmenu
+
+source "kernel/Kconfig"
+source "forth/Kconfig"
+source "libopenbios/Kconfig"
+source "drivers/Kconfig"
diff --git a/roms/openbios/arch/x86/boot.c b/roms/openbios/arch/x86/boot.c
new file mode 100644
index 00000000..d40ab8c5
--- /dev/null
+++ b/roms/openbios/arch/x86/boot.c
@@ -0,0 +1,74 @@
+/* tag: openbios boot command for x86
+ *
+ * Copyright (C) 2003-2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#undef BOOTSTRAP
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "libc/diskio.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+
+void go(void)
+{
+ ucell address, type, size;
+ int image_retval = 0;
+
+ /* Get the entry point and the type (see forth/debugging/client.fs) */
+ feval("saved-program-state >sps.entry @");
+ address = POP();
+ feval("saved-program-state >sps.file-type @");
+ type = POP();
+ feval("saved-program-state >sps.file-size @");
+ size = POP();
+
+ printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type);
+
+ switch (type) {
+ case 0x0:
+ /* Start ELF boot image */
+ image_retval = start_elf(address, (uint32_t)&elf_boot_notes);
+ break;
+
+ case 0x1:
+ /* Start ELF image */
+ image_retval = start_elf(address, (uint32_t)NULL);
+ break;
+
+ case 0x5:
+ /* Start a.out image */
+ image_retval = start_elf(address, (uint32_t)NULL);
+ break;
+
+ case 0x10:
+ /* Start Fcode image */
+ printk("Evaluating FCode...\n");
+ PUSH(address);
+ PUSH(1);
+ fword("byte-load");
+ image_retval = 0;
+ break;
+
+ case 0x11:
+ /* Start Forth image */
+ PUSH(address);
+ PUSH(size);
+ fword("eval2");
+ image_retval = 0;
+ break;
+ }
+
+ printk("Image returned with return value %#x\n", image_retval);
+}
+
+
+void boot(void)
+{
+ /* No platform-specific boot code */
+ return;
+}
diff --git a/roms/openbios/arch/x86/boot.h b/roms/openbios/arch/x86/boot.h
new file mode 100644
index 00000000..749c608b
--- /dev/null
+++ b/roms/openbios/arch/x86/boot.h
@@ -0,0 +1,18 @@
+/* tag: openbios loader prototypes for x86
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+/* linux_load.c */
+int linux_load(struct sys_info *info, const char *file, const char *cmdline);
+
+/* context.c */
+extern struct context *__context;
+unsigned int start_elf(unsigned long entry_point, unsigned long param);
+
+/* boot.c */
+extern void boot(void);
+extern void go(void);
diff --git a/roms/openbios/arch/x86/build.xml b/roms/openbios/arch/x86/build.xml
new file mode 100644
index 00000000..260a3325
--- /dev/null
+++ b/roms/openbios/arch/x86/build.xml
@@ -0,0 +1,86 @@
+<build condition="X86">
+
+ <dictionary name="openbios-x86" init="openbios">
+ <object source="init.fs" target="forth"/>
+ <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/>
+ </dictionary>
+
+ <library name="x86" type="static" target="target">
+ <object source="openbios.c"/>
+ <object source="exception.c"/>
+ <object source="console.c"/>
+ <object source="lib.c"/>
+ <object source="boot.c"/>
+ <object source="context.c"/>
+ <object source="linux_load.c"/>
+ <object source="segment.c"/>
+ <object source="sys_info.c"/>
+ <object source="entry.S"/>
+ <object source="xbox/console.c" condition="XBOX"/>
+ <object source="xbox/methods.c" condition="XBOX"/>
+ </library>
+
+ <executable name="openbios.multiboot" target="target" condition="IMAGE_ELF_MULTIBOOT">
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/x86/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-multiboot.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="multiboot.c"/>
+ <external-object source="libx86.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+ <executable name="openbios-plain.elf" target="target" condition="IMAGE_ELF">
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/x86/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-plain.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <object source="plainboot.c"/>
+ <external-object source="libx86.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+ <!-- HACK ALERT -->
+
+ <executable name="target/include/static-dict.h" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <rule><![CDATA[
+ $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule>
+ <external-object source="openbios-x86.dict"/>
+ </executable>
+
+ <executable name="target/arch/x86/builtin.o" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <rule><![CDATA[ $(SRCDIR)/arch/x86/builtin.c $(ODIR)/target/include/static-dict.h
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/x86/builtin.c, " CC $(TARGET_DIR)$@")]]></rule>
+ </executable>
+
+ <!-- END OF HACK ALERT -->
+
+ <executable name="openbios-builtin.elf" target="target" condition="IMAGE_ELF_EMBEDDED">
+ <rule>
+ $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/x86/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@")
+ $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-builtin.syms," GEN $(TARGET_DIR)$@.syms")
+ $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule>
+ <external-object source="target/arch/x86/builtin.o"/>
+ <external-object source="libx86.a"/>
+ <external-object source="libbootstrap.a"/>
+ <external-object source="libopenbios.a"/>
+ <external-object source="libpackages.a"/>
+ <external-object source="libdrivers.a"/>
+ <external-object source="liblibc.a"/>
+ <external-object source="libfs.a"/>
+ <external-object source="libgcc.a"/>
+ </executable>
+
+</build>
diff --git a/roms/openbios/arch/x86/builtin.c b/roms/openbios/arch/x86/builtin.c
new file mode 100644
index 00000000..f7d8aba6
--- /dev/null
+++ b/roms/openbios/arch/x86/builtin.c
@@ -0,0 +1,32 @@
+/* tag: openbios forth starter for builtin dictionary
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/sys_info.h"
+
+/*
+ * wrap an array around the hex'ed dictionary file
+ */
+
+/* 256K for the dictionary */
+#define DICTIONARY_SIZE (256 * 1024 / sizeof(ucell))
+#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary))
+
+static ucell forth_dictionary[DICTIONARY_SIZE] = {
+#include "static-dict.h"
+};
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ info->dict_start=(unsigned long *)forth_dictionary;
+ info->dict_end = (unsigned long *)FORTH_DICTIONARY_END;
+ info->dict_last = (ucell *)((unsigned char *)forth_dictionary +
+ FORTH_DICTIONARY_LAST);
+ info->dict_limit = sizeof(forth_dictionary);
+}
diff --git a/roms/openbios/arch/x86/console.c b/roms/openbios/arch/x86/console.c
new file mode 100644
index 00000000..906e69c2
--- /dev/null
+++ b/roms/openbios/arch/x86/console.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "openbios.h"
+#include "libopenbios/console.h"
+
+#ifdef CONFIG_DEBUG_CONSOLE
+
+/* ******************************************************************
+ * serial console functions
+ * ****************************************************************** */
+
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+
+#define RBR(x) x==2?0x2f8:0x3f8
+#define THR(x) x==2?0x2f8:0x3f8
+#define IER(x) x==2?0x2f9:0x3f9
+#define IIR(x) x==2?0x2fa:0x3fa
+#define LCR(x) x==2?0x2fb:0x3fb
+#define MCR(x) x==2?0x2fc:0x3fc
+#define LSR(x) x==2?0x2fd:0x3fd
+#define MSR(x) x==2?0x2fe:0x3fe
+#define SCR(x) x==2?0x2ff:0x3ff
+#define DLL(x) x==2?0x2f8:0x3f8
+#define DLM(x) x==2?0x2f9:0x3f9
+
+static int uart_charav(int port)
+{
+ if (!port)
+ return -1;
+ return ((inb(LSR(port)) & 1) != 0);
+}
+
+static char uart_getchar(int port)
+{
+ if (!port)
+ return -1;
+ while (!uart_charav(port));
+ return ((char) inb(RBR(port)) & 0177);
+}
+
+static void uart_putchar(int port, unsigned char c)
+{
+ if (!port)
+ return;
+ if (c == '\n')
+ uart_putchar(port, '\r');
+ while (!(inb(LSR(port)) & 0x20));
+ outb(c, THR(port));
+}
+
+static void uart_init_line(int port, unsigned long baud)
+{
+ int i, baudconst;
+
+ if (!port)
+ return;
+
+ switch (baud) {
+ case 115200:
+ baudconst = 1;
+ break;
+ case 57600:
+ baudconst = 2;
+ break;
+ case 38400:
+ baudconst = 3;
+ break;
+ case 19200:
+ baudconst = 6;
+ break;
+ case 9600:
+ default:
+ baudconst = 12;
+ break;
+ }
+
+ outb(0x87, LCR(port));
+ outb(0x00, DLM(port));
+ outb(baudconst, DLL(port));
+ outb(0x07, LCR(port));
+ outb(0x0f, MCR(port));
+
+ for (i = 10; i > 0; i--) {
+ if (inb(LSR(port)) == (unsigned int) 0)
+ break;
+ inb(RBR(port));
+ }
+}
+
+int uart_init(int port, unsigned long speed)
+{
+ if (port)
+ uart_init_line(port, speed);
+ return -1;
+}
+
+static void serial_putchar(int c)
+{
+ uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff));
+}
+
+static void serial_cls(void)
+{
+ serial_putchar(27);
+ serial_putchar('[');
+ serial_putchar('H');
+ serial_putchar(27);
+ serial_putchar('[');
+ serial_putchar('J');
+}
+
+#endif
+
+/* ******************************************************************
+ * simple polling video/keyboard console functions
+ * ****************************************************************** */
+
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+
+/* raw vga text mode */
+#define COLUMNS 80 /* The number of columns. */
+#define LINES 25 /* The number of lines. */
+#define ATTRIBUTE 7 /* The attribute of an character. */
+
+#define VGA_BASE 0xB8000 /* The video memory address. */
+
+/* VGA Index and Data Registers */
+#define VGA_REG_INDEX 0x03D4 /* VGA index register */
+#define VGA_REG_DATA 0x03D5 /* VGA data register */
+
+#define VGA_IDX_CURMSL 0x09 /* cursor maximum scan line */
+#define VGA_IDX_CURSTART 0x0A /* cursor start */
+#define VGA_IDX_CUREND 0x0B /* cursor end */
+#define VGA_IDX_CURLO 0x0F /* cursor position (low 8 bits) */
+#define VGA_IDX_CURHI 0x0E /* cursor position (high 8 bits) */
+
+/* Save the X and Y position. */
+static int xpos, ypos;
+/* Point to the video memory. */
+static volatile unsigned char *video = (unsigned char *) VGA_BASE;
+
+static void video_initcursor(void)
+{
+ u8 val;
+ outb(VGA_IDX_CURMSL, VGA_REG_INDEX);
+ val = inb(VGA_REG_DATA) & 0x1f; /* maximum scan line -1 */
+
+ outb(VGA_IDX_CURSTART, VGA_REG_INDEX);
+ outb(0, VGA_REG_DATA);
+
+ outb(VGA_IDX_CUREND, VGA_REG_INDEX);
+ outb(val, VGA_REG_DATA);
+}
+
+
+
+static void video_poscursor(unsigned int x, unsigned int y)
+{
+ unsigned short pos;
+
+ /* Calculate new cursor position as a function of x and y */
+ pos = (y * COLUMNS) + x;
+
+ /* Output the new position to VGA card */
+ outb(VGA_IDX_CURLO, VGA_REG_INDEX); /* output low 8 bits */
+ outb((u8) (pos), VGA_REG_DATA);
+ outb(VGA_IDX_CURHI, VGA_REG_INDEX); /* output high 8 bits */
+ outb((u8) (pos >> 8), VGA_REG_DATA);
+
+};
+
+
+static void video_newline(void)
+{
+ xpos = 0;
+
+ if (ypos < LINES - 1) {
+ ypos++;
+ } else {
+ int i;
+ memmove((void *) video, (void *) (video + 2 * COLUMNS),
+ (LINES - 1) * COLUMNS * 2);
+
+ for (i = ((LINES - 1) * 2 * COLUMNS);
+ i < 2 * COLUMNS * LINES;) {
+ video[i++] = 0;
+ video[i++] = ATTRIBUTE;
+ }
+ }
+
+}
+
+/* Put the character C on the screen. */
+static void video_putchar(int c)
+{
+ int p=1;
+
+ if (c == '\n' || c == '\r') {
+ video_newline();
+ return;
+ }
+
+ if (c == '\b') {
+ if (xpos) xpos--;
+ c=' ';
+ p=0;
+ }
+
+
+ if (xpos >= COLUMNS)
+ video_newline();
+
+ *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
+ *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
+
+ if (p)
+ xpos++;
+
+ video_poscursor(xpos, ypos);
+}
+
+static void video_cls(void)
+{
+ int i;
+
+ for (i = 0; i < 2 * COLUMNS * LINES;) {
+ video[i++] = 0;
+ video[i++] = ATTRIBUTE;
+ }
+
+
+ xpos = 0;
+ ypos = 0;
+
+ video_initcursor();
+ video_poscursor(xpos, ypos);
+}
+
+void video_init(void)
+{
+ video=phys_to_virt((unsigned char*)VGA_BASE);
+}
+
+/*
+ * keyboard driver
+ */
+
+static const char normal[] = {
+ 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
+ '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
+ 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j',
+ 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b',
+ 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f
+};
+
+static const char shifted[] = {
+ 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
+ '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
+ 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J',
+ 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B',
+ 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8',
+ '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f
+};
+
+static int key_ext;
+static int key_lshift = 0, key_rshift = 0, key_caps = 0;
+
+static char last_key;
+
+static void keyboard_cmd(unsigned char cmd, unsigned char val)
+{
+ outb(cmd, 0x60);
+ /* wait until keyboard controller accepts cmds: */
+ while (inb(0x64) & 2);
+ outb(val, 0x60);
+ while (inb(0x64) & 2);
+}
+
+static char keyboard_poll(void)
+{
+ unsigned int c;
+ if (inb(0x64) & 1) {
+ c = inb(0x60);
+ switch (c) {
+ case 0xe0:
+ key_ext = 1;
+ return 0;
+ case 0x2a:
+ key_lshift = 1;
+ return 0;
+ case 0x36:
+ key_rshift = 1;
+ return 0;
+ case 0xaa:
+ key_lshift = 0;
+ return 0;
+ case 0xb6:
+ key_rshift = 0;
+ return 0;
+ case 0x3a:
+ if (key_caps) {
+ key_caps = 0;
+ keyboard_cmd(0xed, 0);
+ } else {
+ key_caps = 1;
+ keyboard_cmd(0xed, 4); /* set caps led */
+ }
+ return 0;
+ }
+
+ if (key_ext) {
+ // void printk(const char *format, ...);
+ printk("extended keycode: %x\n", c);
+
+ key_ext = 0;
+ return 0;
+ }
+
+ if (c & 0x80) /* unhandled key release */
+ return 0;
+
+ if (key_lshift || key_rshift)
+ return key_caps ? normal[c] : shifted[c];
+ else
+ return key_caps ? shifted[c] : normal[c];
+ }
+ return 0;
+}
+
+static int keyboard_dataready(void)
+{
+ if (last_key)
+ return 1;
+
+ last_key = keyboard_poll();
+
+ return (last_key != 0);
+}
+
+static unsigned char keyboard_readdata(void)
+{
+ char tmp;
+ while (!keyboard_dataready());
+ tmp = last_key;
+ last_key = 0;
+ return tmp;
+}
+#endif
+
+
+/* ******************************************************************
+ * common functions, implementing simple concurrent console
+ * ****************************************************************** */
+
+static int arch_putchar(int c)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ serial_putchar(c);
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ video_putchar(c);
+#endif
+ return c;
+}
+
+static int arch_availchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return 1;
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ if (keyboard_dataready())
+ return 1;
+#endif
+ return 0;
+}
+
+static int arch_getchar(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ if (uart_charav(CONFIG_SERIAL_PORT))
+ return (uart_getchar(CONFIG_SERIAL_PORT));
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ if (keyboard_dataready())
+ return (keyboard_readdata());
+#endif
+ return 0;
+}
+
+void cls(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ serial_cls();
+#endif
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ video_cls();
+#endif
+}
+
+struct _console_ops arch_console_ops = {
+ .putchar = arch_putchar,
+ .availchar = arch_availchar,
+ .getchar = arch_getchar
+};
+
+#endif // CONFIG_DEBUG_CONSOLE
diff --git a/roms/openbios/arch/x86/context.c b/roms/openbios/arch/x86/context.c
new file mode 100644
index 00000000..d543f748
--- /dev/null
+++ b/roms/openbios/arch/x86/context.c
@@ -0,0 +1,130 @@
+/* tag: x86 context switching
+ *
+ * 2003-10 by SONE Takeshi
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "segment.h"
+#include "context.h"
+#include "libopenbios/sys_info.h"
+#include "boot.h"
+#include "openbios.h"
+
+#define MAIN_STACK_SIZE 16384
+#define IMAGE_STACK_SIZE 4096
+
+#define debug printk
+
+static void start_main(void); /* forward decl. */
+void __exit_context(void); /* assembly routine */
+
+/*
+ * Main context structure
+ * It is placed at the bottom of our stack, and loaded by assembly routine
+ * to start us up.
+ */
+static struct context main_ctx __attribute__((section (".initctx"))) = {
+ .gdt_base = (uint32_t) gdt,
+ .gdt_limit = GDT_LIMIT,
+ .cs = FLAT_CS,
+ .ds = FLAT_DS,
+ .es = FLAT_DS,
+ .fs = FLAT_DS,
+ .gs = FLAT_DS,
+ .ss = FLAT_DS,
+ .esp = (uint32_t) ESP_LOC(&main_ctx),
+ .eip = (uint32_t) start_main,
+ .return_addr = (uint32_t) __exit_context,
+};
+
+/* This is used by assembly routine to load/store the context which
+ * it is to switch/switched. */
+struct context *__context = &main_ctx;
+
+/* Stack for loaded ELF image */
+static uint8_t image_stack[IMAGE_STACK_SIZE];
+
+/* Pointer to startup context (physical address) */
+unsigned long __boot_ctx;
+
+/*
+ * Main starter
+ * This is the C function that runs first.
+ */
+static void start_main(void)
+{
+ int retval;
+
+ /* Save startup context, so we can refer to it later.
+ * We have to keep it in physical address since we will relocate. */
+ __boot_ctx = virt_to_phys(__context);
+
+ init_exceptions();
+ /* Start the real fun */
+ retval = openbios();
+
+ /* Pass return value to startup context. Bootloader may see it. */
+ boot_ctx->eax = retval;
+
+ /* Returning from here should jump to __exit_context */
+ __context = boot_ctx;
+}
+
+/* Setup a new context using the given stack.
+ */
+struct context *
+init_context(uint8_t *stack, uint32_t stack_size, int num_params)
+{
+ struct context *ctx;
+
+ ctx = (struct context *)
+ (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t)));
+ memset(ctx, 0, sizeof(*ctx));
+
+ /* Fill in reasonable default for flat memory model */
+ ctx->gdt_base = virt_to_phys(gdt);
+ ctx->gdt_limit = GDT_LIMIT;
+ ctx->cs = FLAT_CS;
+ ctx->ds = FLAT_DS;
+ ctx->es = FLAT_DS;
+ ctx->fs = FLAT_DS;
+ ctx->gs = FLAT_DS;
+ ctx->ss = FLAT_DS;
+ ctx->esp = virt_to_phys(ESP_LOC(ctx));
+ ctx->return_addr = virt_to_phys(__exit_context);
+
+ return ctx;
+}
+
+/* Switch to another context. */
+struct context *switch_to(struct context *ctx)
+{
+ struct context *save, *ret;
+
+ debug("switching to new context:\n");
+ save = __context;
+ __context = ctx;
+ asm ("pushl %cs; call __switch_context");
+ ret = __context;
+ __context = save;
+ return ret;
+}
+
+/* Start ELF Boot image */
+unsigned int start_elf(unsigned long entry_point, unsigned long param)
+{
+ struct context *ctx;
+
+ ctx = init_context(image_stack, sizeof image_stack, 1);
+ ctx->eip = entry_point;
+ ctx->param[0] = param;
+ ctx->eax = 0xe1fb007;
+ ctx->ebx = param;
+
+ ctx = switch_to(ctx);
+ return ctx->eax;
+}
diff --git a/roms/openbios/arch/x86/context.h b/roms/openbios/arch/x86/context.h
new file mode 100644
index 00000000..6a1c5adb
--- /dev/null
+++ b/roms/openbios/arch/x86/context.h
@@ -0,0 +1,48 @@
+#ifndef i386_CONTEXT_H
+#define i386_CONTEXT_H
+
+struct context {
+ /* Stack Segment, placed here because of the alignment issue... */
+ uint16_t ss;
+ /* Used with sgdt/lgdt */
+ uint16_t gdt_limit;
+ uint32_t gdt_base;
+ /* General registers, accessed with pushal/popal */
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t esp; /* points just below eax */
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+#define ESP_LOC(ctx) (&(ctx)->gs)
+ /* Segment registers */
+ uint32_t gs;
+ uint32_t fs;
+ uint32_t es;
+ uint32_t ds;
+ /* Flags */
+ uint32_t eflags;
+ /* Code segment:offset */
+ uint32_t eip;
+ uint32_t cs;
+ /* Optional stack contents */
+ uint32_t return_addr;
+ uint32_t param[0];
+};
+
+/* Create a new context in the given stack */
+struct context *
+init_context(uint8_t *stack, uint32_t stack_size, int num_param);
+
+/* Switch context */
+struct context *switch_to(struct context *);
+
+/* Holds physical address of boot context */
+extern unsigned long __boot_ctx;
+
+/* This can always be safely used to refer to the boot context */
+#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx))
+
+#endif /* i386_CONTEXT_H */
diff --git a/roms/openbios/arch/x86/defconfig b/roms/openbios/arch/x86/defconfig
new file mode 100644
index 00000000..b0a02ab3
--- /dev/null
+++ b/roms/openbios/arch/x86/defconfig
@@ -0,0 +1,65 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_X86=y
+CONFIG_LITTLE_ENDIAN=y
+
+#
+# Kernel binaries (x86)
+#
+CONFIG_IMAGE_ELF=y
+CONFIG_IMAGE_ELF_EMBEDDED=y
+CONFIG_IMAGE_ELF_MULTIBOOT=y
+
+#
+# Build hosted UNIX Binary
+#
+CONFIG_HOST_UNIX=y
+# CONFIG_PLUGIN_PCI is not set
+
+#
+# Kernel Debugging
+#
+# CONFIG_DEBUG is not set
+CONFIG_DEBUG_CONSOLE=y
+CONFIG_DEBUG_CONSOLE_SERIAL=y
+CONFIG_SERIAL_PORT=1
+CONFIG_SERIAL_SPEED=115200
+CONFIG_DEBUG_CONSOLE_VGA=y
+
+#
+# Module Configuration
+#
+CONFIG_CMDLINE=y
+CONFIG_DEBLOCKER=y
+
+#
+# Filesystem Configuration
+#
+CONFIG_DISK_LABEL=y
+CONFIG_PART_SUPPORT=y
+CONFIG_PC_PARTS=y
+CONFIG_FS=y
+CONFIG_GRUBFS=y
+CONFIG_FSYS_EXT2FS=y
+CONFIG_FSYS_FAT=y
+CONFIG_FSYS_JFS=y
+# CONFIG_FSYS_MINIX is not set
+CONFIG_FSYS_REISERFS=y
+CONFIG_FSYS_XFS=y
+CONFIG_FSYS_ISO9660=y
+# CONFIG_FSYS_FFS is not set
+# CONFIG_FSYS_VSTAFS is not set
+# CONFIG_DEBUG_FS is not set
+
+#
+# Miscellaneous
+#
+CONFIG_LINUXBIOS=y
+
+#
+# Drivers
+#
+CONFIG_DRIVER_PCI=y
+CONFIG_DRIVER_IDE=y
+# CONFIG_DEBUG_IDE is not set
diff --git a/roms/openbios/arch/x86/entry.S b/roms/openbios/arch/x86/entry.S
new file mode 100644
index 00000000..8f1e42ee
--- /dev/null
+++ b/roms/openbios/arch/x86/entry.S
@@ -0,0 +1,315 @@
+ .globl entry, __switch_context, __exit_context, halt, init_exceptions
+
+ .text
+ .align 4
+
+/*
+ * Entry point
+ * We start execution from here.
+ * It is assumed that CPU is in 32-bit protected mode and
+ * all segments are 4GB and base zero (flat model).
+ */
+entry:
+ /* Save boot context and switch to our main context.
+ * Main context is statically defined in C.
+ */
+ pushl %cs
+ call __switch_context
+
+ /* We get here when the main context switches back to
+ * the boot context.
+ * Return to previous bootloader.
+ */
+ ret
+
+/*
+ * Switch execution context
+ * This saves registers, segments, and GDT in the stack, then
+ * switches the stack, and restores everything from the new stack.
+ * This function takes no argument. New stack pointer is
+ * taken from global variable __context, and old stack pointer
+ * is also saved to __context. This way we can just jump to
+ * this routine to get back to the original context.
+ *
+ * Call this routine with lcall or pushl %cs; call.
+ */
+__switch_context:
+ /* Save everything in current stack */
+ pushfl /* 56 */
+ pushl %ds /* 52 */
+ pushl %es /* 48 */
+ pushl %fs /* 44 */
+ pushl %gs /* 40 */
+ pushal /* 8 */
+ subl $8, %esp
+ movw %ss, (%esp) /* 0 */
+ sgdt 2(%esp) /* 2 */
+
+#if 0
+ /* Swap %cs and %eip on the stack, so lret will work */
+ movl 60(%esp), %eax
+ xchgl %eax, 64(%esp)
+ movl %eax, 60(%esp)
+#endif
+
+ /* At this point we don't know if we are on flat segment
+ * or relocated. So compute the address offset from %eip.
+ * Assuming CS.base==DS.base==SS.base.
+ */
+ call 1f
+1: popl %ebx
+ subl $1b, %ebx
+
+ /* Interrupts are not allowed... */
+ cli
+
+ /* Current context pointer is our stack pointer */
+ movl %esp, %esi
+
+ /* Normalize the ctx pointer */
+ subl %ebx, %esi
+
+ /* Swap it with new value */
+ xchgl %esi, __context(%ebx)
+
+ /* Adjust new ctx pointer for current address offset */
+ addl %ebx, %esi
+
+ /* Load new %ss and %esp to temporary */
+ movzwl (%esi), %edx
+ movl 20(%esi), %eax
+
+ /* Load new GDT */
+ lgdt 2(%esi)
+
+ /* Load new stack segment with new GDT */
+ movl %edx, %ss
+
+ /* Set new stack pointer, but we have to adjust it because
+ * pushal saves %esp value before pushal, and we want the value
+ * after pushal.
+ */
+ leal -32(%eax), %esp
+
+ /* Load the rest from new stack */
+ popal
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popfl
+
+ /* Finally, load new %cs and %eip */
+ lret
+
+__exit_context:
+ /* Get back to the original context */
+ pushl %cs
+ call __switch_context
+
+ /* We get here if the other context attempt to switch to this
+ * dead context. This should not happen. */
+
+halt:
+ cli
+ hlt
+ jmp halt
+
+/*
+ * initialize exception handler. All exceptions end up in the same
+ * C function.
+ */
+
+init_exceptions:
+ pushl %ebx
+ pushl %edi
+
+ /* Initialize the Interrupt Descriptor table */
+ leal _idt, %edi
+ leal vec0, %ebx
+ movl $(0x08 << 16), %eax /* cs selector */
+
+1: movw %bx, %ax
+ movl %ebx, %edx
+ movw $0x8E00, %dx /* Interrupt gate - dpl=0, present */
+ movl %eax, 0(%edi)
+ movl %edx, 4(%edi)
+ addl $6, %ebx
+ addl $8, %edi
+ cmpl $_idt_end, %edi
+ jne 1b
+
+ /* Load the Interrupt descriptor table */
+ lidt idtarg
+
+ movl $0, %eax
+ popl %edi
+ popl %ebx
+ ret
+
+vec0:
+ pushl $0 /* error code */
+ pushl $0 /* vector */
+ jmp int_hand
+vec1:
+ pushl $0 /* error code */
+ pushl $1 /* vector */
+ jmp int_hand
+
+vec2:
+ pushl $0 /* error code */
+ pushl $2 /* vector */
+ jmp int_hand
+
+vec3:
+ pushl $0 /* error code */
+ pushl $3 /* vector */
+ jmp int_hand
+
+vec4:
+ pushl $0 /* error code */
+ pushl $4 /* vector */
+ jmp int_hand
+
+vec5:
+ pushl $0 /* error code */
+ pushl $5 /* vector */
+ jmp int_hand
+
+vec6:
+ pushl $0 /* error code */
+ pushl $6 /* vector */
+ jmp int_hand
+vec7:
+ pushl $0 /* error code */
+ pushl $7 /* vector */
+ jmp int_hand
+
+vec8:
+ /* error code */
+ pushl $8 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec9:
+ pushl $0 /* error code */
+ pushl $9 /* vector */
+ jmp int_hand
+
+vec10:
+ /* error code */
+ pushl $10 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec11:
+ /* error code */
+ pushl $11 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec12:
+ /* error code */
+ pushl $12 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec13:
+ /* error code */
+ pushl $13 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec14:
+ /* error code */
+ pushl $14 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec15:
+ pushl $0 /* error code */
+ pushl $15 /* vector */
+ jmp int_hand
+
+vec16:
+ pushl $0 /* error code */
+ pushl $16 /* vector */
+ jmp int_hand
+
+vec17:
+ /* error code */
+ pushl $17 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec18:
+ pushl $0 /* error code */
+ pushl $18 /* vector */
+ jmp int_hand
+
+vec19:
+ pushl $0 /* error code */
+ pushl $19 /* vector */
+ jmp int_hand
+
+__divide_error:
+ pushl $0 /* error code */
+ pushl $20 /* vector */
+ jmp int_hand
+ .global __divide_error
+
+int_hand:
+ /* At this point on the stack there is:
+ * 0(%esp) vector
+ * 4(%esp) error code
+ * 8(%esp) eip
+ * 12(%esp) cs
+ * 16(%esp) eflags
+ */
+ pushl %edi
+ pushl %esi
+ pushl %ebp
+ /* Original stack pointer */
+ leal 32(%esp), %ebp
+ pushl %ebp
+ pushl %ebx
+ pushl %edx
+ pushl %ecx
+ pushl %eax
+
+ pushl %esp /* Pointer to structure on the stack */
+
+ call x86_exception
+ pop %eax /* Drop the pointer */
+
+ popl %eax
+ popl %ecx
+ popl %edx
+ popl %ebx
+ popl %ebp /* Ignore saved %esp value */
+ popl %ebp
+ popl %esi
+ popl %edi
+
+ addl $8, %esp /* pop of the vector and error code */
+
+ iret
+
+idtarg:
+ .word _idt_end - _idt - 1 /* limit */
+ .long _idt
+ .word 0
+_idt:
+ .fill 20, 8, 0 # idt is unitiailzed
+_idt_end:
+
+ .globl arch_nvram_size, arch_nvram_get, arch_nvram_put
+arch_nvram_size:
+ xor %eax, %eax
+ ret
+
+arch_nvram_get:
+ ret
+
+arch_nvram_put:
+ ret
diff --git a/roms/openbios/arch/x86/exception.c b/roms/openbios/arch/x86/exception.c
new file mode 100644
index 00000000..fa07242c
--- /dev/null
+++ b/roms/openbios/arch/x86/exception.c
@@ -0,0 +1,92 @@
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "asm/types.h"
+
+
+
+/* program counter */
+extern ucell PC;
+
+extern unsigned char *dict;
+extern cell dicthead;
+extern ucell *last;
+
+
+
+struct eregs {
+ uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
+ uint32_t vector;
+ uint32_t error_code;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+};
+
+static const char * const exception_names[]= {
+ "division by zero",
+ "single step",
+ "NMI",
+ "breakpoint",
+ "interrupt overflow",
+ "bound range exceeded",
+ "invalid opcode",
+ "device unavailable",
+ "double fault",
+ "FPU segment overrun",
+ "invalid TSS",
+ "segment not present",
+ "stack exception",
+ "general protection fault",
+ "page fault",
+ "reserved",
+ "floating point exception",
+ "alignment check",
+ "machine check exception",
+};
+
+void do_nothing(void);
+void do_nothing(void)
+{
+ printk("Doing nothing\n");
+}
+
+void x86_exception(struct eregs *info);
+void x86_exception(struct eregs *info)
+{
+ if(info->vector <= 18) {
+ printk("\nUnexpected Exception: %s",
+ exception_names[info->vector]);
+ } else {
+ printk("\nUnexpected Exception: %d", info->vector);
+ }
+
+ printk(
+ " @ %02x:%08lx - Halting\n"
+ "Code: %d eflags: %08lx\n"
+ "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n"
+ "edi: %08lx esi: %08lx ebp: %08lx esp: %08lx\n",
+ info->cs, (unsigned long)info->eip,
+ info->error_code, (unsigned long)info->eflags,
+ (unsigned long)info->eax, (unsigned long)info->ebx,
+ (unsigned long)info->ecx, (unsigned long)info->edx,
+ (unsigned long)info->edi, (unsigned long)info->esi,
+ (unsigned long)info->ebp, (unsigned long)info->esp);
+
+ printk("\ndict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n",
+ (ucell)dict, (ucell)dict + dicthead, dicthead, PC, PC - (ucell) dict);
+ printk("dstackcnt=%d rstackcnt=%d\n",
+ dstackcnt, rstackcnt);
+
+ rstackcnt=0;
+ dstackcnt=0;
+
+ PC=findword("outer-interpreter");
+
+ info->eip=(uint32_t)&do_nothing;
+
+/*
+ for (;;)
+ asm("hlt;");
+ ;
+*/
+}
diff --git a/roms/openbios/arch/x86/init.fs b/roms/openbios/arch/x86/init.fs
new file mode 100644
index 00000000..eef72e9b
--- /dev/null
+++ b/roms/openbios/arch/x86/init.fs
@@ -0,0 +1,84 @@
+include config.fs
+
+:noname
+ ." Type 'help' for detailed information" cr
+ \ ." boot secondary slave cdrom: " cr
+ \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr
+ ; DIAG-initializer
+
+" /" find-device
+
+new-device
+ " memory" device-name
+ \ 12230 encode-int " reg" property
+ external
+ : open true ;
+ : close ;
+ \ claim ( phys size align -- base )
+ \ release ( phys size -- )
+finish-device
+
+new-device
+ " cpus" device-name
+ 1 " #address-cells" int-property
+ 0 " #size-cells" int-property
+
+ external
+ : open true ;
+ : close ;
+ : decode-unit parse-hex ;
+
+finish-device
+
+: make-openable ( path )
+ find-dev if
+ begin ?dup while
+ \ install trivial open and close methods
+ dup active-package! is-open
+ parent
+ repeat
+ then
+;
+
+: preopen ( chosen-str node-path )
+ 2dup make-openable
+
+ " /chosen" find-device
+ open-dev ?dup if
+ encode-int 2swap property
+ else
+ 2drop
+ then
+ device-end
+;
+
+:noname
+ set-defaults
+; SYSTEM-initializer
+
+\ preopen device nodes (and store the ihandles under /chosen)
+:noname
+ " memory" " /memory" preopen
+ " mmu" " /cpus/@0" preopen
+ " stdout" " /builtin/console" preopen
+ " stdin" " /builtin/console" preopen
+
+; SYSTEM-initializer
+
+\ use the tty interface if available
+:noname
+ " /builtin/console" find-dev if drop
+ " /builtin/console" " input-device" $setenv
+ " /builtin/console" " output-device" $setenv
+ then
+; SYSTEM-initializer
+
+:noname
+ " keyboard" input
+; CONSOLE-IN-initializer
+
+\ Load VGA FCode driver blob
+[IFDEF] CONFIG_DRIVER_VGA
+ -1 value vga-driver-fcode
+ " QEMU,VGA.bin" $encode-file to vga-driver-fcode
+[THEN]
diff --git a/roms/openbios/arch/x86/ldscript b/roms/openbios/arch/x86/ldscript
new file mode 100644
index 00000000..8976c7af
--- /dev/null
+++ b/roms/openbios/arch/x86/ldscript
@@ -0,0 +1,73 @@
+OUTPUT_FORMAT(elf32-i386)
+OUTPUT_ARCH(i386)
+
+ENTRY(entry)
+
+/* Initial load address
+ * To be loaded by GRUB, this must be >= 1MB
+ */
+BASE_ADDR = 0x100000;
+
+/* 16KB heap and stack */
+HEAP_SIZE = 16384;
+STACK_SIZE = 16384;
+
+SECTIONS
+{
+ . = BASE_ADDR;
+
+ /* Put Multiboot header near beginning of file, if any. */
+ .hdr : { *(.hdr) *(.hdr.*) }
+
+ /* Start of the program.
+ * Now the version string is in the note, we must include it
+ * in the program. Otherwise we lose the string after relocation. */
+ . = ALIGN(16);
+ _start = .;
+
+ /* Putting ELF notes near beginning of file might help bootloaders.
+ * We discard .note sections other than .note.ELFBoot,
+ * because some versions of GCC generates useless ones. */
+ .note : { *(.note.ELFBoot) }
+
+ /* Normal sections */
+ .text : { *(.text) *(.text.*) }
+ .rodata : {
+ . = ALIGN(4);
+ sound_drivers_start = .;
+ *(.rodata.sound_drivers)
+ sound_drivers_end = .;
+ *(.rodata)
+ *(.rodata.*)
+ }
+ .data : { *(.data) *(.data.*) }
+
+ .bss : {
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+
+ /* Put heap and stack here, so they are included in PT_LOAD segment
+ * and the bootloader is aware of it. */
+
+ . = ALIGN(16);
+ _heap = .;
+ . += HEAP_SIZE;
+ . = ALIGN(16);
+ _eheap = .;
+
+ _stack = .;
+ . += STACK_SIZE;
+ . = ALIGN(16);
+ _estack = .;
+ }
+
+ .initctx : {
+ /* Initial contents of stack. This MUST BE just after the stack. */
+ *(.initctx)
+ }
+
+ _end = .;
+
+ /DISCARD/ : { *(.comment) *(.note) }
+}
diff --git a/roms/openbios/arch/x86/lib.c b/roms/openbios/arch/x86/lib.c
new file mode 100644
index 00000000..eeb901b4
--- /dev/null
+++ b/roms/openbios/arch/x86/lib.c
@@ -0,0 +1,56 @@
+/* lib.c
+ * tag: simple function library
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "asm/types.h"
+#include <stdarg.h>
+#include "libc/stdlib.h"
+#include "libc/vsprintf.h"
+#include "kernel/kernel.h"
+
+/* Format a string and print it on the screen, just like the libc
+ * function printf.
+ */
+int printk( const char *fmt, ... )
+{
+ char *p, buf[512];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ for( p=buf; *p; p++ )
+ putchar(*p);
+ return i;
+}
+
+// dumb quick memory allocator until we get a decent thing here.
+
+#define MEMSIZE 128*1024
+static char memory[MEMSIZE];
+static void *memptr=memory;
+static int memsize=MEMSIZE;
+
+void *malloc(int size)
+{
+ void *ret=(void *)0;
+ if(memsize>=size) {
+ memsize-=size;
+ ret=memptr;
+ memptr = (void *)((unsigned long)memptr + size);
+ }
+ return ret;
+}
+
+void free(void *ptr)
+{
+ /* Nothing yet */
+}
diff --git a/roms/openbios/arch/x86/linux_load.c b/roms/openbios/arch/x86/linux_load.c
new file mode 100644
index 00000000..e06326b0
--- /dev/null
+++ b/roms/openbios/arch/x86/linux_load.c
@@ -0,0 +1,671 @@
+/*
+ * Linux/i386 loader
+ * Supports bzImage, zImage and Image format.
+ *
+ * Based on work by Steve Gehlbach.
+ * Portions are taken from mkelfImage.
+ *
+ * 2003-09 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/sys_info.h"
+#include "context.h"
+#include "segment.h"
+#include "libc/diskio.h"
+#include "boot.h"
+
+#define printf printk
+#define debug printk
+#define strtoull_with_suffix strtol
+
+#define LINUX_PARAM_LOC 0x90000
+#define COMMAND_LINE_LOC 0x91000
+#define GDT_LOC 0x92000
+#define STACK_LOC 0x93000
+
+#define E820MAX 32 /* number of entries in E820MAP */
+struct e820entry {
+ unsigned long long addr; /* start of memory segment */
+ unsigned long long size; /* size of memory segment */
+ unsigned long type; /* type of memory segment */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
+#define E820_NVS 4
+};
+
+/* The header of Linux/i386 kernel */
+struct linux_header {
+ uint8_t reserved1[0x1f1]; /* 0x000 */
+ uint8_t setup_sects; /* 0x1f1 */
+ uint16_t root_flags; /* 0x1f2 */
+ uint8_t reserved2[6]; /* 0x1f4 */
+ uint16_t vid_mode; /* 0x1fa */
+ uint16_t root_dev; /* 0x1fc */
+ uint16_t boot_sector_magic; /* 0x1fe */
+ /* 2.00+ */
+ uint8_t reserved3[2]; /* 0x200 */
+ uint8_t header_magic[4]; /* 0x202 */
+ uint16_t protocol_version; /* 0x206 */
+ uint32_t realmode_swtch; /* 0x208 */
+ uint16_t start_sys; /* 0x20c */
+ uint16_t kver_addr; /* 0x20e */
+ uint8_t type_of_loader; /* 0x210 */
+ uint8_t loadflags; /* 0x211 */
+ uint16_t setup_move_size; /* 0x212 */
+ uint32_t code32_start; /* 0x214 */
+ uint32_t ramdisk_image; /* 0x218 */
+ uint32_t ramdisk_size; /* 0x21c */
+ uint8_t reserved4[4]; /* 0x220 */
+ /* 2.01+ */
+ uint16_t heap_end_ptr; /* 0x224 */
+ uint8_t reserved5[2]; /* 0x226 */
+ /* 2.02+ */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ /* 2.03+ */
+ uint32_t initrd_addr_max; /* 0x22c */
+} __attribute__ ((packed));
+
+
+/* Paramters passed to 32-bit part of Linux
+ * This is another view of the structure above.. */
+struct linux_params {
+ uint8_t orig_x; /* 0x00 */
+ uint8_t orig_y; /* 0x01 */
+ uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */
+ uint16_t orig_video_page; /* 0x04 */
+ uint8_t orig_video_mode; /* 0x06 */
+ uint8_t orig_video_cols; /* 0x07 */
+ uint16_t unused2; /* 0x08 */
+ uint16_t orig_video_ega_bx; /* 0x0a */
+ uint16_t unused3; /* 0x0c */
+ uint8_t orig_video_lines; /* 0x0e */
+ uint8_t orig_video_isVGA; /* 0x0f */
+ uint16_t orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ uint16_t lfb_width; /* 0x12 */
+ uint16_t lfb_height; /* 0x14 */
+ uint16_t lfb_depth; /* 0x16 */
+ uint32_t lfb_base; /* 0x18 */
+ uint32_t lfb_size; /* 0x1c */
+ uint16_t cl_magic; /* 0x20 */
+#define CL_MAGIC_VALUE 0xA33F
+ uint16_t cl_offset; /* 0x22 */
+ uint16_t lfb_linelength; /* 0x24 */
+ uint8_t red_size; /* 0x26 */
+ uint8_t red_pos; /* 0x27 */
+ uint8_t green_size; /* 0x28 */
+ uint8_t green_pos; /* 0x29 */
+ uint8_t blue_size; /* 0x2a */
+ uint8_t blue_pos; /* 0x2b */
+ uint8_t rsvd_size; /* 0x2c */
+ uint8_t rsvd_pos; /* 0x2d */
+ uint16_t vesapm_seg; /* 0x2e */
+ uint16_t vesapm_off; /* 0x30 */
+ uint16_t pages; /* 0x32 */
+ uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */
+
+ //struct apm_bios_info apm_bios_info; /* 0x40 */
+ uint8_t apm_bios_info[0x40];
+ //struct drive_info_struct drive_info; /* 0x80 */
+ uint8_t drive_info[0x20];
+ //struct sys_desc_table sys_desc_table; /* 0xa0 */
+ uint8_t sys_desc_table[0x140];
+ uint32_t alt_mem_k; /* 0x1e0 */
+ uint8_t reserved5[4]; /* 0x1e4 */
+ uint8_t e820_map_nr; /* 0x1e8 */
+ uint8_t reserved6[9]; /* 0x1e9 */
+ uint16_t mount_root_rdonly; /* 0x1f2 */
+ uint8_t reserved7[4]; /* 0x1f4 */
+ uint16_t ramdisk_flags; /* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_PROMPT_FLAG 0x8000
+#define RAMDISK_LOAD_FLAG 0x4000
+ uint8_t reserved8[2]; /* 0x1fa */
+ uint16_t orig_root_dev; /* 0x1fc */
+ uint8_t reserved9[1]; /* 0x1fe */
+ uint8_t aux_device_info; /* 0x1ff */
+ uint8_t reserved10[2]; /* 0x200 */
+ uint8_t param_block_signature[4]; /* 0x202 */
+ uint16_t param_block_version; /* 0x206 */
+ uint8_t reserved11[8]; /* 0x208 */
+ uint8_t loader_type; /* 0x210 */
+#define LOADER_TYPE_LOADLIN 1
+#define LOADER_TYPE_BOOTSECT_LOADER 2
+#define LOADER_TYPE_SYSLINUX 3
+#define LOADER_TYPE_ETHERBOOT 4
+#define LOADER_TYPE_KERNEL 5
+ uint8_t loader_flags; /* 0x211 */
+ uint8_t reserved12[2]; /* 0x212 */
+ uint32_t kernel_start; /* 0x214 */
+ uint32_t initrd_start; /* 0x218 */
+ uint32_t initrd_size; /* 0x21c */
+ uint8_t reserved12_5[8]; /* 0x220 */
+ uint32_t cmd_line_ptr; /* 0x228 */
+ uint8_t reserved13[164]; /* 0x22c */
+ struct e820entry e820_map[E820MAX]; /* 0x2d0 */
+ uint8_t reserved16[688]; /* 0x550 */
+#define COMMAND_LINE_SIZE 256
+ /* Command line is copied here by 32-bit i386/kernel/head.S.
+ * So I will follow the boot protocol, rather than putting it
+ * directly here. --ts1 */
+ uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */
+ uint8_t reserved17[1792]; /* 0x900 - 0x1000 */
+};
+
+static uint64_t forced_memsize;
+static int fd;
+
+static unsigned long file_size(void)
+{
+ long long fpos, fsize;
+
+ /* Save current position */
+ fpos = tell(fd);
+
+ /* Go to end of file and get position */
+ seek_io(fd, -1);
+ fsize = tell(fd);
+
+ /* Go back to old position */
+ seek_io(fd, 0);
+ seek_io(fd, fpos);
+
+ return fsize;
+}
+
+/* Load the first part the file and check if it's Linux */
+static uint32_t load_linux_header(struct linux_header *hdr)
+{
+ int load_high;
+ uint32_t kern_addr;
+
+ if (read_io(fd, hdr, sizeof *hdr) != sizeof *hdr) {
+ debug("Can't read Linux header\n");
+ return 0;
+ }
+ if (hdr->boot_sector_magic != 0xaa55) {
+ debug("Not a Linux kernel image\n");
+ return 0;
+ }
+
+ /* Linux is found. Print some information */
+ if (memcmp(hdr->header_magic, "HdrS", 4) != 0) {
+ /* This may be floppy disk image or something.
+ * Perform a simple (incomplete) sanity check. */
+ if (hdr->setup_sects >= 16
+ || file_size() - (hdr->setup_sects<<9) >= 512<<10) {
+ debug("This looks like a bootdisk image but not like Linux...\n");
+ return 0;
+ }
+
+ printf("Possible very old Linux");
+ /* This kernel does not even have a protocol version.
+ * Force the value. */
+ hdr->protocol_version = 0; /* pre-2.00 */
+ } else
+ printf("Found Linux");
+ if (hdr->protocol_version >= 0x200 && hdr->kver_addr) {
+ char kver[256];
+ seek_io(fd, hdr->kver_addr + 0x200);
+ if (read_io(fd, kver, sizeof kver) != 0) {
+ kver[255] = 0;
+ printf(" version %s", kver);
+ }
+ }
+ debug(" (protocol %#x)", hdr->protocol_version);
+ load_high = 0;
+ if (hdr->protocol_version >= 0x200) {
+ debug(" (loadflags %#x)", hdr->loadflags);
+ load_high = hdr->loadflags & 1;
+ }
+ if (load_high) {
+ printf(" bzImage");
+ kern_addr = 0x100000;
+ } else {
+ printf(" zImage or Image");
+ kern_addr = 0x1000;
+ }
+ printf(".\n");
+
+ return kern_addr;
+}
+
+/* Set up parameters for 32-bit kernel */
+static void
+init_linux_params(struct linux_params *params, struct linux_header *hdr)
+{
+ debug("Setting up paramters at %#lx\n", virt_to_phys(params));
+ memset(params, 0, sizeof *params);
+
+ /* Copy some useful values from header */
+ params->mount_root_rdonly = hdr->root_flags;
+ params->orig_root_dev = hdr->root_dev;
+
+ /* Video parameters.
+ * This assumes we have VGA in standard 80x25 text mode,
+ * just like our vga.c does.
+ * Cursor position is filled later to allow some more printf's. */
+ params->orig_video_mode = 3;
+ params->orig_video_cols = 80;
+ params->orig_video_lines = 25;
+ params->orig_video_isVGA = 1;
+ params->orig_video_points = 16;
+
+ params->loader_type = 0xff; /* Unregistered Linux loader */
+}
+
+/* Memory map */
+static void
+set_memory_size(struct linux_params *params, struct sys_info *info)
+{
+ int i;
+ uint64_t end;
+ uint32_t ramtop = 0;
+ struct e820entry *linux_map;
+ struct memrange *filo_map;
+
+ linux_map = params->e820_map;
+ filo_map = info->memrange;
+ for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) {
+ if (i < E820MAX) {
+ /* Convert to BIOS e820 style */
+ linux_map->addr = filo_map->base;
+ linux_map->size = filo_map->size;
+ linux_map->type = E820_RAM;
+ debug("%016Lx - %016Lx\n", linux_map->addr,
+ linux_map->addr + linux_map->size);
+ params->e820_map_nr = i+1;
+ }
+
+ /* Find out top of RAM. XXX This ignores hole above 1MB */
+ end = filo_map->base + filo_map->size;
+ if (end < (1ULL << 32)) { /* don't count memory above 4GB */
+ if (end > ramtop)
+ ramtop = (uint32_t) end;
+ }
+ }
+ debug("ramtop=%#x\n", ramtop);
+ /* Size of memory above 1MB in KB */
+ params->alt_mem_k = (ramtop - (1<<20)) >> 10;
+ /* old style, 64MB max */
+ if (ramtop >= (64<<20))
+ params->ext_mem_k = (63<<10);
+ else
+ params->ext_mem_k = params->alt_mem_k;
+ debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k);
+}
+
+/*
+ * Parse command line
+ * Some parameters, like initrd=<file>, are not passed to kernel,
+ * we are responsible to process them.
+ * Parameters for kernel are copied to kern_cmdline. Returns name of initrd.
+ */
+static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline)
+{
+ const char *start, *sep, *end, *val;
+ char name[64];
+ int len;
+ int k_len;
+ int to_kern;
+ char *initrd = NULL;
+ int toolong = 0;
+
+ forced_memsize = 0;
+
+ if (!orig_cmdline) {
+ *kern_cmdline = 0;
+ return NULL;
+ }
+
+ k_len = 0;
+ debug("original command line: \"%s\"\n", orig_cmdline);
+ debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline));
+
+ start = orig_cmdline;
+ while (*start == ' ')
+ start++;
+ while (*start) {
+ end = strchr(start, ' ');
+ if (!end)
+ end = start + strlen(start);
+ sep = strchr(start, '=');
+ if (!sep || sep > end)
+ sep = end;
+ len = sep - start;
+ if (len >= sizeof(name))
+ len = sizeof(name) - 1;
+ memcpy(name, start, len);
+ name[len] = 0;
+
+ if (*sep == '=') {
+ val = sep + 1;
+ len = end - val;
+ } else {
+ val = NULL;
+ len = 0;
+ }
+
+ /* Only initrd= and mem= are handled here. vga= is not,
+ * which I believe is a paramter to the realmode part of Linux,
+ * which we don't execute. */
+ if (strcmp(name, "initrd") == 0) {
+ if (!val)
+ printf("Missing filename to initrd parameter\n");
+ else {
+ initrd = malloc(len + 1);
+ memcpy(initrd, val, len);
+ initrd[len] = 0;
+ debug("initrd=%s\n", initrd);
+ }
+ /* Don't pass this to kernel */
+ to_kern = 0;
+ } else if (strcmp(name, "mem") == 0) {
+ if (!val)
+ printf("Missing value for mem parameter\n");
+ else {
+ forced_memsize = strtoull_with_suffix(val, (char**)&val, 0);
+ if (forced_memsize == 0)
+ printf("Invalid mem option, ignored\n");
+ if (val != end) {
+ printf("Garbage after mem=<size>, ignored\n");
+ forced_memsize = 0;
+ }
+ debug("mem=%Lu\n", forced_memsize);
+ }
+ /* mem= is for both loader and kernel */
+ to_kern = 1;
+ } else
+ to_kern = 1;
+
+ if (to_kern) {
+ /* Copy to kernel command line buffer */
+ if (k_len != 0)
+ kern_cmdline[k_len++] = ' '; /* put separator */
+ len = end - start;
+ if (k_len + len >= COMMAND_LINE_SIZE) {
+ len = COMMAND_LINE_SIZE - k_len - 1;
+ if (!toolong) {
+ printf("Kernel command line is too long; truncated to "
+ "%d bytes\n", COMMAND_LINE_SIZE-1);
+ toolong = 1;
+ }
+ }
+ memcpy(kern_cmdline + k_len, start, len);
+ k_len += len;
+ }
+
+ start = end;
+ while (*start == ' ')
+ start++;
+ }
+ kern_cmdline[k_len] = 0;
+ debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline);
+
+ return initrd;
+}
+
+/* Set command line location */
+static void set_command_line_loc(struct linux_params *params,
+ struct linux_header *hdr)
+{
+ if (hdr->protocol_version >= 0x202) {
+ /* new style */
+ params->cmd_line_ptr = COMMAND_LINE_LOC;
+ } else {
+ /* old style */
+ params->cl_magic = CL_MAGIC_VALUE;
+ params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC;
+ }
+}
+
+/* Load 32-bit part of kernel */
+static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr)
+{
+ uint32_t kern_offset, kern_size;
+
+ if (hdr->setup_sects == 0)
+ hdr->setup_sects = 4;
+ kern_offset = (hdr->setup_sects + 1) * 512;
+ seek_io(fd, kern_offset);
+ kern_size = file_size() - kern_offset;
+ debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size);
+
+#if 0
+ if (using_devsize) {
+ printf("Attempt to load up to end of device as kernel; "
+ "specify the image size\n");
+ return 0;
+ }
+#endif
+
+ printf("Loading kernel... ");
+ if (read_io(fd, phys_to_virt(kern_addr), kern_size) != kern_size) {
+ printf("Can't read kernel\n");
+ return 0;
+ }
+ printf("ok\n");
+
+ return kern_size;
+}
+
+static int load_initrd(struct linux_header *hdr, struct sys_info *info,
+ uint32_t kern_end, struct linux_params *params, const char *initrd_file)
+{
+ uint32_t max;
+ uint32_t start, end, size;
+ uint64_t forced;
+
+ fd = open_io(initrd_file);
+ if (fd == -1) {
+ printf("Can't open initrd: %s\n", initrd_file);
+ return -1;
+ }
+
+#if 0
+ if (using_devsize) {
+ printf("Attempt to load up to end of device as initrd; "
+ "specify the image size\n");
+ return -1;
+ }
+#endif
+
+ size = file_size();
+
+
+ /* Find out the kernel's restriction on how high the initrd can be
+ * placed */
+ if (hdr->protocol_version >= 0x203)
+ max = hdr->initrd_addr_max;
+ else
+ max = 0x38000000; /* Hardcoded value for older kernels */
+
+ /* FILO itself is at the top of RAM. (relocated)
+ * So, try putting initrd just below us. */
+ end = virt_to_phys(_start);
+ if (end > max)
+ end = max;
+
+ /* If "mem=" option is given, we have to put the initrd within
+ * the specified range. */
+ if (forced_memsize) {
+ forced = forced_memsize;
+ if (forced > max)
+ forced = max;
+ /* If the "mem=" is lower, it's easy */
+ if (forced <= end)
+ end = forced;
+ else {
+ /* Otherwise, see if we can put it above us */
+ if (virt_to_phys(_end) + size <= forced)
+ end = forced; /* Ok */
+ }
+ }
+
+ start = end - size;
+ start &= ~0xfff; /* page align */
+ end = start + size;
+
+ debug("start=%#x end=%#x\n", start, end);
+
+ if (start < kern_end) {
+ printf("Initrd is too big to fit in memory\n");
+ return -1;
+ }
+
+ printf("Loading initrd... ");
+ if (read_io(fd, phys_to_virt(start), size) != size) {
+ printf("Can't read initrd\n");
+ return -1;
+ }
+ printf("ok\n");
+
+ params->initrd_start = start;
+ params->initrd_size = size;
+
+ close_io(fd);
+
+ return 0;
+}
+
+static void hardware_setup(void)
+{
+ /* Disable nmi */
+ outb(0x80, 0x70);
+
+ /* Make sure any coprocessor is properly reset.. */
+ outb(0, 0xf0);
+ outb(0, 0xf1);
+
+ /* we're getting screwed again and again by this problem of the 8259.
+ * so we're going to leave this lying around for inclusion into
+ * crt0.S on an as-needed basis.
+ *
+ * well, that went ok, I hope. Now we have to reprogram the interrupts :-(
+ * we put them right after the intel-reserved hardware interrupts, at
+ * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
+ * messed this up with the original PC, and they haven't been able to
+ * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
+ * which is used for the internal hardware interrupts as well. We just
+ * have to reprogram the 8259's, and it isn't fun.
+ */
+
+ outb(0x11, 0x20); /* initialization sequence to 8259A-1 */
+ outb(0x11, 0xA0); /* and to 8259A-2 */
+
+ outb(0x20, 0x21); /* start of hardware int's (0x20) */
+ outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */
+
+ outb(0x04, 0x21); /* 8259-1 is master */
+ outb(0x02, 0xA1); /* 8259-2 is slave */
+
+ outb(0x01, 0x21); /* 8086 mode for both */
+ outb(0x01, 0xA1);
+
+ outb(0xFF, 0xA1); /* mask off all interrupts for now */
+ outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */
+}
+
+/* Start Linux */
+static int start_linux(uint32_t kern_addr, struct linux_params *params)
+{
+ struct segment_desc *linux_gdt;
+ struct context *ctx;
+ //extern int cursor_x, cursor_y;
+
+ ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
+
+ /* Linux expects GDT being in low memory */
+ linux_gdt = phys_to_virt(GDT_LOC);
+ memset(linux_gdt, 0, 13*sizeof(struct segment_desc));
+ /* Normal kernel code/data segments */
+ linux_gdt[2] = gdt[FLAT_CODE];
+ linux_gdt[3] = gdt[FLAT_DATA];
+ /* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible
+ * segments (2 and 3), so it SHOULD not be a problem.
+ * However, some distro kernels (eg. RH9) with backported threading
+ * patch use 12 and 13 also when booting... */
+ linux_gdt[12] = gdt[FLAT_CODE];
+ linux_gdt[13] = gdt[FLAT_DATA];
+ ctx->gdt_base = GDT_LOC;
+ ctx->gdt_limit = 14*8-1;
+ ctx->cs = 0x10;
+ ctx->ds = 0x18;
+ ctx->es = 0x18;
+ ctx->fs = 0x18;
+ ctx->gs = 0x18;
+ ctx->ss = 0x18;
+
+ /* Parameter location */
+ ctx->esi = virt_to_phys(params);
+
+ /* Entry point */
+ ctx->eip = kern_addr;
+
+ debug("eip=%#x\n", kern_addr);
+ printf("Jumping to entry point...\n");
+
+#ifdef VGA_CONSOLE
+ /* Update VGA cursor position.
+ * This must be here because the printf changes the value! */
+ params->orig_x = cursor_x;
+ params->orig_y = cursor_y;
+#endif
+
+ /* Go... */
+ ctx = switch_to(ctx);
+
+ /* It's impossible but... */
+ printf("Returned with eax=%#x\n", ctx->eax);
+
+ return ctx->eax;
+}
+
+int linux_load(struct sys_info *info, const char *file, const char *cmdline)
+{
+ struct linux_header hdr;
+ struct linux_params *params;
+ uint32_t kern_addr, kern_size;
+ char *initrd_file = NULL;
+
+ fd = open_io(file);
+ if (fd == -1) {
+ return -1;
+ }
+
+ kern_addr = load_linux_header(&hdr);
+ if (kern_addr == 0)
+ return LOADER_NOT_SUPPORT;
+
+ params = phys_to_virt(LINUX_PARAM_LOC);
+ init_linux_params(params, &hdr);
+ set_memory_size(params, info);
+ initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
+ set_command_line_loc(params, &hdr);
+
+ kern_size = load_linux_kernel(&hdr, kern_addr);
+ if (kern_size == 0) {
+ if (initrd_file)
+ free(initrd_file);
+ return -1;
+ }
+
+ if (initrd_file) {
+ if (load_initrd(&hdr, info, kern_addr+kern_size, params, initrd_file)
+ != 0) {
+ free(initrd_file);
+ return -1;
+ }
+ free(initrd_file);
+ }
+
+ hardware_setup();
+
+ start_linux(kern_addr, params);
+ return 0;
+}
diff --git a/roms/openbios/arch/x86/multiboot.c b/roms/openbios/arch/x86/multiboot.c
new file mode 100644
index 00000000..6f6b23dc
--- /dev/null
+++ b/roms/openbios/arch/x86/multiboot.c
@@ -0,0 +1,127 @@
+/* Support for Multiboot */
+
+#include "config.h"
+#include "asm/io.h"
+#include "libopenbios/sys_info.h"
+#include "multiboot.h"
+
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+struct mbheader {
+ unsigned int magic, flags, checksum;
+};
+
+static const struct mbheader multiboot_header
+ __attribute__((section (".hdr"))) =
+{
+ MULTIBOOT_HEADER_MAGIC,
+ MULTIBOOT_HEADER_FLAGS,
+ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+};
+
+/* Multiboot information structure, provided by loader to us */
+
+struct multiboot_mmap {
+ unsigned entry_size;
+ unsigned base_lo, base_hi;
+ unsigned size_lo, size_hi;
+ unsigned type;
+};
+
+#define MULTIBOOT_MEM_VALID 0x01
+#define MULTIBOOT_BOOT_DEV_VALID 0x02
+#define MULTIBOOT_CMDLINE_VALID 0x04
+#define MULTIBOOT_MODS_VALID 0x08
+#define MULTIBOOT_AOUT_SYMS_VALID 0x10
+#define MULTIBOOT_ELF_SYMS_VALID 0x20
+#define MULTIBOOT_MMAP_VALID 0x40
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ struct multiboot_info *mbinfo;
+ struct multiboot_mmap *mbmem;
+ unsigned mbcount, mbaddr;
+ int i;
+ struct memrange *mmap;
+ int mmap_count;
+ module_t *mod;
+
+ if (info->boot_type != 0x2BADB002)
+ return;
+
+ debug("Using Multiboot information at %#lx\n", info->boot_data);
+
+ mbinfo = phys_to_virt(info->boot_data);
+
+ if (mbinfo->mods_count != 1) {
+ printk("multiboot: no dictionary\n");
+ return;
+ }
+
+ mod = (module_t *) mbinfo->mods_addr;
+ info->dict_start=(unsigned long *)mod->mod_start;
+ info->dict_end=(unsigned long *)mod->mod_end;
+ debug("multiboot: dictionary at %p-%p\n",
+ info->dict_start, info->dict_end);
+
+ if (mbinfo->flags & MULTIBOOT_MMAP_VALID) {
+ /* convert mmap records */
+ mbmem = phys_to_virt(mbinfo->mmap_addr);
+ mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4);
+ mmap = malloc(mbcount * sizeof(struct memrange));
+ mmap_count = 0;
+ mbaddr = mbinfo->mmap_addr;
+ for (i = 0; i < mbcount; i++) {
+ mbmem = phys_to_virt(mbaddr);
+ debug("%08x%08x %08x%08x (%d)\n",
+ mbmem->base_hi,
+ mbmem->base_lo,
+ mbmem->size_hi,
+ mbmem->size_lo,
+ mbmem->type);
+ if (mbmem->type == 1) { /* Only normal RAM */
+ mmap[mmap_count].base = mbmem->base_lo
+ + (((unsigned long long) mbmem->base_hi) << 32);
+ mmap[mmap_count].size = mbmem->size_lo
+ + (((unsigned long long) mbmem->size_hi) << 32);
+ mmap_count++;
+ }
+ mbaddr += mbmem->entry_size + 4;
+ if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length)
+ break;
+ }
+ /* simple sanity check - there should be at least 2 RAM segments
+ * (base 640k and extended) */
+ if (mmap_count >= 2)
+ goto got_it;
+
+ printk("Multiboot mmap is broken\n");
+ free(mmap);
+ /* fall back to mem_lower/mem_upper */
+ }
+
+ if (mbinfo->flags & MULTIBOOT_MEM_VALID) {
+ /* use mem_lower and mem_upper */
+ mmap_count = 2;
+ mmap = malloc(2 * sizeof(*mmap));
+ mmap[0].base = 0;
+ mmap[0].size = mbinfo->mem_lower << 10;
+ mmap[1].base = 1 << 20; /* 1MB */
+ mmap[1].size = mbinfo->mem_upper << 10;
+ goto got_it;
+ }
+
+ printk("Can't get memory information from Multiboot\n");
+ return;
+
+got_it:
+ info->memrange = mmap;
+ info->n_memranges = mmap_count;
+
+ return;
+}
diff --git a/roms/openbios/arch/x86/multiboot.h b/roms/openbios/arch/x86/multiboot.h
new file mode 100644
index 00000000..fd0fe973
--- /dev/null
+++ b/roms/openbios/arch/x86/multiboot.h
@@ -0,0 +1,96 @@
+/* multiboot.h
+ * tag: header for multiboot
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+/* magic number for multiboot header */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* flags for multiboot header */
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+
+/* magic number passed by multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The size of our stack (8KB). */
+#define STACK_SIZE 0x2000
+
+/* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym) _ ## sym
+#else
+# define EXT_C(sym) sym
+#endif
+
+#ifndef ASM
+/* We don't want these declarations in boot.S */
+
+/* multiboot header */
+typedef struct multiboot_header {
+ unsigned long magic;
+ unsigned long flags;
+ unsigned long checksum;
+ unsigned long header_addr;
+ unsigned long load_addr;
+ unsigned long load_end_addr;
+ unsigned long bss_end_addr;
+ unsigned long entry_addr;
+} multiboot_header_t;
+
+/* symbol table for a.out */
+typedef struct aout_symbol_table {
+ unsigned long tabsize;
+ unsigned long strsize;
+ unsigned long addr;
+ unsigned long reserved;
+} aout_symbol_table_t;
+
+/* section header table for ELF */
+typedef struct elf_section_header_table {
+ unsigned long num;
+ unsigned long size;
+ unsigned long addr;
+ unsigned long shndx;
+} elf_section_header_table_t;
+
+/* multiboot information */
+typedef struct multiboot_info {
+ unsigned long flags;
+ unsigned long mem_lower;
+ unsigned long mem_upper;
+ unsigned long boot_device;
+ unsigned long cmdline;
+ unsigned long mods_count;
+ unsigned long mods_addr;
+ union {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ unsigned long mmap_length;
+ unsigned long mmap_addr;
+} multiboot_info_t;
+
+/* module structure */
+typedef struct module {
+ unsigned long mod_start;
+ unsigned long mod_end;
+ unsigned long string;
+ unsigned long reserved;
+} module_t;
+
+/* memory map. Be careful that the offset 0 is base_addr_low
+ but no size. */
+typedef struct memory_map {
+ unsigned long size;
+ unsigned long base_addr_low;
+ unsigned long base_addr_high;
+ unsigned long length_low;
+ unsigned long length_high;
+ unsigned long type;
+} memory_map_t;
+
+#endif /* ! ASM */
diff --git a/roms/openbios/arch/x86/openbios.c b/roms/openbios/arch/x86/openbios.c
new file mode 100644
index 00000000..6145436f
--- /dev/null
+++ b/roms/openbios/arch/x86/openbios.c
@@ -0,0 +1,134 @@
+/* tag: openbios forth environment, executable code
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "asm/types.h"
+#include "dict.h"
+#include "kernel/kernel.h"
+#include "kernel/stack.h"
+#include "drivers/drivers.h"
+#include "drivers/pci.h"
+#include "libopenbios/sys_info.h"
+#include "libopenbios/video.h"
+#include "openbios.h"
+#include "relocate.h"
+#include "boot.h"
+
+void collect_sys_info(struct sys_info *info);
+
+#ifdef CONFIG_DRIVER_PCI
+static const pci_arch_t default_pci_host = {
+ .name = "Intel,i440FX",
+ .vendor_id = PCI_VENDOR_ID_INTEL,
+ .device_id = PCI_DEVICE_ID_INTEL_82441,
+ .io_base = 0x1000,
+};
+#endif
+
+static void init_memory(void)
+{
+ /* push start and end of available memory to the stack
+ * so that the forth word QUIT can initialize memory
+ * management. For now we use hardcoded memory between
+ * 0x10000 and 0x9ffff (576k). If we need more memory
+ * than that we have serious bloat.
+ */
+
+ PUSH(0x10000);
+ PUSH(0x9FFFF);
+}
+
+static void
+arch_init( void )
+{
+ openbios_init();
+ modules_init();
+#ifdef CONFIG_DRIVER_PCI
+ arch = &default_pci_host;
+ ob_pci_init();
+#endif
+#ifdef CONFIG_DRIVER_IDE
+ setup_timers();
+ ob_ide_init("/pci/isa", 0x1f0, 0x3f6, 0x170, 0x376);
+#endif
+#ifdef CONFIG_DRIVER_FLOPPY
+ ob_floppy_init("/isa", "floppy0", 0x3f0, 0);
+#endif
+#ifdef CONFIG_XBOX
+ setup_video();
+
+ /* Force video to 32-bit depth */
+ VIDEO_DICT_VALUE(video.depth) = 32;
+
+ init_video();
+ node_methods_init();
+#endif
+ device_end();
+ bind_func("platform-boot", boot );
+ bind_func("(go)", go );
+}
+
+extern struct _console_ops arch_console_ops;
+
+int openbios(void)
+{
+#ifdef CONFIG_DEBUG_CONSOLE
+ init_console(arch_console_ops);
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+ uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED);
+#endif
+ /* Clear the screen. */
+ cls();
+#endif
+
+ collect_sys_info(&sys_info);
+
+ dict = (unsigned char *)sys_info.dict_start;
+ dicthead = (cell)sys_info.dict_end;
+ last = sys_info.dict_last;
+ dictlimit = sys_info.dict_limit;
+
+ forth_init();
+
+ relocate(&sys_info);
+
+#ifdef CONFIG_DEBUG_CONSOLE_VGA
+ video_init();
+#endif
+#ifdef CONFIG_DEBUG_BOOT
+ printk("forth started.\n");
+ printk("initializing memory...");
+#endif
+
+ init_memory();
+
+#ifdef CONFIG_DEBUG_BOOT
+ printk("done\n");
+#endif
+
+ PUSH_xt( bind_noname_func(arch_init) );
+ fword("PREPOST-initializer");
+
+ PC = (ucell)findword("initialize-of");
+
+ if (!PC) {
+ printk("panic: no dictionary entry point.\n");
+ return -1;
+ }
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("done (%d bytes).\n", dicthead);
+ printk("Jumping to dictionary...\n");
+#endif
+
+ enterforth((xt_t)PC);
+
+ return 0;
+}
diff --git a/roms/openbios/arch/x86/openbios.h b/roms/openbios/arch/x86/openbios.h
new file mode 100644
index 00000000..a1308227
--- /dev/null
+++ b/roms/openbios/arch/x86/openbios.h
@@ -0,0 +1,32 @@
+/*
+ * Creation Date: <2004/01/15 16:14:05 samuel>
+ * Time-stamp: <2004/01/15 16:14:05 samuel>
+ *
+ * <openbios.h>
+ *
+ *
+ *
+ * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_OPENBIOS
+#define _H_OPENBIOS
+
+int openbios(void);
+
+/* entry.S */
+void init_exceptions(void);
+
+/* console.c */
+extern void cls(void);
+#ifdef CONFIG_DEBUG_CONSOLE
+extern int uart_init(int port, unsigned long speed);
+extern void video_init(void);
+#endif
+
+#endif /* _H_OPENBIOS */
diff --git a/roms/openbios/arch/x86/plainboot.c b/roms/openbios/arch/x86/plainboot.c
new file mode 100644
index 00000000..08dab2d1
--- /dev/null
+++ b/roms/openbios/arch/x86/plainboot.c
@@ -0,0 +1,21 @@
+/* tag: openbios fixed address forth starter
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/sys_info.h"
+#include "multiboot.h"
+
+#define FIXED_DICTSTART 0xfffe0000
+#define FIXED_DICTEND 0xfffeffff
+
+void collect_multiboot_info(struct sys_info *info);
+void collect_multiboot_info(struct sys_info *info)
+{
+ info->dict_start=(unsigned long *)FIXED_DICTSTART;
+ info->dict_end=(unsigned long *)FIXED_DICTEND;
+}
diff --git a/roms/openbios/arch/x86/relocate.h b/roms/openbios/arch/x86/relocate.h
new file mode 100644
index 00000000..d91160a0
--- /dev/null
+++ b/roms/openbios/arch/x86/relocate.h
@@ -0,0 +1 @@
+void relocate(struct sys_info *);
diff --git a/roms/openbios/arch/x86/segment.c b/roms/openbios/arch/x86/segment.c
new file mode 100644
index 00000000..5146cd30
--- /dev/null
+++ b/roms/openbios/arch/x86/segment.c
@@ -0,0 +1,133 @@
+/* Segmentation of the i386 architecture.
+ *
+ * 2003-07 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/sys_info.h"
+#include "relocate.h"
+#include "segment.h"
+
+#define printf printk
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+/* i386 lgdt argument */
+struct gdtarg {
+ unsigned short limit;
+ unsigned int base;
+} __attribute__((packed));
+
+/* How far the virtual address (used in C) is different from physical
+ * address. Since we start in flat mode, the initial value is zero. */
+unsigned long virt_offset = 0;
+
+/* GDT, the global descriptor table */
+struct segment_desc gdt[NUM_SEG] = {
+ /* 0x00: null segment */
+ {0, 0, 0, 0, 0, 0},
+ /* 0x08: flat code segment */
+ {0xffff, 0, 0, 0x9f, 0xcf, 0},
+ /* 0x10: flat data segment */
+ {0xffff, 0, 0, 0x93, 0xcf, 0},
+ /* 0x18: code segment for relocated execution */
+ {0xffff, 0, 0, 0x9f, 0xcf, 0},
+ /* 0x20: data segment for relocated execution */
+ {0xffff, 0, 0, 0x93, 0xcf, 0},
+};
+
+
+void relocate(struct sys_info *info)
+{
+ int i;
+ unsigned long prog_addr;
+ unsigned long prog_size;
+ unsigned long addr, new_base;
+ unsigned long long segsize;
+ unsigned long new_offset;
+ unsigned d0, d1, d2;
+ struct gdtarg gdtarg;
+#define ALIGNMENT 16
+
+ prog_addr = virt_to_phys(&_start);
+ prog_size = virt_to_phys(&_end) - virt_to_phys(&_start);
+ debug("Current location: %#lx-%#lx\n", prog_addr, prog_addr+prog_size-1);
+
+ new_base = 0;
+ for (i = 0; i < info->n_memranges; i++) {
+ if (info->memrange[i].base >= 1ULL<<32)
+ continue;
+ segsize = info->memrange[i].size;
+ if (info->memrange[i].base + segsize > 1ULL<<32)
+ segsize = (1ULL<<32) - info->memrange[i].base;
+ if (segsize < prog_size+ALIGNMENT)
+ continue;
+ addr = info->memrange[i].base + segsize - prog_size;
+ addr &= ~(ALIGNMENT-1);
+ if (addr >= prog_addr && addr < prog_addr + prog_size)
+ continue;
+ if (prog_addr >= addr && prog_addr < addr + prog_size)
+ continue;
+ if (addr > new_base)
+ new_base = addr;
+ }
+ if (new_base == 0) {
+ printf("Can't find address to relocate\n");
+ return;
+ }
+
+ debug("Relocating to %#lx-%#lx... ",
+ new_base, new_base + prog_size - 1);
+
+ /* New virtual address offset */
+ new_offset = new_base - (unsigned long) &_start;
+
+ /* Tweak the GDT */
+ gdt[RELOC_CODE].base_0 = (unsigned short) new_offset;
+ gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset>>16);
+ gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset>>24);
+ gdt[RELOC_DATA].base_0 = (unsigned short) new_offset;
+ gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset>>16);
+ gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset>>24);
+
+ /* Load new GDT and reload segments */
+ gdtarg.base = new_offset + (unsigned long) gdt;
+ gdtarg.limit = GDT_LIMIT;
+ __asm__ __volatile__ (
+ "rep; movsb\n\t" /* copy everything */
+ "lgdt %3\n\t"
+ "ljmp %4, $1f\n1:\t"
+ "movw %5, %%ds\n\t"
+ "movw %5, %%es\n\t"
+ "movw %5, %%fs\n\t"
+ "movw %5, %%gs\n\t"
+ "movw %5, %%ss\n"
+ : "=&S" (d0), "=&D" (d1), "=&c" (d2)
+ : "m" (gdtarg), "n" (RELOC_CS), "q" ((unsigned short) RELOC_DS),
+ "0" (&_start), "1" (new_base), "2" (prog_size));
+
+ virt_offset = new_offset;
+ debug("ok\n");
+}
+
+#if 0
+/* Copy GDT to new location and reload it */
+void move_gdt(unsigned long newgdt)
+{
+ struct gdtarg gdtarg;
+
+ debug("Moving GDT to %#lx...", newgdt);
+ memcpy(phys_to_virt(newgdt), gdt, sizeof gdt);
+ gdtarg.base = newgdt;
+ gdtarg.limit = GDT_LIMIT;
+ debug("reloading GDT...");
+ __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
+ debug("reloading CS for fun...");
+ __asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS));
+ debug("ok\n");
+}
+#endif
diff --git a/roms/openbios/arch/x86/segment.h b/roms/openbios/arch/x86/segment.h
new file mode 100644
index 00000000..0371a80a
--- /dev/null
+++ b/roms/openbios/arch/x86/segment.h
@@ -0,0 +1,30 @@
+
+/* Segment indexes. Must match the gdt definition in segment.c. */
+enum {
+ NULL_SEG,
+ FLAT_CODE,
+ FLAT_DATA,
+ RELOC_CODE,
+ RELOC_DATA,
+ NUM_SEG,
+};
+
+/* Values for segment selector register */
+#define FLAT_CS (FLAT_CODE << 3)
+#define FLAT_DS (FLAT_DATA << 3)
+#define RELOC_CS (RELOC_CODE << 3)
+#define RELOC_DS (RELOC_DATA << 3)
+
+/* i386 segment descriptor */
+struct segment_desc {
+ unsigned short limit_0;
+ unsigned short base_0;
+ unsigned char base_16;
+ unsigned char types;
+ unsigned char flags;
+ unsigned char base_24;
+};
+
+extern struct segment_desc gdt[NUM_SEG];
+
+#define GDT_LIMIT ((NUM_SEG << 3) - 1)
diff --git a/roms/openbios/arch/x86/sys_info.c b/roms/openbios/arch/x86/sys_info.c
new file mode 100644
index 00000000..9361c9d6
--- /dev/null
+++ b/roms/openbios/arch/x86/sys_info.c
@@ -0,0 +1,57 @@
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/sys_info.h"
+#include "context.h"
+
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+void collect_multiboot_info(struct sys_info *);
+void collect_sys_info(struct sys_info *info);
+
+void collect_sys_info(struct sys_info *info)
+{
+ int i;
+ unsigned long long total = 0;
+ struct memrange *mmap;
+
+ /* Pick up paramters given by bootloader to us */
+ info->boot_type = boot_ctx->eax;
+ info->boot_data = boot_ctx->ebx;
+ info->boot_arg = boot_ctx->param[0];
+ debug("boot eax = %#lx\n", info->boot_type);
+ debug("boot ebx = %#lx\n", info->boot_data);
+ debug("boot arg = %#lx\n", info->boot_arg);
+
+ collect_elfboot_info(info);
+#ifdef CONFIG_LINUXBIOS
+ collect_linuxbios_info(info);
+#endif
+#ifdef CONFIG_IMAGE_ELF_MULTIBOOT
+ collect_multiboot_info(info);
+#endif
+
+ if (!info->memrange) {
+ printk("Can't get memory map from firmware. "
+ "Using hardcoded default.\n");
+ info->n_memranges = 2;
+ info->memrange = malloc(2 * sizeof(struct memrange));
+ info->memrange[0].base = 0;
+ info->memrange[0].size = 640*1024;
+ info->memrange[1].base = 1024*1024;
+ info->memrange[1].size = 32*1024*1024
+ - info->memrange[1].base;
+ }
+
+ debug("\n");
+ mmap=info->memrange;
+ for (i = 0; i < info->n_memranges; i++) {
+ debug("%016Lx-", mmap[i].base);
+ debug("%016Lx\n", mmap[i].base+mmap[i].size);
+ total += mmap[i].size;
+ }
+ debug("RAM %Ld MB\n", (total + 512*1024) >> 20);
+}
diff --git a/roms/openbios/arch/x86/xbox/console.c b/roms/openbios/arch/x86/xbox/console.c
new file mode 100644
index 00000000..e96e04f0
--- /dev/null
+++ b/roms/openbios/arch/x86/xbox/console.c
@@ -0,0 +1,23 @@
+/*
+ * Xbox framebuffer - Video + Console
+ *
+ * Copyright (C) 2005 Ed Schouten <ed@fxq.nl>,
+ * Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation
+ */
+
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+
+typedef struct osi_fb_info {
+ unsigned long mphys;
+ int rb, w, h, depth;
+} osi_fb_info_t;
+
+#include "../../../packages/video.c"
+#include "../../../libopenbios/console_common.c"
diff --git a/roms/openbios/arch/x86/xbox/methods.c b/roms/openbios/arch/x86/xbox/methods.c
new file mode 100644
index 00000000..741d15c0
--- /dev/null
+++ b/roms/openbios/arch/x86/xbox/methods.c
@@ -0,0 +1,102 @@
+/*
+ * Creation Date: <2004/08/28 18:38:22 greg>
+ * Time-stamp: <2004/08/28 18:38:22 greg>
+ *
+ * <methods.c>
+ *
+ * Misc device node methods
+ *
+ * Copyright (C) 2004 Greg Watson
+ *
+ * Based on MOL specific code which is
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+// #include "libopenbios/ofmem.h"
+
+/************************************************************************/
+/* stdout */
+/************************************************************************/
+
+DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" );
+
+/* ( addr len -- actual ) */
+static void
+stdout_write( void )
+{
+ int len = POP();
+ char *addr = (char*)POP();
+
+ printk( "%s", s );
+ //vfd_draw_str( s );
+ console_draw_fstr(addr, len);
+
+ PUSH( len );
+}
+
+NODE_METHODS( video_stdout ) = {
+ { "write", stdout_write },
+};
+
+
+/************************************************************************/
+/* tty */
+/************************************************************************/
+
+DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" );
+
+/* ( addr len -- actual ) */
+static void
+tty_read( void )
+{
+ int ch, len = POP();
+ char *p = (char*)POP();
+ int ret=0;
+
+ if( len > 0 ) {
+ ret = 1;
+ ch = getchar();
+ if( ch >= 0 ) {
+ *p = ch;
+ } else {
+ ret = 0;
+ }
+ }
+ PUSH( ret );
+}
+
+/* ( addr len -- actual ) */
+static void
+tty_write( void )
+{
+ int i, len = POP();
+ char *p = (char*)POP();
+ for( i=0; i<len; i++ )
+ putchar( *p++ );
+ RET( len );
+}
+
+NODE_METHODS( tty ) = {
+ { "read", tty_read },
+ { "write", tty_write },
+};
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+node_methods_init( void )
+{
+ REGISTER_NODE( video_stdout );
+ REGISTER_NODE( tty );
+}
diff --git a/roms/openbios/build.xml b/roms/openbios/build.xml
new file mode 100644
index 00000000..f776b9a4
--- /dev/null
+++ b/roms/openbios/build.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<xmlmake>
+ <project name="openbios">
+ <include href="kernel/build.xml"/>
+ <include href="forth/build.xml"/>
+ <include href="libc/build.xml"/>
+ <include href="libgcc/build.xml"/>
+ <include href="libopenbios/build.xml"/>
+ <include href="packages/build.xml"/>
+ <include href="drivers/build.xml"/>
+ <include href="fs/build.xml"/>
+ <include href="arch/build.xml"/>
+ </project>
+</xmlmake>
diff --git a/roms/openbios/config/examples/amd64_config.xml b/roms/openbios/config/examples/amd64_config.xml
new file mode 100644
index 00000000..e8904b78
--- /dev/null
+++ b/roms/openbios/config/examples/amd64_config.xml
@@ -0,0 +1,61 @@
+ <!-- kernel binaries (AMD64) -->
+ <option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/>
+
+ <!-- Kernel Debugging -->
+ <option name="CONFIG_DEBUG" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_BOOT" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
+ <option name="CONFIG_SERIAL_PORT" type="boolean" value="true"/>
+ <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>
+ <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/>
+
+
+ <!-- Module Configuration -->
+ <option name="CONFIG_CMDLINE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X8" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X16" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_AOUT" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_XCOFF" type="boolean" value="false"/>
+
+ <!-- Filesystem Configuration -->
+ <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/>
+ <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/>
+ <option name="CONFIG_PC_PARTS" type="boolean" value="true"/>
+ <option name="CONFIG_HFS" type="boolean" value="false"/>
+ <option name="CONFIG_HFSP" type="boolean" value="true"/>
+ <option name="CONFIG_GRUBFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_REISERFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_UFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_ISO9660" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_FFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_FS" type="boolean" value="true"/>
+
+ <!-- Miscellaneous -->
+ <option name="CONFIG_LINUXBIOS" type="boolean" value="true"/>
+
+ <!-- Drivers -->
+ <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/>
+ <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="4"/>
+ <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_VGA" type="boolean" value="false"/>
diff --git a/roms/openbios/config/examples/ppc64_config.xml b/roms/openbios/config/examples/ppc64_config.xml
new file mode 100644
index 00000000..5f79c21c
--- /dev/null
+++ b/roms/openbios/config/examples/ppc64_config.xml
@@ -0,0 +1,77 @@
+ <!-- Kernel Debugging -->
+ <option name="CONFIG_DEBUG" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
+ <option name="CONFIG_SERIAL_PORT" type="integer" value="0"/>
+ <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>
+ <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_OFMEM" type="boolean" value="false"/>
+
+
+ <!-- Module Configuration -->
+ <option name="CONFIG_CMDLINE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X8" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X16" type="boolean" value="false"/>
+ <option name="CONFIG_OFMEM" type="boolean" value="true"/>
+ <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="4"/>
+ <option name="CONFIG_VGA_WIDTH" type="integer" value="800"/>
+ <option name="CONFIG_VGA_HEIGHT" type="integer" value="600"/>
+ <option name="CONFIG_VGA_DEPTH" type="integer" value="8"/>
+ <option name="CONFIG_LOADER_AOUT" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_XCOFF" type="boolean" value="true"/>
+
+ <!-- Filesystem Configuration -->
+ <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/>
+ <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/>
+ <option name="CONFIG_MAC_PARTS" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_MAC_PARTS" type="boolean" value="false"/>
+ <option name="CONFIG_PC_PARTS" type="boolean" value="true"/>
+ <option name="CONFIG_HFS" type="boolean" value="true"/>
+ <option name="CONFIG_HFSP" type="boolean" value="true"/>
+ <option name="CONFIG_ISO9660" type="boolean" value="true"/>
+ <option name="CONFIG_EXT2" type="boolean" value="true"/>
+ <option name="CONFIG_GRUBFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_UFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_ISO9660" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_FFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/>
+
+ <!-- Miscellaneous -->
+ <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/>
+ <option name="CONFIG_RTAS" type="boolean" value="false"/>
+
+ <!-- Drivers -->
+ <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/>
+ <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="2"/>
+ <option name="CONFIG_IDE_FIRST_UNIT" type="integer" value="1"/>
+ <option name="CONFIG_IDE_DEV_NAME" type="string" value="ata-%d"/>
+ <option name="CONFIG_IDE_DEV_TYPE" type="string" value="ata"/>
+ <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_ADB" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_MACIO" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_ESCC" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_FW_CFG" type="boolean" value="true"/>
+ <option name="CONFIG_FW_CFG_ADDR" type="integer" value="0xf0000510"/>
diff --git a/roms/openbios/config/examples/ppc_config.xml b/roms/openbios/config/examples/ppc_config.xml
new file mode 100644
index 00000000..4c14eb6c
--- /dev/null
+++ b/roms/openbios/config/examples/ppc_config.xml
@@ -0,0 +1,85 @@
+ <!-- Kernel Debugging -->
+ <option name="CONFIG_DEBUG" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_PC_SERIAL" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_PC_KBD" type="boolean" value="true"/>
+ <option name="CONFIG_SERIAL_PORT" type="integer" value="0"/>
+ <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>
+ <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_OFMEM" type="boolean" value="false"/>
+
+
+ <!-- Module Configuration -->
+ <option name="CONFIG_CMDLINE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X8" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X16" type="boolean" value="false"/>
+ <option name="CONFIG_OFMEM" type="boolean" value="true"/>
+ <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="4"/>
+ <option name="CONFIG_VGA_WIDTH" type="integer" value="800"/>
+ <option name="CONFIG_VGA_HEIGHT" type="integer" value="600"/>
+ <option name="CONFIG_VGA_DEPTH" type="integer" value="8"/>
+ <option name="CONFIG_LOADER_AOUT" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_BOOTCODE" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_XCOFF" type="boolean" value="true"/>
+
+ <!-- Filesystem Configuration -->
+ <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/>
+ <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/>
+ <option name="CONFIG_MAC_PARTS" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_MAC_PARTS" type="boolean" value="false"/>
+ <option name="CONFIG_PC_PARTS" type="boolean" value="true"/>
+ <option name="CONFIG_HFS" type="boolean" value="true"/>
+ <option name="CONFIG_HFSP" type="boolean" value="true"/>
+ <option name="CONFIG_ISO9660" type="boolean" value="true"/>
+ <option name="CONFIG_EXT2" type="boolean" value="true"/>
+ <option name="CONFIG_GRUBFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_UFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_ISO9660" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_FFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/>
+
+ <!-- Miscellaneous -->
+ <option name="CONFIG_PPC_64BITSUPPORT" type="boolean" value="true"/>
+ <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/>
+ <option name="CONFIG_RTAS" type="boolean" value="false"/>
+ <option name="CONFIG_LOCALS" type="boolean" value="true"/>
+
+ <!-- Drivers -->
+ <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/>
+ <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="2"/>
+ <option name="CONFIG_IDE_FIRST_UNIT" type="integer" value="1"/>
+ <option name="CONFIG_IDE_DEV_NAME" type="string" value="ata-%d"/>
+ <option name="CONFIG_IDE_DEV_TYPE" type="string" value="ata"/>
+ <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_ADB" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_MACIO" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_ESCC" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_FW_CFG" type="boolean" value="true"/>
+ <option name="CONFIG_FW_CFG_ADDR" type="integer" value="0xf0000510"/>
+ <option name="CONFIG_DRIVER_USB" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_USB" type="boolean" value="false"/>
+ <option name="CONFIG_USB_HID" type="boolean" value="true"/>
diff --git a/roms/openbios/config/examples/sparc32_config.xml b/roms/openbios/config/examples/sparc32_config.xml
new file mode 100644
index 00000000..f2d6afc7
--- /dev/null
+++ b/roms/openbios/config/examples/sparc32_config.xml
@@ -0,0 +1,74 @@
+ <!-- kernel binaries (SPARC32) -->
+ <option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/>
+
+ <!-- Kernel Debugging -->
+ <option name="CONFIG_DEBUG" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_CONSOLE_VIDEO" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_ESP" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_SUN_PARTS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_OBP" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_IOMMU" type="boolean" value="false"/>
+ <option name="CONFIG_SERIAL_PORT" type="integer" value="0"/>
+ <option name="CONFIG_SERIAL_SPEED" type="integer" value="9600"/>
+ <option name="CONFIG_DEBUG_OFMEM" type="boolean" value="false"/>
+
+
+ <!-- Module Configuration -->
+ <option name="CONFIG_CMDLINE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X8" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X16" type="boolean" value="false"/>
+ <option name="CONFIG_OFMEM" type="boolean" value="true"/>
+ <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="8"/>
+ <option name="CONFIG_LOADER_AOUT" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_XCOFF" type="boolean" value="false"/>
+
+ <!-- Filesystem Configuration -->
+ <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/>
+ <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/>
+ <option name="CONFIG_PC_PARTS" type="boolean" value="false"/>
+ <option name="CONFIG_SUN_PARTS" type="boolean" value="true"/>
+ <option name="CONFIG_HFS" type="boolean" value="false"/>
+ <option name="CONFIG_HFSP" type="boolean" value="false"/>
+ <option name="CONFIG_GRUBFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_UFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_ISO9660" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_FFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_EXT2FS" type="boolean" value="false"/>
+
+ <!-- Miscellaneous -->
+ <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/>
+
+ <!-- Drivers -->
+ <option name="CONFIG_DRIVER_SBUS" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_SBUS" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_OBIO" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_ESP" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_FLOPPY" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_ESCC" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_ESCC_SUN" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_FW_CFG" type="boolean" value="true"/>
+ <option name="CONFIG_FW_CFG_ADDR" type="integer" value="0xd00000510ULL"/>
diff --git a/roms/openbios/config/examples/sparc64_config.xml b/roms/openbios/config/examples/sparc64_config.xml
new file mode 100644
index 00000000..a4e1336b
--- /dev/null
+++ b/roms/openbios/config/examples/sparc64_config.xml
@@ -0,0 +1,74 @@
+ <!-- kernel binaries (SPARC64) -->
+ <option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/>
+
+ <!-- Kernel Debugging -->
+ <option name="CONFIG_DEBUG" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_SUN_PARTS" type="boolean" value="false"/>
+ <option name="CONFIG_SERIAL_PORT" type="integer" value="0"/>
+ <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>
+ <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_OFMEM" type="boolean" value="false"/>
+
+
+ <!-- Module Configuration -->
+ <option name="CONFIG_CMDLINE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X8" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X16" type="boolean" value="false"/>
+ <option name="CONFIG_OFMEM" type="boolean" value="true"/>
+ <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="8"/>
+ <option name="CONFIG_LOADER_AOUT" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_FCODE" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_XCOFF" type="boolean" value="false"/>
+
+ <!-- Filesystem Configuration -->
+ <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/>
+ <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/>
+ <option name="CONFIG_PC_PARTS" type="boolean" value="false"/>
+ <option name="CONFIG_SUN_PARTS" type="boolean" value="true"/>
+ <option name="CONFIG_HFS" type="boolean" value="false"/>
+ <option name="CONFIG_HFSP" type="boolean" value="false"/>
+ <option name="CONFIG_GRUBFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_UFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_ISO9660" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_FFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_EXT2FS" type="boolean" value="false"/>
+
+ <!-- Miscellaneous -->
+ <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/>
+
+ <!-- Drivers -->
+ <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/>
+ <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="2"/>
+ <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_FLOPPY" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_EBUS" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_PC_KBD" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_PC_SERIAL" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_FW_CFG" type="boolean" value="true"/>
+ <option name="CONFIG_FW_CFG_ADDR" type="integer" value="0x510"/>
diff --git a/roms/openbios/config/examples/x86_config.xml b/roms/openbios/config/examples/x86_config.xml
new file mode 100644
index 00000000..390eaba5
--- /dev/null
+++ b/roms/openbios/config/examples/x86_config.xml
@@ -0,0 +1,63 @@
+ <!-- kernel binaries (AMD64) -->
+ <option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/>
+
+ <!-- Kernel Debugging -->
+ <option name="CONFIG_DEBUG" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_BOOT" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
+ <option name="CONFIG_SERIAL_PORT" type="boolean" value="true"/>
+ <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>
+ <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/>
+
+
+ <!-- Module Configuration -->
+ <option name="CONFIG_CMDLINE" type="boolean" value="true"/>
+ <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X8" type="boolean" value="true"/>
+ <option name="CONFIG_FONT_8X16" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_AOUT" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/>
+ <option name="CONFIG_LOADER_FORTH" type="boolean" value="true"/>
+ <option name="CONFIG_LOADER_XCOFF" type="boolean" value="false"/>
+
+ <!-- Filesystem Configuration -->
+ <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/>
+ <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/>
+ <option name="CONFIG_PC_PARTS" type="boolean" value="true"/>
+ <option name="CONFIG_HFS" type="boolean" value="false"/>
+ <option name="CONFIG_HFSP" type="boolean" value="false"/>
+ <option name="CONFIG_GRUBFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_REISERFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_UFS" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_ISO9660" type="boolean" value="true"/>
+ <option name="CONFIG_FSYS_FFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/>
+ <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/>
+
+ <!-- Miscellaneous -->
+ <option name="CONFIG_LINUXBIOS" type="boolean" value="true"/>
+
+ <!-- Drivers -->
+ <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/>
+ <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/>
+ <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="4"/>
+ <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/>
+ <option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/>
+ <option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="false"/>
+ <option name="CONFIG_DEBUG_FLOPPY" type="boolean" value="false"/>
diff --git a/roms/openbios/config/scripts/reldir b/roms/openbios/config/scripts/reldir
new file mode 100755
index 00000000..50f384ec
--- /dev/null
+++ b/roms/openbios/config/scripts/reldir
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+PREF="."
+for x in 0 1 2 3 4 5 6 7 ; do
+ test -f $PREF/config/configure.in && break
+ PREF="../$PREF"
+done
+ROOT=$( echo $(pwd) | sed "s,\(//*[^/][^/]*\)\{$x\}/*\$,," )
+RELNAME=$( echo $(pwd) | sed "s,^$ROOT/*,,g" )
+echo $RELNAME
diff --git a/roms/openbios/config/scripts/switch-arch b/roms/openbios/config/scripts/switch-arch
new file mode 100755
index 00000000..d5e2f771
--- /dev/null
+++ b/roms/openbios/config/scripts/switch-arch
@@ -0,0 +1,427 @@
+#!/bin/sh
+
+#
+# MOLPATH is needed if you want to build openbios-mol.elf
+#
+MOLPATH=$HOME/mol-0.9.71
+
+if [ x"$1" = x -o "$1" = "-help" ]; then
+ printf "Usage:\n $0 [arch-config]...\n"
+ printf "arch-config values supported for native or cross compiled builds:\n"
+ printf " amd64, ppc, sparc32, sparc64, x86\n\n"
+ printf "Add \"unix-\" prefix to compile openbios-unix executable (native only)\n"
+ printf "Add \"builtin-\" prefix to compile openbios-builtin executables\n\n"
+ printf "Without prefixes, builtin and unix targets are selected\n\n"
+ printf "Special targets: mol-ppc briq-ppc pearpc-ppc qemu-ppc qemu-ppc64 xbox-x86\n\n"
+ printf "Example: $0 builtin-sparc32 unix-amd64 builtin-amd64\n"
+ exit 0
+fi
+
+crosscflags()
+{
+ host=$1
+ target=$2
+
+ if test "$host" = "powerpc" -o "$host" = "ppc" \
+ -o "$host" = "mips" -o "$host" = "s390" \
+ -o "$host" = "sparc32" -o "$host" = "sparc64" \
+ -o "$host" = "m68k" -o "$host" = "armv4b"; then
+ hostbigendian="yes"
+ else
+ hostbigendian="no"
+ fi
+
+# host long bits test
+ if test "$host" = "sparc64" -o "$host" = "ia64" \
+ -o "$host" = "amd64" -o "$host" = "x86_64" \
+ -o "$host" = "alpha"; then
+ hostlongbits="64"
+ else
+ hostlongbits="32"
+ fi
+
+ if test "$target" = "powerpc" -o "$target" = "ppc" \
+ -o "$target" = "powerpc64" -o "$target" = "ppc64" \
+ -o "$target" = "mips" -o "$target" = "s390" \
+ -o "$target" = "sparc32" -o "$target" = "sparc64" \
+ -o "$target" = "m68k" -o "$target" = "armv4b"; then
+ targetbigendian="yes"
+ else
+ targetbigendian="no"
+ fi
+
+# target long bits test
+ if test "$target" = "sparc64" -o "$target" = "ia64" \
+ -o "$target" = "amd64" -o "$target" = "x86_64" \
+ -o "$target" = "powerpc64" -o "$target" = "ppc64" \
+ -o "$target" = "alpha"; then
+ targetlongbits="64"
+ else
+ targetlongbits="32"
+ fi
+
+ if test "$targetbigendian" = "$hostbigendian"; then
+ cflags="-USWAP_ENDIANNESS"
+ else
+ cflags="-DSWAP_ENDIANNESS"
+ fi
+
+ if test "$targetlongbits" = "$hostlongbits"; then
+ cflags="$cflags -DNATIVE_BITWIDTH_EQUALS_HOST_BITWIDTH"
+ elif test "$targetlongbits" -lt "$hostlongbits"; then
+ cflags="$cflags -DNATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH"
+ else
+ cflags="$cflags -DNATIVE_BITWIDTH_LARGER_THAN_HOST_BITWIDTH"
+ fi
+
+ if test "$target" = "sparc64" -o "$target" = "ia64" \
+ -o "$target" = "amd64" -o "$target" = "x86_64" \
+ -o "$target" = "alpha"; then
+ if test "$host" = "x86"; then
+ cflags="$cflags -DNEED_FAKE_INT128_T"
+ elif test "$host" = "arm"; then
+ cflags="$cflags -DNEED_FAKE_INT128_T"
+ elif test "$host" = "ppc" -a `uname -s` = "Darwin"; then
+ cflags="$cflags -DNEED_FAKE_INT128_T"
+ fi
+ fi
+
+ CROSSCFLAGS=$cflags
+}
+
+archname()
+{
+ HOSTARCH=`uname -m | sed -e s/i.86/x86/ -e s/i86pc/x86/ \
+ -e s/sun4u/sparc64/ -e s/sparc$/sparc32/ \
+ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/x86_64/amd64/ \
+ -e "s/Power Macintosh/ppc/"`
+}
+
+select_prefix()
+{
+ TARGETS="${1}-unknown-linux-gnu- ${1}-linux-gnu- ${1}-linux- ${1}-elf- ${1}-eabi-"
+
+ if [ x"$CROSS_COMPILE" != "x" ]; then
+ TARGETS=$CROSS_COMPILE
+ fi
+
+ for TARGET in $TARGETS
+ do
+ if type ${TARGET}gcc > /dev/null 2>&1
+ then
+ return
+ fi
+ done
+ if [ "$ARCH" = "$HOSTARCH" ]; then
+ return
+ fi
+ echo "ERROR: no ${1} cross-compiler found !" 1>&2
+ exit 1
+}
+
+config_set_boolean()
+{
+ option=`echo $1 | tr a-z A-Z`
+ echo "<option name=\"$option\" type=\"boolean\" value=\"true\" />"
+}
+
+exists()
+{
+ type "$1" >/dev/null 2>&1
+}
+
+
+SRCDIR=`dirname "$0"`/../..
+BUILDDIR=`pwd`
+
+# make source path absolute
+SRCDIR=`cd "$SRCDIR"; pwd`
+
+if test "x$HOSTARCH" = "x"; then
+ archname
+fi
+
+VERSION=`head $SRCDIR/VERSION`
+
+echo "Configuring OpenBIOS on $HOSTARCH for $*"
+
+if exists toke; then
+ :
+else
+ echo "Unable to locate toke executable from the fcode-utils package - aborting"
+ exit 1
+fi
+
+target_list=""
+for target in $*; do
+ case $target in
+ unix-*|builtin-*|plain-*|mol-ppc|briq-ppc|pearpc-ppc|qemu-ppc|qemu-ppc64|xbox-x86)
+ target_list="$target_list $target"
+ ;;
+ cross-*)
+ echo "\"cross-\" prefix is no longer needed"
+ target=`echo $target | sed s/cross-//g`
+ target_list="$target_list builtin-$target"
+ ;;
+ *)
+ #default: build builtin and if possible, unix target
+ target_list="$target_list builtin-$target unix-$target"
+ ;;
+ esac
+done
+
+arch_list=""
+for target in $target_list; do
+ arch=`echo $target | sed s/.*-//g`
+ if ! test -f $SRCDIR/config/examples/${arch}_config.xml; then
+ echo "Cannot find $SRCDIR/config/examples/${arch}_config.xml" >&2
+ exit 1
+ fi
+ if ! echo $arch_list | grep -q "$arch"; then
+ arch_list="$arch_list $arch"
+ fi
+done
+
+for ARCH in $arch_list; do
+ unix="no"
+ builtin="no"
+ plain="no"
+ mol="no"
+ briq="no"
+ pearpc="no"
+ qemu="no"
+ xbox="no"
+ cross="no"
+
+ for target in $target_list; do
+ case $target in
+ *-$ARCH)
+ :
+ ;;
+ *)
+ continue
+ ;;
+ esac
+ case $target in
+ mol-ppc)
+ mol="yes"
+ ;;
+ briq-ppc)
+ briq="yes"
+ ;;
+ pearpc-ppc)
+ pearpc="yes"
+ ;;
+ builtin-ppc|qemu-ppc|builtin-ppc64|qemu-ppc64)
+ qemu="yes"
+ ;;
+ xbox-x86)
+ xbox="yes"
+ ;;
+ builtin-sparc32)
+ builtin="yes"
+ qemu="yes"
+ ;;
+ builtin-sparc64)
+ builtin="yes"
+ qemu="yes"
+ ;;
+ unix-*)
+ if [ "$ARCH" != "$HOSTARCH" ]; then
+ # Can't cross compile Unix target
+ continue
+ fi
+ unix="yes"
+ ;;
+ builtin-*)
+ builtin="yes"
+ ;;
+ plain-*)
+ plain="yes"
+ ;;
+ esac
+ done
+
+ BASEARCH=$ARCH
+ case $ARCH in
+ amd64)
+ select_prefix x86_64
+ CFLAGS="-fno-builtin"
+ AS_FLAGS=
+ ;;
+
+ ppc)
+ select_prefix powerpc
+ if [ "$unix" = "no" ]; then
+ CFLAGS="-m32 -msoft-float -fno-builtin-bcopy -fno-builtin-log2"
+ AS_FLAGS="-m32"
+ else
+ CFLAGS="-fno-builtin"
+ AS_FLAGS=
+ fi
+ ;;
+
+ ppc64)
+ select_prefix powerpc64
+ CFLAGS="-Wa,-a64 -m64 -msoft-float -fno-builtin"
+ AS_FLAGS="-Wa,-a64"
+ BASEARCH=ppc
+ ;;
+
+ sparc32)
+ select_prefix sparc
+ CFLAGS="-Wa,-xarch=v8 -Wa,-32 -m32 -mcpu=supersparc -fno-builtin"
+ AS_FLAGS="-Wa,-xarch=v8 -Wa,-32"
+ ;;
+
+ sparc64)
+ select_prefix sparc64
+ CFLAGS="-Wa,-xarch=v9b -Wa,-64 -m64 -mcpu=ultrasparc -mcmodel=medany -fno-builtin"
+ AS_FLAGS="-Wa,-xarch=v9b -Wa,-64"
+ ;;
+
+ x86)
+ select_prefix i486
+ CFLAGS="-fno-builtin -m32"
+ AS_FLAGS="-Wa,-32"
+ ;;
+ esac
+ if [ "$ARCH" != "$HOSTARCH" -o `uname -s` = "Darwin" ]; then
+ cross="yes"
+ fi
+ crosscflags $HOSTARCH $ARCH
+ OBJDIR=$BUILDDIR/obj-$ARCH
+ ODIRS="$ODIRS $OBJDIR"
+
+ printf "Initializing build tree $OBJDIR..."
+ rm -rf "$OBJDIR"
+ mkdir "$OBJDIR"
+ mkdir -p $OBJDIR/target
+ mkdir -p $OBJDIR/target/include
+ mkdir -p $OBJDIR/target/arch
+ mkdir -p $OBJDIR/target/arch/unix
+ mkdir -p $OBJDIR/target/arch/$ARCH
+ mkdir -p $OBJDIR/target/libgcc
+ mkdir -p $OBJDIR/target/kernel
+ mkdir -p $OBJDIR/target/libopenbios
+ mkdir -p $OBJDIR/target/packages
+ mkdir -p $OBJDIR/target/fs
+ mkdir -p $OBJDIR/target/fs/grubfs
+ mkdir -p $OBJDIR/target/fs/hfs
+ mkdir -p $OBJDIR/target/fs/hfsplus
+ mkdir -p $OBJDIR/target/fs/iso9660
+ mkdir -p $OBJDIR/target/fs/ext2
+ mkdir -p $OBJDIR/target/drivers
+ mkdir -p $OBJDIR/target/libc
+ mkdir -p $OBJDIR/host/include
+ mkdir -p $OBJDIR/host/kernel
+ mkdir -p $OBJDIR/forth
+ ln -s $SRCDIR/include/arch/$BASEARCH $OBJDIR/target/include/asm
+ #compile the host binary with target settings instead
+ #ln -s $SRCDIR/include/arch/$HOSTARCH $OBJDIR/host/include/asm
+ if [ "$mol" = "yes" ]; then
+ printf "\nUsing MOL path $MOLPATH...\n"
+ mkdir -p $OBJDIR/target/arch/ppc/mol
+ ln -s $MOLPATH/src/shared/osi_calls.h $OBJDIR/target/include/
+ ln -s $MOLPATH/src/shared/osi.h $OBJDIR/target/include/
+ ln -s $MOLPATH/src/shared/prom.h $OBJDIR/target/include/
+ ln -s $MOLPATH/src/include/boothelper_sh.h $OBJDIR/target/include/
+ ln -s $MOLPATH/src/include/video_sh.h $OBJDIR/target/include/
+ ln -s $MOLPATH/src/include/pseudofs_sh.h $OBJDIR/target/include/
+ ln -s $MOLPATH/src/include/kbd_sh.h $OBJDIR/target/include/
+ ln -s $MOLPATH/src/drivers/disk/include/scsi_sh.h $OBJDIR/target/include/
+ ln -s $MOLPATH/src/drivers/disk/include/ablk_sh.h $OBJDIR/target/include/
+ fi
+ if [ "$briq" = "yes" ]; then
+ mkdir -p $OBJDIR/target/arch/ppc/briq
+ fi
+ if [ "$pearpc" = "yes" ]; then
+ mkdir -p $OBJDIR/target/arch/ppc/pearpc
+ fi
+ if [ "$qemu" = "yes" ]; then
+ mkdir -p $OBJDIR/target/arch/ppc/qemu
+ fi
+ if [ "$xbox" = "yes" ]; then
+ mkdir -p $OBJDIR/target/arch/x86/xbox
+ fi
+ echo "ok."
+
+ ODIR=$OBJDIR
+
+ printf "Creating target config.mak..."
+ echo "ARCH=$ARCH" > $ODIR/config.mak
+ if [ "$cross" = "yes" ]; then
+ echo "TARGET=$TARGET" >> $ODIR/config.mak
+ fi
+ echo "CFLAGS=$CFLAGS" >> $ODIR/config.mak
+ echo "AS_FLAGS=$AS_FLAGS" >> $ODIR/config.mak
+ echo "HOSTARCH?=$HOSTARCH" >> $ODIR/config.mak
+ echo "CROSSCFLAGS=$CROSSCFLAGS" >> $ODIR/config.mak
+ echo "VERSION=\"$VERSION\"" >> $ODIR/config.mak
+ echo "SRCDIR=$SRCDIR" >> $ODIR/config.mak
+ echo "ok."
+
+ printf "Creating target rules.mak..."
+ ln -s $SRCDIR/config/xml/rules.xml $ODIR/rules.xml
+ echo "<?xml version=\"1.0\"?><config>" > $ODIR/config.xml
+ # Generic
+ config_set_boolean CONFIG_$ARCH >> $ODIR/config.xml
+ if [ "$BASEARCH" != "$ARCH" ]; then
+ config_set_boolean CONFIG_$BASEARCH >> $ODIR/config.xml
+ fi
+ if [ "$mol" = "yes" ]; then
+ config_set_boolean CONFIG_MOL >> $ODIR/config.xml
+ fi
+ if [ "$briq" = "yes" ]; then
+ config_set_boolean CONFIG_BRIQ >> $ODIR/config.xml
+ fi
+ if [ "$pearpc" = "yes" ]; then
+ config_set_boolean CONFIG_PEARPC >> $ODIR/config.xml
+ fi
+ if [ "$qemu" = "yes" ]; then
+ config_set_boolean CONFIG_QEMU >> $ODIR/config.xml
+ fi
+ if [ "$xbox" = "yes" ]; then
+ config_set_boolean CONFIG_XBOX >> $ODIR/config.xml
+ fi
+ if [ "$targetbigendian" = "yes" ]; then
+ config_set_boolean CONFIG_BIG_ENDIAN >> $ODIR/config.xml
+ else
+ config_set_boolean CONFIG_LITTLE_ENDIAN >> $ODIR/config.xml
+ fi
+ # Kernel binaries
+ if [ "$plain" = "yes" ]; then
+ config_set_boolean CONFIG_IMAGE_ELF >> $ODIR/config.xml
+ fi
+ if [ "$builtin" = "yes" ]; then
+ config_set_boolean CONFIG_IMAGE_ELF_EMBEDDED >> $ODIR/config.xml
+ fi
+ # Build hosted Unix binary?
+ if [ "$unix" = "yes" ]; then
+ config_set_boolean CONFIG_HOST_UNIX >> $ODIR/config.xml
+ #config_set_boolean CONFIG_UNIX_QT >> $ODIR/config.xml
+ #config_set_boolean CONFIG_PLUGINS >> $ODIR/config.xml
+ fi
+ cat $SRCDIR/config/examples/${ARCH}_config.xml >> $ODIR/config.xml
+
+ cd $ODIR
+ echo "</config>" >> $ODIR/config.xml
+ ln -s $SRCDIR/Makefile.target $ODIR/Makefile
+ xsltproc $SRCDIR/config/xml/xinclude.xsl $SRCDIR/build.xml > $ODIR/build-full.xml
+ xsltproc $SRCDIR/config/xml/makefile.xsl $ODIR/build-full.xml > $ODIR/rules.mak
+ echo "ok."
+ printf "Creating config files..."
+ xsltproc $SRCDIR/config/xml/config-c.xsl $ODIR/config.xml > $ODIR/host/include/autoconf.h
+ xsltproc $SRCDIR/config/xml/config-c.xsl $ODIR/config.xml > $ODIR/target/include/autoconf.h
+ xsltproc $SRCDIR/config/xml/config-forth.xsl $ODIR/config.xml > $ODIR/forth/config.fs
+ echo "ok."
+
+ cd $BUILDDIR
+done
+
+if [ "$SRCDIR" != "$BUILDDIR" ]; then
+ ln -s $SRCDIR/Makefile $BUILDDIR
+fi
+
+echo "ODIRS=$ODIRS" >> $BUILDDIR/config-host.mak
+echo "TARGETS=$arch_list" >> $BUILDDIR/config-host.mak
diff --git a/roms/openbios/config/xml/config-c.xsl b/roms/openbios/config/xml/config-c.xsl
new file mode 100644
index 00000000..62ed8544
--- /dev/null
+++ b/roms/openbios/config/xml/config-c.xsl
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="ISO-8859-15" ?>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template match="/">
+ <!-- add comment -->
+ <xsl:text>/*&#10; * Automatically generated C config: don't edit&#10; */&#10;&#10;</xsl:text>
+
+ <!-- scan all config options -->
+ <xsl:for-each select="config/option">
+ <xsl:choose>
+
+ <!-- config option "boolean" -->
+ <xsl:when test="@type='boolean'">
+ <xsl:choose>
+ <xsl:when test="@value='true'">
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text> 1</xsl:text>
+ </xsl:when>
+ <xsl:when test="@value='false'">
+ <xsl:text>#undef </xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">&#10;ERROR: boolean configuration option '<xsl:value-of select="@name"/>' has unsupported value '<xsl:value-of select="@type"/>' instead of [true|false].</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+
+ <!-- config option "integer" -->
+ <xsl:when test="@type='integer'">
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="@name"/><xsl:text> </xsl:text>
+ <xsl:value-of select="@value"/>
+ </xsl:when>
+
+ <!-- config option "string" -->
+ <xsl:when test="@type='string'">
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="@name"/><xsl:text> </xsl:text> "<xsl:value-of select="@value"/>" </xsl:when>
+
+ <!-- unsupported config option: bail out -->
+ <xsl:otherwise>
+ <xsl:message terminate="yes">&#10;ERROR: configuration option '<xsl:value-of select="@name"/> has unsupported type '<xsl:value-of select="@type"/>'.</xsl:message>
+ </xsl:otherwise>
+
+ </xsl:choose>
+
+ <xsl:text>&#10;</xsl:text>
+ </xsl:for-each>
+
+ </xsl:template>
+
+ <xsl:output method="text" indent="no" encoding="iso-8859-15"/>
+
+</xsl:stylesheet>
diff --git a/roms/openbios/config/xml/config-forth.xsl b/roms/openbios/config/xml/config-forth.xsl
new file mode 100644
index 00000000..cace0deb
--- /dev/null
+++ b/roms/openbios/config/xml/config-forth.xsl
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-15" ?>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template match="/">
+ <xsl:for-each select="config/option">
+ <xsl:choose>
+ <xsl:when test="@type='boolean'">
+ <xsl:choose>
+ <xsl:when test="@value='true'">
+ <xsl:text>[DEFINE] </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@value='false'">
+ <!-- nothing to do -->
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">&#10;ERROR: boolean configuration option '<xsl:value-of select="@name"/>' has unsupported value '<xsl:value-of select="@type"/>' instead of [true|false].</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@type='integer'">
+ <!-- this makes absolutely no sense but the old code did it as well -->
+ <xsl:text>[DEFINE] </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ <!-- config option "string" -->
+ <xsl:when test="@type='string'">
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">&#10;ERROR: configuration option '<xsl:value-of select="@name"/>' has unsupported type '<xsl:value-of select="@type"/>'.</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:output method="text" indent="no" encoding="iso-8859-15"/>
+
+</xsl:stylesheet>
diff --git a/roms/openbios/config/xml/dictionary.xsl b/roms/openbios/config/xml/dictionary.xsl
new file mode 100644
index 00000000..61f62d84
--- /dev/null
+++ b/roms/openbios/config/xml/dictionary.xsl
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="ISO-8859-15" ?>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template match="/" mode="dictionaries">
+
+ <xsl:text>&#10;#&#10;# dictionary rules&#10;#&#10;&#10;</xsl:text>
+
+ <!-- Set all dictionary source lists empty -->
+ <xsl:for-each select="//dictionary">
+ <xsl:sort select="@name"/>
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions = 0">
+
+ <xsl:if test="not(preceding::dictionary/@name = @name)">
+ <xsl:value-of select="@name"/>
+ <xsl:text>-DICTIONARY :=&#10;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+
+ <!-- Add all forth source files to their dictionaries -->
+ <xsl:for-each select="//dictionary/object">
+
+ <xsl:variable name="path">
+ <xsl:for-each select="ancestor::build">
+ <xsl:call-template name="get-dirname">
+ <xsl:with-param select="@base" name="path"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="dictname">
+ <xsl:value-of select="parent::*/@name"/>
+ </xsl:variable>
+
+ <xsl:if test="$conditions=0">
+
+ <xsl:variable name="source"><xsl:value-of select="@source" /></xsl:variable>
+
+ <!-- Handle just Forth source, not FCode -->
+ <xsl:if test="not(@target = 'fcode')">
+ <xsl:value-of select="$dictname"/><xsl:text>-DICTIONARY:=$(</xsl:text>
+ <xsl:value-of select="$dictname"/><xsl:text>-DICTIONARY) </xsl:text>
+
+ <xsl:value-of select="$path"/>
+ <xsl:value-of select="$source"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:text>&#10;&#10;</xsl:text>
+
+ <!-- Create targets for all dictionaries -->
+ <xsl:for-each select="//dictionary">
+ <xsl:sort select="@name"/>
+
+ <xsl:variable name="outer-conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$outer-conditions = 0">
+
+ <xsl:if test="not(preceding::dictionary/@name = @name)">
+ <xsl:variable name="name"><xsl:value-of select="@name"/></xsl:variable>
+ <xsl:variable name="init">
+ <xsl:value-of select="(//dictionary[@name=$name]/attribute::init)[last()]"/>
+ </xsl:variable>
+ <!-- dictionary name and dependencies -->
+ <xsl:text>$(ODIR)/</xsl:text>
+ <xsl:value-of select="@name"/><xsl:text>.dict: $(</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>-DICTIONARY) $(ODIR)/forthstrap</xsl:text>
+ <xsl:if test="$init!=''">
+ <xsl:text> $(ODIR)/</xsl:text><xsl:value-of select="$init"/><xsl:text>.dict</xsl:text>
+ </xsl:if>
+
+ <!-- Check for Fcode dependency -->
+ <xsl:for-each select="object[@target = 'fcode']">
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions = 0">
+
+ <xsl:text> $(ODIR)/</xsl:text>
+ <xsl:value-of select="@source"/>
+
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:text>&#10;</xsl:text>
+ <!-- rule -->
+ <xsl:text>&#9;$(call quiet-command,$(ODIR)/forthstrap</xsl:text>
+ <xsl:for-each select="//dictionary[@name = @name]">
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="path">
+ <xsl:for-each select="ancestor::build">
+ <xsl:call-template name="get-dirname">
+ <xsl:with-param select="@base" name="path"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions = 0">
+ <xsl:text> -I</xsl:text>
+ <xsl:text>$(SRCDIR)/</xsl:text>
+ <xsl:value-of select="$path"/>
+ </xsl:if>
+ </xsl:for-each>
+
+ <!-- needed to locate files with full path -->
+ <xsl:text> -I$(SRCDIR)</xsl:text>
+ <!-- needed to include config and build date -->
+ <xsl:text> -I$(ODIR)/forth</xsl:text>
+
+ <xsl:text> -D $@</xsl:text>
+ <xsl:text> -M $@.d</xsl:text>
+ <xsl:if test="$init!=''">
+ <xsl:text> -d $(ODIR)/</xsl:text><xsl:value-of select="$init"/><xsl:text>.dict</xsl:text>
+ </xsl:if>
+ <xsl:text> -c $@-console.log</xsl:text>
+ <xsl:text> $(</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>-DICTIONARY)," GEN $(TARGET_DIR)$@")&#10;&#10;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+
+ <!-- Create dictionaries target containing all dictionaries -->
+ <xsl:text>dictionaries: </xsl:text>
+ <xsl:for-each select="//dictionary">
+ <xsl:sort select="@name"/>
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions = 0">
+
+ <xsl:if test="not(preceding::dictionary/@name = @name)">
+ <xsl:text>$(ODIR)/</xsl:text>
+ <xsl:value-of select="@name"/><xsl:text>.dict </xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/roms/openbios/config/xml/fcode.xsl b/roms/openbios/config/xml/fcode.xsl
new file mode 100644
index 00000000..ccc7e6e8
--- /dev/null
+++ b/roms/openbios/config/xml/fcode.xsl
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="ISO-8859-15" ?>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template match="/" mode="fcode">
+
+ <xsl:text>&#10;#&#10;# fcode rules&#10;#&#10;&#10;</xsl:text>
+
+ <!-- Create linker targets for FCode roms -->
+ <xsl:for-each select="//fcode">
+ <xsl:variable name="outer-conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$outer-conditions = 0">
+ <xsl:if test="(ancestor-or-self::*)">
+
+ <xsl:variable name="path">
+ <xsl:for-each select="ancestor::build">
+ <xsl:call-template name="get-dirname">
+ <xsl:with-param select="@base" name="path"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <!-- Fcode name -->
+ <xsl:text>$(ODIR)/</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>:</xsl:text>
+
+ <xsl:text> $(SRCDIR)/</xsl:text>
+ <xsl:value-of select="$path"/>
+ <xsl:value-of select="@source"/>
+
+ <!-- FIXME this requires strict spaces in rules.xml -->
+ <xsl:value-of select="document('rules.xml',.)//rule[@target='host'][@entity='fcode']"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/roms/openbios/config/xml/makefile.xsl b/roms/openbios/config/xml/makefile.xsl
new file mode 100644
index 00000000..56c494cc
--- /dev/null
+++ b/roms/openbios/config/xml/makefile.xsl
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="ISO-8859-15" ?>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:include href="util.xsl"/>
+ <xsl:include href="dictionary.xsl"/>
+ <xsl:include href="object.xsl"/>
+ <xsl:include href="fcode.xsl"/>
+
+ <xsl:template match="/">
+ <xsl:value-of select="document('rules.xml',.)/rules/pre"/>
+ <xsl:apply-templates select="." mode="dictionaries"/>
+ <xsl:apply-templates select="." mode="fcode"/>
+ <xsl:apply-templates select="." mode="objects"/>
+ </xsl:template>
+
+ <xsl:output method="text" indent="no" encoding="iso-8859-15"/>
+
+</xsl:stylesheet>
+
diff --git a/roms/openbios/config/xml/object.xsl b/roms/openbios/config/xml/object.xsl
new file mode 100644
index 00000000..cf521f59
--- /dev/null
+++ b/roms/openbios/config/xml/object.xsl
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="ISO-8859-15" ?>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <!-- wrapper that calls "objects" with parameters -->
+ <xsl:template match="/" mode="objects">
+ <xsl:call-template name="objects">
+ <xsl:with-param name="target" select="'host'"/>
+ </xsl:call-template>
+ <xsl:call-template name="objects">
+ <xsl:with-param name="target" select="'target'"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- main work happens here -->
+ <xsl:template name="objects">
+
+ <xsl:param name="target"/>
+
+ <xsl:text>&#10;#&#10;# </xsl:text>
+ <xsl:value-of select="$target"/>
+ <xsl:text> compiler rules&#10;#&#10;&#10;</xsl:text>
+
+ <!-- create rules for all compile objects -->
+ <xsl:for-each select="//object[(ancestor-or-self::*)[@target = $target]]">
+
+ <xsl:variable name="path">
+ <xsl:for-each select="ancestor::build">
+ <xsl:call-template name="get-dirname">
+ <xsl:with-param select="@base" name="path"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions=0">
+
+ <!-- full path of object file -->
+ <xsl:text>$(ODIR)/</xsl:text>
+ <xsl:value-of select="$target"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="$path"/>
+ <xsl:value-of select="substring-before(@source,'.')"/>
+ <xsl:text>.o: </xsl:text>
+
+ <!-- path of source file -->
+ <xsl:value-of select="$path"/>
+ <xsl:value-of select="@source"/>
+
+
+ <xsl:choose>
+ <xsl:when test="child::rule">
+ <xsl:value-of select="child::rule"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@flags!=''">
+ <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='object'][@extracflags='1']"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@flags"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='object'][@extracflags='2']"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- FIXME this requires strict spaces in rules.xml -->
+ <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='object']"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:if>
+ </xsl:for-each>
+
+ <!-- Create linker targets for all executables -->
+ <xsl:for-each select="//executable">
+
+ <xsl:variable name="outer-conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$outer-conditions = 0">
+ <xsl:if test="(ancestor-or-self::*)[@target = $target]">
+
+ <!-- executable name -->
+ <xsl:text>$(ODIR)/</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>:</xsl:text>
+
+ <!-- add all objects -->
+ <xsl:for-each select="object">
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions=0">
+
+ <xsl:variable name="path">
+ <xsl:for-each select="ancestor::build">
+ <xsl:call-template name="get-dirname">
+ <xsl:with-param select="@base" name="path"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:text> $(ODIR)/</xsl:text>
+ <xsl:value-of select="$target"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="$path"/>
+ <xsl:value-of select="substring-before(@source,'.')"/>
+ <xsl:text>.o</xsl:text>
+
+ </xsl:if>
+ </xsl:for-each>
+
+ <!-- external objects last -->
+ <xsl:for-each select="external-object">
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions=0">
+ <xsl:text> $(ODIR)/</xsl:text>
+ <xsl:value-of select="@source"/>
+ </xsl:if>
+
+ </xsl:for-each>
+
+ <!-- print executable rule -->
+ <xsl:choose>
+ <xsl:when test="child::rule">
+ <xsl:value-of select="child::rule"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- FIXME this requires strict spaces in rules.xml -->
+ <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='executable']"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+
+ <!-- create linker targets for all libs -->
+ <xsl:for-each select="//library">
+ <xsl:sort select="@name"/>
+
+ <xsl:variable name="outer-conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$outer-conditions = 0">
+
+
+ <xsl:if test="(ancestor-or-self::*)[@target = $target]">
+
+ <xsl:if test="not(preceding::library/@name = @name)">
+
+ <!-- output library name -->
+ <xsl:text>$(ODIR)/lib</xsl:text>
+ <xsl:value-of select="@name"/>
+
+ <xsl:choose>
+ <xsl:when test="@type='static'">
+ <xsl:text>.a</xsl:text>
+ </xsl:when>
+ <xsl:when test="@type='dynamic'">
+ <xsl:text>.so</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:text>: </xsl:text>
+
+ <xsl:variable name="name"><xsl:value-of select="@name"/></xsl:variable>
+
+ <!-- enumerate all objects for library target -->
+ <xsl:for-each select="//library[@name=$name]/object">
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions=0">
+
+ <xsl:variable name="path">
+ <xsl:for-each select="ancestor::build">
+ <xsl:call-template name="get-dirname">
+ <xsl:with-param select="@base" name="path"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:text>$(ODIR)/</xsl:text>
+ <xsl:value-of select="$target"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="$path"/>
+ <xsl:value-of select="substring-before(@source,'.')"/>
+ <xsl:text>.o </xsl:text>
+
+ </xsl:if>
+
+ </xsl:for-each>
+
+ <!-- external objects last -->
+ <xsl:for-each select="external-object">
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:if test="$conditions=0">
+ <xsl:text> $(ODIR)/</xsl:text>
+ <xsl:value-of select="@source"/>
+ </xsl:if>
+
+ </xsl:for-each>
+
+
+ <!-- FIXME this requires strict spaces in rules.xml -->
+ <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='library']"/>
+
+ </xsl:if>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+
+ <!-- create libs rule for all libraries -->
+ <xsl:value-of select="$target"/>
+ <xsl:text>-libraries: </xsl:text>
+
+ <!-- don't build unused libraries
+ <xsl:for-each select="//library">
+ <xsl:if test="object[(ancestor-or-self::*)[@target = $target]]">
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:if test="$conditions=0">
+ <xsl:text> $(ODIR)/</xsl:text>
+ <xsl:text>lib</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:choose>
+ <xsl:when test="@type='static'">
+ <xsl:text>.a</xsl:text>
+ </xsl:when>
+ <xsl:when test="@type='dynamic'">
+ <xsl:text>.so</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ -->
+ <xsl:text>&#10;</xsl:text>
+
+ <!-- create exe rule for all executables -->
+ <xsl:value-of select="$target"/>
+ <xsl:text>-executables: </xsl:text>
+
+ <xsl:for-each select="//executable">
+ <xsl:if test="(ancestor-or-self::*)[@target = $target]">
+
+ <xsl:variable name="conditions">
+ <xsl:text>0</xsl:text>
+ <xsl:for-each select="(ancestor-or-self::*)[@condition!='']">
+ <xsl:call-template name="resolve-condition">
+ <xsl:with-param select="@condition" name="expression"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:if test="$conditions=0">
+ <xsl:text> $(ODIR)/</xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:text>&#10;</xsl:text>
+
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/roms/openbios/config/xml/rules.xml b/roms/openbios/config/xml/rules.xml
new file mode 100644
index 00000000..29a720a0
--- /dev/null
+++ b/roms/openbios/config/xml/rules.xml
@@ -0,0 +1,34 @@
+<rules>
+ <!-- host compiler build rules -->
+<rule target="host" entity="executable">
+ $(call quiet-command,$(HOSTCC) $(HOSTCFLAGS) -o $@ $^," HOSTCC $(TARGET_DIR)$@")
+</rule>
+<rule target="host" entity="object">
+ $(call quiet-command,$(HOSTCC) $(HOSTCFLAGS) $(HOSTINCLUDES) -c -o $@ $&lt;," HOSTCC $(TARGET_DIR)$@")
+</rule>
+<rule target="host" entity="object" extracflags="1">
+ $(call quiet-command,$(HOSTCC) $(HOSTCFLAGS) $(HOSTINCLUDES)</rule>
+<rule target="host" entity="object" extracflags="2"> -c -o $@ $&lt;," HOSTCC $(TARGET_DIR)$@")
+</rule>
+<rule target="host" entity="library">
+ $(call quiet--command,$(AR) cru $@ $^; $(RANLIB) $@," HOSTAR $(TARGET_DIR)$@")
+</rule>
+<rule target="host" entity="fcode">
+ $(call quiet-command,$(TOKE) -o $@ $^," TOKE $(TARGET_DIR)$@")
+</rule>
+
+ <!-- target/cross compiler build rules -->
+<rule target="target" entity="executable">
+ $(call quiet-command,$(CC) $(CFLAGS) -o $@ $^," CC $(TARGET_DIR)$@")
+</rule>
+<rule target="target" entity="object">
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $&lt;," CC $(TARGET_DIR)$@")
+</rule>
+<rule target="target" entity="object" extracflags="1">
+ $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES)</rule>
+<rule target="target" entity="object" extracflags="2"> -c -o $@ $&lt;," CC $(TARGET_DIR)$@")
+</rule>
+<rule target="target" entity="library">
+ $(call quiet-command,$(AR) cru $@ $^; $(RANLIB) $@," AR $(TARGET_DIR)$@")
+</rule>
+</rules>
diff --git a/roms/openbios/config/xml/util.xsl b/roms/openbios/config/xml/util.xsl
new file mode 100644
index 00000000..3b583b9a
--- /dev/null
+++ b/roms/openbios/config/xml/util.xsl
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="ISO-8859-15" ?>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+<!-- get-dirname: get directory part of file $path-->
+
+<!-- call me with:
+ <xsl:param name="path">
+ <xsl:for-each select="ancestor::build">
+ <xsl:call-template name="get-dirname">
+ <xsl:with-param select="@base" name="path"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:param>
+ -->
+
+<xsl:template name="get-dirname">
+ <xsl:param name="path"/>
+ <xsl:choose>
+ <xsl:when test="contains($path, '/')">
+ <xsl:choose>
+ <xsl:when test="substring($path, string-length($path)) != '/'">
+ <xsl:call-template name="get-dirname">
+ <xsl:with-param select="substring($path, 1, string-length($path)-1)" name="path"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$path"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ No valid relative path
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!-- return value: 0=found, 1=not found -->
+<xsl:template name="resolve-condition">
+ <xsl:param name="expression"/>
+ <xsl:param name="confexpr">CONFIG_<xsl:value-of select="$expression"/></xsl:param>
+
+ <xsl:choose>
+ <xsl:when test="$expression!=''">
+ <xsl:variable name="value"><xsl:value-of select="document('config.xml',.)//option[@name=$confexpr]/attribute::value"/></xsl:variable>
+ <xsl:variable name="type"><xsl:value-of select="document('config.xml',.)//option[@name=$confexpr]/attribute::type"/></xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$type='boolean'">
+ <xsl:choose>
+ <xsl:when test="$value='true'"><xsl:text>0</xsl:text></xsl:when>
+ <xsl:when test="$value='false'"><xsl:text>1</xsl:text></xsl:when>
+ <!-- boolean but no value is false -->
+ <xsl:when test="$value=''"><xsl:text>1</xsl:text></xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">Error:<xsl:value-of select="$confexpr"/> has no valid value '<xsl:value-of select="$value"/>'.</xsl:message>
+ </xsl:otherwise>
+
+ </xsl:choose>
+ </xsl:when>
+ <!-- if it doesn't exist, it is false -->
+ <xsl:when test="$type=''"><xsl:text>1</xsl:text></xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">Error:<xsl:value-of select="$confexpr"/> is not a boolean value ('<xsl:value-of select="$type"/>').</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- debug - ->
+ <xsl:message>
+ <xsl:value-of select="$confexpr"/> = <xsl:value-of select="$value"/>
+ </xsl:message>
+ <!- - -->
+ </xsl:when>
+ <!-- if no expression is there we return true -->
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+</xsl:stylesheet>
diff --git a/roms/openbios/config/xml/xinclude.xsl b/roms/openbios/config/xml/xinclude.xsl
new file mode 100644
index 00000000..5bcbf535
--- /dev/null
+++ b/roms/openbios/config/xml/xinclude.xsl
@@ -0,0 +1,43 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <!--
+ Stefans own xinclude implementation.
+ We really don't want to bother the users with namespaces
+ -->
+
+ <xsl:output method="xml" indent="yes"/>
+ <xsl:strip-space elements="*"/>
+
+ <xsl:template match="node() | @*">
+ <xsl:copy>
+ <xsl:apply-templates select="@* | node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+
+<!-- <xsl:template match="xi:include" xmlns:xi="http://www.w3.org/2001/XInclude"> -->
+ <xsl:template match="include">
+ <xsl:variable name="href"><xsl:value-of select="@href"/>
+ </xsl:variable>
+ <xsl:for-each select="document(@href)">
+ <!--
+ <xsl:copy><xsl:copy-of select="@*"/>
+ <xsl:attribute name="base">
+ <xsl:value-of select="$href"/>
+ </xsl:attribute>
+ <xsl:apply-templates select="node()" />
+ </xsl:copy>
+ -->
+ <xsl:element name="{local-name(*)}" namespace="{namespace-uri(..)}">
+ <xsl:copy-of select="*/@*"/>
+ <xsl:attribute name="base">
+ <xsl:value-of select="$href"/>
+ </xsl:attribute>
+ <xsl:for-each select="*">
+ <xsl:apply-templates/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/roms/openbios/drivers/Kconfig b/roms/openbios/drivers/Kconfig
new file mode 100644
index 00000000..3bebc029
--- /dev/null
+++ b/roms/openbios/drivers/Kconfig
@@ -0,0 +1,59 @@
+
+
+menu "Drivers"
+
+config DRIVER_PCI
+ bool "PCI driver"
+ default y
+ help
+ Builtin PCI driver
+
+config DEBUG_PCI
+ bool "Debug PCI driver"
+ default n
+ help
+ Debug PCI driver
+
+config DRIVER_IDE
+ depends X86 || AMD64 || PPC
+ bool "Legacy IDE"
+ default y
+ help
+ If you want to be able to boot from IDE, enable this option.
+
+config IDE_NUM_CHANNELS
+ depends DRIVER_IDE
+ int "Number of IDE channels to be probed"
+ default 4
+ help
+ Number of IDE channels to be probed. This should be set to
+ one or two if you build OpenBIOS for the Total Impact BRIQ.
+
+config DEBUG_IDE
+ depends DRIVER_IDE
+ bool "Debug IDE driver"
+ default n
+ help
+ Debug IDE driver
+
+config DRIVER_USB
+ bool "USB Support"
+ default n
+ help
+ If you want to be able to use USB devices, enable this option.
+
+config DEBUG_USB
+ depends DRIVER_USB
+ bool "Debug USB driver"
+ default n
+ help
+ Debug USB driver
+
+config USB_HID
+ depends DRIVER_USB
+ bool "USB driver for HID devices"
+ default n
+ help
+ If you want to be able to use USB keyboard, enable this option.
+
+endmenu
diff --git a/roms/openbios/drivers/adb_bus.c b/roms/openbios/drivers/adb_bus.c
new file mode 100644
index 00000000..d67d1f1a
--- /dev/null
+++ b/roms/openbios/drivers/adb_bus.c
@@ -0,0 +1,257 @@
+/*
+ *
+ * Open Hack'Ware BIOS ADB bus support, ported to OpenBIOS
+ *
+ * Copyright (c) 2005 Jocelyn Mayer
+ * Copyright (c) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/vsprintf.h"
+
+#include "adb_bus.h"
+#include "adb_kbd.h"
+#include "adb_mouse.h"
+
+DECLARE_UNNAMED_NODE( adb, INSTALL_OPEN, sizeof(int));
+
+static void
+adb_initialize (int *idx)
+{
+ phandle_t ph=get_cur_dev();
+
+ push_str("adb");
+ fword("device-type");
+
+ set_property(ph, "compatible", "adb", 4);
+ set_int_property(ph, "#address-cells", 1);
+ set_int_property(ph, "#size-cells", 0);
+}
+
+static void
+adb_open(int *idx)
+{
+ RET(-1);
+}
+
+static void
+adb_close(int *idx)
+{
+}
+
+NODE_METHODS( adb ) = {
+ { NULL, adb_initialize },
+ { "open", adb_open },
+ { "close", adb_close },
+};
+
+adb_bus_t *adb_bus_new (void *host,
+ int (*req)(void *host, const uint8_t *snd_buf,
+ int len, uint8_t *rcv_buf))
+{
+ adb_bus_t *new;
+
+ new = malloc(sizeof(adb_bus_t));
+ if (new == NULL)
+ return NULL;
+ new->host = host;
+ new->req = req;
+
+ return new;
+}
+
+/* Check and relocate all ADB devices as suggested in
+ * ADB_manager Apple documentation
+ */
+
+int adb_bus_init (char *path, adb_bus_t *bus)
+{
+ char buf[64];
+ uint8_t buffer[ADB_BUF_SIZE];
+ uint8_t adb_addresses[16] =
+ { 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, 0, };
+ adb_dev_t tmp_device, **cur;
+ int address;
+ int reloc = 0, next_free = 7;
+ int keep;
+
+ snprintf(buf, sizeof(buf), "%s/adb", path);
+ REGISTER_NAMED_NODE( adb, buf);
+ /* Reset the bus */
+ // ADB_DPRINTF("\n");
+ adb_reset(bus);
+ cur = &bus->devices;
+ memset(&tmp_device, 0, sizeof(adb_dev_t));
+ tmp_device.bus = bus;
+ for (address = 1; address < 8 && adb_addresses[reloc] > 0;) {
+ if (address == ADB_RES) {
+ /* Reserved */
+ address++;
+ continue;
+ }
+ //ADB_DPRINTF("Check device on ADB address %d\n", address);
+ tmp_device.addr = address;
+ switch (adb_reg_get(&tmp_device, 3, buffer)) {
+ case 0:
+ //ADB_DPRINTF("No device on ADB address %d\n", address);
+ /* Register this address as free */
+ if (adb_addresses[next_free] != 0)
+ adb_addresses[next_free++] = address;
+ /* Check next ADB address */
+ address++;
+ break;
+ case 2:
+ /* One device answered :
+ * make it available and relocate it to a free address
+ */
+ if (buffer[0] == ADB_CHADDR) {
+ /* device self test failed */
+ ADB_DPRINTF("device on ADB address %d self-test failed "
+ "%02x %02x %02x\n", address,
+ buffer[0], buffer[1], buffer[2]);
+ keep = 0;
+ } else {
+ //ADB_DPRINTF("device on ADB address %d self-test OK\n",
+ // address);
+ keep = 1;
+ }
+ ADB_DPRINTF("Relocate device on ADB address %d to %d (%d)\n",
+ address, adb_addresses[reloc], reloc);
+ buffer[0] = ((buffer[0] & 0x40) & ~0x90) | adb_addresses[reloc];
+ if (keep == 1)
+ buffer[0] |= 0x20;
+ buffer[1] = ADB_CHADDR_NOCOLL;
+ if (adb_reg_set(&tmp_device, 3, buffer, 2) < 0) {
+ ADB_DPRINTF("ADB device relocation failed\n");
+ return -1;
+ }
+ if (keep == 1) {
+ *cur = malloc(sizeof(adb_dev_t));
+ if (*cur == NULL) {
+ return -1;
+ }
+ (*cur)->type = address;
+ (*cur)->bus = bus;
+ (*cur)->addr = adb_addresses[reloc++];
+ /* Flush buffers */
+ adb_flush(*cur);
+ switch ((*cur)->type) {
+ case ADB_PROTECT:
+ ADB_DPRINTF("Found one protected device\n");
+ break;
+ case ADB_KEYBD:
+ ADB_DPRINTF("Found one keyboard on address %d\n", address);
+ adb_kbd_new(buf, *cur);
+ break;
+ case ADB_MOUSE:
+ ADB_DPRINTF("Found one mouse on address %d\n", address);
+ adb_mouse_new(buf, *cur);
+ break;
+ case ADB_ABS:
+ ADB_DPRINTF("Found one absolute positioning device\n");
+ break;
+ case ADB_MODEM:
+ ADB_DPRINTF("Found one modem\n");
+ break;
+ case ADB_RES:
+ ADB_DPRINTF("Found one ADB res device\n");
+ break;
+ case ADB_MISC:
+ ADB_DPRINTF("Found one ADB misc device\n");
+ break;
+ }
+ cur = &((*cur)->next);
+ }
+ break;
+ case 1:
+ case 3 ... 7:
+ /* SHOULD NOT HAPPEN : register 3 is always two bytes long */
+ ADB_DPRINTF("Invalid returned len for ADB register 3\n");
+ return -1;
+ case -1:
+ /* ADB ERROR */
+ ADB_DPRINTF("error gettting ADB register 3\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg,
+ uint8_t *buf, int len)
+{
+ uint8_t adb_send[ADB_BUF_SIZE], adb_rcv[ADB_BUF_SIZE];
+
+ //ADB_DPRINTF("cmd: %d reg: %d len: %d\n", cmd, reg, len);
+ if (dev->bus == NULL || dev->bus->req == NULL) {
+ ADB_DPRINTF("ERROR: invalid bus !\n");
+ for (;;);
+ }
+ /* Sanity checks */
+ if (cmd != ADB_LISTEN && len != 0) {
+ /* No buffer transmitted but for LISTEN command */
+ ADB_DPRINTF("in buffer for cmd %d\n", cmd);
+ return -1;
+ }
+ if (cmd == ADB_LISTEN && ((len < 2 || len > 8) || buf == NULL)) {
+ /* Need a buffer with a regular register size for LISTEN command */
+ ADB_DPRINTF("no/invalid buffer for ADB_LISTEN (%d)\n", len);
+ return -1;
+ }
+ if ((cmd == ADB_TALK || cmd == ADB_LISTEN) && reg > 3) {
+ /* Need a valid register number for LISTEN and TALK commands */
+ ADB_DPRINTF("invalid reg for TALK/LISTEN command (%d %d)\n", cmd, reg);
+ return -1;
+ }
+ switch (cmd) {
+ case ADB_SEND_RESET:
+ adb_send[0] = ADB_SEND_RESET;
+ break;
+ case ADB_FLUSH:
+ adb_send[0] = (dev->addr << 4) | ADB_FLUSH;
+ break;
+ case ADB_LISTEN:
+ memcpy(adb_send + 1, buf, len);
+ /* No break here */
+ case ADB_TALK:
+ adb_send[0] = (dev->addr << 4) | cmd | reg;
+ break;
+ }
+ memset(adb_rcv, 0, ADB_BUF_SIZE);
+ len = (*dev->bus->req)(dev->bus->host, adb_send, len + 1, adb_rcv);
+#ifdef DEBUG_ADB
+ //printk("%x %x %x %x\n", adb_rcv[0], adb_rcv[1], adb_rcv[2], adb_rcv[3]);
+#endif
+ switch (len) {
+ case 0:
+ /* No data */
+ break;
+ case 2 ... 8:
+ /* Register transmitted */
+ if (buf != NULL)
+ memcpy(buf, adb_rcv, len);
+ break;
+ default:
+ /* Should never happen */
+ //ADB_DPRINTF("Cmd %d returned %d bytes !\n", cmd, len);
+ return -1;
+ }
+ //ADB_DPRINTF("retlen: %d\n", len);
+
+ return len;
+}
diff --git a/roms/openbios/drivers/adb_bus.h b/roms/openbios/drivers/adb_bus.h
new file mode 100644
index 00000000..205b3753
--- /dev/null
+++ b/roms/openbios/drivers/adb_bus.h
@@ -0,0 +1,104 @@
+/*
+ * ADB bus definitions for Open Hack'Ware
+ *
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+typedef struct adb_bus_t adb_bus_t;
+typedef struct adb_dev_t adb_dev_t;
+
+#define ADB_BUF_SIZE 8
+struct adb_bus_t {
+ void *host;
+ int (*req)(void *host, const uint8_t *snd_buf, int len, uint8_t *rcv_buf);
+ adb_dev_t *devices;
+};
+
+struct adb_dev_t {
+ adb_dev_t *next;
+ adb_bus_t *bus;
+ uint8_t addr;
+ uint8_t type;
+ void *state;
+};
+
+#define ADB_BUF_SIZE 8
+
+/* ADB commands */
+enum {
+ ADB_SEND_RESET = 0x00,
+ ADB_FLUSH = 0x01,
+ ADB_LISTEN = 0x08,
+ ADB_TALK = 0x0C,
+};
+/* ADB default IDs before relocation */
+enum {
+ ADB_PROTECT = 0x01,
+ ADB_KEYBD = 0x02,
+ ADB_MOUSE = 0x03,
+ ADB_ABS = 0x04,
+ ADB_MODEM = 0x05,
+ ADB_RES = 0x06,
+ ADB_MISC = 0x07,
+};
+/* ADB special device handlers IDs */
+enum {
+ ADB_CHADDR = 0x00,
+ ADB_CHADDR_ACTIV = 0xFD,
+ ADB_CHADDR_NOCOLL = 0xFE,
+ ADB_SELF_TEST = 0xFF,
+};
+
+int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg,
+ uint8_t *buf, int len);
+void adb_bus_reset (adb_bus_t *bus);
+adb_bus_t *adb_bus_new (void *host,
+ int (*req)(void *host, const uint8_t *snd_buf,
+ int len, uint8_t *rcv_buf));
+int adb_bus_init (char *path, adb_bus_t *bus);
+
+static inline int adb_reset (adb_bus_t *bus)
+{
+ adb_dev_t fake_device;
+
+ memset(&fake_device, 0, sizeof(adb_dev_t));
+ fake_device.bus = bus;
+
+ return adb_cmd(&fake_device, ADB_SEND_RESET, 0, NULL, 0);
+}
+
+static inline int adb_flush (adb_dev_t *dev)
+{
+ return adb_cmd(dev, ADB_FLUSH, 0, NULL, 0);
+}
+
+static inline int adb_reg_get (adb_dev_t *dev, uint8_t reg, uint8_t *buf)
+{
+ return adb_cmd(dev, ADB_TALK, reg, buf, 0);
+}
+
+static inline int adb_reg_set (adb_dev_t *dev, uint8_t reg,
+ uint8_t *buf, int len)
+{
+ return adb_cmd(dev, ADB_LISTEN, reg, buf, len);
+}
+
+#ifdef DEBUG_ADB
+#define ADB_DPRINTF(fmt, args...) \
+do { printk("ADB - %s: " fmt, __func__ , ##args); } while (0)
+#else
+#define ADB_DPRINTF(fmt, args...) do { } while (0)
+#endif
diff --git a/roms/openbios/drivers/adb_kbd.c b/roms/openbios/drivers/adb_kbd.c
new file mode 100644
index 00000000..be6099a0
--- /dev/null
+++ b/roms/openbios/drivers/adb_kbd.c
@@ -0,0 +1,595 @@
+/*
+ *
+ * Open Hack'Ware BIOS ADB keyboard support, ported to OpenBIOS
+ *
+ * Copyright (c) 2005 Jocelyn Mayer
+ * Copyright (c) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "kbd.h"
+
+#include "adb_bus.h"
+#include "adb_kbd.h"
+
+DECLARE_UNNAMED_NODE( keyboard, INSTALL_OPEN, sizeof(int));
+
+static void
+keyboard_open(int *idx)
+{
+ RET(-1);
+}
+
+static void
+keyboard_close(int *idx)
+{
+}
+
+static void keyboard_read(void);
+static void keyboard_getkeymap(void);
+
+NODE_METHODS( keyboard ) = {
+ { "open", keyboard_open },
+ { "close", keyboard_close },
+ { "read", keyboard_read },
+ { "get-key-map", keyboard_getkeymap },
+};
+
+/* VT100 escape sequences */
+
+enum {
+ KEY_UP = 0, KEY_DOWN, KEY_RIGHT, KEY_LEFT, KEY_PAGE_UP, KEY_PAGE_DOWN,
+ KEY_DELETE, KEY_HOME, KEY_END, KEY_HELP,
+ KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
+ KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16
+};
+
+#define ADB_MAX_SEQUENCE_LEN 16
+
+static const char *ADB_sequences[] = {
+ [KEY_UP] = "A[",
+ [KEY_DOWN] = "B[",
+ [KEY_RIGHT] = "C[",
+ [KEY_LEFT] = "D[",
+ [KEY_PAGE_UP] = "~5[",
+ [KEY_PAGE_DOWN] = "~6[",
+ [KEY_DELETE] = "~3[",
+ [KEY_HOME] = "HO",
+ [KEY_END] = "FO",
+ [KEY_HELP] = "~2[",
+ [KEY_F1] = "PO",
+ [KEY_F2] = "QO",
+ [KEY_F3] = "RO",
+ [KEY_F4] = "SO",
+ [KEY_F5] = "~15[",
+ [KEY_F6] = "~17[",
+ [KEY_F7] = "~18[",
+ [KEY_F8] = "~19[",
+ [KEY_F9] = "~20[",
+ [KEY_F10] = "~21[",
+ [KEY_F11] = "~23[",
+ [KEY_F12] = "~24[",
+ [KEY_F13] = "~25[",
+ [KEY_F14] = "~26[",
+ [KEY_F15] = "~28[",
+ [KEY_F15] = "~29[",
+};
+
+/* ADB US keyboard translation map */
+
+static const keymap_t ADB_kbd_us[] = {
+ /* 0x00 */
+ { KBD_SH_CAPS, { 0x61, 0x41, 0x01, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x73, 0x53, 0x13, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x64, 0x44, 0x04, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x66, 0x46, 0x06, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x68, 0x48, 0x08, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x67, 0x47, 0x07, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x7A, 0x5A, 0x1A, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x78, 0x58, 0x18, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ /* 0x08 */
+ { KBD_SH_CAPS, { 0x63, 0x43, 0x03, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x76, 0x56, 0x16, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x60, 0x40, 0x00, -1, -1, -1, -1, -1, /* ? */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x62, 0x42, 0x02, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x71, 0x51, 0x11, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x77, 0x57, 0x17, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x65, 0x45, 0x05, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x72, 0x52, 0x12, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ /* 0x10 */
+ { KBD_SH_CAPS, { 0x79, 0x59, 0x19, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x74, 0x54, 0x14, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x31, 0x21, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x32, 0x40, 0x00, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x33, 0x23, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x34, 0x24, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x36, 0x5E, 0x1E, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x35, 0x25, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ /* 0x18 */
+ { KBD_SH_CAPS, { 0x3D, 0x2B, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x39, 0x28, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x37, 0x26, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x2D, 0x5F, 0x1F, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x38, 0x2A, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x30, 0x29, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x5D, 0x7D, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x6F, 0x4F, 0x0F, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ /* 0x20 */
+ { KBD_SH_CAPS, { 0x75, 0x55, 0x15, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x5B, 0x7B, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x69, 0x49, 0x09, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x70, 0x50, 0x10, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_MOD_MAP(0x0D), },
+ { KBD_SH_CAPS, { 0x6C, 0x4C, 0x0C, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x6A, 0x4A, 0x0A, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x27, 0x22, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ /* 0x28 */
+ { KBD_SH_CAPS, { 0x6B, 0x4B, 0x0B, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x3B, 0x3A, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x5C, 0x7C, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x2C, 0x3C, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x2F, 0x3F, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x6E, 0x4E, 0x0E, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x6D, 0x4D, 0x0D, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_CAPS, { 0x2E, 0x3E, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ /* 0x30 : tab */
+ { KBD_MOD_MAP(0x09), },
+ /* 0x31 : space */
+ { KBD_MOD_MAP(0x20), },
+ /* 0x32 : '<' '>' */
+ { KBD_SH_CAPS, { 0x3C, 0x3E, -1, -1, -1, -1, -1, -1, /* ? */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ /* 0x33 : backspace */
+ { KBD_MOD_MAP(0x08), },
+ { KBD_MAP_NONE, },
+ /* 0x35 : ESC */
+ { KBD_MOD_MAP(0x1B), },
+ /* 0x36 : control */
+ { KBD_MOD_MAP_LCTRL, },
+ /* 0x37 : command */
+ { KBD_MOD_MAP_LCMD, },
+ /* 0x38 : left shift */
+ { KBD_MOD_MAP_LSHIFT, },
+ /* 0x39 : caps-lock */
+ { KBD_MOD_MAP_CAPS, },
+ /* 0x3A : option */
+ { KBD_MOD_MAP_LOPT, },
+ /* 0x3B : left */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_LEFT)), },
+ /* 0x3C : right */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_RIGHT)), },
+ /* 0x3D : down */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_DOWN)), },
+ /* 0x3E : up */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_UP)), },
+ { KBD_MAP_NONE, },
+ /* 0x40 */
+ { KBD_MAP_NONE, },
+ { KBD_SH_NUML, { 0x7F, 0x2E, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_MAP_NONE, },
+ { KBD_SH_NONE, { 0x2A, 0x2A, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_MAP_NONE, },
+ { KBD_SH_NONE, { 0x2B, 0x2B, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_MAP_NONE, },
+ { KBD_MOD_MAP(0x7F), },
+ /* 0x48 */
+ { KBD_MAP_NONE, },
+ { KBD_MAP_NONE, },
+ { KBD_MAP_NONE, },
+ { KBD_SH_NONE, { 0x2F, 0x2F, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_MOD_MAP(0x0D), },
+ { KBD_MAP_NONE, },
+ { KBD_SH_NONE, { 0x2D, 0x2D, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_MAP_NONE, },
+ /* 0x50 */
+ { KBD_MAP_NONE, },
+ { KBD_SH_NONE, { 0x3D, 0x3D, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_NUML, { -1, 0x30, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_NUML, { -1, 0x31, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_NUML, { -1, 0x32, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_NUML, { -1, 0x33, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_NUML, { -1, 0x34, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_NUML, { -1, 0x35, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ /* 0x58 */
+ { KBD_SH_NUML, { -1, 0x36, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_NUML, { -1, 0x37, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_MAP_NONE, },
+ { KBD_SH_NUML, { -1, 0x38, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_SH_NUML, { -1, 0x39, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, }, },
+ { KBD_MAP_NONE, },
+ { KBD_MOD_MAP(0x2F), },
+ { KBD_MAP_NONE, },
+ /* 0x60 : F5 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F5)), },
+ /* 0x61 : F6 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F6)), },
+ /* 0x62 : F7 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F7)), },
+ /* 0x63 : F3 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F3)), },
+ /* 0x64 : F8 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F8)), },
+ /* 0x65 : F9 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F9)), },
+ { KBD_MAP_NONE, },
+ /* 0x67 : F11 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F11)), },
+ /* 0x68 */
+ { KBD_MAP_NONE, },
+ /* 0x69 : F13 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F13)), },
+ { KBD_MAP_NONE, },
+ /* 0x6B : F14 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F14)), },
+ { KBD_MAP_NONE, },
+ /* 0x6D : F10 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F10)), },
+ { KBD_MAP_NONE, },
+ /* 0x6F : F12 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F12)), },
+ /* 0x70 */
+ { KBD_MAP_NONE, },
+ /* 0x71 : F15 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F15)), },
+ /* 0x72 : help */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_HELP)), },
+ /* 0x73 : home */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_HOME)), },
+ /* 0x74 : page up */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_PAGE_UP)), },
+ /* 0x75 : del */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_DELETE)), },
+ /* 0x76 : F4 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F4)), },
+ /* 0x77 : end */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_END)), },
+ /* 0x78 : F2 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F2)), },
+ /* 0x79 : page down */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_PAGE_UP)), },
+ /* 0x7A : F1 */
+ { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F1)), },
+ /* 0x7B : right shift */
+ { KBD_MOD_MAP_RSHIFT, },
+ /* 0x7C : right option */
+ { KBD_MOD_MAP_ROPT, },
+ /* 0x7D : right control */
+ { KBD_MOD_MAP_RCTRL, },
+ { KBD_MAP_NONE, },
+ /* 0x7F : power */
+ { KBD_MAP_NONE, },
+};
+
+typedef struct adb_kbd_t adb_kbd_t;
+struct adb_kbd_t {
+ kbd_t kbd;
+ int next_key;
+ char sequence[ADB_MAX_SEQUENCE_LEN];
+ int len;
+ char keytable[32];
+};
+
+static adb_dev_t *my_adb_dev = NULL;
+
+static int adb_kbd_read (void *private)
+{
+ uint8_t buffer[ADB_BUF_SIZE];
+ adb_dev_t *dev = private;
+ adb_kbd_t *kbd;
+ int key;
+ int ret;
+
+ kbd = dev->state;
+
+ if (kbd->len > 0) {
+ ret = kbd->sequence[kbd->len-- - 1];
+ ADB_DPRINTF("Buffered %d (%02x)\n", ret, ret);
+ return ret;
+ }
+
+ /* Get saved state */
+ ret = -1;
+ for (key = -1; key == -1; ) {
+ if (kbd->next_key != -1) {
+ key = kbd->next_key;
+ kbd->next_key = -1;
+ } else {
+ if (adb_reg_get(dev, 0, buffer) != 2)
+ break;
+ kbd->next_key = buffer[1] == 0xFF ? -1 : buffer[1];
+ key = buffer[0];
+ }
+ ret = kbd_translate_key(&kbd->kbd, key & 0x7F, key >> 7, kbd->sequence);
+ if (ret > 0) {
+ kbd->len = ret;
+ ret = kbd->sequence[kbd->len-- - 1];
+ }
+
+ ADB_DPRINTF("Translated %d (%02x) into %d (%02x)\n",
+ key, key, ret, ret);
+ }
+
+ return ret;
+}
+
+
+void *adb_kbd_new (char *path, void *private)
+{
+ char buf[64];
+ int props[1];
+ phandle_t ph, aliases;
+ adb_kbd_t *kbd;
+ adb_dev_t *dev = private;
+ kbd = (adb_kbd_t*)malloc(sizeof(adb_kbd_t));
+ if (kbd != NULL) {
+ memset(kbd, 0, sizeof(adb_kbd_t));
+ kbd_set_keymap(&kbd->kbd, sizeof(ADB_kbd_us) / sizeof(keymap_t),
+ ADB_kbd_us, ADB_sequences);
+ kbd->next_key = -1;
+ kbd->len = 0;
+
+ /* Debugging BootX: the lines below force get-key-map to report that
+ * cmd-V is being held down, which forces BootX to run in verbose mode
+ * for debugging.
+ *
+ * TODO: if we can find a mapping between the get-key-map bitmap and
+ * ADB scancodes, the keyboard driver should be altered to update this
+ * accordingly.
+ */
+
+ /*
+ kbd->keytable[3] = 0x40;
+ kbd->keytable[28] = 0x10;
+ */
+
+ dev->state = kbd;
+ my_adb_dev = dev;
+ }
+
+ snprintf(buf, sizeof(buf), "%s/keyboard", path);
+ REGISTER_NAMED_NODE( keyboard, buf);
+
+ ph = find_dev(buf);
+
+ set_property(ph, "device_type", "keyboard", 9);
+ props[0] = __cpu_to_be32(dev->addr);
+ set_property(ph, "reg", (char *)&props, sizeof(props));
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "adb-keyboard", buf, strlen(buf) + 1);
+
+ return kbd;
+}
+
+/* ( addr len -- actual ) */
+static void keyboard_read(void)
+{
+ char *addr;
+ int len, key, i;
+ len=POP();
+ addr=(char *)cell2pointer(POP());
+
+ for (i = 0; i < len; i++) {
+ key = adb_kbd_read(my_adb_dev);
+ if (key == -1 || key == -2)
+ break;
+ *addr++ = (char)key;
+ }
+ PUSH(i);
+}
+
+/* ( -- keymap ) (?) */
+/* should return a pointer to an array with 32 bytes (256 bits) */
+static void keyboard_getkeymap(void)
+{
+ adb_kbd_t *kbd = my_adb_dev->state;
+
+ PUSH( pointer2cell(kbd->keytable) );
+}
diff --git a/roms/openbios/drivers/adb_kbd.h b/roms/openbios/drivers/adb_kbd.h
new file mode 100644
index 00000000..b219c12e
--- /dev/null
+++ b/roms/openbios/drivers/adb_kbd.h
@@ -0,0 +1,22 @@
+/*
+ *
+ * Open Hack'Ware BIOS ADB keyboard support, ported to OpenBIOS
+ *
+ * Copyright (c) 2005 Jocelyn Mayer
+ * Copyright (c) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+void *adb_kbd_new (char *path, void *private);
diff --git a/roms/openbios/drivers/adb_mouse.c b/roms/openbios/drivers/adb_mouse.c
new file mode 100644
index 00000000..b94a3442
--- /dev/null
+++ b/roms/openbios/drivers/adb_mouse.c
@@ -0,0 +1,67 @@
+/*
+ *
+ * Open Hack'Ware BIOS ADB mouse support, ported to OpenBIOS
+ *
+ * Copyright (c) 2005 Jocelyn Mayer
+ * Copyright (c) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "adb_bus.h"
+#include "adb_mouse.h"
+
+DECLARE_UNNAMED_NODE( mouse, INSTALL_OPEN, sizeof(int));
+
+static void
+mouse_open(int *idx)
+{
+ RET(-1);
+}
+
+static void
+mouse_close(int *idx)
+{
+}
+
+NODE_METHODS( mouse ) = {
+ { "open", mouse_open },
+ { "close", mouse_close },
+};
+
+void adb_mouse_new (char *path, void *private)
+{
+ char buf[64];
+ int props[1];
+ phandle_t ph, aliases;
+ adb_dev_t *dev = private;
+
+ snprintf(buf, sizeof(buf), "%s/mouse", path);
+ REGISTER_NAMED_NODE( mouse, buf);
+
+ ph = find_dev(buf);
+
+ set_property(ph, "device_type", "mouse", 6);
+ props[0] = __cpu_to_be32(dev->addr);
+ set_property(ph, "reg", (char *)&props, sizeof(props));
+ set_int_property(ph, "#buttons", 3);
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "adb-mouse", buf, strlen(buf) + 1);
+}
diff --git a/roms/openbios/drivers/adb_mouse.h b/roms/openbios/drivers/adb_mouse.h
new file mode 100644
index 00000000..1f37dac7
--- /dev/null
+++ b/roms/openbios/drivers/adb_mouse.h
@@ -0,0 +1,22 @@
+/*
+ *
+ * Open Hack'Ware BIOS ADB mouse support, ported to OpenBIOS
+ *
+ * Copyright (c) 2005 Jocelyn Mayer
+ * Copyright (c) 2005 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+void adb_mouse_new (char *path, void *private);
diff --git a/roms/openbios/drivers/build.xml b/roms/openbios/drivers/build.xml
new file mode 100644
index 00000000..bd1abd35
--- /dev/null
+++ b/roms/openbios/drivers/build.xml
@@ -0,0 +1,41 @@
+<build>
+
+ <library name="drivers" type="static" target="target">
+ <object source="pci.c" condition="DRIVER_PCI"/>
+ <object source="pci_database.c" condition="DRIVER_PCI"/>
+ <object source="ide.c" condition="DRIVER_IDE"/>
+ <object source="timer.c" condition="DRIVER_IDE"/>
+ <object source="kbd.c" condition="DRIVER_ADB"/>
+ <object source="adb_bus.c" condition="DRIVER_ADB"/>
+ <object source="adb_kbd.c" condition="DRIVER_ADB"/>
+ <object source="adb_mouse.c" condition="DRIVER_ADB"/>
+ <object source="cuda.c" condition="DRIVER_ADB"/>
+ <object source="floppy.c" condition="DRIVER_FLOPPY"/>
+ <object source="iommu.c" condition="DRIVER_SBUS"/>
+ <object source="sbus.c" condition="DRIVER_SBUS"/>
+ <object source="esp.c" condition="DRIVER_ESP"/>
+ <object source="obio.c" condition="DRIVER_OBIO"/>
+ <object source="vga_load_regs.c" condition="DRIVER_VGA"/>
+ <object source="vga_set_mode.c" condition="DRIVER_VGA"/>
+ <object source="macio.c" condition="DRIVER_MACIO"/>
+ <object source="pc_kbd.c" condition="DRIVER_PC_KBD"/>
+ <object source="pc_serial.c" condition="DRIVER_PC_SERIAL"/>
+ <object source="escc.c" condition="DRIVER_ESCC"/>
+ <object source="fw_cfg.c" condition="DRIVER_FW_CFG"/>
+ <object source="usb.c" condition="DRIVER_USB"/>
+ <object source="usbhid.c" condition="USB_HID"/>
+ <object source="usbohci.c" condition="DRIVER_USB"/>
+ <object source="usbohci_rh.c" condition="DRIVER_USB"/>
+ </library>
+
+ <dictionary name="openbios" target="forth">
+ <object source="pci.fs" condition="DRIVER_PCI"/>
+ <object source="sbus.fs" condition="DRIVER_SBUS"/>
+ <object source="esp.fs" condition="DRIVER_ESP"/>
+ </dictionary>
+
+ <fcode source="tcx.fs" name="QEMU,tcx.bin" condition="DRIVER_SBUS" />
+ <fcode source="cgthree.fs" name="QEMU,cgthree.bin" condition="DRIVER_SBUS" />
+ <fcode source="vga.fs" name="QEMU,VGA.bin" condition="DRIVER_VGA" />
+
+</build>
diff --git a/roms/openbios/drivers/cgthree.fs b/roms/openbios/drivers/cgthree.fs
new file mode 100644
index 00000000..aa0c90cd
--- /dev/null
+++ b/roms/openbios/drivers/cgthree.fs
@@ -0,0 +1,197 @@
+\
+\ Fcode payload for QEMU CG3 graphics card
+\
+\ This is the Forth source for an Fcode payload to initialise
+\ the QEMU CG3 graphics card.
+\
+\ (C) Copyright 2013 Mark Cave-Ayland
+\
+
+fcode-version3
+
+\
+\ Instead of using fixed values for the framebuffer address and the width
+\ and height, grab the ones passed in by QEMU/generated by OpenBIOS
+\
+
+: (find-xt) \ ( str len -- xt | -1 )
+ $find if
+ exit
+ else
+ 2drop
+ -1
+ then
+;
+
+: (is-openbios) \ ( -- true | false )
+ " openbios-video-width" (find-xt) -1 <> if
+ -1
+ else
+ 0
+ then
+;
+
+" openbios-video-width" (find-xt) cell+ value openbios-video-width-xt
+" openbios-video-height" (find-xt) cell+ value openbios-video-height-xt
+" depth-bits" (find-xt) cell+ value depth-bits-xt
+" line-bytes" (find-xt) cell+ value line-bytes-xt
+" debug-type" (find-xt) value debug-type-xt
+
+: openbios-video-width
+ (is-openbios) if
+ openbios-video-width-xt @
+ else
+ h# 400
+ then
+;
+
+: openbios-video-height
+ (is-openbios) if
+ openbios-video-height-xt @
+ else
+ h# 300
+ then
+;
+
+: depth-bits
+ (is-openbios) if
+ depth-bits-xt @
+ else
+ h# 8
+ then
+;
+
+: line-bytes
+ (is-openbios) if
+ line-bytes-xt @
+ else
+ h# 400
+ then
+;
+
+: debug-type debug-type-xt execute ;
+
+\
+\ Registers
+\
+
+h# 400000 constant cg3-off-dac
+h# 20 constant /cg3-off-dac
+
+h# 800000 constant cg3-off-fb
+h# c0000 constant /cg3-off-fb
+
+: >cg3-reg-spec ( offset size -- encoded-reg )
+ >r 0 my-address d+ my-space encode-phys r> encode-int encode+
+;
+
+: cg3-reg
+ \ A real cg3 rom appears to just map the entire region with a
+ \ single entry
+ h# 0 h# 1000000 >cg3-reg-spec
+ " reg" property
+;
+
+: do-map-in ( offset size -- virt )
+ >r my-space r> " map-in" $call-parent
+;
+
+: do-map-out ( virt size )
+ " map-out" $call-parent
+;
+
+\
+\ DAC
+\
+
+-1 value cg3-dac
+-1 value fb-addr
+
+: dac! ( data reg# -- )
+ cg3-dac + c!
+;
+
+external
+
+: color! ( r g b c# -- )
+ 0 dac! ( r g b )
+ swap rot ( b g r )
+ 4 dac! ( b g )
+ 4 dac! ( b )
+ 4 dac! ( )
+;
+
+headerless
+
+\
+\ Mapping
+\
+
+: dac-map
+ cg3-off-dac /cg3-off-dac do-map-in to cg3-dac
+;
+
+: fb-map
+ cg3-off-fb h# c0000 do-map-in to fb-addr
+;
+
+: map-regs
+ dac-map fb-map
+;
+
+\
+\ Installation
+\
+
+" cgthree" device-name
+" display" device-type
+" SUNW,501-1415" model
+
+: qemu-cg3-driver-install ( -- )
+ cg3-dac -1 = if
+ map-regs
+
+ \ Initial pallette taken from Sun's "Writing FCode Programs"
+ h# ff h# ff h# ff h# 0 color! \ Background white
+ h# 0 h# 0 h# 0 h# ff color! \ Foreground black
+ h# 64 h# 41 h# b4 h# 1 color! \ SUN-blue logo
+
+ fb-addr to frame-buffer-adr
+ default-font set-font
+
+ frame-buffer-adr encode-int " address" property
+
+ openbios-video-width openbios-video-height over char-width / over char-height /
+ fb8-install
+ then
+;
+
+: qemu-cg3-driver-init
+
+ cg3-reg
+
+ openbios-video-height encode-int " height" property
+ openbios-video-width encode-int " width" property
+ line-bytes encode-int " linebytes" property
+
+ h# 39 encode-int 0 encode-int encode+ " intr" property
+
+ \ Monitor sense. Some searching suggests that this is
+ \ 5 for 1024x768 and 7 for 1152x900
+ openbios-video-width h# 480 = if
+ h# 7
+ else
+ h# 5
+ then
+ encode-int " monitor-sense" property
+
+ " SUNW" encode-string " manufacturer" property
+ " ISO8859-1" encode-string " character-set" property
+ h# c encode-int " cursorshift" property
+
+ ['] qemu-cg3-driver-install is-install
+;
+
+qemu-cg3-driver-init
+
+end0
diff --git a/roms/openbios/drivers/cuda.c b/roms/openbios/drivers/cuda.c
new file mode 100644
index 00000000..9555dea4
--- /dev/null
+++ b/roms/openbios/drivers/cuda.c
@@ -0,0 +1,424 @@
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "drivers/drivers.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "macio.h"
+#include "cuda.h"
+
+//#define DEBUG_CUDA
+#ifdef DEBUG_CUDA
+#define CUDA_DPRINTF(fmt, args...) \
+ do { printk("CUDA - %s: " fmt, __func__ , ##args); } while (0)
+#else
+#define CUDA_DPRINTF(fmt, args...) do { } while (0)
+#endif
+
+#define IO_CUDA_OFFSET 0x00016000
+#define IO_CUDA_SIZE 0x00002000
+
+/* VIA registers - spaced 0x200 bytes apart */
+#define RS 0x200 /* skip between registers */
+#define B 0 /* B-side data */
+#define A RS /* A-side data */
+#define DIRB (2*RS) /* B-side direction (1=output) */
+#define DIRA (3*RS) /* A-side direction (1=output) */
+#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
+#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
+#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
+#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
+#define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */
+#define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */
+#define SR (10*RS) /* Shift register */
+#define ACR (11*RS) /* Auxiliary control register */
+#define PCR (12*RS) /* Peripheral control register */
+#define IFR (13*RS) /* Interrupt flag register */
+#define IER (14*RS) /* Interrupt enable register */
+#define ANH (15*RS) /* A-side data, no handshake */
+
+/* Bits in B data register: all active low */
+#define TREQ 0x08 /* Transfer request (input) */
+#define TACK 0x10 /* Transfer acknowledge (output) */
+#define TIP 0x20 /* Transfer in progress (output) */
+
+/* Bits in ACR */
+#define SR_CTRL 0x1c /* Shift register control bits */
+#define SR_EXT 0x0c /* Shift on external clock */
+#define SR_OUT 0x10 /* Shift out if 1 */
+
+/* Bits in IFR and IER */
+#define IER_SET 0x80 /* set bits in IER */
+#define IER_CLR 0 /* clear bits in IER */
+#define SR_INT 0x04 /* Shift register full/empty */
+
+#define CUDA_BUF_SIZE 16
+
+#define ADB_PACKET 0
+#define CUDA_PACKET 1
+
+/* CUDA commands (2nd byte) */
+#define CUDA_GET_TIME 0x03
+#define CUDA_SET_TIME 0x09
+#define CUDA_POWERDOWN 0x0a
+#define CUDA_RESET_SYSTEM 0x11
+
+static uint8_t cuda_readb (cuda_t *dev, int reg)
+{
+ return *(volatile uint8_t *)(dev->base + reg);
+}
+
+static void cuda_writeb (cuda_t *dev, int reg, uint8_t val)
+{
+ *(volatile uint8_t *)(dev->base + reg) = val;
+}
+
+static void cuda_wait_irq (cuda_t *dev)
+{
+ int val;
+
+// CUDA_DPRINTF("\n");
+ for(;;) {
+ val = cuda_readb(dev, IFR);
+ cuda_writeb(dev, IFR, val & 0x7f);
+ if (val & SR_INT)
+ break;
+ }
+}
+
+
+
+static int cuda_request (cuda_t *dev, uint8_t pkt_type, const uint8_t *buf,
+ int buf_len, uint8_t *obuf)
+{
+ int i, obuf_len, val;
+
+ cuda_writeb(dev, ACR, cuda_readb(dev, ACR) | SR_OUT);
+ cuda_writeb(dev, SR, pkt_type);
+ cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP);
+ if (buf) {
+ //CUDA_DPRINTF("Send buf len: %d\n", buf_len);
+ /* send 'buf' */
+ for(i = 0; i < buf_len; i++) {
+ cuda_wait_irq(dev);
+ cuda_writeb(dev, SR, buf[i]);
+ cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK);
+ }
+ }
+ cuda_wait_irq(dev);
+ cuda_writeb(dev, ACR, cuda_readb(dev, ACR) & ~SR_OUT);
+ cuda_readb(dev, SR);
+ cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK);
+
+ obuf_len = 0;
+ if (obuf) {
+ cuda_wait_irq(dev);
+ cuda_readb(dev, SR);
+ cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP);
+ for(;;) {
+ cuda_wait_irq(dev);
+ val = cuda_readb(dev, SR);
+ if (obuf_len < CUDA_BUF_SIZE)
+ obuf[obuf_len++] = val;
+ if (cuda_readb(dev, B) & TREQ)
+ break;
+ cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK);
+ }
+ cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK);
+
+ cuda_wait_irq(dev);
+ cuda_readb(dev, SR);
+ }
+// CUDA_DPRINTF("Got len: %d\n", obuf_len);
+
+ return obuf_len;
+}
+
+
+
+static int cuda_adb_req (void *host, const uint8_t *snd_buf, int len,
+ uint8_t *rcv_buf)
+{
+ uint8_t buffer[CUDA_BUF_SIZE], *pos;
+
+ // CUDA_DPRINTF("len: %d %02x\n", len, snd_buf[0]);
+ len = cuda_request(host, ADB_PACKET, snd_buf, len, buffer);
+ if (len > 1 && buffer[0] == ADB_PACKET) {
+ pos = buffer + 2;
+ len -= 2;
+ } else {
+ pos = buffer + 1;
+ len = -1;
+ }
+ memcpy(rcv_buf, pos, len);
+
+ return len;
+}
+
+
+DECLARE_UNNAMED_NODE(ob_cuda, INSTALL_OPEN, sizeof(int));
+
+static cuda_t *main_cuda;
+
+static void
+ppc32_reset_all(void)
+{
+ uint8_t cmdbuf[2], obuf[64];
+
+ cmdbuf[0] = CUDA_RESET_SYSTEM;
+ cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf);
+}
+
+static void
+ppc32_poweroff(void)
+{
+ uint8_t cmdbuf[2], obuf[64];
+
+ cmdbuf[0] = CUDA_POWERDOWN;
+ cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf);
+}
+
+static void
+ob_cuda_initialize (int *idx)
+{
+ phandle_t ph=get_cur_dev();
+ int props[2];
+
+ push_str("via-cuda");
+ fword("device-type");
+
+ set_int_property(ph, "#address-cells", 1);
+ set_int_property(ph, "#size-cells", 0);
+
+ set_property(ph, "compatible", "cuda", 5);
+
+ props[0] = __cpu_to_be32(IO_CUDA_OFFSET);
+ props[1] = __cpu_to_be32(IO_CUDA_SIZE);
+
+ set_property(ph, "reg", (char *)&props, sizeof(props));
+
+ /* on newworld machines the cuda is on interrupt 0x19 */
+
+ props[0] = 0x19;
+ props[1] = 0;
+ NEWWORLD(set_property(ph, "interrupts", (char *)props, sizeof(props)));
+ NEWWORLD(set_int_property(ph, "#interrupt-cells", 2));
+
+ /* we emulate an oldworld hardware, so we must use
+ * non-standard oldworld property (needed by linux 2.6.18)
+ */
+
+ OLDWORLD(set_int_property(ph, "AAPL,interrupts", 0x12));
+
+ bind_func("ppc32-reset-all", ppc32_reset_all);
+ push_str("' ppc32-reset-all to reset-all");
+ fword("eval");
+}
+
+static void
+ob_cuda_open(int *idx)
+{
+ RET(-1);
+}
+
+static void
+ob_cuda_close(int *idx)
+{
+}
+
+NODE_METHODS(ob_cuda) = {
+ { NULL, ob_cuda_initialize },
+ { "open", ob_cuda_open },
+ { "close", ob_cuda_close },
+};
+
+DECLARE_UNNAMED_NODE(rtc, INSTALL_OPEN, sizeof(int));
+
+static void
+rtc_open(int *idx)
+{
+ RET(-1);
+}
+
+/*
+ * get-time ( -- second minute hour day month year )
+ *
+ */
+
+static const int days_month[12] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static const int days_month_leap[12] =
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static inline int is_leap(int year)
+{
+ return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
+}
+
+static void
+rtc_get_time(int *idx)
+{
+ uint8_t cmdbuf[2], obuf[64];
+ ucell second, minute, hour, day, month, year;
+ uint32_t now;
+ int current;
+ const int *days;
+
+ cmdbuf[0] = CUDA_GET_TIME;
+ cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf);
+
+ /* seconds since 01/01/1904 */
+
+ now = (obuf[3] << 24) + (obuf[4] << 16) + (obuf[5] << 8) + obuf[6];
+
+ second = now % 60;
+ now /= 60;
+
+ minute = now % 60;
+ now /= 60;
+
+ hour = now % 24;
+ now /= 24;
+
+ year = now * 100 / 36525;
+ now -= year * 36525 / 100;
+ year += 1904;
+
+ days = is_leap(year) ? days_month_leap : days_month;
+
+ current = 0;
+ month = 0;
+ while (month < 12) {
+ if (now <= current + days[month]) {
+ break;
+ }
+ current += days[month];
+ month++;
+ }
+ month++;
+
+ day = now - current;
+
+ PUSH(second);
+ PUSH(minute);
+ PUSH(hour);
+ PUSH(day);
+ PUSH(month);
+ PUSH(year);
+}
+
+/*
+ * set-time ( second minute hour day month year -- )
+ *
+ */
+
+static void
+rtc_set_time(int *idx)
+{
+ uint8_t cmdbuf[5], obuf[3];
+ ucell second, minute, hour, day, month, year;
+ const int *days;
+ uint32_t now;
+ unsigned int nb_days;
+ int i;
+
+ year = POP();
+ month = POP();
+ day = POP();
+ hour = POP();
+ minute = POP();
+ second = POP();
+
+ days = is_leap(year) ? days_month_leap : days_month;
+ nb_days = (year - 1904) * 36525 / 100 + day;
+ for (i = 0; i < month - 1; i++)
+ nb_days += days[i];
+
+ now = (((nb_days * 24) + hour) * 60 + minute) * 60 + second;
+
+ cmdbuf[0] = CUDA_SET_TIME;
+ cmdbuf[1] = now >> 24;
+ cmdbuf[2] = now >> 16;
+ cmdbuf[3] = now >> 8;
+ cmdbuf[4] = now;
+
+ cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf);
+}
+
+NODE_METHODS(rtc) = {
+ { "open", rtc_open },
+ { "get-time", rtc_get_time },
+ { "set-time", rtc_set_time },
+};
+
+static void
+rtc_init(char *path)
+{
+ phandle_t ph, aliases;
+ char buf[64];
+
+ snprintf(buf, sizeof(buf), "%s/rtc", path);
+ REGISTER_NAMED_NODE(rtc, buf);
+
+ ph = find_dev(buf);
+ set_property(ph, "device_type", "rtc", 4);
+ set_property(ph, "compatible", "rtc", 4);
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "rtc", buf, strlen(buf) + 1);
+
+}
+
+static void
+powermgt_init(char *path)
+{
+ phandle_t ph;
+ char buf[64];
+
+ snprintf(buf, sizeof(buf), "%s/power-mgt", path);
+ REGISTER_NAMED_NODE(rtc, buf);
+
+ ph = find_dev(buf);
+ set_property(ph, "device_type", "power-mgt", 10);
+ set_property(ph, "compatible", "power-mgt", 10);
+}
+
+cuda_t *cuda_init (const char *path, phys_addr_t base)
+{
+ cuda_t *cuda;
+ char buf[64];
+ phandle_t aliases;
+
+ base += IO_CUDA_OFFSET;
+ CUDA_DPRINTF(" base=" FMT_plx "\n", base);
+ cuda = malloc(sizeof(cuda_t));
+ if (cuda == NULL)
+ return NULL;
+
+ snprintf(buf, sizeof(buf), "%s/via-cuda", path);
+ REGISTER_NAMED_NODE(ob_cuda, buf);
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "via-cuda", buf, strlen(buf) + 1);
+
+ cuda->base = base;
+ cuda_writeb(cuda, B, cuda_readb(cuda, B) | TREQ | TIP);
+#ifdef CONFIG_DRIVER_ADB
+ cuda->adb_bus = adb_bus_new(cuda, &cuda_adb_req);
+ if (cuda->adb_bus == NULL) {
+ free(cuda);
+ return NULL;
+ }
+ adb_bus_init(buf, cuda->adb_bus);
+#endif
+
+ rtc_init(buf);
+ powermgt_init(buf);
+
+ main_cuda = cuda;
+
+ device_end();
+ bind_func("poweroff", ppc32_poweroff);
+
+ return cuda;
+}
diff --git a/roms/openbios/drivers/cuda.h b/roms/openbios/drivers/cuda.h
new file mode 100644
index 00000000..d3818c03
--- /dev/null
+++ b/roms/openbios/drivers/cuda.h
@@ -0,0 +1,17 @@
+#include "adb_bus.h"
+
+struct cuda_t {
+ phys_addr_t base;
+ adb_bus_t *adb_bus;
+};
+typedef struct cuda_t cuda_t;
+
+enum {
+ CHARDEV_KBD = 0,
+ CHARDEV_MOUSE,
+ CHARDEV_SERIAL,
+ CHARDEV_DISPLAY,
+ CHARDEV_LAST,
+};
+
+cuda_t *cuda_init (const char *path, phys_addr_t base);
diff --git a/roms/openbios/drivers/escc.c b/roms/openbios/drivers/escc.c
new file mode 100644
index 00000000..240043be
--- /dev/null
+++ b/roms/openbios/drivers/escc.c
@@ -0,0 +1,476 @@
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "drivers/drivers.h"
+#include "libopenbios/ofmem.h"
+
+#include "escc.h"
+
+/* ******************************************************************
+ * serial console functions
+ * ****************************************************************** */
+
+static volatile unsigned char *escc_serial_dev;
+
+#define CTRL(addr) (*(volatile unsigned char *)(uintptr_t)(addr))
+#ifdef CONFIG_DRIVER_ESCC_SUN
+#define DATA(addr) (*(volatile unsigned char *)(uintptr_t)(addr + 2))
+#else
+#define DATA(addr) (*(volatile unsigned char *)(uintptr_t)(addr + 16))
+#endif
+
+/* Conversion routines to/from brg time constants from/to bits
+ * per second.
+ */
+#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
+
+#ifdef CONFIG_DRIVER_ESCC_SUN
+#define ESCC_CLOCK 4915200 /* Zilog input clock rate. */
+#else
+#define ESCC_CLOCK 3686400
+#endif
+#define ESCC_CLOCK_DIVISOR 16 /* Divisor this driver uses. */
+
+/* Write Register 3 */
+#define RxENAB 0x1 /* Rx Enable */
+#define Rx8 0xc0 /* Rx 8 Bits/Character */
+
+/* Write Register 4 */
+#define SB1 0x4 /* 1 stop bit/char */
+#define X16CLK 0x40 /* x16 clock mode */
+
+/* Write Register 5 */
+#define RTS 0x2 /* RTS */
+#define TxENAB 0x8 /* Tx Enable */
+#define Tx8 0x60 /* Tx 8 bits/character */
+#define DTR 0x80 /* DTR */
+
+/* Write Register 14 (Misc control bits) */
+#define BRENAB 1 /* Baud rate generator enable */
+#define BRSRC 2 /* Baud rate generator source */
+
+/* Read Register 0 */
+#define Rx_CH_AV 0x1 /* Rx Character Available */
+#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
+
+int escc_uart_charav(uintptr_t port)
+{
+ return (CTRL(port) & Rx_CH_AV) != 0;
+}
+
+char escc_uart_getchar(uintptr_t port)
+{
+ while (!escc_uart_charav(port))
+ ;
+ return DATA(port) & 0177;
+}
+
+static void escc_uart_port_putchar(uintptr_t port, unsigned char c)
+{
+ if (!escc_serial_dev)
+ return;
+
+ if (c == '\n')
+ escc_uart_port_putchar(port, '\r');
+ while (!(CTRL(port) & Tx_BUF_EMP))
+ ;
+ DATA(port) = c;
+}
+
+static void uart_init_line(volatile unsigned char *port, unsigned long baud)
+{
+ CTRL(port) = 4; // reg 4
+ CTRL(port) = SB1 | X16CLK; // no parity, async, 1 stop bit, 16x
+ // clock
+
+ baud = BPS_TO_BRG(baud, ESCC_CLOCK / ESCC_CLOCK_DIVISOR);
+
+ CTRL(port) = 12; // reg 12
+ CTRL(port) = baud & 0xff;
+ CTRL(port) = 13; // reg 13
+ CTRL(port) = (baud >> 8) & 0xff;
+ CTRL(port) = 14; // reg 14
+ CTRL(port) = BRSRC | BRENAB;
+
+ CTRL(port) = 3; // reg 3
+ CTRL(port) = RxENAB | Rx8; // enable rx, 8 bits/char
+
+ CTRL(port) = 5; // reg 5
+ CTRL(port) = RTS | TxENAB | Tx8 | DTR; // enable tx, 8 bits/char,
+ // set RTS & DTR
+
+}
+
+int escc_uart_init(phys_addr_t port, unsigned long speed)
+{
+#ifdef CONFIG_DRIVER_ESCC_SUN
+ escc_serial_dev = (unsigned char *)ofmem_map_io(port & ~7ULL, ZS_REGS);
+ escc_serial_dev += port & 7ULL;
+#else
+ escc_serial_dev = (unsigned char *)(uintptr_t)port;
+#endif
+ uart_init_line(escc_serial_dev, speed);
+ return -1;
+}
+
+void escc_uart_putchar(int c)
+{
+ escc_uart_port_putchar((uintptr_t)escc_serial_dev, (unsigned char) (c & 0xff));
+}
+
+void serial_cls(void)
+{
+ escc_uart_putchar(27);
+ escc_uart_putchar('[');
+ escc_uart_putchar('H');
+ escc_uart_putchar(27);
+ escc_uart_putchar('[');
+ escc_uart_putchar('J');
+}
+
+/* ( addr len -- actual ) */
+static void
+escc_read(ucell *address)
+{
+ char *addr;
+ int len;
+
+ len = POP();
+ addr = (char *)cell2pointer(POP());
+
+ if (len < 1)
+ printk("escc_read: bad len, addr %p len %x\n", addr, len);
+
+ if (escc_uart_charav(*address)) {
+ *addr = (char)escc_uart_getchar(*address);
+ PUSH(1);
+ } else {
+ PUSH(0);
+ }
+}
+
+/* ( addr len -- actual ) */
+static void
+escc_write(ucell *address)
+{
+ unsigned char *addr;
+ int i, len;
+
+ len = POP();
+ addr = (unsigned char *)cell2pointer(POP());
+
+ for (i = 0; i < len; i++) {
+ escc_uart_port_putchar(*address, addr[i]);
+ }
+ PUSH(len);
+}
+
+static void
+escc_close(void)
+{
+}
+
+static void
+escc_open(ucell *address)
+{
+#ifdef CONFIG_DRIVER_ESCC_SUN
+ int len;
+ phandle_t ph;
+ unsigned long *prop;
+ char *args;
+
+ fword("my-self");
+ fword("ihandle>phandle");
+ ph = (phandle_t)POP();
+ prop = (unsigned long *)get_property(ph, "address", &len);
+ *address = *prop;
+ fword("my-args");
+ args = pop_fstr_copy();
+ if (args) {
+ if (args[0] == 'a')
+ *address += 4;
+ //printk("escc_open: address %lx, args %s\n", *address, args);
+ free(args);
+ }
+#else
+ *address = (unsigned long)escc_serial_dev; // XXX
+#endif
+ RET ( -1 );
+}
+
+DECLARE_UNNAMED_NODE(escc, INSTALL_OPEN, sizeof(ucell));
+
+NODE_METHODS(escc) = {
+ { "open", escc_open },
+ { "close", escc_close },
+ { "read", escc_read },
+ { "write", escc_write },
+};
+
+#ifdef CONFIG_DRIVER_ESCC_SUN
+static volatile unsigned char *kbd_dev;
+
+void kbd_init(phys_addr_t base)
+{
+ kbd_dev = (unsigned char *)ofmem_map_io(base, 2 * 4);
+ kbd_dev += 4;
+}
+
+static const unsigned char sunkbd_keycode[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\\', 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ' ',
+};
+
+static const unsigned char sunkbd_keycode_shifted[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
+ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '|', 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ' ',
+};
+
+static int shiftstate;
+
+int
+keyboard_dataready(void)
+{
+ return ((kbd_dev[0] & 1) == 1);
+}
+
+unsigned char
+keyboard_readdata(void)
+{
+ unsigned char ch;
+
+ while (!keyboard_dataready()) { }
+
+ do {
+ ch = kbd_dev[2] & 0xff;
+ if (ch == 99)
+ shiftstate |= 1;
+ else if (ch == 110)
+ shiftstate |= 2;
+ else if (ch == 227)
+ shiftstate &= ~1;
+ else if (ch == 238)
+ shiftstate &= ~2;
+ //printk("getch: %d\n", ch);
+ } // If release, wait for key press
+ while ((ch & 0x80) == 0x80 || ch == 238 || ch == 227);
+ //printk("getch rel: %d\n", ch);
+ ch &= 0x7f;
+ if (shiftstate)
+ ch = sunkbd_keycode_shifted[ch];
+ else
+ ch = sunkbd_keycode[ch];
+ //printk("getch xlate: %d\n", ch);
+
+ return ch;
+}
+
+/* ( addr len -- actual ) */
+static void
+escc_read_keyboard(void)
+{
+ unsigned char *addr;
+ int len;
+
+ len = POP();
+ addr = (unsigned char *)POP();
+
+ if (len < 1)
+ printk("escc_read: bad len, addr %p len %x\n", addr, len);
+
+ if (keyboard_dataready()) {
+ *addr = keyboard_readdata();
+ PUSH(1);
+ } else {
+ PUSH(0);
+ }
+}
+
+DECLARE_UNNAMED_NODE(escc_keyboard, INSTALL_OPEN, sizeof(ucell));
+
+NODE_METHODS(escc_keyboard) = {
+ { "open", escc_open },
+ { "close", escc_close },
+ { "read", escc_read_keyboard },
+};
+
+void
+ob_zs_init(phys_addr_t base, uint64_t offset, int intr, int slave, int keyboard)
+{
+ char nodebuff[256];
+ phandle_t aliases;
+
+ ob_new_obio_device("zs", "serial");
+
+ ob_reg(base, offset, ZS_REGS, 1);
+
+ PUSH(slave);
+ fword("encode-int");
+ push_str("slave");
+ fword("property");
+
+ if (keyboard) {
+ PUSH(0);
+ PUSH(0);
+ push_str("keyboard");
+ fword("property");
+
+ PUSH(0);
+ PUSH(0);
+ push_str("mouse");
+ fword("property");
+ }
+
+ ob_intr(intr);
+
+ PUSH(0);
+ PUSH(0);
+ push_str("port-a-ignore-cd");
+ fword("property");
+
+ PUSH(0);
+ PUSH(0);
+ push_str("port-b-ignore-cd");
+ fword("property");
+
+ fword("finish-device");
+
+ snprintf(nodebuff, sizeof(nodebuff), "/obio/zs@0,%x",
+ (int)offset & 0xffffffff);
+ if (keyboard) {
+ REGISTER_NODE_METHODS(escc_keyboard, nodebuff);
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "keyboard", nodebuff, strlen(nodebuff) + 1);
+ } else {
+ REGISTER_NODE_METHODS(escc, nodebuff);
+
+ aliases = find_dev("/aliases");
+ snprintf(nodebuff, sizeof(nodebuff), "/obio/zs@0,%x:a",
+ (int)offset & 0xffffffff);
+ set_property(aliases, "ttya", nodebuff, strlen(nodebuff) + 1);
+
+ snprintf(nodebuff, sizeof(nodebuff), "/obio/zs@0,%x:b",
+ (int)offset & 0xffffffff);
+ set_property(aliases, "ttyb", nodebuff, strlen(nodebuff) + 1);
+
+ }
+}
+
+#else
+
+static void
+escc_add_channel(const char *path, const char *node, phys_addr_t addr,
+ uint32_t offset)
+{
+ char buf[64], tty[32];
+ phandle_t dnode, aliases;
+ int len;
+ cell props[2];
+
+ /* add device */
+
+ snprintf(buf, sizeof(buf), "%s/ch-%s", path, node);
+
+ REGISTER_NAMED_NODE(escc, buf);
+
+ activate_device(buf);
+
+ /* add aliases */
+
+ aliases = find_dev("/aliases");
+
+ snprintf(buf, sizeof(buf), "%s/ch-%s", path, node);
+ OLDWORLD(snprintf(tty, sizeof(tty), "tty%s", node));
+ OLDWORLD(set_property(aliases, tty, buf, strlen(buf) + 1));
+ snprintf(tty, sizeof(tty), "scc%s", node);
+ set_property(aliases, tty, buf, strlen(buf) + 1);
+
+ /* add properties */
+
+ dnode = find_dev(buf);
+ set_property(dnode, "device_type", "serial",
+ strlen("serial") + 1);
+
+ snprintf(buf, sizeof(buf), "ch-%s", node);
+ len = strlen(buf) + 1;
+ snprintf(buf + len, sizeof(buf) - len, "CHRP,es2");
+ set_property(dnode, "compatible", buf, len + 9);
+
+ props[0] = IO_ESCC_OFFSET + offset * 0x20;
+ props[1] = 0x00000020;
+ set_property(dnode, "reg", (char *)&props, 2 * sizeof(cell));
+
+ props[0] = addr + IO_ESCC_OFFSET + offset * 0x20;
+ OLDWORLD(set_property(dnode, "AAPL,address",
+ (char *)&props, 1 * sizeof(cell)));
+
+ props[0] = 0x00000010 - offset;
+ OLDWORLD(set_property(dnode, "AAPL,interrupts",
+ (char *)&props, 1 * sizeof(cell)));
+
+ props[0] = (0x24) + offset;
+ props[1] = 0;
+ NEWWORLD(set_property(dnode, "interrupts",
+ (char *)&props, 2 * sizeof(cell)));
+
+ device_end();
+
+ uart_init_line((unsigned char*)addr + IO_ESCC_OFFSET + offset * 0x20,
+ CONFIG_SERIAL_SPEED);
+}
+
+void
+escc_init(const char *path, phys_addr_t addr)
+{
+ char buf[64];
+ int props[2];
+ phandle_t dnode;
+
+ push_str(path);
+ fword("find-device");
+ fword("new-device");
+
+ push_str("escc");
+ fword("device-name");
+
+ snprintf(buf, sizeof(buf), "%s/escc", path);
+
+ dnode = find_dev(buf);
+
+ set_int_property(dnode, "#address-cells", 1);
+ props[0] = __cpu_to_be32(IO_ESCC_OFFSET);
+ props[1] = __cpu_to_be32(IO_ESCC_SIZE);
+ set_property(dnode, "reg", (char *)&props, sizeof(props));
+ set_property(dnode, "device_type", "escc",
+ strlen("escc") + 1);
+ set_property(dnode, "compatible", "escc\0CHRP,es0", 14);
+
+ fword("finish-device");
+
+ escc_add_channel(buf, "a", addr, 1);
+ escc_add_channel(buf, "b", addr, 0);
+
+ escc_serial_dev = (unsigned char *)addr + IO_ESCC_OFFSET +
+ (CONFIG_SERIAL_PORT ? 0 : 0x20);
+}
+#endif
diff --git a/roms/openbios/drivers/escc.h b/roms/openbios/drivers/escc.h
new file mode 100644
index 00000000..caaf00d4
--- /dev/null
+++ b/roms/openbios/drivers/escc.h
@@ -0,0 +1,9 @@
+
+#define IO_ESCC_SIZE 0x00001000
+#define IO_ESCC_OFFSET 0x00013000
+
+#define ZS_REGS 8
+
+void escc_init(const char *path, phys_addr_t addr);
+void ob_zs_init(phys_addr_t base, uint64_t offset, int intr, int slave,
+ int keyboard);
diff --git a/roms/openbios/drivers/esp.c b/roms/openbios/drivers/esp.c
new file mode 100644
index 00000000..ad3db280
--- /dev/null
+++ b/roms/openbios/drivers/esp.c
@@ -0,0 +1,598 @@
+/*
+ * OpenBIOS ESP driver
+ *
+ * Copyright (C) 2004 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ *
+ * Credit goes to Hale Landis for his excellent ata demo software
+ * OF node handling and some fixes by Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "kernel/kernel.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "drivers/drivers.h"
+#include "asm/io.h"
+#include "scsi.h"
+#include "asm/dma.h"
+#include "esp.h"
+#include "libopenbios/ofmem.h"
+
+#define BUFSIZE 4096
+
+#ifdef CONFIG_DEBUG_ESP
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+struct esp_dma {
+ volatile struct sparc_dma_registers *regs;
+ enum dvma_rev revision;
+};
+
+typedef struct sd_private {
+ unsigned int bs;
+ const char *media_str[2];
+ uint32_t sectors;
+ uint8_t media;
+ uint8_t id;
+ uint8_t present;
+ char model[40];
+} sd_private_t;
+
+struct esp_regs {
+ unsigned char regs[ESP_REG_SIZE];
+};
+
+typedef struct esp_private {
+ volatile struct esp_regs *ll;
+ uint32_t buffer_dvma;
+ unsigned int irq; /* device IRQ number */
+ struct esp_dma espdma;
+ unsigned char *buffer;
+ sd_private_t sd[8];
+} esp_private_t;
+
+static esp_private_t *global_esp;
+
+/* DECLARE data structures for the nodes. */
+DECLARE_UNNAMED_NODE(ob_sd, INSTALL_OPEN, sizeof(sd_private_t *));
+DECLARE_UNNAMED_NODE(ob_esp, INSTALL_OPEN, sizeof(esp_private_t *));
+
+#ifdef CONFIG_DEBUG_ESP
+static void dump_drive(sd_private_t *drive)
+{
+ printk("SCSI DRIVE @%lx:\n", (unsigned long)drive);
+ printk("id: %d\n", drive->id);
+ printk("media: %s\n", drive->media_str[0]);
+ printk("media: %s\n", drive->media_str[1]);
+ printk("model: %s\n", drive->model);
+ printk("sectors: %d\n", drive->sectors);
+ printk("present: %d\n", drive->present);
+ printk("bs: %d\n", drive->bs);
+}
+#endif
+
+static int
+do_command(esp_private_t *esp, sd_private_t *sd, int cmdlen, int replylen)
+{
+ int status;
+
+ // Set SCSI target
+ esp->ll->regs[ESP_BUSID] = sd->id & 7;
+ // Set DMA address
+ esp->espdma.regs->st_addr = esp->buffer_dvma;
+ // Set DMA length
+ esp->ll->regs[ESP_TCLOW] = cmdlen & 0xff;
+ esp->ll->regs[ESP_TCMED] = (cmdlen >> 8) & 0xff;
+ // Set DMA direction and enable DMA
+ esp->espdma.regs->cond_reg = DMA_ENABLE;
+ // Set ATN, issue command
+ esp->ll->regs[ESP_CMD] = ESP_CMD_SELA | ESP_CMD_DMA;
+ // Wait for DMA to complete. Can this fail?
+ while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
+ // Check status
+ status = esp->ll->regs[ESP_STATUS];
+ // Clear interrupts to avoid guests seeing spurious interrupts
+ (void)esp->ll->regs[ESP_INTRPT];
+
+ DPRINTF("do_command: id %d, cmd[0] 0x%x, status 0x%x\n", sd->id, esp->buffer[1], status);
+
+ /* Target didn't want all command data? */
+ if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT) {
+ return status;
+ }
+ if (replylen == 0) {
+ return 0;
+ }
+ /* Target went to status phase instead of data phase? */
+ if ((status & ESP_STAT_PMASK) == ESP_STATP) {
+ return status;
+ }
+
+ // Get reply
+ // Set DMA address
+ esp->espdma.regs->st_addr = esp->buffer_dvma;
+ // Set DMA length
+ esp->ll->regs[ESP_TCLOW] = replylen & 0xff;
+ esp->ll->regs[ESP_TCMED] = (replylen >> 8) & 0xff;
+ // Set DMA direction
+ esp->espdma.regs->cond_reg = DMA_ST_WRITE | DMA_ENABLE;
+ // Transfer
+ esp->ll->regs[ESP_CMD] = ESP_CMD_TI | ESP_CMD_DMA;
+ // Wait for DMA to complete
+ while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
+ // Check status
+ status = esp->ll->regs[ESP_STATUS];
+ // Clear interrupts to avoid guests seeing spurious interrupts
+ (void)esp->ll->regs[ESP_INTRPT];
+
+ DPRINTF("do_command_reply: status 0x%x\n", status);
+
+ if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT)
+ return status;
+ else
+ return 0; // OK
+}
+
+// offset is in sectors
+static int
+ob_sd_read_sector(esp_private_t *esp, sd_private_t *sd, int offset)
+{
+ DPRINTF("ob_sd_read_sector id %d sector=%d\n",
+ sd->id, offset);
+
+ // Setup command = Read(10)
+ memset(esp->buffer, 0, 11);
+ esp->buffer[0] = 0x80;
+ esp->buffer[1] = READ_10;
+
+ esp->buffer[3] = (offset >> 24) & 0xff;
+ esp->buffer[4] = (offset >> 16) & 0xff;
+ esp->buffer[5] = (offset >> 8) & 0xff;
+ esp->buffer[6] = offset & 0xff;
+
+ esp->buffer[8] = 0;
+ esp->buffer[9] = 1;
+
+ if (do_command(esp, sd, 11, sd->bs))
+ return 0;
+
+ return 0;
+}
+
+static unsigned int
+read_capacity(esp_private_t *esp, sd_private_t *sd)
+{
+ // Setup command = Read Capacity
+ memset(esp->buffer, 0, 11);
+ esp->buffer[0] = 0x80;
+ esp->buffer[1] = READ_CAPACITY;
+
+ if (do_command(esp, sd, 11, 8)) {
+ sd->sectors = 0;
+ sd->bs = 0;
+ DPRINTF("read_capacity id %d failed\n", sd->id);
+ return 0;
+ }
+ sd->bs = (esp->buffer[4] << 24) | (esp->buffer[5] << 16) | (esp->buffer[6] << 8) | esp->buffer[7];
+ sd->sectors = ((esp->buffer[0] << 24) | (esp->buffer[1] << 16) | (esp->buffer[2] << 8) | esp->buffer[3]) * (sd->bs / 512);
+
+ DPRINTF("read_capacity id %d bs %d sectors %d\n", sd->id, sd->bs,
+ sd->sectors);
+ return 1;
+}
+
+static unsigned int
+test_unit_ready(esp_private_t *esp, sd_private_t *sd)
+{
+ /* Setup command = Test Unit Ready */
+ memset(esp->buffer, 0, 7);
+ esp->buffer[0] = 0x80;
+ esp->buffer[1] = TEST_UNIT_READY;
+
+ if (do_command(esp, sd, 7, 0)) {
+ DPRINTF("test_unit_ready id %d failed\n", sd->id);
+ return 0;
+ }
+
+ DPRINTF("test_unit_ready id %d success\n", sd->id);
+ return 1;
+}
+
+static unsigned int
+inquiry(esp_private_t *esp, sd_private_t *sd)
+{
+ const char *media[2] = { "UNKNOWN", "UNKNOWN"};
+
+ // Setup command = Inquiry
+ memset(esp->buffer, 0, 7);
+ esp->buffer[0] = 0x80;
+ esp->buffer[1] = INQUIRY;
+
+ esp->buffer[5] = 36;
+
+ if (do_command(esp, sd, 7, 36)) {
+ sd->present = 0;
+ sd->media = -1;
+ return 0;
+ }
+ sd->present = 1;
+ sd->media = esp->buffer[0];
+
+ switch (sd->media) {
+ case TYPE_DISK:
+ media[0] = "disk";
+ media[1] = "hd";
+ break;
+ case TYPE_ROM:
+ media[0] = "cdrom";
+ media[1] = "cd";
+ break;
+ }
+ sd->media_str[0] = media[0];
+ sd->media_str[1] = media[1];
+ memcpy(sd->model, &esp->buffer[16], 16);
+ sd->model[17] = '\0';
+
+ return 1;
+}
+
+
+static void
+ob_sd_read_blocks(sd_private_t **sd)
+{
+ cell n = POP(), cnt = n;
+ ucell blk = POP();
+ char *dest = (char*)POP();
+ int pos, spb, sect_offset;
+
+ DPRINTF("ob_sd_read_blocks id %d %lx block=%d n=%d\n", (*sd)->id, (unsigned long)dest, blk, n );
+
+ if ((*sd)->bs == 0) {
+ PUSH(0);
+ return;
+ }
+ spb = (*sd)->bs / 512;
+ while (n) {
+ sect_offset = blk / spb;
+ pos = (blk - sect_offset * spb) * 512;
+
+ if (ob_sd_read_sector(global_esp, *sd, sect_offset)) {
+ DPRINTF("ob_sd_read_blocks: error\n");
+ RET(0);
+ }
+ while (n && pos < spb * 512) {
+ memcpy(dest, global_esp->buffer + pos, 512);
+ pos += 512;
+ dest += 512;
+ n--;
+ blk++;
+ }
+ }
+ PUSH(cnt);
+}
+
+static void
+ob_sd_block_size(__attribute__((unused))sd_private_t **sd)
+{
+ PUSH(512);
+}
+
+static void
+ob_sd_open(__attribute__((unused))sd_private_t **sd)
+{
+ int ret = 1, id;
+ phandle_t ph;
+
+ fword("my-unit");
+ id = POP();
+ POP(); // unit id is 2 ints but we only need one.
+ *sd = &global_esp->sd[id];
+
+#ifdef CONFIG_DEBUG_ESP
+ {
+ char *args;
+
+ fword("my-args");
+ args = pop_fstr_copy();
+ DPRINTF("opening drive %d args %s\n", id, args);
+ free(args);
+ }
+#endif
+
+ selfword("open-deblocker");
+
+ /* interpose disk-label */
+ ph = find_dev("/packages/disk-label");
+ fword("my-args");
+ PUSH_ph( ph );
+ fword("interpose");
+
+ RET ( -ret );
+}
+
+static void
+ob_sd_close(__attribute__((unused)) sd_private_t **sd)
+{
+ selfword("close-deblocker");
+}
+
+NODE_METHODS(ob_sd) = {
+ { "open", ob_sd_open },
+ { "close", ob_sd_close },
+ { "read-blocks", ob_sd_read_blocks },
+ { "block-size", ob_sd_block_size },
+};
+
+
+static int
+espdma_init(unsigned int slot, uint64_t base, unsigned long offset,
+ struct esp_dma *espdma)
+{
+ espdma->regs = (void *)ofmem_map_io(base + (uint64_t)offset, 0x10);
+
+ if (espdma->regs == NULL) {
+ DPRINTF("espdma_init: cannot map registers\n");
+ return -1;
+ }
+
+ DPRINTF("dma1: ");
+
+ switch ((espdma->regs->cond_reg) & DMA_DEVICE_ID) {
+ case DMA_VERS0:
+ espdma->revision = dvmarev0;
+ DPRINTF("Revision 0 ");
+ break;
+ case DMA_ESCV1:
+ espdma->revision = dvmaesc1;
+ DPRINTF("ESC Revision 1 ");
+ break;
+ case DMA_VERS1:
+ espdma->revision = dvmarev1;
+ DPRINTF("Revision 1 ");
+ break;
+ case DMA_VERS2:
+ espdma->revision = dvmarev2;
+ DPRINTF("Revision 2 ");
+ break;
+ case DMA_VERHME:
+ espdma->revision = dvmahme;
+ DPRINTF("HME DVMA gate array ");
+ break;
+ case DMA_VERSPLUS:
+ espdma->revision = dvmarevplus;
+ DPRINTF("Revision 1 PLUS ");
+ break;
+ default:
+ DPRINTF("unknown dma version %x",
+ (espdma->regs->cond_reg) & DMA_DEVICE_ID);
+ /* espdma->allocated = 1; */
+ break;
+ }
+ DPRINTF("\n");
+
+ push_str("/iommu/sbus/espdma");
+ fword("find-device");
+
+ /* set reg */
+ PUSH(slot);
+ fword("encode-int");
+ PUSH(offset);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x00000010);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ return 0;
+}
+
+static void
+ob_esp_initialize(__attribute__((unused)) esp_private_t **esp)
+{
+ phandle_t ph = get_cur_dev();
+
+ set_int_property(ph, "#address-cells", 2);
+ set_int_property(ph, "#size-cells", 0);
+
+ /* set device type */
+ push_str("scsi");
+ fword("device-type");
+
+ /* QEMU's ESP emulation does not support mixing DMA and FIFO messages. By
+ setting this attribute, we prevent the Solaris ESP kernel driver from
+ trying to use this feature when booting a disk image (and failing) */
+ PUSH(0x58);
+ fword("encode-int");
+ push_str("scsi-options");
+ fword("property");
+
+ PUSH(0x24);
+ fword("encode-int");
+ PUSH(0);
+ fword("encode-int");
+ fword("encode+");
+ push_str("intr");
+ fword("property");
+}
+
+static void
+ob_esp_decodeunit(__attribute__((unused)) esp_private_t **esp)
+{
+ fword("decode-unit-scsi");
+}
+
+
+static void
+ob_esp_encodeunit(__attribute__((unused)) esp_private_t **esp)
+{
+ fword("encode-unit-scsi");
+}
+
+NODE_METHODS(ob_esp) = {
+ { NULL, ob_esp_initialize },
+ { "decode-unit", ob_esp_decodeunit },
+ { "encode-unit", ob_esp_encodeunit },
+};
+
+static void
+add_alias(const char *device, const char *alias)
+{
+ DPRINTF("add_alias dev \"%s\" = alias \"%s\"\n", device, alias);
+ push_str("/aliases");
+ fword("find-device");
+ push_str(device);
+ fword("encode-string");
+ push_str(alias);
+ fword("property");
+}
+
+int
+ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset,
+ unsigned long dmaoffset)
+{
+ int id, diskcount = 0, cdcount = 0, *counter_ptr;
+ char nodebuff[256], aliasbuff[256];
+ esp_private_t *esp;
+ unsigned int i;
+
+ DPRINTF("Initializing SCSI...");
+
+ esp = malloc(sizeof(esp_private_t));
+ if (!esp) {
+ DPRINTF("Can't allocate ESP private structure\n");
+ return -1;
+ }
+
+ global_esp = esp;
+
+ if (espdma_init(slot, base, dmaoffset, &esp->espdma) != 0) {
+ return -1;
+ }
+ /* Get the IO region */
+ esp->ll = (void *)ofmem_map_io(base + (uint64_t)espoffset,
+ sizeof(struct esp_regs));
+ if (esp->ll == NULL) {
+ DPRINTF("Can't map ESP registers\n");
+ return -1;
+ }
+
+ esp->buffer = (void *)dvma_alloc(BUFSIZE, &esp->buffer_dvma);
+ if (!esp->buffer || !esp->buffer_dvma) {
+ DPRINTF("Can't get a DVMA buffer\n");
+ return -1;
+ }
+
+ // Chip reset
+ esp->ll->regs[ESP_CMD] = ESP_CMD_RC;
+
+ DPRINTF("ESP at 0x%lx, buffer va 0x%lx dva 0x%lx\n", (unsigned long)esp,
+ (unsigned long)esp->buffer, (unsigned long)esp->buffer_dvma);
+ DPRINTF("done\n");
+ DPRINTF("Initializing SCSI devices...");
+
+ for (id = 0; id < 8; id++) {
+ esp->sd[id].id = id;
+ if (!inquiry(esp, &esp->sd[id])) {
+ DPRINTF("Unit %d not present\n", id);
+ continue;
+ }
+ /* Clear Unit Attention condition from reset */
+ for (i = 0; i < 5; i++) {
+ if (test_unit_ready(esp, &esp->sd[id])) {
+ break;
+ }
+ }
+ if (i == 5) {
+ DPRINTF("Unit %d present but won't become ready\n", id);
+ continue;
+ }
+ DPRINTF("Unit %d present\n", id);
+ read_capacity(esp, &esp->sd[id]);
+
+#ifdef CONFIG_DEBUG_ESP
+ dump_drive(&esp->sd[id]);
+#endif
+ }
+
+ REGISTER_NAMED_NODE(ob_esp, "/iommu/sbus/espdma/esp");
+ device_end();
+ /* set reg */
+ push_str("/iommu/sbus/espdma/esp");
+ fword("find-device");
+ PUSH(slot);
+ fword("encode-int");
+ PUSH(espoffset);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x00000010);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ PUSH(0x02625a00);
+ fword("encode-int");
+ push_str("clock-frequency");
+ fword("property");
+
+ for (id = 0; id < 8; id++) {
+ if (!esp->sd[id].present)
+ continue;
+ push_str("/iommu/sbus/espdma/esp");
+ fword("find-device");
+ fword("new-device");
+ push_str("sd");
+ fword("device-name");
+ push_str("block");
+ fword("device-type");
+ fword("is-deblocker");
+ PUSH(id);
+ fword("encode-int");
+ PUSH(0);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+ fword("finish-device");
+ snprintf(nodebuff, sizeof(nodebuff), "/iommu/sbus/espdma/esp/sd@%d,0",
+ id);
+ REGISTER_NODE_METHODS(ob_sd, nodebuff);
+ if (esp->sd[id].media == TYPE_ROM) {
+ counter_ptr = &cdcount;
+ } else {
+ counter_ptr = &diskcount;
+ }
+ if (*counter_ptr == 0) {
+ add_alias(nodebuff, esp->sd[id].media_str[0]);
+ add_alias(nodebuff, esp->sd[id].media_str[1]);
+ }
+ snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
+ esp->sd[id].media_str[0], *counter_ptr);
+ add_alias(nodebuff, aliasbuff);
+ snprintf(aliasbuff, sizeof(aliasbuff), "%s%d",
+ esp->sd[id].media_str[1], *counter_ptr);
+ add_alias(nodebuff, aliasbuff);
+ snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)", id);
+ add_alias(nodebuff, aliasbuff);
+ snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)@0,0", id);
+ add_alias(nodebuff, aliasbuff);
+ (*counter_ptr)++;
+ }
+ DPRINTF("done\n");
+
+ return 0;
+}
diff --git a/roms/openbios/drivers/esp.fs b/roms/openbios/drivers/esp.fs
new file mode 100644
index 00000000..9e37c0a0
--- /dev/null
+++ b/roms/openbios/drivers/esp.fs
@@ -0,0 +1,18 @@
+\ -------------------------------------------------------------------------
+\ SCSI encode/decode unit
+\ -------------------------------------------------------------------------
+
+: decode-unit-scsi ( str len -- id lun )
+ ascii , left-split
+ ( addr-R len-R addr-L len-L )
+ parse-hex
+ -rot parse-hex
+ swap
+;
+
+: encode-unit-scsi ( id lun -- str len)
+ swap
+ pocket tohexstr
+ " ," pocket tmpstrcat >r
+ rot pocket tohexstr r> tmpstrcat drop
+;
diff --git a/roms/openbios/drivers/esp.h b/roms/openbios/drivers/esp.h
new file mode 100644
index 00000000..2b9bd5e0
--- /dev/null
+++ b/roms/openbios/drivers/esp.h
@@ -0,0 +1,269 @@
+/* $Id: esp.h,v 1.28 2000/03/30 01:33:17 davem Exp $
+ * esp.h: Defines and structures for the Sparc ESP (Enhanced SCSI
+ * Processor) driver under Linux.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_ESP_H
+#define _SPARC_ESP_H
+
+/* For dvma controller register definitions. */
+#include "asm/dma.h"
+
+/* The ESP SCSI controllers have their register sets in three
+ * "classes":
+ *
+ * 1) Registers which are both read and write.
+ * 2) Registers which are read only.
+ * 3) Registers which are write only.
+ *
+ * Yet, they all live within the same IO space.
+ */
+
+/* All the ESP registers are one byte each and are accessed longwords
+ * apart with a big-endian ordering to the bytes.
+ */
+ /* Access Description Offset */
+#define ESP_TCLOW 0x00UL /* rw Low bits of the transfer count 0x00 */
+#define ESP_TCMED 0x04UL /* rw Mid bits of the transfer count 0x04 */
+#define ESP_FDATA 0x08UL /* rw FIFO data bits 0x08 */
+#define ESP_CMD 0x0cUL /* rw SCSI command bits 0x0c */
+#define ESP_STATUS 0x10UL /* ro ESP status register 0x10 */
+#define ESP_BUSID ESP_STATUS /* wo Bus ID for select/reselect 0x10 */
+#define ESP_INTRPT 0x14UL /* ro Kind of interrupt 0x14 */
+#define ESP_TIMEO ESP_INTRPT /* wo Timeout value for select/resel 0x14 */
+#define ESP_SSTEP 0x18UL /* ro Sequence step register 0x18 */
+#define ESP_STP ESP_SSTEP /* wo Transfer period per sync 0x18 */
+#define ESP_FFLAGS 0x1cUL /* ro Bits of current FIFO info 0x1c */
+#define ESP_SOFF ESP_FFLAGS /* wo Sync offset 0x1c */
+#define ESP_CFG1 0x20UL /* rw First configuration register 0x20 */
+#define ESP_CFACT 0x24UL /* wo Clock conversion factor 0x24 */
+#define ESP_STATUS2 ESP_CFACT /* ro HME status2 register 0x24 */
+#define ESP_CTEST 0x28UL /* wo Chip test register 0x28 */
+#define ESP_CFG2 0x2cUL /* rw Second configuration register 0x2c */
+#define ESP_CFG3 0x30UL /* rw Third configuration register 0x30 */
+#define ESP_TCHI 0x38UL /* rw High bits of transfer count 0x38 */
+#define ESP_UID ESP_TCHI /* ro Unique ID code 0x38 */
+#define FAS_RLO ESP_TCHI /* rw HME extended counter 0x38 */
+#define ESP_FGRND 0x3cUL /* rw Data base for fifo 0x3c */
+#define FAS_RHI ESP_FGRND /* rw HME extended counter 0x3c */
+#define ESP_REG_SIZE 0x40UL
+
+/* Various revisions of the ESP board. */
+enum esp_rev {
+ esp100 = 0x00, /* NCR53C90 - very broken */
+ esp100a = 0x01, /* NCR53C90A */
+ esp236 = 0x02,
+ fas236 = 0x03,
+ fas100a = 0x04,
+ fast = 0x05,
+ fashme = 0x06,
+ espunknown = 0x07
+};
+
+/* Bitfield meanings for the above registers. */
+
+/* ESP config reg 1, read-write, found on all ESP chips */
+#define ESP_CONFIG1_ID 0x07 /* My BUS ID bits */
+#define ESP_CONFIG1_CHTEST 0x08 /* Enable ESP chip tests */
+#define ESP_CONFIG1_PENABLE 0x10 /* Enable parity checks */
+#define ESP_CONFIG1_PARTEST 0x20 /* Parity test mode enabled? */
+#define ESP_CONFIG1_SRRDISAB 0x40 /* Disable SCSI reset reports */
+#define ESP_CONFIG1_SLCABLE 0x80 /* Enable slow cable mode */
+
+/* ESP config reg 2, read-write, found only on esp100a+esp200+esp236 chips */
+#define ESP_CONFIG2_DMAPARITY 0x01 /* enable DMA Parity (200,236) */
+#define ESP_CONFIG2_REGPARITY 0x02 /* enable reg Parity (200,236) */
+#define ESP_CONFIG2_BADPARITY 0x04 /* Bad parity target abort */
+#define ESP_CONFIG2_SCSI2ENAB 0x08 /* Enable SCSI-2 features (tmode only) */
+#define ESP_CONFIG2_HI 0x10 /* High Impedance DREQ ??? */
+#define ESP_CONFIG2_HMEFENAB 0x10 /* HME features enable */
+#define ESP_CONFIG2_BCM 0x20 /* Enable byte-ctrl (236) */
+#define ESP_CONFIG2_DISPINT 0x20 /* Disable pause irq (hme) */
+#define ESP_CONFIG2_FENAB 0x40 /* Enable features (fas100,esp216) */
+#define ESP_CONFIG2_SPL 0x40 /* Enable status-phase latch (esp236) */
+#define ESP_CONFIG2_MKDONE 0x40 /* HME magic feature */
+#define ESP_CONFIG2_HME32 0x80 /* HME 32 extended */
+#define ESP_CONFIG2_MAGIC 0xe0 /* Invalid bits... */
+
+/* ESP config register 3 read-write, found only esp236+fas236+fas100a+hme chips */
+#define ESP_CONFIG3_FCLOCK 0x01 /* FAST SCSI clock rate (esp100a/hme) */
+#define ESP_CONFIG3_TEM 0x01 /* Enable thresh-8 mode (esp/fas236) */
+#define ESP_CONFIG3_FAST 0x02 /* Enable FAST SCSI (esp100a/hme) */
+#define ESP_CONFIG3_ADMA 0x02 /* Enable alternate-dma (esp/fas236) */
+#define ESP_CONFIG3_TENB 0x04 /* group2 SCSI2 support (esp100a/hme) */
+#define ESP_CONFIG3_SRB 0x04 /* Save residual byte (esp/fas236) */
+#define ESP_CONFIG3_TMS 0x08 /* Three-byte msg's ok (esp100a/hme) */
+#define ESP_CONFIG3_FCLK 0x08 /* Fast SCSI clock rate (esp/fas236) */
+#define ESP_CONFIG3_IDMSG 0x10 /* ID message checking (esp100a/hme) */
+#define ESP_CONFIG3_FSCSI 0x10 /* Enable FAST SCSI (esp/fas236) */
+#define ESP_CONFIG3_GTM 0x20 /* group2 SCSI2 support (esp/fas236) */
+#define ESP_CONFIG3_IDBIT3 0x20 /* Bit 3 of HME SCSI-ID (hme) */
+#define ESP_CONFIG3_TBMS 0x40 /* Three-byte msg's ok (esp/fas236) */
+#define ESP_CONFIG3_EWIDE 0x40 /* Enable Wide-SCSI (hme) */
+#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */
+#define ESP_CONFIG3_OBPUSH 0x80 /* Push odd-byte to dma (hme) */
+
+/* ESP command register read-write */
+/* Group 1 commands: These may be sent at any point in time to the ESP
+ * chip. None of them can generate interrupts 'cept
+ * the "SCSI bus reset" command if you have not disabled
+ * SCSI reset interrupts in the config1 ESP register.
+ */
+#define ESP_CMD_NULL 0x00 /* Null command, ie. a nop */
+#define ESP_CMD_FLUSH 0x01 /* FIFO Flush */
+#define ESP_CMD_RC 0x02 /* Chip reset */
+#define ESP_CMD_RS 0x03 /* SCSI bus reset */
+
+/* Group 2 commands: ESP must be an initiator and connected to a target
+ * for these commands to work.
+ */
+#define ESP_CMD_TI 0x10 /* Transfer Information */
+#define ESP_CMD_ICCSEQ 0x11 /* Initiator cmd complete sequence */
+#define ESP_CMD_MOK 0x12 /* Message okie-dokie */
+#define ESP_CMD_TPAD 0x18 /* Transfer Pad */
+#define ESP_CMD_SATN 0x1a /* Set ATN */
+#define ESP_CMD_RATN 0x1b /* De-assert ATN */
+
+/* Group 3 commands: ESP must be in the MSGOUT or MSGIN state and be connected
+ * to a target as the initiator for these commands to work.
+ */
+#define ESP_CMD_SMSG 0x20 /* Send message */
+#define ESP_CMD_SSTAT 0x21 /* Send status */
+#define ESP_CMD_SDATA 0x22 /* Send data */
+#define ESP_CMD_DSEQ 0x23 /* Discontinue Sequence */
+#define ESP_CMD_TSEQ 0x24 /* Terminate Sequence */
+#define ESP_CMD_TCCSEQ 0x25 /* Target cmd cmplt sequence */
+#define ESP_CMD_DCNCT 0x27 /* Disconnect */
+#define ESP_CMD_RMSG 0x28 /* Receive Message */
+#define ESP_CMD_RCMD 0x29 /* Receive Command */
+#define ESP_CMD_RDATA 0x2a /* Receive Data */
+#define ESP_CMD_RCSEQ 0x2b /* Receive cmd sequence */
+
+/* Group 4 commands: The ESP must be in the disconnected state and must
+ * not be connected to any targets as initiator for
+ * these commands to work.
+ */
+#define ESP_CMD_RSEL 0x40 /* Reselect */
+#define ESP_CMD_SEL 0x41 /* Select w/o ATN */
+#define ESP_CMD_SELA 0x42 /* Select w/ATN */
+#define ESP_CMD_SELAS 0x43 /* Select w/ATN & STOP */
+#define ESP_CMD_ESEL 0x44 /* Enable selection */
+#define ESP_CMD_DSEL 0x45 /* Disable selections */
+#define ESP_CMD_SA3 0x46 /* Select w/ATN3 */
+#define ESP_CMD_RSEL3 0x47 /* Reselect3 */
+
+/* This bit enables the ESP's DMA on the SBus */
+#define ESP_CMD_DMA 0x80 /* Do DMA? */
+
+
+/* ESP status register read-only */
+#define ESP_STAT_PIO 0x01 /* IO phase bit */
+#define ESP_STAT_PCD 0x02 /* CD phase bit */
+#define ESP_STAT_PMSG 0x04 /* MSG phase bit */
+#define ESP_STAT_PMASK 0x07 /* Mask of phase bits */
+#define ESP_STAT_TDONE 0x08 /* Transfer Completed */
+#define ESP_STAT_TCNT 0x10 /* Transfer Counter Is Zero */
+#define ESP_STAT_PERR 0x20 /* Parity error */
+#define ESP_STAT_SPAM 0x40 /* Real bad error */
+/* This indicates the 'interrupt pending' condition on esp236, it is a reserved
+ * bit on other revs of the ESP.
+ */
+#define ESP_STAT_INTR 0x80 /* Interrupt */
+
+/* HME only: status 2 register */
+#define ESP_STAT2_SCHBIT 0x01 /* Upper bits 3-7 of sstep enabled */
+#define ESP_STAT2_FFLAGS 0x02 /* The fifo flags are now latched */
+#define ESP_STAT2_XCNT 0x04 /* The transfer counter is latched */
+#define ESP_STAT2_CREGA 0x08 /* The command reg is active now */
+#define ESP_STAT2_WIDE 0x10 /* Interface on this adapter is wide */
+#define ESP_STAT2_F1BYTE 0x20 /* There is one byte at top of fifo */
+#define ESP_STAT2_FMSB 0x40 /* Next byte in fifo is most significant */
+#define ESP_STAT2_FEMPTY 0x80 /* FIFO is empty */
+
+/* The status register can be masked with ESP_STAT_PMASK and compared
+ * with the following values to determine the current phase the ESP
+ * (at least thinks it) is in. For our purposes we also add our own
+ * software 'done' bit for our phase management engine.
+ */
+#define ESP_DOP (0) /* Data Out */
+#define ESP_DIP (ESP_STAT_PIO) /* Data In */
+#define ESP_CMDP (ESP_STAT_PCD) /* Command */
+#define ESP_STATP (ESP_STAT_PCD|ESP_STAT_PIO) /* Status */
+#define ESP_MOP (ESP_STAT_PMSG|ESP_STAT_PCD) /* Message Out */
+#define ESP_MIP (ESP_STAT_PMSG|ESP_STAT_PCD|ESP_STAT_PIO) /* Message In */
+
+/* ESP interrupt register read-only */
+#define ESP_INTR_S 0x01 /* Select w/o ATN */
+#define ESP_INTR_SATN 0x02 /* Select w/ATN */
+#define ESP_INTR_RSEL 0x04 /* Reselected */
+#define ESP_INTR_FDONE 0x08 /* Function done */
+#define ESP_INTR_BSERV 0x10 /* Bus service */
+#define ESP_INTR_DC 0x20 /* Disconnect */
+#define ESP_INTR_IC 0x40 /* Illegal command given */
+#define ESP_INTR_SR 0x80 /* SCSI bus reset detected */
+
+/* Interrupt status macros */
+#define ESP_SRESET_IRQ(esp) ((esp)->intreg & (ESP_INTR_SR))
+#define ESP_ILLCMD_IRQ(esp) ((esp)->intreg & (ESP_INTR_IC))
+#define ESP_SELECT_WITH_ATN_IRQ(esp) ((esp)->intreg & (ESP_INTR_SATN))
+#define ESP_SELECT_WITHOUT_ATN_IRQ(esp) ((esp)->intreg & (ESP_INTR_S))
+#define ESP_SELECTION_IRQ(esp) ((ESP_SELECT_WITH_ATN_IRQ(esp)) || \
+ (ESP_SELECT_WITHOUT_ATN_IRQ(esp)))
+#define ESP_RESELECTION_IRQ(esp) ((esp)->intreg & (ESP_INTR_RSEL))
+
+/* ESP sequence step register read-only */
+#define ESP_STEP_VBITS 0x07 /* Valid bits */
+#define ESP_STEP_ASEL 0x00 /* Selection&Arbitrate cmplt */
+#define ESP_STEP_SID 0x01 /* One msg byte sent */
+#define ESP_STEP_NCMD 0x02 /* Was not in command phase */
+#define ESP_STEP_PPC 0x03 /* Early phase chg caused cmnd
+ * bytes to be lost
+ */
+#define ESP_STEP_FINI4 0x04 /* Command was sent ok */
+
+/* Ho hum, some ESP's set the step register to this as well... */
+#define ESP_STEP_FINI5 0x05
+#define ESP_STEP_FINI6 0x06
+#define ESP_STEP_FINI7 0x07
+
+/* ESP chip-test register read-write */
+#define ESP_TEST_TARG 0x01 /* Target test mode */
+#define ESP_TEST_INI 0x02 /* Initiator test mode */
+#define ESP_TEST_TS 0x04 /* Tristate test mode */
+
+/* ESP unique ID register read-only, found on fas236+fas100a only */
+#define ESP_UID_F100A 0x00 /* ESP FAS100A */
+#define ESP_UID_F236 0x02 /* ESP FAS236 */
+#define ESP_UID_REV 0x07 /* ESP revision */
+#define ESP_UID_FAM 0xf8 /* ESP family */
+
+/* ESP fifo flags register read-only */
+/* Note that the following implies a 16 byte FIFO on the ESP. */
+#define ESP_FF_FBYTES 0x1f /* Num bytes in FIFO */
+#define ESP_FF_ONOTZERO 0x20 /* offset ctr not zero (esp100) */
+#define ESP_FF_SSTEP 0xe0 /* Sequence step */
+
+/* ESP clock conversion factor register write-only */
+#define ESP_CCF_F0 0x00 /* 35.01MHz - 40MHz */
+#define ESP_CCF_NEVER 0x01 /* Set it to this and die */
+#define ESP_CCF_F2 0x02 /* 10MHz */
+#define ESP_CCF_F3 0x03 /* 10.01MHz - 15MHz */
+#define ESP_CCF_F4 0x04 /* 15.01MHz - 20MHz */
+#define ESP_CCF_F5 0x05 /* 20.01MHz - 25MHz */
+#define ESP_CCF_F6 0x06 /* 25.01MHz - 30MHz */
+#define ESP_CCF_F7 0x07 /* 30.01MHz - 35MHz */
+
+/* HME only... */
+#define ESP_BUSID_RESELID 0x10
+#define ESP_BUSID_CTR32BIT 0x40
+
+#define ESP_BUS_TIMEOUT 275 /* In milli-seconds */
+#define ESP_TIMEO_CONST 8192
+#define ESP_NEG_DEFP(mhz, cfact) \
+ ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
+#define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000))
+#define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000))
+
+#endif /* !(_SPARC_ESP_H) */
diff --git a/roms/openbios/drivers/floppy.c b/roms/openbios/drivers/floppy.c
new file mode 100644
index 00000000..329987b1
--- /dev/null
+++ b/roms/openbios/drivers/floppy.c
@@ -0,0 +1,1179 @@
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "kernel/kernel.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "drivers/drivers.h"
+
+#include "timer.h"
+
+/* DECLARE data structures for the nodes. */
+DECLARE_UNNAMED_NODE( ob_floppy, INSTALL_OPEN, 2*sizeof(int) );
+
+#ifdef CONFIG_DEBUG_FLOPPY
+#define printk_info printk
+#define printk_debug printk
+#else
+#define printk_info(x ...)
+#define printk_debug(x ...)
+#endif
+#define printk_err printk
+
+#define FD_DRIVE 0
+
+
+#define FD_STATUS_A (0) /* Status register A */
+#define FD_STATUS_B (1) /* Status register B */
+#define FD_DOR (2) /* Digital Output Register */
+#define FD_TDR (3) /* Tape Drive Register */
+#define FD_STATUS (4) /* Main Status Register */
+#define FD_DSR (4) /* Data Rate Select Register (old) */
+#define FD_DATA (5) /* Data Transfer (FIFO) register */
+#define FD_DIR (7) /* Digital Input Register (read) */
+#define FD_DCR (7) /* Diskette Control Register (write)*/
+
+/* Bit of FD_STATUS_A */
+#define STA_INT_PENDING 0x80 /* Interrupt Pending */
+
+/* DOR */
+#define DOR_DRIVE0 0x00
+#define DOR_DRIVE1 0x01
+#define DOR_DRIVE2 0x02
+#define DOR_DRIVE3 0x03
+#define DOR_DRIVE_MASK 0x03
+#define DOR_NO_RESET 0x04
+#define DOR_DMA_EN 0x08
+#define DOR_MOT_EN0 0x10
+#define DOR_MOT_EN1 0x20
+#define DOR_MOT_EN2 0x40
+#define DOR_MOT_EN3 0x80
+
+/* Bits of main status register */
+#define STATUS_BUSYMASK 0x0F /* drive busy mask */
+#define STATUS_BUSY 0x10 /* FDC busy */
+#define STATUS_NON_DMA 0x20 /* 0- DMA mode */
+#define STATUS_DIR 0x40 /* 0- cpu->fdc */
+#define STATUS_READY 0x80 /* Data reg ready */
+
+/* Bits of FD_ST0 */
+#define ST0_DS 0x03 /* drive select mask */
+#define ST0_HA 0x04 /* Head (Address) */
+#define ST0_NR 0x08 /* Not Ready */
+#define ST0_ECE 0x10 /* Equipment check error */
+#define ST0_SE 0x20 /* Seek end */
+#define ST0_INTR 0xC0 /* Interrupt code mask */
+#define ST0_INTR_OK (0 << 6)
+#define ST0_INTR_ERROR (1 << 6)
+#define ST0_INTR_INVALID (2 << 6)
+#define ST0_INTR_POLL_ERROR (3 << 6)
+
+/* Bits of FD_ST1 */
+#define ST1_MAM 0x01 /* Missing Address Mark */
+#define ST1_WP 0x02 /* Write Protect */
+#define ST1_ND 0x04 /* No Data - unreadable */
+#define ST1_OR 0x10 /* OverRun */
+#define ST1_CRC 0x20 /* CRC error in data or addr */
+#define ST1_EOC 0x80 /* End Of Cylinder */
+
+/* Bits of FD_ST2 */
+#define ST2_MAM 0x01 /* Missing Address Mark (again) */
+#define ST2_BC 0x02 /* Bad Cylinder */
+#define ST2_SNS 0x04 /* Scan Not Satisfied */
+#define ST2_SEH 0x08 /* Scan Equal Hit */
+#define ST2_WC 0x10 /* Wrong Cylinder */
+#define ST2_CRC 0x20 /* CRC error in data field */
+#define ST2_CM 0x40 /* Control Mark = deleted */
+
+/* Bits of FD_ST3 */
+#define ST3_HA 0x04 /* Head (Address) */
+#define ST3_DS 0x08 /* drive is double-sided */
+#define ST3_TZ 0x10 /* Track Zero signal (1=track 0) */
+#define ST3_RY 0x20 /* drive is ready */
+#define ST3_WP 0x40 /* Write Protect */
+#define ST3_FT 0x80 /* Drive Fault */
+
+/* Values for FD_COMMAND */
+#define FD_RECALIBRATE 0x07 /* move to track 0 */
+#define FD_SEEK 0x0F /* seek track */
+#define FD_READ 0xA6 /* read with MT, SKip deleted */
+#define FD_WRITE 0xC5 /* write with MT, MFM */
+#define FD_SENSEI 0x08 /* Sense Interrupt Status */
+#define FD_SPECIFY 0x03 /* specify HUT etc */
+#define FD_FORMAT 0x4D /* format one track */
+#define FD_VERSION 0x10 /* get version code */
+#define FD_CONFIGURE 0x13 /* configure FIFO operation */
+#define FD_PERPENDICULAR 0x12 /* perpendicular r/w mode */
+#define FD_GETSTATUS 0x04 /* read ST3 */
+#define FD_DUMPREGS 0x0E /* dump the contents of the fdc regs */
+#define FD_READID 0xEA /* prints the header of a sector */
+#define FD_UNLOCK 0x14 /* Fifo config unlock */
+#define FD_LOCK 0x94 /* Fifo config lock */
+#define FD_RSEEK_OUT 0x8f /* seek out (i.e. to lower tracks) */
+#define FD_RSEEK_IN 0xcf /* seek in (i.e. to higher tracks) */
+
+
+/* the following commands are new in the 82078. They are not used in the
+ * floppy driver, except the first three. These commands may be useful for apps
+ * which use the FDRAWCMD interface. For doc, get the 82078 spec sheets at
+ * http://www-techdoc.intel.com/docs/periph/fd_contr/datasheets/ */
+
+#define FD_PARTID 0x18 /* part id ("extended" version cmd) */
+#define FD_SAVE 0x2e /* save fdc regs for later restore */
+#define FD_DRIVESPEC 0x8e /* drive specification: Access to the
+ * 2 Mbps data transfer rate for tape
+ * drives */
+
+#define FD_RESTORE 0x4e /* later restore */
+#define FD_POWERDOWN 0x27 /* configure FDC's powersave features */
+#define FD_FORMAT_N_WRITE 0xef /* format and write in one go. */
+#define FD_OPTION 0x33 /* ISO format (which is a clean way to
+ * pack more sectors on a track) */
+
+/* FDC version return types */
+#define FDC_NONE 0x00
+#define FDC_UNKNOWN 0x10 /* DO NOT USE THIS TYPE EXCEPT IF IDENTIFICATION
+ FAILS EARLY */
+#define FDC_8272A 0x20 /* Intel 8272a, NEC 765 */
+#define FDC_765ED 0x30 /* Non-Intel 1MB-compatible FDC, can't detect */
+#define FDC_82072 0x40 /* Intel 82072; 8272a + FIFO + DUMPREGS */
+#define FDC_82072A 0x45 /* 82072A (on Sparcs) */
+#define FDC_82077_ORIG 0x51 /* Original version of 82077AA, sans LOCK */
+#define FDC_82077 0x52 /* 82077AA-1 */
+#define FDC_82078_UNKN 0x5f /* Unknown 82078 variant */
+#define FDC_82078 0x60 /* 44pin 82078 or 64pin 82078SL */
+#define FDC_82078_1 0x61 /* 82078-1 (2Mbps fdc) */
+#define FDC_S82078B 0x62 /* S82078B (first seen on Adaptec AVA-2825 VLB
+ * SCSI/EIDE/Floppy controller) */
+#define FDC_87306 0x63 /* National Semiconductor PC 87306 */
+
+/*
+ * Beware: the fdc type list is roughly sorted by increasing features.
+ * Presence of features is tested by comparing the FDC version id with the
+ * "oldest" version that has the needed feature.
+ * If during FDC detection, an obscure test fails late in the sequence, don't
+ * assign FDC_UNKNOWN. Else the FDC will be treated as a dumb 8272a, or worse.
+ * This is especially true if the tests are unneeded.
+ */
+
+/* Parameters for a 1.44 3.5" disk */
+#define DISK_H1440_SIZE 2880
+#define DISK_H1440_SECT 18
+#define DISK_H1440_HEAD 2
+#define DISK_H1440_TRACK 80
+#define DISK_H1440_STRETCH 0
+#define DISK_H1440_GAP 0x1B
+#define DISK_H1440_RATE 0x00
+#define DISK_H1440_SPEC1 0xCF
+#define DISK_H1440_FMT_GAP 0x6C
+
+/* Parameters for a 1.44 3.5" drive */
+#define DRIVE_H1440_MAX_DTR 500
+#define DRIVE_H1440_HLT 16 /* ms */
+#define DRIVE_H1440_HUT 16 /* ms */
+#define DRIVE_H1440_SRT 4000 /* us */
+#define DRIVE_H1440_SPINUP 400 /* ms */
+#define DRIVE_H1440_SPINDOWN 3000 /* ms */
+#define DRIVE_H1440_SPINDOWN_OFFSET 10
+#define DRIVE_H1440_SELECT_DELAY 20 /* ms */
+#define DRIVE_H1440_RPS 5
+#define DRIVE_H1440_TRACKS 83
+#define DRIVE_H1440_TIMEOUT 3000 /* ms */
+#define DRIVE_H1440_INTERLEAVE_SECT 20
+
+/* Floppy drive configuration */
+#define FIFO_DEPTH 10
+#define USE_IMPLIED_SEEK 0
+#define USE_FIFO 1
+#define FIFO_THRESHOLD 10
+#define TRACK_PRECOMPENSATION 0
+
+#define SLOW_FLOPPY 0
+
+#define FD_RESET_DELAY 20 /* microseconds */
+
+/*
+ * FDC state
+ */
+static struct drive_state {
+ unsigned track;
+} drive_state[1];
+
+static struct floppy_fdc_state {
+ int in_sync;
+ int spec1; /* spec1 value last used */
+ int spec2; /* spec2 value last used */
+ int dtr;
+ unsigned char dor;
+ unsigned char version; /* FDC version code */
+ void (*fdc_outb)(unsigned char data, unsigned long port);
+ unsigned char (*fdc_inb)(unsigned long port);
+ unsigned long io_base;
+ unsigned long mmio_base;
+} fdc_state;
+
+/* Synchronization of FDC access. */
+#define FD_COMMAND_NONE -1
+#define FD_COMMAND_ERROR 2
+#define FD_COMMAND_OKAY 3
+
+/*
+ * globals used by 'result()'
+ */
+#define MAX_REPLIES 16
+
+static void show_floppy(void);
+static void floppy_reset(void);
+
+/*
+ * IO port operations
+ */
+static unsigned char
+ob_fdc_inb(unsigned long port)
+{
+ return inb(fdc_state.io_base + port);
+}
+
+static void
+ob_fdc_outb(unsigned char data, unsigned long port)
+{
+ outb(data, fdc_state.io_base + port);
+}
+
+/*
+ * MMIO operations
+ */
+static unsigned char
+ob_fdc_mmio_readb(unsigned long port)
+{
+ return *(unsigned char *)(fdc_state.mmio_base + port);
+}
+
+static void
+ob_fdc_mmio_writeb(unsigned char data, unsigned long port)
+{
+ *(unsigned char *)(fdc_state.mmio_base + port) = data;
+}
+
+static int set_dor(char mask, char data)
+{
+ unsigned char newdor,olddor;
+
+ olddor = fdc_state.dor;
+ newdor = (olddor & mask) | data;
+ if (newdor != olddor){
+ fdc_state.dor = newdor;
+ fdc_state.fdc_outb(newdor, FD_DOR);
+ }
+ return olddor;
+}
+
+/* waits until the fdc becomes ready */
+static int wait_til_ready(void)
+{
+ int counter, status;
+ for (counter = 0; counter < 10000; counter++) {
+ status = fdc_state.fdc_inb(FD_STATUS);
+ if (status & STATUS_READY) {
+ return status;
+ }
+ }
+ printk_debug("Getstatus times out (%x)\n", status);
+ show_floppy();
+ return -3;
+}
+
+
+/* sends a command byte to the fdc */
+static int output_byte(unsigned char byte)
+{
+ int status;
+
+ if ((status = wait_til_ready()) < 0)
+ return status;
+ if ((status & (STATUS_READY|STATUS_DIR|STATUS_NON_DMA)) == STATUS_READY){
+ fdc_state.fdc_outb(byte,FD_DATA);
+ return 0;
+ }
+ printk_debug("Unable to send byte %x to FDC_STATE. Status=%x\n",
+ byte, status);
+
+ show_floppy();
+ return -2;
+}
+
+/* gets the response from the fdc */
+static int result(unsigned char *reply_buffer, int max_replies)
+{
+ int i, status=0;
+
+ for(i=0; i < max_replies; i++) {
+ if ((status = wait_til_ready()) < 0)
+ break;
+ status &= STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_NON_DMA;
+ if ((status & ~STATUS_BUSY) == STATUS_READY){
+ return i;
+ }
+ if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY))
+ reply_buffer[i] = fdc_state.fdc_inb(FD_DATA);
+ else
+ break;
+ }
+ if (i == max_replies)
+ return i;
+ printk_debug("get result error. Last status=%x Read bytes=%d\n",
+ status, i);
+ show_floppy();
+ return -1;
+}
+#define MORE_OUTPUT -2
+/* does the fdc need more output? */
+static int need_more_output(void)
+{
+ unsigned char reply_buffer[MAX_REPLIES];
+ int status;
+ if ((status = wait_til_ready()) < 0)
+ return -1;
+ if ((status & (STATUS_READY|STATUS_DIR|STATUS_NON_DMA)) == STATUS_READY)
+ return MORE_OUTPUT;
+ return result(reply_buffer, MAX_REPLIES);
+}
+
+static int output_command(unsigned char *cmd, int count)
+{
+ int i, status;
+ for(i = 0; i < count; i++) {
+ if ((status = output_byte(cmd[i])) < 0) {
+ printk_err("full command not acceppted, status =%x\n",
+ status);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int output_new_command(unsigned char *cmd, int count)
+{
+ int i, status;
+ if ((status = output_byte(cmd[0])) < 0)
+ return -1;
+ if (need_more_output() != MORE_OUTPUT)
+ return -1;
+ for(i = 1; i < count; i++) {
+ if ((status = output_byte(cmd[i])) < 0) {
+ printk_err("full new command not acceppted, status =%d\n",
+ status);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/* Collect pending interrupt status */
+static unsigned char collect_interrupt(void)
+{
+ unsigned char pcn = 0xff;
+ unsigned char reply_buffer[MAX_REPLIES];
+ int nr;
+#ifdef CONFIG_DEBUG_FLOPPY
+ int i, status;
+#endif
+ nr = result(reply_buffer, MAX_REPLIES);
+ if (nr != 0) {
+ printk_debug("SENSEI\n");
+ }
+ else {
+ int max_sensei = 4;
+ do {
+ if (output_byte(FD_SENSEI) < 0)
+ break;
+ nr = result(reply_buffer, MAX_REPLIES);
+ if (nr == 2) {
+ pcn = reply_buffer[1];
+ printk_debug("SENSEI %02x %02x\n",
+ reply_buffer[0], reply_buffer[1]);
+ }
+ max_sensei--;
+ }while(((reply_buffer[0] & 0x83) != FD_DRIVE) && (nr == 2) && max_sensei);
+#ifdef CONFIG_DEBUG_FLOPPY
+ status = fdc_state.fdc_inb(FD_STATUS);
+ printk_debug("status = %x, reply_buffer=", status);
+ for(i = 0; i < nr; i++) {
+ printk_debug(" %x",
+ reply_buffer[i]);
+ }
+ printk_debug("\n");
+#else
+ fdc_state.fdc_inb(FD_STATUS);
+#endif
+ }
+
+ return pcn;
+}
+
+
+/* selects the fdc and drive, and enables the fdc's input/dma, and it's motor. */
+static void set_drive(int drive)
+{
+ int fdc = (drive >> 2) & 1;
+ int status;
+ unsigned new_dor;
+ if (drive > 3) {
+ printk_err("bad drive value\n");
+ return;
+ }
+ if (fdc != 0) {
+ printk_err("bad fdc value\n");
+ return;
+ }
+ drive &= 3;
+#if 0
+ new_dor = 8; /* Enable the controller */
+#else
+ new_dor = 0; /* Don't enable DMA on the controller */
+#endif
+ new_dor |= (1 << (drive + 4)); /* Spinup the selected drive */
+ new_dor |= drive; /* Select the drive for commands as well */
+ set_dor(0xc, new_dor);
+
+ mdelay(DRIVE_H1440_SPINUP);
+
+ status = fdc_state.fdc_inb(FD_STATUS);
+ printk_debug("set_drive status = %02x, new_dor = %02x\n",
+ status, new_dor);
+ if (status != STATUS_READY) {
+ printk_err("set_drive bad status\n");
+ }
+}
+
+
+/* Disable the motor for a given floppy drive */
+static void floppy_motor_off(int drive)
+{
+ unsigned mask;
+ printk_debug("floppy_motor_off\n");
+ /* fix the number of drives */
+ drive &= 3;
+ /* Clear the bit for the drive we care about */
+ mask = 0xff;
+ mask &= ~(1 << (drive +4));
+ /* Now clear the bit in the Digital Output Register */
+ set_dor(mask, 0);
+}
+
+/* Set the FDC's data transfer rate on behalf of the specified drive.
+ * NOTE: with 82072/82077 FDCs, changing the data rate requires a reissue
+ * of the specify command (i.e. using the fdc_specify function).
+ */
+static void fdc_dtr(unsigned rate)
+{
+ rate &= 3;
+ /* If data rate not already set to desired value, set it. */
+ if (fdc_state.in_sync && (rate == fdc_state.dtr))
+ return;
+
+ /* Set dtr */
+ fdc_state.fdc_outb(rate, FD_DCR);
+
+ /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB)
+ * need a stabilization period of several milliseconds to be
+ * enforced after data rate changes before R/W operations.
+ * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
+ */
+ fdc_state.dtr = rate & 3;
+ mdelay(5);
+} /* fdc_dtr */
+
+static int fdc_configure(int use_implied_seek, int use_fifo,
+ unsigned fifo_threshold, unsigned precompensation)
+{
+ unsigned config_bits;
+ unsigned char cmd[4];
+ /* 0 EIS EFIFO POLL FIFOOTHR[4] */
+
+ /* santize parameters */
+ config_bits = fifo_threshold & 0xf;
+ config_bits |= (1 << 4); /* Always disable background floppy poll */
+ config_bits |= (!use_fifo) << 5;
+ config_bits |= (!!use_implied_seek) << 6;
+
+ precompensation &= 0xff; /* pre-compensation from track 0 upwards */
+
+ cmd[0] = FD_CONFIGURE;
+ cmd[1] = 0;
+ cmd[2] = config_bits;
+ cmd[3] = precompensation;
+
+ /* Turn on FIFO */
+ if (output_new_command(cmd, 4) < 0)
+ return 0;
+ return 1;
+}
+
+#define NOMINAL_DTR 500
+/* Issue a "SPECIFY" command to set the step rate time, head unload time,
+ * head load time, and DMA disable flag to values needed by floppy.
+ *
+ * The value "dtr" is the data transfer rate in Kbps. It is needed
+ * to account for the data rate-based scaling done by the 82072 and 82077
+ * FDC types. This parameter is ignored for other types of FDCs (i.e.
+ * 8272a).
+ *
+ * Note that changing the data transfer rate has a (probably deleterious)
+ * effect on the parameters subject to scaling for 82072/82077 FDCs, so
+ * fdc_specify is called again after each data transfer rate
+ * change.
+ *
+ * srt: 1000 to 16000 in microseconds
+ * hut: 16 to 240 milliseconds
+ * hlt: 2 to 254 milliseconds
+ *
+ * These values are rounded up to the next highest available delay time.
+ */
+static void fdc_specify(
+ unsigned head_load_time, unsigned head_unload_time, unsigned step_rate)
+{
+ unsigned char cmd[3];
+ unsigned long srt, hlt, hut;
+ unsigned long dtr = NOMINAL_DTR;
+ unsigned long scale_dtr = NOMINAL_DTR;
+ int hlt_max_code = 0x7f;
+ int hut_max_code = 0xf;
+
+ printk_debug("fdc_specify\n");
+
+ switch (DISK_H1440_RATE & 0x03) {
+ case 3:
+ dtr = 1000;
+ break;
+ case 1:
+ dtr = 300;
+ if (fdc_state.version >= FDC_82078) {
+ /* chose the default rate table, not the one
+ * where 1 = 2 Mbps */
+ cmd[0] = FD_DRIVESPEC;
+ cmd[1] = FD_DRIVE & 3;
+ cmd[2] = 0xc0;
+ output_new_command(cmd,3);
+ /* FIXME how do I handle errors here? */
+ }
+ break;
+ case 2:
+ dtr = 250;
+ break;
+ }
+
+
+ if (fdc_state.version >= FDC_82072) {
+ scale_dtr = dtr;
+ hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */
+ hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */
+ }
+
+ /* Convert step rate from microseconds to milliseconds and 4 bits */
+ srt = 16 - (step_rate*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR;
+ if (SLOW_FLOPPY) {
+ srt = srt / 4;
+ }
+ if (srt > 0xf) {
+ srt = 0xf;
+ }
+
+ hlt = (head_load_time*scale_dtr/2 + NOMINAL_DTR - 1)/NOMINAL_DTR;
+ if (hlt < 0x01)
+ hlt = 0x01;
+ else if (hlt > 0x7f)
+ hlt = hlt_max_code;
+
+ hut = (head_unload_time*scale_dtr/16 + NOMINAL_DTR - 1)/NOMINAL_DTR;
+ if (hut < 0x1)
+ hut = 0x1;
+ else if (hut > 0xf)
+ hut = hut_max_code;
+
+ cmd[0] = FD_SPECIFY;
+ cmd[1] = (srt << 4) | hut;
+ cmd[2] = (hlt << 1) | 1; /* Always disable DMA */
+
+ /* If these parameters did not change, just return with success */
+ if (!fdc_state.in_sync || fdc_state.spec1 != cmd[1] || fdc_state.spec2 != cmd[2]) {
+ /* Go ahead and set spec1 and spec2 */
+ output_command(cmd, 3);
+ /* FIXME how do I handle errors here... */
+ printk_info("FD_SPECIFY(%02x, %02x)\n", cmd[1], cmd[2]);
+ }
+} /* fdc_specify */
+
+
+/*
+ * reset is done by pulling bit 2 of DOR low for a while (old FDCs),
+ * or by setting the self clearing bit 7 of STATUS (newer FDCs)
+ */
+static void reset_fdc(void)
+{
+ unsigned char reply[MAX_REPLIES];
+
+ fdc_state.in_sync = 0;
+
+ /* Pseudo-DMA may intercept 'reset finished' interrupt. */
+ /* Irrelevant for systems with true DMA (i386). */
+
+ if (fdc_state.version >= FDC_82072A)
+ fdc_state.fdc_outb(0x80 | (fdc_state.dtr &3), FD_DSR);
+ else {
+ fdc_state.fdc_outb(fdc_state.dor & ~DOR_NO_RESET, FD_DOR);
+ udelay(FD_RESET_DELAY);
+ fdc_state.fdc_outb(fdc_state.dor, FD_DOR);
+ }
+ result(reply, MAX_REPLIES);
+}
+
+
+
+static void show_floppy(void)
+{
+
+ printk_debug("\n");
+ printk_debug("floppy driver state\n");
+ printk_debug("-------------------\n");
+
+ printk_debug("fdc_bytes: %02x %02x xx %02x %02x %02x xx %02x\n",
+ fdc_state.fdc_inb(FD_STATUS_A),
+ fdc_state.fdc_inb(FD_STATUS_B),
+ fdc_state.fdc_inb(FD_TDR),
+ fdc_state.fdc_inb(FD_STATUS),
+ fdc_state.fdc_inb(FD_DATA),
+ fdc_state.fdc_inb(FD_DIR));
+
+ printk_debug("status=%x\n", fdc_state.fdc_inb(FD_STATUS));
+ printk_debug("\n");
+}
+
+static void floppy_recalibrate(void)
+{
+ unsigned char cmd[2];
+ unsigned char reply[MAX_REPLIES];
+ int nr, success;
+ success = 0;
+ do {
+ printk_debug("floppy_recalibrate\n");
+ /* Send the recalibrate command to the controller.
+ * We don't have interrupts or anything we can poll
+ * so we have to guess when it is done.
+ */
+ cmd[0] = FD_RECALIBRATE;
+ cmd[1] = 0;
+ if (output_command(cmd, 2) < 0)
+ continue;
+
+ /* Sleep for the maximum time the recalibrate command
+ * can run.
+ */
+ mdelay(80*DRIVE_H1440_SRT/1000);
+
+ /* Now call FD_SENSEI to end the command
+ * and collect up the reply.
+ */
+ if (output_byte(FD_SENSEI) < 0)
+ continue;
+ nr = result(reply, MAX_REPLIES);
+
+ /* Now see if we have succeeded in our seek */
+ success =
+ /* We have the right size result */
+ (nr == 2) &&
+ /* The command didn't terminate in error */
+ ((reply[0] & ST0_INTR) == ST0_INTR_OK) &&
+ /* We finished a seek */
+ (reply[0] & ST0_SE) &&
+ /* We are at cylinder 0 */
+ (reply[1] == 0);
+ } while(!success);
+ /* Remember we are at track 0 */
+ drive_state[FD_DRIVE].track = 0;
+}
+
+
+static int floppy_seek(unsigned track)
+{
+ unsigned char cmd[3];
+ unsigned char reply[MAX_REPLIES];
+ int nr, success;
+ unsigned distance, old_track;
+
+ /* Look up the old track and see if we need to
+ * do anything.
+ */
+ old_track = drive_state[FD_DRIVE].track;
+ if (old_track == track) {
+ return 1;
+ }
+
+ /* Compute the distance we are about to move,
+ * We need to know this so we know how long to sleep...
+ */
+ distance = (old_track > track)?(old_track - track):(track - old_track);
+ distance += 1;
+
+
+ /* Send the seek command to the controller.
+ * We don't have interrupts or anything we can poll
+ * so we have to guess when it is done.
+ */
+ cmd[0] = FD_SEEK;
+ cmd[1] = FD_DRIVE;
+ cmd[2] = track;
+ if (output_command(cmd, 3) < 0)
+ return 0;
+
+ /* Sleep for the time it takes to step throuhg distance tracks.
+ */
+ mdelay(distance*DRIVE_H1440_SRT/1000);
+
+ /* Now call FD_SENSEI to end the command
+ * and collect up the reply.
+ */
+ cmd[0] = FD_SENSEI;
+ if (output_command(cmd, 1) < 0)
+ return 0;
+ nr = result(reply, MAX_REPLIES);
+
+ /* Now see if we have succeeded in our seek */
+ success =
+ /* We have the right size result */
+ (nr == 2) &&
+ /* The command didn't terminate in error */
+ ((reply[0] & ST0_INTR) == ST0_INTR_OK) &&
+ /* We finished a seek */
+ (reply[0] & ST0_SE) &&
+ /* We are at cylinder 0 */
+ (reply[1] == track);
+ if (success)
+ drive_state[FD_DRIVE].track = track;
+ else {
+ printk_debug("seek failed\n");
+ printk_debug("nr = %d\n", nr);
+ printk_debug("ST0 = %02x\n", reply[0]);
+ printk_debug("PCN = %02x\n", reply[1]);
+ printk_debug("status = %d\n", fdc_state.fdc_inb(FD_STATUS));
+ }
+ return success;
+}
+
+static int read_ok(unsigned head)
+{
+ unsigned char results[7];
+ int result_ok;
+ int nr;
+
+ /* read back the read results */
+ nr = result(results, 7);
+
+ /* Now see if they say we are o.k. */
+ result_ok = 0;
+ /* Are my result bytes o.k.? */
+ if (nr == 7) {
+ /* Are we o.k. */
+ if ((results[0] & ST0_INTR) == ST0_INTR_OK) {
+ result_ok = 1;
+ }
+ /* Or did we get just an overflow error */
+ else if (((results[0] & ST0_INTR) == ST0_INTR_ERROR) &&
+ (results[1]== ST1_OR) &&
+ (results[2] == 0)) {
+ result_ok = 1;
+ }
+ /* Verify the reply had the correct head */
+ if (((results[0] & ST0_HA) >> 2) != head) {
+ result_ok = 0;
+ }
+ /* Verify the reply had the correct drive */
+ if (((results[0] & ST0_DS) != FD_DRIVE)) {
+ result_ok = 0;
+ }
+ }
+ if (!result_ok) {
+ printk_debug("result_bytes = %d\n", nr);
+ printk_debug("ST0 = %02x\n", results[0]);
+ printk_debug("ST1 = %02x\n", results[1]);
+ printk_debug("ST2 = %02x\n", results[2]);
+ printk_debug(" C = %02x\n", results[3]);
+ printk_debug(" H = %02x\n", results[4]);
+ printk_debug(" R = %02x\n", results[5]);
+ printk_debug(" N = %02x\n", results[6]);
+ }
+ return result_ok;
+}
+
+static int floppy_read_sectors(
+ char *dest, unsigned byte_offset, unsigned length,
+ unsigned sector, unsigned head, unsigned track)
+{
+ /* MT == Multitrack */
+ /* MFM == MFM or FM Mode */
+ /* SK == Skip deleted data addres Mark */
+ /* HDS == Head number select */
+ /* DS0 == Disk Drive Select 0 */
+ /* DS1 == Disk Drive Select 1 */
+ /* C == Cylinder number 0 - 255 */
+ /* H == Head number */
+ /* R == Record */
+ /* N == The number of data bytes written in a sector */
+ /* EOT == End of Track */
+ /* GPL == Gap Length */
+ /* DTL == Data Length */
+ /* MT MFM SK 0 1 1 0 0 */
+ /* 0 0 0 0 0 HDS DS1 DS0 */
+ /* C, H, R, N, EOT, GPL, DTL */
+
+ int i, status, result_ok;
+ int max_bytes, bytes_read;
+ int ret;
+ unsigned char cmd[9];
+ unsigned end_offset;
+
+ end_offset = byte_offset + length;
+ max_bytes = 512*(DISK_H1440_SECT - sector + 1);
+
+ if (byte_offset >= max_bytes) {
+ return 0;
+ }
+ cmd[0] = FD_READ | (((DISK_H1440_HEAD ==2)?1:0) << 6);
+ cmd[1] = (head << 2) | FD_DRIVE;
+ cmd[2] = track;
+ cmd[3] = head;
+ cmd[4] = sector;
+ cmd[5] = 2; /* 2^N *128 == Sector size. Hard coded to 512 bytes */
+ cmd[6] = DISK_H1440_SECT;
+ cmd[7] = DISK_H1440_GAP;
+ cmd[8] = 0xff;
+
+ /* Output the command bytes */
+ if (output_command(cmd, 9) < 0)
+ return -1;
+
+ /* The execution stage begins when STATUS_READY&STATUS_NON_DMA is set */
+ do {
+ status = fdc_state.fdc_inb(FD_STATUS);
+ status &= STATUS_READY | STATUS_NON_DMA;
+ } while(status != (STATUS_READY|STATUS_NON_DMA));
+
+ for(i = 0; i < max_bytes; i++) {
+ unsigned char byte;
+ if ((status = wait_til_ready()) < 0) {
+ break;
+ }
+ status &= STATUS_READY|STATUS_DIR|STATUS_NON_DMA;
+ if (status != (STATUS_READY|STATUS_DIR|STATUS_NON_DMA)) {
+ break;
+ }
+ byte = fdc_state.fdc_inb(FD_DATA);
+ if ((i >= byte_offset) && (i < end_offset)) {
+ dest[i - byte_offset] = byte;
+ }
+ }
+ bytes_read = i;
+
+ /* The result stage begins when STATUS_NON_DMA is cleared */
+ while((status = fdc_state.fdc_inb(FD_STATUS)) & STATUS_NON_DMA) {
+ /* We get extra bytes in the fifo past
+ * the end of the sector and drop them on the floor.
+ * Otherwise the fifo is polluted.
+ */
+ fdc_state.fdc_inb(FD_DATA);
+ }
+ /* Did I get an error? */
+ result_ok = read_ok(head);
+ /* Did I read enough bytes? */
+ ret = -1;
+ if (result_ok && (bytes_read == max_bytes)) {
+ ret = bytes_read - byte_offset;
+ if (ret > length) {
+ ret = length;
+ }
+ }
+
+ if (ret < 0) {
+ printk_debug("ret = %d\n", ret);
+ printk_debug("bytes_read = %d\n", bytes_read);
+ printk_debug("status = %x\n", status);
+ }
+ return ret;
+}
+
+
+static int __floppy_read(char *dest, unsigned long offset, unsigned long length)
+{
+ unsigned head, track, sector, byte_offset, sector_offset;
+ int ret;
+
+ /* break the offset up into sectors and bytes */
+ byte_offset = offset % 512;
+ sector_offset = offset / 512;
+
+ /* Find the disk block we are starting with... */
+ sector = (sector_offset % DISK_H1440_SECT) + 1;
+ head = (sector_offset / DISK_H1440_SECT) % DISK_H1440_HEAD;
+ track = (sector_offset / (DISK_H1440_SECT *DISK_H1440_HEAD))% DISK_H1440_TRACK;
+
+ /* First seek to our start track */
+ if (!floppy_seek(track)) {
+ return -1;
+ }
+ /* Then read the data */
+ ret = floppy_read_sectors(dest, byte_offset, length, sector, head, track);
+ if (ret >= 0) {
+ return ret;
+ }
+ /* If we failed reset the fdc... */
+ floppy_reset();
+ return -1;
+}
+
+static int floppy_read(char *dest, unsigned long offset, unsigned long length)
+{
+ int fr_result, bytes_read;;
+
+ printk_debug("floppy_read\n");
+ bytes_read = 0;
+ do {
+ int max_errors = 3;
+ do {
+ fr_result = __floppy_read(dest + bytes_read, offset,
+ length - bytes_read);
+ if (max_errors-- == 0) {
+ return (bytes_read)?bytes_read: -1;
+ }
+ } while (fr_result <= 0);
+ offset += fr_result;
+ bytes_read += fr_result;
+ } while(bytes_read < length);
+ return bytes_read;
+}
+
+/* Determine the floppy disk controller type */
+/* This routine was written by David C. Niemi */
+static char get_fdc_version(void)
+{
+ int bytes, ret;
+ unsigned char reply_buffer[MAX_REPLIES];
+
+ ret = output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */
+ if (ret < 0)
+ return FDC_NONE;
+ if ((bytes = result(reply_buffer, MAX_REPLIES)) <= 0x00)
+ return FDC_NONE; /* No FDC present ??? */
+ if ((bytes==1) && (reply_buffer[0] == 0x80)){
+ printk_info("FDC is an 8272A\n");
+ return FDC_8272A; /* 8272a/765 don't know DUMPREGS */
+ }
+ if (bytes != 10) {
+ printk_debug("init: DUMPREGS: unexpected return of %d bytes.\n",
+ bytes);
+ return FDC_UNKNOWN;
+ }
+ if (!fdc_configure(USE_IMPLIED_SEEK, USE_FIFO, FIFO_THRESHOLD,
+ TRACK_PRECOMPENSATION)) {
+ printk_info("FDC is an 82072\n");
+ return FDC_82072; /* 82072 doesn't know CONFIGURE */
+ }
+
+ output_byte(FD_PERPENDICULAR);
+ if (need_more_output() == MORE_OUTPUT) {
+ output_byte(0);
+ } else {
+ printk_info("FDC is an 82072A\n");
+ return FDC_82072A; /* 82072A as found on Sparcs. */
+ }
+
+ output_byte(FD_UNLOCK);
+ bytes = result(reply_buffer, MAX_REPLIES);
+ if ((bytes == 1) && (reply_buffer[0] == 0x80)){
+ printk_info("FDC is a pre-1991 82077\n");
+ return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know
+ * LOCK/UNLOCK */
+ }
+ if ((bytes != 1) || (reply_buffer[0] != 0x00)) {
+ printk_debug("FDC init: UNLOCK: unexpected return of %d bytes.\n",
+ bytes);
+ return FDC_UNKNOWN;
+ }
+ output_byte(FD_PARTID);
+ bytes = result(reply_buffer, MAX_REPLIES);
+ if (bytes != 1) {
+ printk_debug("FDC init: PARTID: unexpected return of %d bytes.\n",
+ bytes);
+ return FDC_UNKNOWN;
+ }
+ if (reply_buffer[0] == 0x80) {
+ printk_info("FDC is a post-1991 82077\n");
+ return FDC_82077; /* Revised 82077AA passes all the tests */
+ }
+ switch (reply_buffer[0] >> 5) {
+ case 0x0:
+ /* Either a 82078-1 or a 82078SL running at 5Volt */
+ printk_info("FDC is an 82078.\n");
+ return FDC_82078;
+ case 0x1:
+ printk_info("FDC is a 44pin 82078\n");
+ return FDC_82078;
+ case 0x2:
+ printk_info("FDC is a S82078B\n");
+ return FDC_S82078B;
+ case 0x3:
+ printk_info("FDC is a National Semiconductor PC87306\n");
+ return FDC_87306;
+ default:
+ printk_info("FDC init: 82078 variant with unknown PARTID=%d.\n",
+ reply_buffer[0] >> 5);
+ return FDC_82078_UNKN;
+ }
+} /* get_fdc_version */
+
+
+static int floppy_init(unsigned long io_base, unsigned long mmio_base)
+{
+ printk_debug("floppy_init\n");
+ fdc_state.in_sync = 0;
+ fdc_state.spec1 = -1;
+ fdc_state.spec2 = -1;
+ fdc_state.dtr = -1;
+ fdc_state.dor = DOR_NO_RESET;
+ fdc_state.version = FDC_UNKNOWN;
+ if (mmio_base) {
+ fdc_state.fdc_inb = ob_fdc_mmio_readb;
+ fdc_state.fdc_outb = ob_fdc_mmio_writeb;
+ } else {
+ fdc_state.fdc_inb = ob_fdc_inb;
+ fdc_state.fdc_outb = ob_fdc_outb;
+ }
+ fdc_state.io_base = io_base;
+ fdc_state.mmio_base = mmio_base;
+ reset_fdc();
+ /* Try to determine the floppy controller type */
+ fdc_state.version = get_fdc_version();
+ if (fdc_state.version == FDC_NONE) {
+ return -1;
+ }
+ floppy_reset();
+ printk_info("fdc_state.version = %04x\n", fdc_state.version);
+ return 0;
+}
+
+static void floppy_reset(void)
+{
+ printk_debug("floppy_reset\n");
+ floppy_motor_off(FD_DRIVE);
+ reset_fdc();
+ fdc_dtr(DISK_H1440_RATE);
+ /* program data rate via ccr */
+ collect_interrupt();
+ fdc_configure(USE_IMPLIED_SEEK, USE_FIFO, FIFO_THRESHOLD,
+ TRACK_PRECOMPENSATION);
+ fdc_specify(DRIVE_H1440_HLT, DRIVE_H1440_HUT, DRIVE_H1440_SRT);
+ set_drive(FD_DRIVE);
+ floppy_recalibrate();
+ fdc_state.in_sync = 1;
+}
+
+static void
+ob_floppy_initialize(const char *path)
+{
+ int props[3];
+ phandle_t ph = find_dev(path);
+
+ set_property(ph, "device_type", "block", sizeof("block"));
+
+ // Set dummy reg properties
+ props[0] = __cpu_to_be32(0); props[1] = __cpu_to_be32(0); props[2] = __cpu_to_be32(0);
+ set_property(ph, "reg", (char *)&props, 3*sizeof(int));
+
+ fword("is-deblocker");
+}
+
+
+static void
+ob_floppy_open(int *idx)
+{
+ int ret = 1;
+ phandle_t ph;
+
+ fword("my-unit");
+ idx[0]=POP();
+
+ fword("my-parent");
+ fword("ihandle>phandle");
+ ph=(phandle_t)POP();
+
+ selfword("open-deblocker");
+
+ /* interpose disk-label */
+ ph = find_dev("/packages/disk-label");
+ fword("my-args");
+ PUSH_ph( ph );
+ fword("interpose");
+
+ RET ( -ret );
+}
+
+static void
+ob_floppy_close(int *idx)
+{
+ selfword("close-deblocker");
+}
+
+static void
+ob_floppy_read_blocks(int *idx)
+{
+ cell cnt = POP();
+ ucell blk = POP();
+ char *dest = (char*)POP();
+ floppy_read(dest, blk*512, cnt*512);
+ PUSH(cnt);
+}
+
+
+static void
+ob_floppy_block_size(int *idx)
+{
+ PUSH(512);
+}
+
+static void
+ob_floppy_max_transfer(int *idx)
+{
+ // Fixme
+ PUSH(18 * 512);
+}
+
+NODE_METHODS(ob_floppy) = {
+ { "open", ob_floppy_open },
+ { "close", ob_floppy_close },
+ { "read-blocks", ob_floppy_read_blocks },
+ { "block-size", ob_floppy_block_size },
+ { "max-transfer", ob_floppy_max_transfer },
+};
+
+
+int ob_floppy_init(const char *path, const char *dev_name,
+ unsigned long io_base, unsigned long mmio_base)
+{
+ char nodebuff[128];
+ phandle_t aliases;
+
+ snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name);
+ if (!mmio_base) {
+ REGISTER_NAMED_NODE(ob_floppy, nodebuff);
+ ob_floppy_initialize(nodebuff);
+ } else {
+ // Already in tree and mapped
+ REGISTER_NODE_METHODS(ob_floppy, nodebuff);
+ }
+ floppy_init(io_base, mmio_base);
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "floppy", nodebuff, strlen(nodebuff) + 1);
+
+ return 0;
+}
diff --git a/roms/openbios/drivers/floppy.h b/roms/openbios/drivers/floppy.h
new file mode 100644
index 00000000..b0f30d55
--- /dev/null
+++ b/roms/openbios/drivers/floppy.h
@@ -0,0 +1,9 @@
+#ifndef FLOPPY_SUBR_H
+#define FLOPPY_SUBR_H
+
+int floppy_init(void);
+int floppy_read(char *dest, unsigned long offset, unsigned long length);
+void floppy_fini(void);
+
+
+#endif /* FLOPPY_SUBR_H */
diff --git a/roms/openbios/drivers/fw_cfg.c b/roms/openbios/drivers/fw_cfg.c
new file mode 100644
index 00000000..40275707
--- /dev/null
+++ b/roms/openbios/drivers/fw_cfg.c
@@ -0,0 +1,76 @@
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/byteorder.h"
+#include "libopenbios/ofmem.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+
+#if !defined(CONFIG_SPARC64)
+static volatile uint16_t *fw_cfg_cmd;
+static volatile uint8_t *fw_cfg_data;
+
+void
+fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes)
+{
+ unsigned int i;
+
+ *fw_cfg_cmd = cmd;
+ for (i = 0; i < nbytes; i++)
+ buf[i] = *fw_cfg_data;
+}
+#else
+// XXX depends on PCI bus location, should be removed
+void
+fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes)
+{
+ unsigned int i;
+
+ outw(cmd, CONFIG_FW_CFG_ADDR);
+ for (i = 0; i < nbytes; i++)
+ buf[i] = inb(CONFIG_FW_CFG_ADDR + 1);
+}
+#endif
+
+uint64_t
+fw_cfg_read_i64(uint16_t cmd)
+{
+ uint64_t buf;
+
+ fw_cfg_read(cmd, (char *)&buf, sizeof(uint64_t));
+
+ return __le64_to_cpu(buf);
+}
+
+uint32_t
+fw_cfg_read_i32(uint16_t cmd)
+{
+ uint32_t buf;
+
+ fw_cfg_read(cmd, (char *)&buf, sizeof(uint32_t));
+
+ return __le32_to_cpu(buf);
+}
+
+uint16_t
+fw_cfg_read_i16(uint16_t cmd)
+{
+ uint16_t buf;
+
+ fw_cfg_read(cmd, (char *)&buf, sizeof(uint16_t));
+
+ return __le16_to_cpu(buf);
+}
+
+void
+fw_cfg_init(void)
+{
+#if defined(CONFIG_SPARC32)
+ fw_cfg_cmd = (void *)ofmem_map_io(CONFIG_FW_CFG_ADDR, 2);
+ fw_cfg_data = (uint8_t *)fw_cfg_cmd + 2;
+#elif defined(CONFIG_SPARC64)
+ // Nothing for the port version
+#elif defined(CONFIG_PPC)
+ fw_cfg_cmd = (void *)CONFIG_FW_CFG_ADDR;
+ fw_cfg_data = (void *)(CONFIG_FW_CFG_ADDR + 2);
+#endif
+}
diff --git a/roms/openbios/drivers/hdreg.h b/roms/openbios/drivers/hdreg.h
new file mode 100644
index 00000000..91e4d1ff
--- /dev/null
+++ b/roms/openbios/drivers/hdreg.h
@@ -0,0 +1,289 @@
+/*
+ * this header holds data structures as dictated by spec
+ */
+#ifndef HDREG_H
+#define HDREG_H
+
+struct hd_driveid {
+ unsigned short config; /* lots of obsolete bit flags */
+ unsigned short cyls; /* Obsolete, "physical" cyls */
+ unsigned short reserved2; /* reserved (word 2) */
+ unsigned short heads; /* Obsolete, "physical" heads */
+ unsigned short track_bytes; /* unformatted bytes per track */
+ unsigned short sector_bytes; /* unformatted bytes per sector */
+ unsigned short sectors; /* Obsolete, "physical" sectors per track */
+ unsigned short vendor0; /* vendor unique */
+ unsigned short vendor1; /* vendor unique */
+ unsigned short vendor2; /* Retired vendor unique */
+ unsigned char serial_no[20]; /* 0 = not_specified */
+ unsigned short buf_type; /* Retired */
+ unsigned short buf_size; /* Retired, 512 byte increments
+ * 0 = not_specified
+ */
+ unsigned short ecc_bytes; /* for r/w long cmds; 0 = not_specified */
+ unsigned char fw_rev[8]; /* 0 = not_specified */
+ unsigned char model[40]; /* 0 = not_specified */
+ unsigned char max_multsect; /* 0=not_implemented */
+ unsigned char vendor3; /* vendor unique */
+ unsigned short dword_io; /* 0=not_implemented; 1=implemented */
+ unsigned char vendor4; /* vendor unique */
+ unsigned char capability; /* (upper byte of word 49)
+ * 3: IORDYsup
+ * 2: IORDYsw
+ * 1: LBA
+ * 0: DMA
+ */
+ unsigned short reserved50; /* reserved (word 50) */
+ unsigned char vendor5; /* Obsolete, vendor unique */
+ unsigned char tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */
+ unsigned char vendor6; /* Obsolete, vendor unique */
+ unsigned char tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */
+ unsigned short field_valid; /* (word 53)
+ * 2: ultra_ok word 88
+ * 1: eide_ok words 64-70
+ * 0: cur_ok words 54-58
+ */
+ unsigned short cur_cyls; /* Obsolete, logical cylinders */
+ unsigned short cur_heads; /* Obsolete, l heads */
+ unsigned short cur_sectors; /* Obsolete, l sectors per track */
+ unsigned short cur_capacity0; /* Obsolete, l total sectors on drive */
+ unsigned short cur_capacity1; /* Obsolete, (2 words, misaligned int) */
+ unsigned char multsect; /* current multiple sector count */
+ unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
+ unsigned int lba_capacity; /* Obsolete, total number of sectors */
+ unsigned short dma_1word; /* Obsolete, single-word dma info */
+ unsigned short dma_mword; /* multiple-word dma info */
+ unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
+ unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
+ unsigned short eide_dma_time; /* recommended mword dma cycle time (ns) */
+ unsigned short eide_pio; /* min cycle time (ns), no IORDY */
+ unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
+ unsigned short words69_70[2]; /* reserved words 69-70
+ * future command overlap and queuing
+ */
+ /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
+ unsigned short words71_74[4]; /* reserved words 71-74
+ * for IDENTIFY PACKET DEVICE command
+ */
+ unsigned short queue_depth; /* (word 75)
+ * 15:5 reserved
+ * 4:0 Maximum queue depth -1
+ */
+ unsigned short words76_79[4]; /* reserved words 76-79 */
+ unsigned short major_rev_num; /* (word 80) */
+ unsigned short minor_rev_num; /* (word 81) */
+ unsigned short command_set_1; /* (word 82) supported
+ * 15: Obsolete
+ * 14: NOP command
+ * 13: READ_BUFFER
+ * 12: WRITE_BUFFER
+ * 11: Obsolete
+ * 10: Host Protected Area
+ * 9: DEVICE Reset
+ * 8: SERVICE Interrupt
+ * 7: Release Interrupt
+ * 6: look-ahead
+ * 5: write cache
+ * 4: PACKET Command
+ * 3: Power Management Feature Set
+ * 2: Removable Feature Set
+ * 1: Security Feature Set
+ * 0: SMART Feature Set
+ */
+ unsigned short command_set_2; /* (word 83)
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13: FLUSH CACHE EXT
+ * 12: FLUSH CACHE
+ * 11: Device Configuration Overlay
+ * 10: 48-bit Address Feature Set
+ * 9: Automatic Acoustic Management
+ * 8: SET MAX security
+ * 7: reserved 1407DT PARTIES
+ * 6: SetF sub-command Power-Up
+ * 5: Power-Up in Standby Feature Set
+ * 4: Removable Media Notification
+ * 3: APM Feature Set
+ * 2: CFA Feature Set
+ * 1: READ/WRITE DMA QUEUED
+ * 0: Download MicroCode
+ */
+ unsigned short cfsse; /* (word 84)
+ * cmd set-feature supported extensions
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:6 reserved
+ * 5: General Purpose Logging
+ * 4: Streaming Feature Set
+ * 3: Media Card Pass Through
+ * 2: Media Serial Number Valid
+ * 1: SMART selt-test supported
+ * 0: SMART error logging
+ */
+ unsigned short cfs_enable_1; /* (word 85)
+ * command set-feature enabled
+ * 15: Obsolete
+ * 14: NOP command
+ * 13: READ_BUFFER
+ * 12: WRITE_BUFFER
+ * 11: Obsolete
+ * 10: Host Protected Area
+ * 9: DEVICE Reset
+ * 8: SERVICE Interrupt
+ * 7: Release Interrupt
+ * 6: look-ahead
+ * 5: write cache
+ * 4: PACKET Command
+ * 3: Power Management Feature Set
+ * 2: Removable Feature Set
+ * 1: Security Feature Set
+ * 0: SMART Feature Set
+ */
+ unsigned short cfs_enable_2; /* (word 86)
+ * command set-feature enabled
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13: FLUSH CACHE EXT
+ * 12: FLUSH CACHE
+ * 11: Device Configuration Overlay
+ * 10: 48-bit Address Feature Set
+ * 9: Automatic Acoustic Management
+ * 8: SET MAX security
+ * 7: reserved 1407DT PARTIES
+ * 6: SetF sub-command Power-Up
+ * 5: Power-Up in Standby Feature Set
+ * 4: Removable Media Notification
+ * 3: APM Feature Set
+ * 2: CFA Feature Set
+ * 1: READ/WRITE DMA QUEUED
+ * 0: Download MicroCode
+ */
+ unsigned short csf_default; /* (word 87)
+ * command set-feature default
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:6 reserved
+ * 5: General Purpose Logging enabled
+ * 4: Valid CONFIGURE STREAM executed
+ * 3: Media Card Pass Through enabled
+ * 2: Media Serial Number Valid
+ * 1: SMART selt-test supported
+ * 0: SMART error logging
+ */
+ unsigned short dma_ultra; /* (word 88) */
+ unsigned short trseuc; /* time required for security erase */
+ unsigned short trsEuc; /* time required for enhanced erase */
+ unsigned short CurAPMvalues; /* current APM values */
+ unsigned short mprc; /* master password revision code */
+ unsigned short hw_config; /* hardware config (word 93)
+ * 15: Shall be ZERO
+ * 14: Shall be ONE
+ * 13:
+ * 12:
+ * 11:
+ * 10:
+ * 9:
+ * 8:
+ * 7:
+ * 6:
+ * 5:
+ * 4:
+ * 3:
+ * 2:
+ * 1:
+ * 0: Shall be ONE
+ */
+ unsigned short acoustic; /* (word 94)
+ * 15:8 Vendor's recommended value
+ * 7:0 current value
+ */
+ unsigned short msrqs; /* min stream request size */
+ unsigned short sxfert; /* stream transfer time */
+ unsigned short sal; /* stream access latency */
+ unsigned int spg; /* stream performance granularity */
+ unsigned long long lba_capacity_2;/* 48-bit total number of sectors */
+ unsigned short words104_125[22];/* reserved words 104-125 */
+ unsigned short last_lun; /* (word 126) */
+ unsigned short word127; /* (word 127) Feature Set
+ * Removable Media Notification
+ * 15:2 reserved
+ * 1:0 00 = not supported
+ * 01 = supported
+ * 10 = reserved
+ * 11 = reserved
+ */
+ unsigned short dlf; /* (word 128)
+ * device lock function
+ * 15:9 reserved
+ * 8 security level 1:max 0:high
+ * 7:6 reserved
+ * 5 enhanced erase
+ * 4 expire
+ * 3 frozen
+ * 2 locked
+ * 1 en/disabled
+ * 0 capability
+ */
+ unsigned short csfo; /* (word 129)
+ * current set features options
+ * 15:4 reserved
+ * 3: auto reassign
+ * 2: reverting
+ * 1: read-look-ahead
+ * 0: write cache
+ */
+ unsigned short words130_155[26];/* reserved vendor words 130-155 */
+ unsigned short word156; /* reserved vendor word 156 */
+ unsigned short words157_159[3];/* reserved vendor words 157-159 */
+ unsigned short cfa_power; /* (word 160) CFA Power Mode
+ * 15 word 160 supported
+ * 14 reserved
+ * 13
+ * 12
+ * 11:0
+ */
+ unsigned short words161_175[15];/* Reserved for CFA */
+ unsigned short words176_205[30];/* Current Media Serial Number */
+ unsigned short words206_254[49];/* reserved words 206-254 */
+ unsigned short integrity_word; /* (word 255)
+ * 15:8 Checksum
+ * 7:0 Signature
+ */
+};
+
+struct request_sense {
+#if defined(CONFIG_BIG_ENDIAN)
+ u8 valid : 1;
+ u8 error_code : 7;
+#elif defined(CONFIG_LITTLE_ENDIAN)
+ u8 error_code : 7;
+ u8 valid : 1;
+#endif
+ u8 segment_number;
+#if defined(CONFIG_BIG_ENDIAN)
+ u8 reserved1 : 2;
+ u8 ili : 1;
+ u8 reserved2 : 1;
+ u8 sense_key : 4;
+#elif defined(CONFIG_LITTLE_ENDIAN)
+ u8 sense_key : 4;
+ u8 reserved2 : 1;
+ u8 ili : 1;
+ u8 reserved1 : 2;
+#endif
+ u8 information[4];
+ u8 add_sense_len;
+ u8 command_info[4];
+ u8 asc;
+ u8 ascq;
+ u8 fruc;
+ u8 sks[3];
+ u8 asb[46];
+};
+
+struct atapi_capacity {
+ u32 lba;
+ u32 block_size;
+};
+
+#endif
diff --git a/roms/openbios/drivers/ide.c b/roms/openbios/drivers/ide.c
new file mode 100644
index 00000000..327c64a4
--- /dev/null
+++ b/roms/openbios/drivers/ide.c
@@ -0,0 +1,1685 @@
+/*
+ * OpenBIOS polled ide driver
+ *
+ * Copyright (C) 2004 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ *
+ * Credit goes to Hale Landis for his excellent ata demo software
+ * OF node handling and some fixes by Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "kernel/kernel.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "drivers/drivers.h"
+#include "ide.h"
+#include "hdreg.h"
+#include "timer.h"
+
+#ifdef CONFIG_DEBUG_IDE
+#define IDE_DPRINTF(fmt, args...) \
+do { printk("IDE - %s: " fmt, __func__ , ##args); } while (0)
+#else
+#define IDE_DPRINTF(fmt, args...) do { } while (0)
+#endif
+
+/* DECLARE data structures for the nodes. */
+DECLARE_UNNAMED_NODE( ob_ide, INSTALL_OPEN, sizeof(struct ide_drive*) );
+DECLARE_UNNAMED_NODE( ob_ide_ctrl, INSTALL_OPEN, sizeof(int));
+
+/*
+ * define to 2 for the standard 2 channels only
+ */
+#ifndef CONFIG_IDE_NUM_CHANNELS
+#define IDE_NUM_CHANNELS 4
+#else
+#define IDE_NUM_CHANNELS CONFIG_IDE_NUM_CHANNELS
+#endif
+#define IDE_MAX_CHANNELS 4
+
+#ifndef CONFIG_IDE_FIRST_UNIT
+#define FIRST_UNIT 0
+#else
+#define FIRST_UNIT CONFIG_IDE_FIRST_UNIT
+#endif
+
+#ifndef CONFIG_IDE_DEV_TYPE
+#define DEV_TYPE "ide"
+#else
+#define DEV_TYPE CONFIG_IDE_DEV_TYPE
+#endif
+
+#ifndef CONFIG_IDE_DEV_NAME
+#define DEV_NAME "ide%d"
+#else
+#define DEV_NAME CONFIG_IDE_DEV_NAME
+#endif
+
+static int current_channel = FIRST_UNIT;
+
+static struct ide_channel *channels = NULL;
+
+static inline void ide_add_channel(struct ide_channel *chan)
+{
+ chan->next = channels;
+ channels = chan;
+}
+
+static struct ide_channel *ide_seek_channel(const char *name)
+{
+ struct ide_channel *current;
+
+ current = channels;
+ while (current) {
+ if (!strcmp(current->name, name))
+ return current;
+ current = current->next;
+ }
+ return NULL;
+}
+
+/*
+ * don't be pedantic
+ */
+#undef ATA_PEDANTIC
+
+static void dump_drive(struct ide_drive *drive)
+{
+#ifdef CONFIG_DEBUG_IDE
+ printk("IDE DRIVE @%lx:\n", (unsigned long)drive);
+ printk("unit: %d\n",drive->unit);
+ printk("present: %d\n",drive->present);
+ printk("type: %d\n",drive->type);
+ printk("media: %d\n",drive->media);
+ printk("model: %s\n",drive->model);
+ printk("nr: %d\n",drive->nr);
+ printk("cyl: %d\n",drive->cyl);
+ printk("head: %d\n",drive->head);
+ printk("sect: %d\n",drive->sect);
+ printk("bs: %d\n",drive->bs);
+#endif
+}
+
+/*
+ * old style io port operations
+ */
+static unsigned char
+ob_ide_inb(struct ide_channel *chan, unsigned int port)
+{
+ return inb(chan->io_regs[port]);
+}
+
+static void
+ob_ide_outb(struct ide_channel *chan, unsigned char data, unsigned int port)
+{
+ outb(data, chan->io_regs[port]);
+}
+
+static void
+ob_ide_insw(struct ide_channel *chan,
+ unsigned int port, unsigned char *addr, unsigned int count)
+{
+ insw(chan->io_regs[port], addr, count);
+}
+
+static void
+ob_ide_outsw(struct ide_channel *chan,
+ unsigned int port, unsigned char *addr, unsigned int count)
+{
+ outsw(chan->io_regs[port], addr, count);
+}
+
+static inline unsigned char
+ob_ide_pio_readb(struct ide_drive *drive, unsigned int offset)
+{
+ struct ide_channel *chan = drive->channel;
+
+ return chan->obide_inb(chan, offset);
+}
+
+static inline void
+ob_ide_pio_writeb(struct ide_drive *drive, unsigned int offset,
+ unsigned char data)
+{
+ struct ide_channel *chan = drive->channel;
+
+ chan->obide_outb(chan, data, offset);
+}
+
+static inline void
+ob_ide_pio_insw(struct ide_drive *drive, unsigned int offset,
+ unsigned char *addr, unsigned int len)
+{
+ struct ide_channel *chan = drive->channel;
+
+ if (len & 1) {
+ IDE_DPRINTF("%d: command not word aligned\n", drive->nr);
+ return;
+ }
+
+ chan->obide_insw(chan, offset, addr, len / 2);
+}
+
+static inline void
+ob_ide_pio_outsw(struct ide_drive *drive, unsigned int offset,
+ unsigned char *addr, unsigned int len)
+{
+ struct ide_channel *chan = drive->channel;
+
+ if (len & 1) {
+ IDE_DPRINTF("%d: command not word aligned\n", drive->nr);
+ return;
+ }
+
+ chan->obide_outsw(chan, offset, addr, len / 2);
+}
+
+static void
+ob_ide_400ns_delay(struct ide_drive *drive)
+{
+ (void) ob_ide_pio_readb(drive, IDEREG_ASTATUS);
+ (void) ob_ide_pio_readb(drive, IDEREG_ASTATUS);
+ (void) ob_ide_pio_readb(drive, IDEREG_ASTATUS);
+ (void) ob_ide_pio_readb(drive, IDEREG_ASTATUS);
+
+ udelay(1);
+}
+
+static void
+ob_ide_error(struct ide_drive *drive, unsigned char stat, const char *msg)
+{
+#ifdef CONFIG_DEBUG_IDE
+ struct ide_channel *chan = drive->channel;
+ unsigned char err;
+#endif
+
+ if (!stat)
+ stat = ob_ide_pio_readb(drive, IDEREG_STATUS);
+
+ IDE_DPRINTF("ob_ide_error drive<%d>: %s:\n", drive->nr, msg);
+ IDE_DPRINTF(" cmd=%x, stat=%x", chan->ata_cmd.command, stat);
+
+ if ((stat & (BUSY_STAT | ERR_STAT)) == ERR_STAT) {
+#ifdef CONFIG_DEBUG_IDE
+ err =
+#endif
+ ob_ide_pio_readb(drive, IDEREG_ERROR);
+ IDE_DPRINTF(", err=%x", err);
+ }
+ IDE_DPRINTF("\n");
+
+#ifdef CONFIG_DEBUG_IDE
+ /*
+ * see if sense is valid and dump that
+ */
+ if (chan->ata_cmd.command == WIN_PACKET) {
+ struct atapi_command *cmd = &chan->atapi_cmd;
+ unsigned char old_cdb = cmd->cdb[0];
+
+ if (cmd->cdb[0] == ATAPI_REQ_SENSE) {
+ old_cdb = cmd->old_cdb;
+
+ IDE_DPRINTF(" atapi opcode=%02x", old_cdb);
+ } else {
+ int i;
+
+ IDE_DPRINTF(" cdb: ");
+ for (i = 0; i < sizeof(cmd->cdb); i++)
+ IDE_DPRINTF("%02x ", cmd->cdb[i]);
+ }
+ if (cmd->sense_valid)
+ IDE_DPRINTF(", sense: %02x/%02x/%02x",
+ cmd->sense.sense_key, cmd->sense.asc,
+ cmd->sense.ascq);
+ else
+ IDE_DPRINTF(", no sense");
+ IDE_DPRINTF("\n");
+ }
+#endif
+}
+
+/*
+ * wait for 'stat' to be set. returns 1 if failed, 0 if succesful
+ */
+static int
+ob_ide_wait_stat(struct ide_drive *drive, unsigned char ok_stat,
+ unsigned char bad_stat, unsigned char *ret_stat)
+{
+ unsigned char stat;
+ int i;
+
+ ob_ide_400ns_delay(drive);
+
+ for (i = 0; i < 5000; i++) {
+ stat = ob_ide_pio_readb(drive, IDEREG_STATUS);
+ if (!(stat & BUSY_STAT))
+ break;
+
+ udelay(1000);
+ }
+
+ if (ret_stat)
+ *ret_stat = stat;
+
+ if (stat & bad_stat)
+ return 1;
+
+ if ((stat & ok_stat) || !ok_stat)
+ return 0;
+
+ return 1;
+}
+
+static int
+ob_ide_select_drive(struct ide_drive *drive)
+{
+ struct ide_channel *chan = drive->channel;
+ unsigned char control = IDEHEAD_DEV0;
+
+ if (ob_ide_wait_stat(drive, 0, BUSY_STAT, NULL)) {
+ IDE_DPRINTF("select_drive: timed out\n");
+ return 1;
+ }
+
+ /*
+ * don't select drive if already active. Note: we always
+ * wait for BUSY clear
+ */
+ if (drive->unit == chan->selected)
+ return 0;
+
+ if (drive->unit)
+ control = IDEHEAD_DEV1;
+
+ ob_ide_pio_writeb(drive, IDEREG_CURRENT, control);
+ ob_ide_400ns_delay(drive);
+
+ if (ob_ide_wait_stat(drive, 0, BUSY_STAT, NULL)) {
+ IDE_DPRINTF("select_drive: timed out\n");
+ return 1;
+ }
+
+ chan->selected = drive->unit;
+ return 0;
+}
+
+static void
+ob_ide_write_tasklet(struct ide_drive *drive, struct ata_command *cmd)
+{
+ ob_ide_pio_writeb(drive, IDEREG_FEATURE, cmd->task[1]);
+ ob_ide_pio_writeb(drive, IDEREG_NSECTOR, cmd->task[3]);
+ ob_ide_pio_writeb(drive, IDEREG_SECTOR, cmd->task[7]);
+ ob_ide_pio_writeb(drive, IDEREG_LCYL, cmd->task[8]);
+ ob_ide_pio_writeb(drive, IDEREG_HCYL, cmd->task[9]);
+
+ ob_ide_pio_writeb(drive, IDEREG_FEATURE, cmd->task[0]);
+ ob_ide_pio_writeb(drive, IDEREG_NSECTOR, cmd->task[2]);
+ ob_ide_pio_writeb(drive, IDEREG_SECTOR, cmd->task[4]);
+ ob_ide_pio_writeb(drive, IDEREG_LCYL, cmd->task[5]);
+ ob_ide_pio_writeb(drive, IDEREG_HCYL, cmd->task[6]);
+
+ if (drive->unit)
+ cmd->device_head |= IDEHEAD_DEV1;
+
+ ob_ide_pio_writeb(drive, IDEREG_CURRENT, cmd->device_head);
+
+ ob_ide_pio_writeb(drive, IDEREG_COMMAND, cmd->command);
+ ob_ide_400ns_delay(drive);
+}
+
+static void
+ob_ide_write_registers(struct ide_drive *drive, struct ata_command *cmd)
+{
+ /*
+ * we are _always_ polled
+ */
+ ob_ide_pio_writeb(drive, IDEREG_CONTROL, cmd->control | IDECON_NIEN);
+
+ ob_ide_pio_writeb(drive, IDEREG_FEATURE, cmd->feature);
+ ob_ide_pio_writeb(drive, IDEREG_NSECTOR, cmd->nsector);
+ ob_ide_pio_writeb(drive, IDEREG_SECTOR, cmd->sector);
+ ob_ide_pio_writeb(drive, IDEREG_LCYL, cmd->lcyl);
+ ob_ide_pio_writeb(drive, IDEREG_HCYL, cmd->hcyl);
+
+ if (drive->unit)
+ cmd->device_head |= IDEHEAD_DEV1;
+
+ ob_ide_pio_writeb(drive, IDEREG_CURRENT, cmd->device_head);
+
+ ob_ide_pio_writeb(drive, IDEREG_COMMAND, cmd->command);
+ ob_ide_400ns_delay(drive);
+}
+
+/*
+ * execute command with "pio non data" protocol
+ */
+#if 0
+static int
+ob_ide_pio_non_data(struct ide_drive *drive, struct ata_command *cmd)
+{
+ if (ob_ide_select_drive(drive))
+ return 1;
+
+ ob_ide_write_registers(drive, cmd);
+
+ if (ob_ide_wait_stat(drive, 0, BUSY_STAT, NULL))
+ return 1;
+
+ return 0;
+}
+#endif
+
+/*
+ * execute given command with a pio data-in phase.
+ */
+static int
+ob_ide_pio_data_in(struct ide_drive *drive, struct ata_command *cmd)
+{
+ unsigned char stat;
+ unsigned int bytes, timeout;
+
+ if (ob_ide_select_drive(drive))
+ return 1;
+
+ /*
+ * ATA must set ready and seek stat, ATAPI need only clear busy
+ */
+ timeout = 0;
+ do {
+ stat = ob_ide_pio_readb(drive, IDEREG_STATUS);
+
+ if (drive->type == ide_type_ata) {
+ /*
+ * this is BIOS code, don't be too pedantic
+ */
+#ifdef ATA_PEDANTIC
+ if ((stat & (BUSY_STAT | READY_STAT | SEEK_STAT)) ==
+ (READY_STAT | SEEK_STAT))
+ break;
+#else
+ if ((stat & (BUSY_STAT | READY_STAT)) == READY_STAT)
+ break;
+#endif
+ } else {
+ if (!(stat & BUSY_STAT))
+ break;
+ }
+ ob_ide_400ns_delay(drive);
+ } while (timeout++ < 1000);
+
+ if (timeout >= 1000) {
+ ob_ide_error(drive, stat, "drive timed out");
+ cmd->stat = stat;
+ return 1;
+ }
+
+ ob_ide_write_registers(drive, cmd);
+
+ /*
+ * now read the data
+ */
+ bytes = cmd->buflen;
+ do {
+ unsigned count = cmd->buflen;
+
+ if (count > drive->bs)
+ count = drive->bs;
+
+ /* delay 100ms for ATAPI? */
+
+ /*
+ * wait for BUSY clear
+ */
+ if (ob_ide_wait_stat(drive, 0, BUSY_STAT | ERR_STAT, &stat)) {
+ ob_ide_error(drive, stat, "timed out waiting for BUSY clear");
+ cmd->stat = stat;
+ break;
+ }
+
+ /*
+ * transfer the data
+ */
+ if ((stat & (BUSY_STAT | DRQ_STAT)) == DRQ_STAT) {
+ ob_ide_pio_insw(drive, IDEREG_DATA, cmd->buffer, count);
+ cmd->bytes -= count;
+ cmd->buffer += count;
+ bytes -= count;
+
+ ob_ide_400ns_delay(drive);
+ }
+
+ if (stat & (BUSY_STAT | WRERR_STAT | ERR_STAT)) {
+ cmd->stat = stat;
+ break;
+ }
+
+ if (!(stat & DRQ_STAT)) {
+ cmd->stat = stat;
+ break;
+ }
+ } while (bytes);
+
+ if (bytes)
+ IDE_DPRINTF("bytes=%d, stat=%x\n", bytes, stat);
+
+ return bytes ? 1 : 0;
+}
+
+/*
+ * execute ata command with pio packet protocol
+ */
+static int
+ob_ide_pio_packet(struct ide_drive *drive, struct atapi_command *cmd)
+{
+ unsigned char stat, reason, lcyl, hcyl;
+ struct ata_command *acmd = &drive->channel->ata_cmd;
+ unsigned char *buffer;
+ unsigned int bytes;
+
+ if (ob_ide_select_drive(drive))
+ return 1;
+
+ if (cmd->buflen && cmd->data_direction == atapi_ddir_none)
+ IDE_DPRINTF("non-zero buflen but no data direction\n");
+
+ memset(acmd, 0, sizeof(*acmd));
+ acmd->lcyl = cmd->buflen & 0xff;
+ acmd->hcyl = (cmd->buflen >> 8) & 0xff;
+ acmd->command = WIN_PACKET;
+ ob_ide_write_registers(drive, acmd);
+
+ /*
+ * BUSY must be set, _or_ DRQ | ERR
+ */
+ stat = ob_ide_pio_readb(drive, IDEREG_ASTATUS);
+ if ((stat & BUSY_STAT) == 0) {
+ if (!(stat & (DRQ_STAT | ERR_STAT))) {
+ ob_ide_error(drive, stat, "bad stat in atapi cmd");
+ cmd->stat = stat;
+ return 1;
+ }
+ }
+
+ if (ob_ide_wait_stat(drive, 0, BUSY_STAT | ERR_STAT, &stat)) {
+ ob_ide_error(drive, stat, "timeout, ATAPI BUSY clear");
+ cmd->stat = stat;
+ return 1;
+ }
+
+ if ((stat & (BUSY_STAT | DRQ_STAT | ERR_STAT)) != DRQ_STAT) {
+ /*
+ * if command isn't request sense, then we have a problem. if
+ * we are doing a sense, ERR_STAT == CHECK_CONDITION
+ */
+ if (cmd->cdb[0] != ATAPI_REQ_SENSE) {
+ IDE_DPRINTF("odd, drive didn't want to transfer %x\n",
+ stat);
+ return 1;
+ }
+ }
+
+ /*
+ * transfer cdb
+ */
+ ob_ide_pio_outsw(drive, IDEREG_DATA, cmd->cdb,sizeof(cmd->cdb));
+ ob_ide_400ns_delay(drive);
+
+ /*
+ * ok, cdb was sent to drive, now do data transfer (if any)
+ */
+ bytes = cmd->buflen;
+ buffer = cmd->buffer;
+ do {
+ unsigned int bc;
+
+ if (ob_ide_wait_stat(drive, 0, BUSY_STAT | ERR_STAT, &stat)) {
+ ob_ide_error(drive, stat, "busy not clear after cdb");
+ cmd->stat = stat;
+ break;
+ }
+
+ /*
+ * transfer complete!
+ */
+ if ((stat & (BUSY_STAT | DRQ_STAT)) == 0)
+ break;
+
+ if ((stat & (BUSY_STAT | DRQ_STAT)) != DRQ_STAT)
+ break;
+
+ reason = ob_ide_pio_readb(drive, IDEREG_NSECTOR);
+ lcyl = ob_ide_pio_readb(drive, IDEREG_LCYL);
+ hcyl = ob_ide_pio_readb(drive, IDEREG_HCYL);
+
+ /*
+ * check if the drive wants to transfer data in the same
+ * direction as we do...
+ */
+ if ((reason & IREASON_CD) && cmd->data_direction != atapi_ddir_read) {
+ ob_ide_error(drive, stat, "atapi, bad transfer ddir");
+ break;
+ }
+
+ bc = (hcyl << 8) | lcyl;
+ if (!bc)
+ break;
+
+ if (bc > bytes)
+ bc = bytes;
+
+ if (cmd->data_direction == atapi_ddir_read)
+ ob_ide_pio_insw(drive, IDEREG_DATA, buffer, bc);
+ else
+ ob_ide_pio_outsw(drive, IDEREG_DATA, buffer, bc);
+
+ bytes -= bc;
+ buffer += bc;
+
+ ob_ide_400ns_delay(drive);
+ } while (bytes);
+
+ if (cmd->data_direction != atapi_ddir_none)
+ (void) ob_ide_wait_stat(drive, 0, BUSY_STAT, &stat);
+
+ if (bytes)
+ IDE_DPRINTF("cdb failed, bytes=%d, stat=%x\n", bytes, stat);
+
+ return (stat & ERR_STAT) || bytes;
+}
+
+/*
+ * execute a packet command, with retries if appropriate
+ */
+static int
+ob_ide_atapi_packet(struct ide_drive *drive, struct atapi_command *cmd)
+{
+ int retries = 5, ret;
+
+ if (drive->type != ide_type_atapi)
+ return 1;
+ if (cmd->buflen > 0xffff)
+ return 1;
+
+ /*
+ * retry loop
+ */
+ do {
+ ret = ob_ide_pio_packet(drive, cmd);
+ if (!ret)
+ break;
+
+ /*
+ * request sense failed, bummer
+ */
+ if (cmd->cdb[0] == ATAPI_REQ_SENSE)
+ break;
+
+ if (ob_ide_atapi_request_sense(drive))
+ break;
+
+ /*
+ * we know sense is valid. retry if the drive isn't ready,
+ * otherwise don't bother.
+ */
+ if (cmd->sense.sense_key != ATAPI_SENSE_NOT_READY)
+ break;
+ /*
+ * ... except 'medium not present'
+ */
+ if (cmd->sense.asc == 0x3a)
+ break;
+
+ udelay(1000000);
+ } while (retries--);
+
+ if (ret)
+ ob_ide_error(drive, 0, "atapi command");
+
+ return ret;
+}
+
+static int
+ob_ide_atapi_request_sense(struct ide_drive *drive)
+{
+ struct atapi_command *cmd = &drive->channel->atapi_cmd;
+ unsigned char old_cdb;
+
+ /*
+ * save old cdb for debug error
+ */
+ old_cdb = cmd->cdb[0];
+
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->cdb[0] = ATAPI_REQ_SENSE;
+ cmd->cdb[4] = 18;
+ cmd->buffer = (unsigned char *) &cmd->sense;
+ cmd->buflen = 18;
+ cmd->data_direction = atapi_ddir_read;
+ cmd->old_cdb = old_cdb;
+
+ if (ob_ide_atapi_packet(drive, cmd))
+ return 1;
+
+ cmd->sense_valid = 1;
+ return 0;
+}
+
+/*
+ * make sure drive is ready and media loaded
+ */
+static int
+ob_ide_atapi_drive_ready(struct ide_drive *drive)
+{
+ struct atapi_command *cmd = &drive->channel->atapi_cmd;
+ struct atapi_capacity cap;
+
+ IDE_DPRINTF("ob_ide_atapi_drive_ready\n");
+
+ /*
+ * Test Unit Ready is like a ping
+ */
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->cdb[0] = ATAPI_TUR;
+
+ if (ob_ide_atapi_packet(drive, cmd)) {
+ IDE_DPRINTF("%d: TUR failed\n", drive->nr);
+ return 1;
+ }
+
+ /*
+ * don't force load of tray (bit 2 in byte 4 of cdb), it's
+ * annoying and we don't want to deal with errors from drives
+ * that cannot do it
+ */
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->cdb[0] = ATAPI_START_STOP_UNIT;
+ cmd->cdb[4] = 0x01;
+
+ if (ob_ide_atapi_packet(drive, cmd)) {
+ IDE_DPRINTF("%d: START_STOP unit failed\n", drive->nr);
+ return 1;
+ }
+
+ /*
+ * finally, get capacity and block size
+ */
+ memset(cmd, 0, sizeof(*cmd));
+ memset(&cap, 0, sizeof(cap));
+
+ cmd->cdb[0] = ATAPI_READ_CAPACITY;
+ cmd->buffer = (unsigned char *) &cap;
+ cmd->buflen = sizeof(cap);
+ cmd->data_direction = atapi_ddir_read;
+
+ if (ob_ide_atapi_packet(drive, cmd)) {
+ drive->sectors = 0x1fffff;
+ drive->bs = 2048;
+ return 1;
+ }
+
+ drive->sectors = __be32_to_cpu(cap.lba) + 1;
+ drive->bs = __be32_to_cpu(cap.block_size);
+ return 0;
+}
+
+/*
+ * read from an atapi device, using READ_10
+ */
+static int
+ob_ide_read_atapi(struct ide_drive *drive, unsigned long long block,
+ unsigned char *buf, unsigned int sectors)
+{
+ struct atapi_command *cmd = &drive->channel->atapi_cmd;
+
+ if (ob_ide_atapi_drive_ready(drive))
+ return 1;
+
+ memset(cmd, 0, sizeof(*cmd));
+
+ /*
+ * READ_10 should work on generally any atapi device
+ */
+ cmd->cdb[0] = ATAPI_READ_10;
+ cmd->cdb[2] = (block >> 24) & 0xff;
+ cmd->cdb[3] = (block >> 16) & 0xff;
+ cmd->cdb[4] = (block >> 8) & 0xff;
+ cmd->cdb[5] = block & 0xff;
+ cmd->cdb[7] = (sectors >> 8) & 0xff;
+ cmd->cdb[8] = sectors & 0xff;
+
+ cmd->buffer = buf;
+ cmd->buflen = sectors * 2048;
+ cmd->data_direction = atapi_ddir_read;
+
+ return ob_ide_atapi_packet(drive, cmd);
+}
+
+static int
+ob_ide_read_ata_chs(struct ide_drive *drive, unsigned long long block,
+ unsigned char *buf, unsigned int sectors)
+{
+ struct ata_command *cmd = &drive->channel->ata_cmd;
+ unsigned int track = (block / drive->sect);
+ unsigned int sect = (block % drive->sect) + 1;
+ unsigned int head = (track % drive->head);
+ unsigned int cyl = (track / drive->head);
+
+ /*
+ * fill in chs command to read from disk at given location
+ */
+ cmd->buffer = buf;
+ cmd->buflen = sectors * 512;
+
+ cmd->nsector = sectors & 0xff;
+ cmd->sector = sect;
+ cmd->lcyl = cyl;
+ cmd->hcyl = cyl >> 8;
+ cmd->device_head = head;
+
+ cmd->command = WIN_READ;
+
+ return ob_ide_pio_data_in(drive, cmd);
+}
+
+static int
+ob_ide_read_ata_lba28(struct ide_drive *drive, unsigned long long block,
+ unsigned char *buf, unsigned int sectors)
+{
+ struct ata_command *cmd = &drive->channel->ata_cmd;
+
+ memset(cmd, 0, sizeof(*cmd));
+
+ /*
+ * fill in 28-bit lba command to read from disk at given location
+ */
+ cmd->buffer = buf;
+ cmd->buflen = sectors * 512;
+
+ cmd->nsector = sectors;
+ cmd->sector = block;
+ cmd->lcyl = block >>= 8;
+ cmd->hcyl = block >>= 8;
+ cmd->device_head = ((block >> 8) & 0x0f);
+ cmd->device_head |= (1 << 6);
+
+ cmd->command = WIN_READ;
+
+ return ob_ide_pio_data_in(drive, cmd);
+}
+
+static int
+ob_ide_read_ata_lba48(struct ide_drive *drive, unsigned long long block,
+ unsigned char *buf, unsigned int sectors)
+{
+ struct ata_command *cmd = &drive->channel->ata_cmd;
+
+ memset(cmd, 0, sizeof(*cmd));
+
+ cmd->buffer = buf;
+ cmd->buflen = sectors * 512;
+
+ /*
+ * we are using tasklet addressing here
+ */
+ cmd->task[2] = sectors;
+ cmd->task[3] = sectors >> 8;
+ cmd->task[4] = block;
+ cmd->task[5] = block >> 8;
+ cmd->task[6] = block >> 16;
+ cmd->task[7] = block >> 24;
+ cmd->task[8] = (u64) block >> 32;
+ cmd->task[9] = (u64) block >> 40;
+
+ cmd->command = WIN_READ_EXT;
+
+ ob_ide_write_tasklet(drive, cmd);
+
+ return ob_ide_pio_data_in(drive, cmd);
+}
+/*
+ * read 'sectors' sectors from ata device
+ */
+static int
+ob_ide_read_ata(struct ide_drive *drive, unsigned long long block,
+ unsigned char *buf, unsigned int sectors)
+{
+ unsigned long long end_block = block + sectors;
+ const int need_lba48 = (end_block > (1ULL << 28)) || (sectors > 255);
+
+ if (end_block > drive->sectors)
+ return 1;
+ if (need_lba48 && drive->addressing != ide_lba48)
+ return 1;
+
+ /*
+ * use lba48 if we have to, otherwise use the faster lba28
+ */
+ if (need_lba48)
+ return ob_ide_read_ata_lba48(drive, block, buf, sectors);
+ else if (drive->addressing != ide_chs)
+ return ob_ide_read_ata_lba28(drive, block, buf, sectors);
+
+ return ob_ide_read_ata_chs(drive, block, buf, sectors);
+}
+
+static int
+ob_ide_read_sectors(struct ide_drive *drive, unsigned long long block,
+ unsigned char *buf, unsigned int sectors)
+{
+ if (!sectors)
+ return 1;
+ if (block + sectors > drive->sectors)
+ return 1;
+
+ IDE_DPRINTF("ob_ide_read_sectors: block=%lu sectors=%u\n",
+ (unsigned long) block, sectors);
+
+ if (drive->type == ide_type_ata)
+ return ob_ide_read_ata(drive, block, buf, sectors);
+ else
+ return ob_ide_read_atapi(drive, block, buf, sectors);
+}
+
+/*
+ * byte swap the string if necessay, and strip leading/trailing blanks
+ */
+static void
+ob_ide_fixup_string(unsigned char *s, unsigned int len)
+{
+ unsigned char *p = s, *end = &s[len & ~1];
+
+ /*
+ * if big endian arch, byte swap the string
+ */
+#ifdef CONFIG_BIG_ENDIAN
+ for (p = end ; p != s;) {
+ unsigned short *pp = (unsigned short *) (p -= 2);
+ *pp = __le16_to_cpu(*pp);
+ }
+#endif
+
+ while (s != end && *s == ' ')
+ ++s;
+ while (s != end && *s)
+ if (*s++ != ' ' || (s != end && *s && *s != ' '))
+ *p++ = *(s-1);
+ while (p != end)
+ *p++ = '\0';
+}
+
+/*
+ * it's big endian, we need to swap (if on little endian) the items we use
+ */
+static int
+ob_ide_fixup_id(struct hd_driveid *id)
+{
+ ob_ide_fixup_string(id->model, 40);
+ id->config = __le16_to_cpu(id->config);
+ id->lba_capacity = __le32_to_cpu(id->lba_capacity);
+ id->cyls = __le16_to_cpu(id->cyls);
+ id->heads = __le16_to_cpu(id->heads);
+ id->sectors = __le16_to_cpu(id->sectors);
+ id->command_set_2 = __le16_to_cpu(id->command_set_2);
+ id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2);
+
+ return 0;
+}
+
+static int
+ob_ide_identify_drive(struct ide_drive *drive)
+{
+ struct ata_command *cmd = &drive->channel->ata_cmd;
+ struct hd_driveid id;
+
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->buffer = (unsigned char *) &id;
+ cmd->buflen = 512;
+
+ if (drive->type == ide_type_ata)
+ cmd->command = WIN_IDENTIFY;
+ else if (drive->type == ide_type_atapi)
+ cmd->command = WIN_IDENTIFY_PACKET;
+ else {
+ IDE_DPRINTF("%s: called with bad device type %d\n",
+ __FUNCTION__, drive->type);
+ return 1;
+ }
+
+ if (ob_ide_pio_data_in(drive, cmd))
+ return 1;
+
+ ob_ide_fixup_id(&id);
+
+ if (drive->type == ide_type_atapi) {
+ drive->media = (id.config >> 8) & 0x1f;
+ drive->sectors = 0x7fffffff;
+ drive->bs = 2048;
+ drive->max_sectors = 31;
+ } else {
+ drive->media = ide_media_disk;
+ drive->sectors = id.lba_capacity;
+ drive->bs = 512;
+ drive->max_sectors = 255;
+
+#ifdef CONFIG_IDE_LBA48
+ if ((id.command_set_2 & 0x0400) && (id.cfs_enable_2 & 0x0400)) {
+ drive->addressing = ide_lba48;
+ drive->max_sectors = 65535;
+ } else
+#endif
+ if (id.capability & 2)
+ drive->addressing = ide_lba28;
+ else {
+ drive->addressing = ide_chs;
+ }
+
+ /* only set these in chs mode? */
+ drive->cyl = id.cyls;
+ drive->head = id.heads;
+ drive->sect = id.sectors;
+ }
+
+ strncpy(drive->model, (char*)id.model, sizeof(id.model));
+ drive->model[40] = '\0';
+ return 0;
+}
+
+/*
+ * identify type of devices on channel. must have already been probed.
+ */
+static void
+ob_ide_identify_drives(struct ide_channel *chan)
+{
+ struct ide_drive *drive;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ drive = &chan->drives[i];
+
+ if (!drive->present)
+ continue;
+
+ ob_ide_identify_drive(drive);
+ }
+}
+
+/*
+ * software reset (ATA-4, section 8.3)
+ */
+static void
+ob_ide_software_reset(struct ide_drive *drive)
+{
+ struct ide_channel *chan = drive->channel;
+
+ ob_ide_pio_writeb(drive, IDEREG_CONTROL, IDECON_NIEN | IDECON_SRST);
+ ob_ide_400ns_delay(drive);
+ ob_ide_pio_writeb(drive, IDEREG_CONTROL, IDECON_NIEN);
+ ob_ide_400ns_delay(drive);
+
+ /*
+ * if master is present, wait for BUSY clear
+ */
+ if (chan->drives[0].present)
+ ob_ide_wait_stat(drive, 0, BUSY_STAT, NULL);
+
+ /*
+ * if slave is present, wait until it allows register access
+ */
+ if (chan->drives[1].present) {
+ unsigned char sectorn, sectorc;
+ int timeout = 1000;
+
+ do {
+ /*
+ * select it
+ */
+ ob_ide_pio_writeb(drive, IDEREG_CURRENT, IDEHEAD_DEV1);
+ ob_ide_400ns_delay(drive);
+
+ sectorn = ob_ide_pio_readb(drive, IDEREG_SECTOR);
+ sectorc = ob_ide_pio_readb(drive, IDEREG_NSECTOR);
+
+ if (sectorc == 0x01 && sectorn == 0x01)
+ break;
+
+ } while (--timeout);
+ }
+
+ /*
+ * reset done, reselect original device
+ */
+ drive->channel->selected = -1;
+ ob_ide_select_drive(drive);
+}
+
+/*
+ * this serves as both a device check, and also to verify that the drives
+ * we initially "found" are really there
+ */
+static void
+ob_ide_device_type_check(struct ide_drive *drive)
+{
+ unsigned char sc, sn, cl, ch, st;
+
+ if (ob_ide_select_drive(drive))
+ return;
+
+ sc = ob_ide_pio_readb(drive, IDEREG_NSECTOR);
+ sn = ob_ide_pio_readb(drive, IDEREG_SECTOR);
+
+ if (sc == 0x01 && sn == 0x01) {
+ /*
+ * read device signature
+ */
+ cl = ob_ide_pio_readb(drive, IDEREG_LCYL);
+ ch = ob_ide_pio_readb(drive, IDEREG_HCYL);
+ st = ob_ide_pio_readb(drive, IDEREG_STATUS);
+ if (cl == 0x14 && ch == 0xeb)
+ drive->type = ide_type_atapi;
+ else if (cl == 0x00 && ch == 0x00 && st != 0x00)
+ drive->type = ide_type_ata;
+ else
+ drive->present = 0;
+ } else
+ drive->present = 0;
+}
+
+/*
+ * pure magic
+ */
+static void
+ob_ide_device_check(struct ide_drive *drive)
+{
+ unsigned char sc, sn;
+
+ /*
+ * non-existing io port should return 0xff, don't probe this
+ * channel at all then
+ */
+ if (ob_ide_pio_readb(drive, IDEREG_STATUS) == 0xff) {
+ drive->channel->present = 0;
+ return;
+ }
+
+ if (ob_ide_select_drive(drive))
+ return;
+
+ ob_ide_pio_writeb(drive, IDEREG_NSECTOR, 0x55);
+ ob_ide_pio_writeb(drive, IDEREG_SECTOR, 0xaa);
+ ob_ide_pio_writeb(drive, IDEREG_NSECTOR, 0xaa);
+ ob_ide_pio_writeb(drive, IDEREG_SECTOR, 0x55);
+ ob_ide_pio_writeb(drive, IDEREG_NSECTOR, 0x55);
+ ob_ide_pio_writeb(drive, IDEREG_SECTOR, 0xaa);
+
+ sc = ob_ide_pio_readb(drive, IDEREG_NSECTOR);
+ sn = ob_ide_pio_readb(drive, IDEREG_SECTOR);
+
+ /*
+ * we _think_ the device is there, we will make sure later
+ */
+ if (sc == 0x55 && sn == 0xaa) {
+ drive->present = 1;
+ drive->type = ide_type_unknown;
+ }
+}
+
+/*
+ * probe the legacy ide ports and find attached devices.
+ */
+static void
+ob_ide_probe(struct ide_channel *chan)
+{
+ struct ide_drive *drive;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ drive = &chan->drives[i];
+
+ ob_ide_device_check(drive);
+
+ /*
+ * no point in continuing
+ */
+ if (!chan->present)
+ break;
+
+ if (!drive->present)
+ continue;
+
+ /*
+ * select and reset device
+ */
+ if (ob_ide_select_drive(drive))
+ continue;
+
+ ob_ide_software_reset(drive);
+
+ ob_ide_device_type_check(drive);
+ }
+}
+
+/*
+ * The following functions are interfacing with OpenBIOS. They
+ * are device node methods. Thus they have to do proper stack handling.
+ *
+ */
+
+/*
+ * 255 sectors for ata lba28, 65535 for lba48, and 31 sectors for atapi
+ */
+static void
+ob_ide_max_transfer(int *idx)
+{
+ struct ide_drive *drive = *(struct ide_drive **)idx;
+
+ IDE_DPRINTF("max_transfer %x\n", drive->max_sectors * drive->bs);
+
+ PUSH(drive->max_sectors * drive->bs);
+}
+
+static void
+ob_ide_read_blocks(int *idx)
+{
+ cell n = POP(), cnt=n;
+ ucell blk = POP();
+ unsigned char *dest = (unsigned char *)cell2pointer(POP());
+ struct ide_drive *drive = *(struct ide_drive **)idx;
+
+ IDE_DPRINTF("ob_ide_read_blocks %lx block=%ld n=%ld\n",
+ (unsigned long)dest, (unsigned long)blk, (long)n);
+
+ while (n) {
+ int len = n;
+ if (len > drive->max_sectors)
+ len = drive->max_sectors;
+
+ if (ob_ide_read_sectors(drive, blk, dest, len)) {
+ IDE_DPRINTF("ob_ide_read_blocks: error\n");
+ RET(0);
+ }
+
+ dest += len * drive->bs;
+ n -= len;
+ blk += len;
+ }
+
+ PUSH(cnt);
+}
+
+static void
+ob_ide_block_size(int *idx)
+{
+ struct ide_drive *drive = *(struct ide_drive **)idx;
+
+ IDE_DPRINTF("ob_ide_block_size: block size %x\n", drive->bs);
+
+ PUSH(drive->bs);
+}
+
+static void
+ob_ide_initialize(int *idx)
+{
+ int props[3];
+ phandle_t ph=get_cur_dev();
+
+ push_str("block");
+ fword("device-type");
+
+ // Set dummy reg properties
+
+ set_int_property(ph, "#address-cells", 1);
+ set_int_property(ph, "#size-cells", 0);
+
+ props[0] = __cpu_to_be32(0); props[1] = __cpu_to_be32(0); props[2] = __cpu_to_be32(0);
+ set_property(ph, "reg", (char *)&props, 3*sizeof(int));
+
+ fword("is-deblocker");
+}
+
+static void
+ob_ide_open(int *idx)
+{
+ int ret=1, len;
+ phandle_t ph;
+ struct ide_drive *drive;
+ struct ide_channel *chan;
+ char *idename;
+ int unit;
+
+ fword("my-unit");
+ unit = POP();
+
+ fword("my-parent");
+ fword("ihandle>phandle");
+ ph=(phandle_t)POP();
+ idename=get_property(ph, "name", &len);
+
+ chan = ide_seek_channel(idename);
+ drive = &chan->drives[unit];
+ *(struct ide_drive **)idx = drive;
+
+ IDE_DPRINTF("opening channel %d unit %d\n", idx[1], idx[0]);
+ dump_drive(drive);
+
+ if (drive->type != ide_type_ata)
+ ret= !ob_ide_atapi_drive_ready(drive);
+
+ selfword("open-deblocker");
+
+ /* interpose disk-label */
+ ph = find_dev("/packages/disk-label");
+ fword("my-args");
+ PUSH_ph( ph );
+ fword("interpose");
+
+ RET ( -ret );
+}
+
+static void
+ob_ide_close(struct ide_drive *drive)
+{
+ selfword("close-deblocker");
+}
+
+NODE_METHODS(ob_ide) = {
+ { NULL, ob_ide_initialize },
+ { "open", ob_ide_open },
+ { "close", ob_ide_close },
+ { "read-blocks", ob_ide_read_blocks },
+ { "block-size", ob_ide_block_size },
+ { "max-transfer", ob_ide_max_transfer },
+};
+
+static void
+ob_ide_ctrl_initialize(int *idx)
+{
+ phandle_t ph=get_cur_dev();
+
+ /* set device type */
+ push_str(DEV_TYPE);
+ fword("device-type");
+
+ set_int_property(ph, "#address-cells", 1);
+ set_int_property(ph, "#size-cells", 0);
+}
+
+static void
+ob_ide_ctrl_decodeunit(int *idx)
+{
+ fword("parse-hex");
+}
+
+NODE_METHODS(ob_ide_ctrl) = {
+ { NULL, ob_ide_ctrl_initialize },
+ { "decode-unit", ob_ide_ctrl_decodeunit },
+};
+
+static void set_cd_alias(const char *path)
+{
+ phandle_t aliases;
+
+ aliases = find_dev("/aliases");
+
+ if (get_property(aliases, "cd", NULL))
+ return;
+
+ set_property(aliases, "cd", path, strlen(path) + 1);
+ set_property(aliases, "cdrom", path, strlen(path) + 1);
+}
+
+static void set_hd_alias(const char *path)
+{
+ phandle_t aliases;
+
+ aliases = find_dev("/aliases");
+
+ if (get_property(aliases, "hd", NULL))
+ return;
+
+ set_property(aliases, "hd", path, strlen(path) + 1);
+ set_property(aliases, "disk", path, strlen(path) + 1);
+}
+
+static void set_ide_alias(const char *path)
+{
+ phandle_t aliases;
+ static int ide_counter = 0;
+ char idestr[8];
+
+ aliases = find_dev("/aliases");
+
+ snprintf(idestr, sizeof(idestr), "ide%d", ide_counter++);
+ set_property(aliases, idestr, path, strlen(path) + 1);
+}
+
+int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0,
+ uint32_t io_port1, uint32_t ctl_port1)
+{
+ int i, j;
+ char nodebuff[128];
+ phandle_t dnode;
+ struct ide_channel *chan;
+ int io_ports[IDE_MAX_CHANNELS];
+ int ctl_ports[IDE_MAX_CHANNELS];
+ u32 props[6];
+
+ io_ports[0] = io_port0;
+ ctl_ports[0] = ctl_port0;
+ io_ports[1] = io_port1;
+ ctl_ports[1] = ctl_port1;
+
+ for (i = 0; i < IDE_NUM_CHANNELS; i++, current_channel++) {
+
+ chan = malloc(sizeof(struct ide_channel));
+
+ snprintf(chan->name, sizeof(chan->name),
+ DEV_NAME, current_channel);
+
+ chan->mmio = 0;
+
+ for (j = 0; j < 8; j++)
+ chan->io_regs[j] = io_ports[i] + j;
+
+ chan->io_regs[8] = ctl_ports[i];
+ chan->io_regs[9] = ctl_ports[i] + 1;
+
+ chan->obide_inb = ob_ide_inb;
+ chan->obide_insw = ob_ide_insw;
+ chan->obide_outb = ob_ide_outb;
+ chan->obide_outsw = ob_ide_outsw;
+
+ chan->selected = -1;
+
+ /*
+ * assume it's there, if not io port dead check will clear
+ */
+ chan->present = 1;
+
+ for (j = 0; j < 2; j++) {
+ chan->drives[j].present = 0;
+ chan->drives[j].unit = j;
+ chan->drives[j].channel = chan;
+ /* init with a decent value */
+ chan->drives[j].bs = 512;
+
+ chan->drives[j].nr = i * 2 + j;
+ }
+
+ ide_add_channel(chan);
+
+ ob_ide_probe(chan);
+
+ if (!chan->present)
+ continue;
+
+ ob_ide_identify_drives(chan);
+
+ snprintf(nodebuff, sizeof(nodebuff), "%s/" DEV_NAME, path,
+ current_channel);
+ REGISTER_NAMED_NODE(ob_ide_ctrl, nodebuff);
+
+ dnode = find_dev(nodebuff);
+
+#if !defined(CONFIG_PPC) && !defined(CONFIG_SPARC64)
+ props[0]=14; props[1]=0;
+ set_property(dnode, "interrupts",
+ (char *)&props, 2*sizeof(props[0]));
+#endif
+
+ props[0] = __cpu_to_be32(chan->io_regs[0]);
+ props[1] = __cpu_to_be32(1); props[2] = __cpu_to_be32(8);
+ props[3] = __cpu_to_be32(chan->io_regs[8]);
+ props[4] = __cpu_to_be32(1); props[5] = __cpu_to_be32(2);
+ set_property(dnode, "reg", (char *)&props, 6*sizeof(props[0]));
+
+ IDE_DPRINTF(DEV_NAME": [io ports 0x%x-0x%x,0x%x]\n",
+ current_channel, chan->io_regs[0],
+ chan->io_regs[0] + 7, chan->io_regs[8]);
+
+ for (j = 0; j < 2; j++) {
+ struct ide_drive *drive = &chan->drives[j];
+ const char *media = "UNKNOWN";
+
+ if (!drive->present)
+ continue;
+
+ IDE_DPRINTF(" drive%d [ATA%s ", j,
+ drive->type == ide_type_atapi ? "PI" : "");
+ switch (drive->media) {
+ case ide_media_floppy:
+ media = "floppy";
+ break;
+ case ide_media_cdrom:
+ media = "cdrom";
+ break;
+ case ide_media_optical:
+ media = "mo";
+ break;
+ case ide_media_disk:
+ media = "disk";
+ break;
+ }
+ IDE_DPRINTF("%s]: %s\n", media, drive->model);
+ snprintf(nodebuff, sizeof(nodebuff),
+ "%s/" DEV_NAME "/%s", path, current_channel,
+ media);
+ REGISTER_NAMED_NODE(ob_ide, nodebuff);
+ dnode=find_dev(nodebuff);
+ set_int_property(dnode, "reg", j);
+
+ /* create aliases */
+
+ set_ide_alias(nodebuff);
+ if (drive->media == ide_media_cdrom)
+ set_cd_alias(nodebuff);
+ if (drive->media == ide_media_disk)
+ set_hd_alias(nodebuff);
+ }
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_DRIVER_MACIO)
+static unsigned char
+macio_ide_inb(struct ide_channel *chan, unsigned int port)
+{
+ return in_8((unsigned char*)(chan->mmio + (port << 4)));
+}
+
+static void
+macio_ide_outb(struct ide_channel *chan, unsigned char data, unsigned int port)
+{
+ out_8((unsigned char*)(chan->mmio + (port << 4)), data);
+}
+
+static void
+macio_ide_insw(struct ide_channel *chan,
+ unsigned int port, unsigned char *addr, unsigned int count)
+{
+ _insw((uint16_t*)(chan->mmio + (port << 4)), addr, count);
+}
+
+static void
+macio_ide_outsw(struct ide_channel *chan,
+ unsigned int port, unsigned char *addr, unsigned int count)
+{
+ _outsw((uint16_t*)(chan->mmio + (port << 4)), addr, count);
+}
+
+#define MACIO_IDE_OFFSET 0x00020000
+#define MACIO_IDE_SIZE 0x00001000
+
+int macio_ide_init(const char *path, uint32_t addr, int nb_channels)
+{
+ int i, j;
+ char nodebuff[128];
+ phandle_t dnode;
+ u32 props[8];
+ struct ide_channel *chan;
+
+ /* IDE ports on Macs are numbered from 3.
+ * Also see comments in macio.c:openpic_init() */
+ current_channel = 3;
+
+ for (i = 0; i < nb_channels; i++, current_channel++) {
+
+ chan = malloc(sizeof(struct ide_channel));
+
+ snprintf(chan->name, sizeof(chan->name),
+ DEV_NAME, current_channel);
+
+ chan->mmio = addr + MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE;
+
+ chan->obide_inb = macio_ide_inb;
+ chan->obide_insw = macio_ide_insw;
+ chan->obide_outb = macio_ide_outb;
+ chan->obide_outsw = macio_ide_outsw;
+
+ chan->selected = -1;
+
+ /*
+ * assume it's there, if not io port dead check will clear
+ */
+ chan->present = 1;
+
+ for (j = 0; j < 2; j++) {
+ chan->drives[j].present = 0;
+ chan->drives[j].unit = j;
+ chan->drives[j].channel = chan;
+ /* init with a decent value */
+ chan->drives[j].bs = 512;
+
+ chan->drives[j].nr = i * 2 + j;
+ }
+
+ ob_ide_probe(chan);
+
+ if (!chan->present) {
+ free(chan);
+ continue;
+ }
+
+ ide_add_channel(chan);
+
+ ob_ide_identify_drives(chan);
+
+ snprintf(nodebuff, sizeof(nodebuff), "%s/" DEV_NAME, path,
+ current_channel);
+ REGISTER_NAMED_NODE(ob_ide_ctrl, nodebuff);
+
+ dnode = find_dev(nodebuff);
+
+ set_property(dnode, "compatible", (is_oldworld() ?
+ "heathrow-ata" : "keylargo-ata"), 13);
+
+ props[0] = 0x00000526;
+ props[1] = 0x00000085;
+ props[2] = 0x00000025;
+ props[3] = 0x00000025;
+ props[4] = 0x00000025;
+ props[5] = 0x00000000;
+ props[6] = 0x00000000;
+ props[7] = 0x00000000;
+ OLDWORLD(set_property(dnode, "AAPL,pio-timing",
+ (char *)&props, 8*sizeof(props[0])));
+
+ /* The first interrupt entry is the ide interrupt, the second
+ the dbdma interrupt */
+ switch (i) {
+ case 0:
+ props[0] = 0x0000000d;
+ props[2] = 0x00000002;
+ break;
+ case 1:
+ props[0] = 0x0000000e;
+ props[2] = 0x00000003;
+ break;
+ case 2:
+ props[0] = 0x0000000f;
+ props[2] = 0x00000004;
+ break;
+ default:
+ props[0] = 0x00000000;
+ props[2] = 0x00000000;
+ break;
+ }
+ props[1] = 0x00000000; /* XXX level triggered on real hw */
+ props[3] = 0x00000000;
+ NEWWORLD(set_property(dnode, "interrupts",
+ (char *)&props, 4*sizeof(props[0])));
+ NEWWORLD(set_int_property(dnode, "#interrupt-cells", 2));
+
+ props[1] = props[2];
+ OLDWORLD(set_property(dnode, "AAPL,interrupts",
+ (char *)&props, 2*sizeof(props[0])));
+
+ props[0] = MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE;
+ props[1] = MACIO_IDE_SIZE;
+ props[2] = 0x00008b00 + i * 0x0200;
+ props[3] = 0x0200;
+ set_property(dnode, "reg", (char *)&props, 4*sizeof(props[0]));
+
+ props[0] = addr + MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE;
+ props[1] = addr + 0x00008b00 + i * 0x0200;
+ OLDWORLD(set_property(dnode, "AAPL,address",
+ (char *)&props, 2*sizeof(props[0])));
+
+ props[0] = 0;
+ OLDWORLD(set_property(dnode, "AAPL,bus-id", (char*)props,
+ 1 * sizeof(props[0])));
+ IDE_DPRINTF(DEV_NAME": [io ports 0x%lx]\n",
+ current_channel, chan->mmio);
+
+ for (j = 0; j < 2; j++) {
+ struct ide_drive *drive = &chan->drives[j];
+ const char *media = "UNKNOWN";
+
+ if (!drive->present)
+ continue;
+
+ IDE_DPRINTF(" drive%d [ATA%s ", j,
+ drive->type == ide_type_atapi ? "PI" : "");
+ switch (drive->media) {
+ case ide_media_floppy:
+ media = "floppy";
+ break;
+ case ide_media_cdrom:
+ media = "cdrom";
+ break;
+ case ide_media_optical:
+ media = "mo";
+ break;
+ case ide_media_disk:
+ media = "disk";
+ break;
+ }
+ IDE_DPRINTF("%s]: %s\n", media, drive->model);
+ snprintf(nodebuff, sizeof(nodebuff),
+ "%s/" DEV_NAME "/%s", path, current_channel,
+ media);
+ REGISTER_NAMED_NODE(ob_ide, nodebuff);
+ dnode = find_dev(nodebuff);
+ set_int_property(dnode, "reg", j);
+
+ /* create aliases */
+
+ set_ide_alias(nodebuff);
+ if (drive->media == ide_media_cdrom)
+ set_cd_alias(nodebuff);
+ if (drive->media == ide_media_disk)
+ set_hd_alias(nodebuff);
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_DRIVER_MACIO */
diff --git a/roms/openbios/drivers/ide.h b/roms/openbios/drivers/ide.h
new file mode 100644
index 00000000..d6c4b9f5
--- /dev/null
+++ b/roms/openbios/drivers/ide.h
@@ -0,0 +1,213 @@
+#ifndef IDE_H
+#define IDE_H
+
+#include "hdreg.h"
+
+/*
+ * legacy ide ports
+ */
+#define IDEREG_DATA 0x00
+#define IDEREG_ERROR 0x01
+#define IDEREG_FEATURE IDEREG_ERROR
+#define IDEREG_NSECTOR 0x02
+#define IDEREG_SECTOR 0x03
+#define IDEREG_LCYL 0x04
+#define IDEREG_HCYL 0x05
+#define IDEREG_CURRENT 0x06
+#define IDEREG_STATUS 0x07
+#define IDEREG_COMMAND IDEREG_STATUS
+#define IDEREG_CONTROL 0x08
+#define IDEREG_ASTATUS IDEREG_CONTROL
+
+/*
+ * device control bits
+ */
+#define IDECON_NIEN 0x02
+#define IDECON_SRST 0x04
+
+/*
+ * device head bits
+ */
+#define IDEHEAD_LBA 0x40
+#define IDEHEAD_DEV0 0x00
+#define IDEHEAD_DEV1 0x10
+
+/*
+ * status bytes
+ */
+#define ERR_STAT 0x01
+#define DRQ_STAT 0x08
+#define SEEK_STAT 0x10
+#define WRERR_STAT 0x20
+#define READY_STAT 0x40
+#define BUSY_STAT 0x80
+
+#define IREASON_CD 0x01
+#define IREASON_IO 0x02
+
+/*
+ * ATA opcodes
+ */
+#define WIN_READ 0x20
+#define WIN_READ_EXT 0x24
+#define WIN_IDENTIFY 0xEC
+#define WIN_PACKET 0xA0
+#define WIN_IDENTIFY_PACKET 0xA1
+
+/*
+ * ATAPI opcodes
+ */
+#define ATAPI_TUR 0x00
+#define ATAPI_READ_10 0x28
+#define ATAPI_REQ_SENSE 0x03
+#define ATAPI_START_STOP_UNIT 0x1b
+#define ATAPI_READ_CAPACITY 0x25
+
+/*
+ * atapi sense keys
+ */
+#define ATAPI_SENSE_NOT_READY 0x02
+
+/*
+ * supported device types
+ */
+enum {
+ ide_type_unknown,
+ ide_type_ata,
+ ide_type_atapi,
+};
+
+enum {
+ ide_media_floppy = 0x00,
+ ide_media_cdrom = 0x05,
+ ide_media_optical = 0x07,
+ ide_media_disk = 0x20,
+};
+
+/*
+ * drive addressing
+ */
+enum {
+ ide_chs = 1,
+ ide_lba28,
+ ide_lba48,
+};
+
+/*
+ * simple ata command that works for everything (except 48-bit lba commands)
+ */
+struct ata_command {
+ unsigned char *buffer;
+ unsigned int buflen;
+
+ /*
+ * data register
+ */
+ unsigned char data;
+ unsigned char feature;
+ unsigned char nsector;
+ unsigned char sector;
+ unsigned char lcyl;
+ unsigned char hcyl;
+ unsigned char device_head;
+ unsigned char command;
+ unsigned char control;
+
+ /*
+ * or tasklet, just for lba48 for now (above could be scrapped)
+ */
+ unsigned char task[10];
+
+ /*
+ * output
+ */
+ unsigned char stat;
+ unsigned int bytes;
+};
+
+struct atapi_command {
+ unsigned char cdb[12];
+ unsigned char *buffer;
+ unsigned int buflen;
+ unsigned char data_direction;
+
+ unsigned char stat;
+ unsigned char sense_valid;
+ struct request_sense sense;
+ unsigned char old_cdb;
+};
+
+struct ide_channel;
+
+struct ide_drive {
+ char unit; /* 0: master, 1: slave */
+ char present; /* there or not */
+ char type; /* ata or atapi */
+ char media; /* disk, cdrom, etc */
+ char addressing; /* chs/lba28/lba48 */
+
+ char model[41]; /* name */
+ int nr;
+
+ unsigned long sectors;
+
+ unsigned int max_sectors;
+
+ /*
+ * for legacy chs crap
+ */
+ unsigned int cyl;
+ unsigned int head;
+ unsigned int sect;
+
+ unsigned int bs; /* block size */
+
+ struct ide_channel *channel;
+};
+
+struct ide_channel {
+
+ char name[32];
+ struct ide_channel *next;
+
+ /*
+ * either mmio or io_regs is set to indicate mmio or not
+ */
+ unsigned long mmio;
+ int io_regs[10];
+
+ /*
+ * can be set to a mmio hook, default it legacy outb/inb
+ */
+ void (*obide_outb)(struct ide_channel *chan,
+ unsigned char addr, unsigned int port);
+ unsigned char (*obide_inb)(struct ide_channel *chan,
+ unsigned int port);
+ void (*obide_insw)(struct ide_channel *chan,
+ unsigned int port, unsigned char *addr,
+ unsigned int count);
+ void (*obide_outsw)(struct ide_channel *chan,
+ unsigned int port, unsigned char *addr,
+ unsigned int count);
+
+ struct ide_drive drives[2];
+ char selected;
+ char present;
+
+ /*
+ * only one can be busy per channel
+ */
+ struct ata_command ata_cmd;
+ struct atapi_command atapi_cmd;
+
+};
+
+enum {
+ atapi_ddir_none,
+ atapi_ddir_read,
+ atapi_ddir_write,
+};
+
+static int ob_ide_atapi_request_sense(struct ide_drive *drive);
+
+#endif
diff --git a/roms/openbios/drivers/iommu.c b/roms/openbios/drivers/iommu.c
new file mode 100644
index 00000000..cd9a64bb
--- /dev/null
+++ b/roms/openbios/drivers/iommu.c
@@ -0,0 +1,207 @@
+/**
+ ** Proll (PROM replacement)
+ ** iommu.c: Functions for DVMA management.
+ ** Copyright 1999 Pete Zaitcev
+ ** This code is licensed under GNU General Public License.
+ **/
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/ofmem.h"
+#include "drivers/drivers.h"
+#include "iommu.h"
+#include "arch/sparc32/ofmem_sparc32.h"
+
+#ifdef CONFIG_DEBUG_IOMMU
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+/*
+ * IOMMU parameters
+ */
+struct iommu {
+ struct iommu_regs *regs;
+ unsigned int *page_table;
+ unsigned long plow; /* Base bus address */
+};
+
+static struct iommu ciommu;
+
+static void
+iommu_invalidate(struct iommu_regs *iregs)
+{
+ iregs->tlbflush = 0;
+}
+
+/*
+ * XXX This is a problematic interface. We alloc _memory_ which is uncached.
+ * So if we ever reuse allocations somebody is going to get uncached pages.
+ * Returned address is always aligned by page.
+ * BTW, we were not going to give away anonymous storage, were we not?
+ */
+void *
+dvma_alloc(int size, unsigned int *pphys)
+{
+ void *va;
+ unsigned int pa, ba;
+ unsigned int npages;
+ unsigned int mva, mpa;
+ unsigned int i;
+ unsigned int *iopte;
+ struct iommu *t = &ciommu;
+ int ret;
+
+ npages = (size + (PAGE_SIZE-1)) / PAGE_SIZE;
+ ret = ofmem_posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE);
+ if (ret != 0)
+ return NULL;
+
+ ba = (unsigned int)mem_alloc(&cdvmem, npages * PAGE_SIZE, PAGE_SIZE);
+ if (ba == 0)
+ return NULL;
+
+ pa = (unsigned int)va2pa((unsigned long)va);
+
+ /*
+ * Change page attributes in MMU to uncached.
+ */
+ mva = (unsigned int) va;
+ mpa = (unsigned int) pa;
+ ofmem_arch_map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa));
+
+ /*
+ * Map into IOMMU page table.
+ */
+ mpa = (unsigned int) pa;
+ iopte = &t->page_table[(ba - t->plow) / PAGE_SIZE];
+ for (i = 0; i < npages; i++) {
+ *iopte++ = MKIOPTE(mpa);
+ mpa += PAGE_SIZE;
+ }
+
+ *pphys = ba;
+
+ return va;
+}
+
+/*
+ * Initialize IOMMU
+ * This looks like initialization of CPU MMU but
+ * the routine is higher in food chain.
+ */
+static struct iommu_regs *
+iommu_init(struct iommu *t, uint64_t base)
+{
+ unsigned int *ptab;
+ int ptsize;
+#ifdef CONFIG_DEBUG_IOMMU
+ unsigned int impl, vers;
+#endif
+ unsigned int tmp;
+ struct iommu_regs *regs;
+ int ret;
+ unsigned long vasize;
+
+ regs = (struct iommu_regs *)ofmem_map_io(base, IOMMU_REGS);
+ if (regs == NULL) {
+ DPRINTF("Cannot map IOMMU\n");
+ for (;;) { }
+ }
+ t->regs = regs;
+#ifdef CONFIG_DEBUG_IOMMU
+ impl = (regs->control & IOMMU_CTRL_IMPL) >> 28;
+ vers = (regs->control & IOMMU_CTRL_VERS) >> 24;
+#endif
+
+ tmp = regs->control;
+ tmp &= ~(IOMMU_CTRL_RNGE);
+
+ tmp |= (IOMMU_RNGE_32MB | IOMMU_CTRL_ENAB);
+ t->plow = 0xfe000000; /* End - 32 MB */
+ /* Size of VA region that we manage */
+ vasize = 0x2000000; /* 32 MB */
+
+ regs->control = tmp;
+ iommu_invalidate(regs);
+
+ /* Allocate IOMMU page table */
+ /* Tremendous alignment causes great waste... */
+ ptsize = (vasize / PAGE_SIZE) * sizeof(int);
+ ret = ofmem_posix_memalign((void *)&ptab, ptsize, ptsize);
+ if (ret != 0) {
+ DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize);
+ for (;;) { }
+ }
+ t->page_table = ptab;
+
+ /* flush_cache_all(); */
+ /** flush_tlb_all(); **/
+ tmp = (unsigned int)va2pa((unsigned long)ptab);
+ regs->base = tmp >> 4;
+ iommu_invalidate(regs);
+
+ DPRINTF("IOMMU: impl %d vers %d page table at 0x%p (pa 0x%x) of size %d bytes\n",
+ impl, vers, t->page_table, tmp, ptsize);
+
+ mem_init(&cdvmem, (char*)t->plow, (char *)0xfffff000);
+ return regs;
+}
+
+/* ( addr.lo addr.hi size -- virt ) */
+
+static void
+ob_iommu_map_in(void)
+{
+ phys_addr_t phys;
+ ucell size, virt;
+
+ size = POP();
+ phys = POP();
+ phys = (phys << 32) + POP();
+
+ virt = ofmem_map_io(phys, size);
+
+ PUSH(virt);
+}
+
+/* ( virt size ) */
+
+static void
+ob_iommu_map_out(void)
+{
+ ucell size = POP();
+ ucell virt = POP();
+
+ ofmem_release_io(virt, size);
+}
+
+void
+ob_init_iommu(uint64_t base)
+{
+ struct iommu_regs *regs;
+
+ regs = iommu_init(&ciommu, base);
+
+ push_str("/iommu");
+ fword("find-device");
+ PUSH((unsigned long)regs);
+ fword("encode-int");
+ push_str("address");
+ fword("property");
+
+ PUSH(base >> 32);
+ fword("encode-int");
+ PUSH(base & 0xffffffff);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(IOMMU_REGS);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ bind_func("map-in", ob_iommu_map_in);
+ bind_func("map-out", ob_iommu_map_out);
+}
diff --git a/roms/openbios/drivers/iommu.h b/roms/openbios/drivers/iommu.h
new file mode 100644
index 00000000..59e3387c
--- /dev/null
+++ b/roms/openbios/drivers/iommu.h
@@ -0,0 +1,102 @@
+/* iommu.h: Definitions for the sun4m IOMMU.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Adapted for Proll by Pete Zaitcev in 1999 (== made worse than original).
+ */
+
+/* #include <asm/page.h> */
+
+/* The iommu handles all virtual to physical address translations
+ * that occur between the SBUS and physical memory. Access by
+ * the cpu to IO registers and similar go over the mbus so are
+ * translated by the on chip SRMMU. The iommu and the srmmu do
+ * not need to have the same translations at all, in fact most
+ * of the time the translations they handle are a disjunct set.
+ * Basically the iommu handles all dvma sbus activity.
+ */
+
+/* The IOMMU registers occupy three pages in IO space. */
+struct iommu_regs {
+ /* First page */
+ volatile unsigned long control; /* IOMMU control */
+ volatile unsigned long base; /* Physical base of iopte page table */
+ volatile unsigned long _unused1[3];
+ volatile unsigned long tlbflush; /* write only */
+ volatile unsigned long pageflush; /* write only */
+ volatile unsigned long _unused2[1017];
+ /* Second page */
+ volatile unsigned long afsr; /* Async-fault status register */
+ volatile unsigned long afar; /* Async-fault physical address */
+ volatile unsigned long _unused3[2];
+ volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */
+ volatile unsigned long sbuscfg1;
+ volatile unsigned long sbuscfg2;
+ volatile unsigned long sbuscfg3;
+ volatile unsigned long mfsr; /* Memory-fault status register */
+ volatile unsigned long mfar; /* Memory-fault physical address */
+ volatile unsigned long _unused4[1014];
+ /* Third page */
+ volatile unsigned long mid; /* IOMMU module-id */
+};
+
+#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
+#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
+#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
+#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
+#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
+#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
+#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
+#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
+#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
+#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
+#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
+#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
+
+#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
+#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */
+#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */
+#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */
+#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
+#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */
+#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
+#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */
+#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
+
+#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
+#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
+#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
+#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
+ produced by this device as pure
+ physical. */
+
+#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */
+#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */
+#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */
+#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred
+ on the even word of the access, low bit
+ indicated odd word caused the parity error */
+#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */
+#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */
+#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */
+
+#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */
+#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */
+#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */
+#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */
+#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */
+#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */
+#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */
+
+/* The format of an iopte in the page tables */
+#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
+#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
+#define IOPTE_WRITE 0x00000004 /* Writeable */
+#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
+#define IOPTE_WAZ 0x00000001 /* Write as zeros */
+
+#define IOPERM (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID)
+#define MKIOPTE(phys) (((((phys)>>4) & IOPTE_PAGE) | IOPERM) & ~IOPTE_WAZ)
+
+#define IOMMU_REGS 0x300
diff --git a/roms/openbios/drivers/kbd.c b/roms/openbios/drivers/kbd.c
new file mode 100644
index 00000000..43070d87
--- /dev/null
+++ b/roms/openbios/drivers/kbd.c
@@ -0,0 +1,116 @@
+/*
+ * <kbd.c>
+ *
+ * Open Hack'Ware BIOS generic keyboard input translation.
+ *
+ * Copyright (c) 2005 Jocelyn Mayer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include "config.h"
+#include "libc/string.h"
+#include "asm/types.h"
+#include "kbd.h"
+
+//#define DEBUG_KBD
+#ifdef DEBUG_KBD
+#define KBD_DPRINTF(fmt, args...) \
+do { printk("KBD - %s: " fmt, __func__ , ##args); } while (0)
+#else
+#define KBD_DPRINTF(fmt, args...) do { } while (0)
+#endif
+
+int kbd_set_keymap (kbd_t *kbd, int nb_keys, const keymap_t *keymap, const char **sequences)
+{
+ kbd->nb_keys = nb_keys;
+ kbd->keymap = keymap;
+ kbd->sequences = sequences;
+
+ return 0;
+}
+
+int kbd_translate_key (kbd_t *kbd, int keycode, int up_down, char *sequence)
+{
+ const keymap_t *keyt;
+ int mod_state, key, type;
+ int ret;
+
+ ret = -1;
+ /* Get key table */
+ if (keycode < kbd->nb_keys) {
+ keyt = &kbd->keymap[keycode];
+ /* Get modifier state */
+ mod_state = (kbd->mod_state | (kbd->mod_state >> 8)) & 0xFF;
+ /* Adjust with lock */
+ if (keyt->lck_shift >= 0) {
+ if ((kbd->mod_state >> (16 + keyt->lck_shift)) & 0x01) {
+ KBD_DPRINTF("adjust with lock %02x => %02x (%d %08x)\n",
+ mod_state,
+ mod_state ^ ((kbd->mod_state >>
+ (16 + keyt->lck_shift)) &
+ 0x01),
+ keyt->lck_shift, kbd->mod_state);
+ }
+ mod_state ^= (kbd->mod_state >> (16 + keyt->lck_shift)) & 0x01;
+ }
+ key = keyt->trans[mod_state];
+ type = key & 0xFF000000;
+ key &= ~0xFF000000;
+ switch (type) {
+ case KBD_TYPE_REGULAR:
+ if (!up_down) {
+ /* We don't care about up events on "normal" keys */
+ *sequence = key;
+ ret = 1;
+ }
+ break;
+ case KBD_TYPE_SEQUENCE:
+ if (!up_down) {
+ /* We don't care about up events on "normal" keys */
+ ret = strlen(kbd->sequences[key]);
+ memcpy(sequence, kbd->sequences[key], ret);
+ }
+ break;
+ case KBD_TYPE_LOCK:
+ if (!up_down) {
+ kbd->mod_state ^= key;
+ ret = -2;
+ KBD_DPRINTF("Change modifier type %d key %04x %s => %08x\n",
+ type, key, up_down ? "up" : "down",
+ kbd->mod_state);
+ }
+ break;
+ case KBD_TYPE_LMOD:
+ case KBD_TYPE_RMOD:
+ if (up_down)
+ kbd->mod_state &= ~key;
+ else
+ kbd->mod_state |= key;
+ KBD_DPRINTF("Change modifier type %d key %04x %s => %08x\n",
+ type, key, up_down ? "up" : "down", kbd->mod_state);
+ ret = -2; /* The caller may know the key was a modifier */
+ break;
+ default:
+ KBD_DPRINTF("Unknown key: keycode=%02x mod_state=%02x (%08x)\n",
+ keycode, mod_state, kbd->mod_state);
+ break;
+ }
+ } else {
+ KBD_DPRINTF("Unmanaged key: keycode=%02x mod_state %08x\n",
+ keycode, kbd->mod_state);
+ }
+
+ return ret;
+}
diff --git a/roms/openbios/drivers/kbd.h b/roms/openbios/drivers/kbd.h
new file mode 100644
index 00000000..8a7d0d47
--- /dev/null
+++ b/roms/openbios/drivers/kbd.h
@@ -0,0 +1,108 @@
+/*
+ * <kbd.h>
+ *
+ * Open Hack'Ware BIOS generic keyboard management definitions.
+ *
+ * Copyright (c) 2005 Jocelyn Mayer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#if !defined (__OHW_KBD_H__)
+#define __OHW_KBD_H__
+typedef struct kbd_t kbd_t;
+typedef struct keymap_t keymap_t;
+struct kbd_t {
+ uint32_t mod_state;
+ /* Modifier state
+ * 0x00 kk ll rr
+ * | | | |
+ * Not used for now -+ | | |
+ * Locks ---------------+ | |
+ * Left modifiers ---------+ |
+ * Right modifiers -----------+
+ */
+ int nb_keys;
+ const keymap_t *keymap;
+ const char **sequences;
+};
+
+/* Modifiers */
+typedef enum {
+ KBD_MOD_SHIFT = 0x01,
+ KBD_MOD_CTRL = 0x02,
+ KBD_MOD_ALT = 0x04,
+ KBD_MOD_CMD = 0x08,
+ KBD_MOD_OPT = 0x10,
+} kbd_modifiers;
+
+/* Locks */
+typedef enum {
+ KBD_LCK_CAPS = 0x01,
+ KBD_LCK_NUM = 0x02,
+ KBD_LCK_SCROLL = 0x04,
+} kbd_locks;
+
+/* Lock shifts */
+typedef enum {
+ KBD_SH_NONE = -1,
+ KBD_SH_CAPS = 0,
+ KBD_SH_NUML = 1,
+ KBD_SH_SCRL = 2,
+} kbd_lck_shifts;
+
+enum {
+ KBD_TYPE_REGULAR = 0 << 24,
+ KBD_TYPE_LMOD = 1 << 24,
+ KBD_TYPE_RMOD = 2 << 24,
+ KBD_TYPE_LOCK = 3 << 24,
+ KBD_TYPE_SEQUENCE = 4 << 24,
+};
+
+#define KBD_SEQUENCE(sequence) (KBD_TYPE_SEQUENCE | (sequence))
+
+#define KBD_MOD_MAP(mod) \
+KBD_SH_NONE, { (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \
+ (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \
+ (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \
+ (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), }
+#define KBD_MOD_MAP_LSHIFT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_SHIFT)
+#define KBD_MOD_MAP_RSHIFT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_SHIFT << 8))
+#define KBD_MOD_MAP_LCTRL KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_CTRL)
+#define KBD_MOD_MAP_RCTRL KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_CTRL << 8))
+#define KBD_MOD_MAP_LALT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_ALT)
+#define KBD_MOD_MAP_RALT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_ALT << 8))
+#define KBD_MOD_MAP_LCMD KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_CMD)
+#define KBD_MOD_MAP_RCMD KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_CMD << 8))
+#define KBD_MOD_MAP_LOPT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_OPT)
+#define KBD_MOD_MAP_ROPT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_OPT << 8))
+#define KBD_MOD_MAP_CAPS KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_CAPS << 16))
+#define KBD_MOD_MAP_NUML KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_NUML << 16))
+#define KBD_MOD_MAP_SCROLL KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_SCRL << 16))
+#define KBD_MAP_NONE KBD_MOD_MAP(-1)
+
+/* Keymap definition */
+struct keymap_t {
+ /* Set the lock which applies to this key (if any) */
+ int lck_shift;
+ /* Key translations */
+ uint32_t trans[32];
+};
+
+void *kbd_new (int len);
+int kbd_set_keymap (kbd_t *kbd, int nb_keys, const keymap_t *keymap,
+ const char **sequences);
+int kbd_translate_key (kbd_t *kbd, int keycode, int up_down, char *sequence);
+
+#endif /* !defined (__OHW_KBD_H__) */
diff --git a/roms/openbios/drivers/macio.c b/roms/openbios/drivers/macio.c
new file mode 100644
index 00000000..f54bc86d
--- /dev/null
+++ b/roms/openbios/drivers/macio.c
@@ -0,0 +1,281 @@
+/*
+ * derived from mol/mol.c,
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "arch/common/nvram.h"
+#include "packages/nvram.h"
+#include "libopenbios/bindings.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "drivers/drivers.h"
+#include "macio.h"
+#include "cuda.h"
+#include "escc.h"
+#include "drivers/pci.h"
+
+#define OW_IO_NVRAM_SIZE 0x00020000
+#define OW_IO_NVRAM_OFFSET 0x00060000
+#define OW_IO_NVRAM_SHIFT 4
+
+#define NW_IO_NVRAM_SIZE 0x00004000
+#define NW_IO_NVRAM_OFFSET 0xfff04000
+
+#define IO_OPENPIC_SIZE 0x00040000
+#define IO_OPENPIC_OFFSET 0x00040000
+
+static char *nvram;
+
+static int macio_nvram_shift(void)
+{
+ int nvram_flat;
+
+ if (is_oldworld())
+ return OW_IO_NVRAM_SHIFT;
+
+ nvram_flat = fw_cfg_read_i32(FW_CFG_PPC_NVRAM_FLAT);
+ return nvram_flat ? 0 : 1;
+}
+
+int
+macio_get_nvram_size(void)
+{
+ int shift = macio_nvram_shift();
+ if (is_oldworld())
+ return OW_IO_NVRAM_SIZE >> shift;
+ else
+ return NW_IO_NVRAM_SIZE >> shift;
+}
+
+static unsigned long macio_nvram_offset(void)
+{
+ unsigned long r;
+
+ /* Hypervisor tells us where NVRAM lies */
+ r = fw_cfg_read_i32(FW_CFG_PPC_NVRAM_ADDR);
+ if (r)
+ return r;
+
+ /* Fall back to hardcoded addresses */
+ if (is_oldworld())
+ return OW_IO_NVRAM_OFFSET;
+
+ return NW_IO_NVRAM_OFFSET;
+}
+
+static unsigned long macio_nvram_size(void)
+{
+ if (is_oldworld())
+ return OW_IO_NVRAM_SIZE;
+ else
+ return NW_IO_NVRAM_SIZE;
+}
+
+void macio_nvram_init(const char *path, phys_addr_t addr)
+{
+ phandle_t chosen, aliases;
+ phandle_t dnode;
+ int props[2];
+ char buf[64];
+ unsigned long nvram_size, nvram_offset;
+
+ nvram_offset = macio_nvram_offset();
+ nvram_size = macio_nvram_size();
+
+ nvram = (char*)addr + nvram_offset;
+ snprintf(buf, sizeof(buf), "%s/nvram", path);
+ nvram_init(buf);
+ dnode = find_dev(buf);
+ set_int_property(dnode, "#bytes", arch_nvram_size() );
+ props[0] = __cpu_to_be32(nvram_offset);
+ props[1] = __cpu_to_be32(nvram_size);
+ set_property(dnode, "reg", (char *)&props, sizeof(props));
+ set_property(dnode, "device_type", "nvram", 6);
+ NEWWORLD(set_property(dnode, "compatible", "nvram,flash", 12));
+
+ chosen = find_dev("/chosen");
+ push_str(buf);
+ fword("open-dev");
+ set_int_property(chosen, "nvram", POP());
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "nvram", buf, strlen(buf) + 1);
+}
+
+#ifdef DUMP_NVRAM
+static void
+dump_nvram(void)
+{
+ int i, j;
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 16; j++)
+ printk ("%02x ", nvram[(i*16+j)<<4]);
+ printk (" ");
+ for (j = 0; j < 16; j++)
+ if (isprint(nvram[(i*16+j)<<4]))
+ printk("%c", nvram[(i*16+j)<<4]);
+ else
+ printk(".");
+ printk ("\n");
+ }
+}
+#endif
+
+
+void
+macio_nvram_put(char *buf)
+{
+ int i;
+ unsigned int it_shift = macio_nvram_shift();
+
+ for (i=0; i < arch_nvram_size(); i++)
+ nvram[i << it_shift] = buf[i];
+#ifdef DUMP_NVRAM
+ printk("new nvram:\n");
+ dump_nvram();
+#endif
+}
+
+void
+macio_nvram_get(char *buf)
+{
+ int i;
+ unsigned int it_shift = macio_nvram_shift();
+
+ for (i=0; i< arch_nvram_size(); i++)
+ buf[i] = nvram[i << it_shift];
+
+#ifdef DUMP_NVRAM
+ printk("current nvram:\n");
+ dump_nvram();
+#endif
+}
+
+static void
+openpic_init(const char *path, phys_addr_t addr)
+{
+ phandle_t dnode;
+ int props[2];
+ char buf[128];
+
+ push_str(path);
+ fword("find-device");
+ fword("new-device");
+ push_str("interrupt-controller");
+ fword("device-name");
+
+ snprintf(buf, sizeof(buf), "%s/interrupt-controller", path);
+ dnode = find_dev(buf);
+ set_property(dnode, "device_type", "open-pic", 9);
+ set_property(dnode, "compatible", "chrp,open-pic", 14);
+ set_property(dnode, "built-in", "", 0);
+ props[0] = __cpu_to_be32(IO_OPENPIC_OFFSET);
+ props[1] = __cpu_to_be32(IO_OPENPIC_SIZE);
+ set_property(dnode, "reg", (char *)&props, sizeof(props));
+ set_int_property(dnode, "#interrupt-cells", 2);
+ set_int_property(dnode, "#address-cells", 0);
+ set_property(dnode, "interrupt-controller", "", 0);
+ set_int_property(dnode, "clock-frequency", 4166666);
+
+ fword("finish-device");
+}
+
+DECLARE_NODE(ob_macio, INSTALL_OPEN, sizeof(int), "Tmac-io");
+
+/* ( str len -- addr ) */
+
+static void
+ob_macio_decode_unit(void *private)
+{
+ ucell addr;
+
+ const char *arg = pop_fstr_copy();
+
+ addr = strtol(arg, NULL, 16);
+
+ free((char*)arg);
+
+ PUSH(addr);
+}
+
+/* ( addr -- str len ) */
+
+static void
+ob_macio_encode_unit(void *private)
+{
+ char buf[8];
+
+ ucell addr = POP();
+
+ snprintf(buf, sizeof(buf), "%x", addr);
+
+ push_str(buf);
+}
+
+NODE_METHODS(ob_macio) = {
+ { "decode-unit", ob_macio_decode_unit },
+ { "encode-unit", ob_macio_encode_unit },
+};
+
+static void
+ob_unin_init(void)
+{
+ phandle_t dnode;
+ int props[2];
+
+ push_str("/");
+ fword("find-device");
+ fword("new-device");
+ push_str("uni-n");
+ fword("device-name");
+
+ dnode = find_dev("/uni-n");
+ set_property(dnode, "device_type", "memory-controller", 18);
+ set_property(dnode, "compatible", "uni-north", 10);
+ set_int_property(dnode, "device-rev", 0);
+ props[0] = __cpu_to_be32(0xf8000000);
+ props[1] = __cpu_to_be32(0x1000000);
+ set_property(dnode, "reg", (char *)&props, sizeof(props));
+
+ fword("finish-device");
+}
+
+void
+ob_macio_heathrow_init(const char *path, phys_addr_t addr)
+{
+ phandle_t aliases;
+
+ REGISTER_NODE(ob_macio);
+ aliases = find_dev("/aliases");
+ set_property(aliases, "mac-io", path, strlen(path) + 1);
+
+ cuda_init(path, addr);
+ macio_nvram_init(path, addr);
+ escc_init(path, addr);
+ macio_ide_init(path, addr, 2);
+}
+
+void
+ob_macio_keylargo_init(const char *path, phys_addr_t addr)
+{
+ phandle_t aliases;
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "mac-io", path, strlen(path) + 1);
+
+ cuda_init(path, addr);
+ /* The NewWorld NVRAM is not located in the MacIO device */
+ macio_nvram_init("", 0);
+ escc_init(path, addr);
+ macio_ide_init(path, addr, 2);
+ openpic_init(path, addr);
+ ob_unin_init();
+}
diff --git a/roms/openbios/drivers/macio.h b/roms/openbios/drivers/macio.h
new file mode 100644
index 00000000..925b8812
--- /dev/null
+++ b/roms/openbios/drivers/macio.h
@@ -0,0 +1,5 @@
+extern phandle_t pic_handle;
+
+void ob_macio_heathrow_init(const char *path, phys_addr_t addr);
+void ob_macio_keylargo_init(const char *path, phys_addr_t addr);
+void macio_nvram_init(const char *path, phys_addr_t addr);
diff --git a/roms/openbios/drivers/obio.c b/roms/openbios/drivers/obio.c
new file mode 100644
index 00000000..7c135a36
--- /dev/null
+++ b/roms/openbios/drivers/obio.c
@@ -0,0 +1,525 @@
+/*
+ * OpenBIOS Sparc OBIO driver
+ *
+ * (C) 2004 Stefan Reinauer <stepan@openbios.org>
+ * (C) 2005 Ed Schouten <ed@fxq.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "kernel/kernel.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "drivers/drivers.h"
+#include "arch/common/nvram.h"
+#include "libopenbios/ofmem.h"
+#include "obio.h"
+#include "escc.h"
+
+#define PROMDEV_KBD 0 /* input from keyboard */
+#define PROMDEV_SCREEN 0 /* output to screen */
+#define PROMDEV_TTYA 1 /* in/out to ttya */
+
+/* DECLARE data structures for the nodes. */
+DECLARE_UNNAMED_NODE( ob_obio, INSTALL_OPEN, sizeof(int) );
+
+void
+ob_new_obio_device(const char *name, const char *type)
+{
+ push_str("/obio");
+ fword("find-device");
+ fword("new-device");
+
+ push_str(name);
+ fword("device-name");
+
+ if (type) {
+ push_str(type);
+ fword("device-type");
+ }
+}
+
+static unsigned long
+map_reg(uint64_t base, uint64_t offset, unsigned long size, int map,
+ int phys_hi)
+{
+ PUSH(phys_hi);
+ fword("encode-int");
+ PUSH(offset);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(size);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ if (map) {
+ unsigned long addr;
+
+ addr = (unsigned long)ofmem_map_io(base + offset, size);
+
+ PUSH(addr);
+ fword("encode-int");
+ push_str("address");
+ fword("property");
+ return addr;
+ }
+ return 0;
+}
+
+unsigned long
+ob_reg(uint64_t base, uint64_t offset, unsigned long size, int map)
+{
+ return map_reg(base, offset, size, map, 0);
+}
+
+void
+ob_intr(int intr)
+{
+ PUSH(intr);
+ fword("encode-int");
+ PUSH(0);
+ fword("encode-int");
+ fword("encode+");
+ push_str("intr");
+ fword("property");
+}
+
+void
+ob_eccmemctl_init(uint64_t base)
+{
+ uint32_t version, *regs;
+ const char *mc_type;
+
+ push_str("/");
+ fword("find-device");
+ fword("new-device");
+
+ push_str("eccmemctl");
+ fword("device-name");
+
+ PUSH(0x20);
+ fword("encode-int");
+ push_str("width");
+ fword("property");
+
+ regs = (uint32_t *)map_reg(ECC_BASE, 0, ECC_SIZE, 1, ECC_BASE >> 32);
+
+ version = regs[0];
+ switch (version) {
+ case 0x00000000:
+ mc_type = "MCC";
+ break;
+ case 0x10000000:
+ mc_type = "EMC";
+ break;
+ default:
+ case 0x20000000:
+ mc_type = "SMC";
+ break;
+ }
+ push_str(mc_type);
+ fword("encode-string");
+ push_str("mc-type");
+ fword("property");
+
+ fword("finish-device");
+}
+
+static unsigned char *nvram;
+
+#define NVRAM_OB_START (0)
+#define NVRAM_OB_SIZE ((NVRAM_IDPROM - NVRAM_OB_START) & ~15)
+
+void
+arch_nvram_get(char *data)
+{
+ memcpy(data, &nvram[NVRAM_OB_START], NVRAM_OB_SIZE);
+}
+
+void
+arch_nvram_put(char *data)
+{
+ memcpy(&nvram[NVRAM_OB_START], data, NVRAM_OB_SIZE);
+}
+
+int
+arch_nvram_size(void)
+{
+ return NVRAM_OB_SIZE;
+}
+
+void
+ss5_init(uint64_t base)
+{
+ ob_new_obio_device("slavioconfig", NULL);
+
+ ob_reg(base, SLAVIO_SCONFIG, SCONFIG_REGS, 0);
+
+ fword("finish-device");
+}
+
+static void
+ob_nvram_init(uint64_t base, uint64_t offset)
+{
+ ob_new_obio_device("eeprom", NULL);
+
+ nvram = (unsigned char *)ob_reg(base, offset, NVRAM_SIZE, 1);
+
+ PUSH((unsigned long)nvram);
+ fword("encode-int");
+ push_str("address");
+ fword("property");
+
+ push_str("mk48t08");
+ fword("model");
+
+ fword("finish-device");
+
+ // Add /idprom
+ push_str("/");
+ fword("find-device");
+
+ PUSH((long)&nvram[NVRAM_IDPROM]);
+ PUSH(32);
+ fword("encode-bytes");
+ push_str("idprom");
+ fword("property");
+}
+
+static void
+ob_fd_init(uint64_t base, uint64_t offset, int intr)
+{
+ unsigned long addr;
+
+ ob_new_obio_device("SUNW,fdtwo", "block");
+
+ addr = ob_reg(base, offset, FD_REGS, 1);
+
+ ob_intr(intr);
+
+ fword("is-deblocker");
+
+ ob_floppy_init("/obio", "SUNW,fdtwo", 0, addr);
+
+ fword("finish-device");
+}
+
+static void
+ob_auxio_init(uint64_t base, uint64_t offset)
+{
+ ob_new_obio_device("auxio", NULL);
+
+ ob_reg(base, offset, AUXIO_REGS, 1);
+
+ fword("finish-device");
+}
+
+volatile unsigned char *power_reg;
+volatile unsigned int *reset_reg;
+
+static void
+sparc32_reset_all(void)
+{
+ *reset_reg = 1;
+}
+
+// AUX 2 (Software Powerdown Control) and reset
+static void
+ob_aux2_reset_init(uint64_t base, uint64_t offset, int intr)
+{
+ ob_new_obio_device("power", NULL);
+
+ power_reg = (void *)ob_reg(base, offset, AUXIO2_REGS, 1);
+
+ // Not in device tree
+ reset_reg = (unsigned int *)ofmem_map_io(base + (uint64_t)SLAVIO_RESET, RESET_REGS);
+
+ bind_func("sparc32-reset-all", sparc32_reset_all);
+ push_str("' sparc32-reset-all to reset-all");
+ fword("eval");
+
+ ob_intr(intr);
+
+ fword("finish-device");
+}
+
+volatile struct sun4m_timer_regs *counter_regs;
+
+static void
+ob_counter_init(uint64_t base, unsigned long offset, int ncpu)
+{
+ int i;
+
+ ob_new_obio_device("counter", NULL);
+
+ for (i = 0; i < ncpu; i++) {
+ PUSH(0);
+ fword("encode-int");
+ if (i != 0) fword("encode+");
+ PUSH(offset + (i * PAGE_SIZE));
+ fword("encode-int");
+ fword("encode+");
+ PUSH(COUNTER_REGS);
+ fword("encode-int");
+ fword("encode+");
+ }
+
+ PUSH(0);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(offset + 0x10000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(COUNTER_REGS);
+ fword("encode-int");
+ fword("encode+");
+
+ push_str("reg");
+ fword("property");
+
+
+ counter_regs = (struct sun4m_timer_regs *)ofmem_map_io(base + (uint64_t)offset, sizeof(*counter_regs));
+ counter_regs->cfg = 0xfffffffe;
+ counter_regs->l10_timer_limit = 0;
+ counter_regs->cpu_timers[0].l14_timer_limit = 0x9c4000; /* see comment in obio.h */
+ counter_regs->cpu_timers[0].cntrl = 1;
+
+ for (i = 0; i < ncpu; i++) {
+ PUSH((unsigned long)&counter_regs->cpu_timers[i]);
+ fword("encode-int");
+ if (i != 0)
+ fword("encode+");
+ }
+ PUSH((unsigned long)&counter_regs->l10_timer_limit);
+ fword("encode-int");
+ fword("encode+");
+ push_str("address");
+ fword("property");
+
+ fword("finish-device");
+}
+
+static volatile struct sun4m_intregs *intregs;
+
+static void
+ob_interrupt_init(uint64_t base, unsigned long offset, int ncpu)
+{
+ int i;
+
+ ob_new_obio_device("interrupt", NULL);
+
+ for (i = 0; i < ncpu; i++) {
+ PUSH(0);
+ fword("encode-int");
+ if (i != 0) fword("encode+");
+ PUSH(offset + (i * PAGE_SIZE));
+ fword("encode-int");
+ fword("encode+");
+ PUSH(INTERRUPT_REGS);
+ fword("encode-int");
+ fword("encode+");
+ }
+
+ PUSH(0);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(offset + 0x10000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(INTERRUPT_REGS);
+ fword("encode-int");
+ fword("encode+");
+
+ push_str("reg");
+ fword("property");
+
+ intregs = (struct sun4m_intregs *)ofmem_map_io(base | (uint64_t)offset, sizeof(*intregs));
+ intregs->clear = ~SUN4M_INT_MASKALL;
+ intregs->cpu_intregs[0].clear = ~0x17fff;
+
+ for (i = 0; i < ncpu; i++) {
+ PUSH((unsigned long)&intregs->cpu_intregs[i]);
+ fword("encode-int");
+ if (i != 0)
+ fword("encode+");
+ }
+ PUSH((unsigned long)&intregs->tbt);
+ fword("encode-int");
+ fword("encode+");
+ push_str("address");
+ fword("property");
+
+ fword("finish-device");
+}
+
+/* SMP CPU boot structure */
+struct smp_cfg {
+ uint32_t smp_ctx;
+ uint32_t smp_ctxtbl;
+ uint32_t smp_entry;
+ uint32_t valid;
+};
+
+static struct smp_cfg *smp_header;
+
+int
+start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context, int cpu)
+{
+ if (!cpu)
+ return -1;
+
+ cpu &= 7;
+
+ smp_header->smp_entry = pc;
+ smp_header->smp_ctxtbl = context_ptr;
+ smp_header->smp_ctx = context;
+ smp_header->valid = cpu;
+
+ intregs->cpu_intregs[cpu].set = SUN4M_SOFT_INT(14);
+
+ return 0;
+}
+
+static void
+ob_smp_init(unsigned long mem_size)
+{
+ // See arch/sparc32/entry.S for memory layout
+ smp_header = (struct smp_cfg *)ofmem_map_io((uint64_t)(mem_size - 0x100),
+ sizeof(struct smp_cfg));
+}
+
+static void
+ob_obio_open(__attribute__((unused))int *idx)
+{
+ int ret=1;
+ RET ( -ret );
+}
+
+static void
+ob_obio_close(__attribute__((unused))int *idx)
+{
+ selfword("close-deblocker");
+}
+
+static void
+ob_obio_initialize(__attribute__((unused))int *idx)
+{
+ push_str("/");
+ fword("find-device");
+ fword("new-device");
+
+ push_str("obio");
+ fword("device-name");
+
+ push_str("hierarchical");
+ fword("device-type");
+
+ PUSH(2);
+ fword("encode-int");
+ push_str("#address-cells");
+ fword("property");
+
+ PUSH(1);
+ fword("encode-int");
+ push_str("#size-cells");
+ fword("property");
+
+ fword("finish-device");
+}
+
+static void
+ob_set_obio_ranges(uint64_t base)
+{
+ push_str("/obio");
+ fword("find-device");
+ PUSH(0);
+ fword("encode-int");
+ PUSH(0);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(base >> 32);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(base & 0xffffffff);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(SLAVIO_SIZE);
+ fword("encode-int");
+ fword("encode+");
+ push_str("ranges");
+ fword("property");
+}
+
+static void
+ob_obio_decodeunit(__attribute__((unused)) int *idx)
+{
+ fword("decode-unit-sbus");
+}
+
+
+static void
+ob_obio_encodeunit(__attribute__((unused)) int *idx)
+{
+ fword("encode-unit-sbus");
+}
+
+NODE_METHODS(ob_obio) = {
+ { NULL, ob_obio_initialize },
+ { "open", ob_obio_open },
+ { "close", ob_obio_close },
+ { "encode-unit", ob_obio_encodeunit },
+ { "decode-unit", ob_obio_decodeunit },
+};
+
+
+int
+ob_obio_init(uint64_t slavio_base, unsigned long fd_offset,
+ unsigned long counter_offset, unsigned long intr_offset,
+ int intr_ncpu, unsigned long aux1_offset, unsigned long aux2_offset,
+ unsigned long mem_size)
+{
+
+ // All devices were integrated to NCR89C105, see
+ // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
+
+ //printk("Initializing OBIO devices...\n");
+#if 0 // XXX
+ REGISTER_NAMED_NODE(ob_obio, "/obio");
+ device_end();
+#endif
+ ob_set_obio_ranges(slavio_base);
+
+ // Zilog Z8530 serial ports, see http://www.zilog.com
+ // Must be before zs@0,0 or Linux won't boot
+ ob_zs_init(slavio_base, SLAVIO_ZS1, ZS_INTR, 0, 0);
+
+ ob_zs_init(slavio_base, SLAVIO_ZS, ZS_INTR, 1, 1);
+
+ // M48T08 NVRAM, see http://www.st.com
+ ob_nvram_init(slavio_base, SLAVIO_NVRAM);
+
+ // 82078 FDC
+ if (fd_offset != (unsigned long) -1)
+ ob_fd_init(slavio_base, fd_offset, FD_INTR);
+
+ ob_auxio_init(slavio_base, aux1_offset);
+
+ if (aux2_offset != (unsigned long) -1)
+ ob_aux2_reset_init(slavio_base, aux2_offset, AUXIO2_INTR);
+
+ ob_counter_init(slavio_base, counter_offset, intr_ncpu);
+
+ ob_interrupt_init(slavio_base, intr_offset, intr_ncpu);
+
+ ob_smp_init(mem_size);
+
+ return 0;
+}
diff --git a/roms/openbios/drivers/obio.h b/roms/openbios/drivers/obio.h
new file mode 100644
index 00000000..49c3040c
--- /dev/null
+++ b/roms/openbios/drivers/obio.h
@@ -0,0 +1,165 @@
+/* Addresses, interrupt numbers, register sizes */
+
+#define SLAVIO_ZS 0x00000000ULL
+#define SLAVIO_ZS1 0x00100000ULL
+#define ZS_INTR 0x2c
+
+#define SLAVIO_NVRAM 0x00200000ULL
+#define NVRAM_SIZE 0x2000
+#define NVRAM_IDPROM 0x1fd8
+
+#define SLAVIO_FD 0x00400000ULL
+#define FD_REGS 15
+#define FD_INTR 0x2b
+
+#define SLAVIO_SCONFIG 0x00800000ULL
+#define SCONFIG_REGS 1
+
+#define AUXIO_REGS 1
+
+#define AUXIO2_REGS 1
+#define AUXIO2_INTR 0x22
+
+#define SLAVIO_COUNTER 0x00d00000ULL
+#define COUNTER_REGS 0x10
+
+#define SLAVIO_INTERRUPT 0x00e00000ULL
+#define INTERRUPT_REGS 0x10
+
+#define SLAVIO_RESET 0x00f00000ULL
+#define RESET_REGS 1
+
+#define ECC_BASE 0xf00000000ULL
+#define ECC_SIZE 0x20
+
+#define SLAVIO_SIZE 0x01000000
+
+#define SUN4M_NCPUS 16
+
+#define CFG_ADDR 0xd00000510ULL
+#define CFG_SIZE 3
+
+/* linux/include/asm-sparc/timer.h */
+
+/* A sun4m has two blocks of registers which are probably of the same
+ * structure. LSI Logic's L64851 is told to _decrement_ from the limit
+ * value. Aurora behaves similarly but its limit value is compacted in
+ * other fashion (it's wider). Documented fields are defined here.
+ */
+
+/* As with the interrupt register, we have two classes of timer registers
+ * which are per-cpu and master. Per-cpu timers only hit that cpu and are
+ * only level 14 ticks, master timer hits all cpus and is level 10.
+ */
+
+#define SUN4M_PRM_CNT_L 0x80000000
+#define SUN4M_PRM_CNT_LVALUE 0x7FFFFC00
+
+struct sun4m_timer_percpu_info {
+ __volatile__ unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */
+ __volatile__ unsigned int l14_cur_count;
+
+ /* This register appears to be write only and/or inaccessible
+ * on Uni-Processor sun4m machines.
+ */
+ __volatile__ unsigned int l14_limit_noclear; /* Data access error is here */
+
+ __volatile__ unsigned int cntrl; /* =1 after POST on Aurora */
+ __volatile__ unsigned char space[PAGE_SIZE - 16];
+};
+
+struct sun4m_timer_regs {
+ struct sun4m_timer_percpu_info cpu_timers[SUN4M_NCPUS];
+ volatile unsigned int l10_timer_limit;
+ volatile unsigned int l10_cur_count;
+
+ /* Again, this appears to be write only and/or inaccessible
+ * on uni-processor sun4m machines.
+ */
+ volatile unsigned int l10_limit_noclear;
+
+ /* This register too, it must be magic. */
+ volatile unsigned int foobar;
+
+ volatile unsigned int cfg; /* equals zero at boot time... */
+};
+
+/*
+ * Registers of hardware timer in sun4m.
+ */
+struct sun4m_timer_percpu {
+ volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 = 10ms period*/
+ volatile unsigned int l14_cur_count;
+};
+
+struct sun4m_timer_global {
+ volatile unsigned int l10_timer_limit;
+ volatile unsigned int l10_cur_count;
+};
+
+/* linux/include/asm-sparc/irq.h */
+
+/* These registers are used for sending/receiving irqs from/to
+ * different cpu's.
+ */
+struct sun4m_intreg_percpu {
+ unsigned int tbt; /* Interrupts still pending for this cpu. */
+
+ /* These next two registers are WRITE-ONLY and are only
+ * "on bit" sensitive, "off bits" written have NO affect.
+ */
+ unsigned int clear; /* Clear this cpus irqs here. */
+ unsigned int set; /* Set this cpus irqs here. */
+ unsigned char space[PAGE_SIZE - 12];
+};
+
+/*
+ * djhr
+ * Actually the clear and set fields in this struct are misleading..
+ * according to the SLAVIO manual (and the same applies for the SEC)
+ * the clear field clears bits in the mask which will ENABLE that IRQ
+ * the set field sets bits in the mask to DISABLE the IRQ.
+ *
+ * Also the undirected_xx address in the SLAVIO is defined as
+ * RESERVED and write only..
+ *
+ * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
+ * sun4m machines, for MP the layout makes more sense.
+ */
+struct sun4m_intregs {
+ struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS];
+ unsigned int tbt; /* IRQ's that are still pending. */
+ unsigned int irqs; /* Master IRQ bits. */
+
+ /* Again, like the above, two these registers are WRITE-ONLY. */
+ unsigned int clear; /* Clear master IRQ's by setting bits here. */
+ unsigned int set; /* Set master IRQ's by setting bits here. */
+
+ /* This register is both READ and WRITE. */
+ unsigned int undirected_target; /* Which cpu gets undirected irqs. */
+};
+
+/* Dave Redman (djhr@tadpole.co.uk)
+ * The sun4m interrupt registers.
+ */
+#define SUN4M_INT_ENABLE 0x80000000
+#define SUN4M_INT_E14 0x00000080
+#define SUN4M_INT_E10 0x00080000
+
+#define SUN4M_HARD_INT(x) (0x000000001 << (x))
+#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
+
+#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
+#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
+#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */
+#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */
+#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */
+#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */
+#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */
+#define SUN4M_INT_REALTIME 0x00080000 /* system timer */
+#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */
+#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */
+#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */
+#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */
+#define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */
+#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */
diff --git a/roms/openbios/drivers/pc_kbd.c b/roms/openbios/drivers/pc_kbd.c
new file mode 100644
index 00000000..49218f82
--- /dev/null
+++ b/roms/openbios/drivers/pc_kbd.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "kernel/kernel.h"
+#include "drivers/drivers.h"
+#include "libc/vsprintf.h"
+
+/* ******************************************************************
+ * simple polling video/keyboard console functions
+ * ****************************************************************** */
+
+#define SER_SIZE 8
+
+/*
+ * keyboard driver
+ */
+
+static const char normal[] = {
+ 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
+ '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
+ 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j',
+ 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b',
+ 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f
+};
+
+static const char shifted[] = {
+ 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
+ '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
+ 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J',
+ 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B',
+ 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8',
+ '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f
+};
+
+static int key_ext;
+static int key_lshift = 0, key_rshift = 0, key_caps = 0;
+
+static char last_key;
+
+static void pc_kbd_cmd(unsigned char cmd, unsigned char val)
+{
+ outb(cmd, 0x60);
+ /* wait until keyboard controller accepts cmds: */
+ while (inb(0x64) & 2);
+ outb(val, 0x60);
+ while (inb(0x64) & 2);
+}
+
+static void pc_kbd_controller_cmd(unsigned char cmd, unsigned char val)
+{
+ outb(cmd, 0x64);
+ /* wait until keyboard controller accepts cmds: */
+ while (inb(0x64) & 2);
+ outb(val, 0x60);
+ while (inb(0x64) & 2);
+}
+
+static char pc_kbd_poll(void)
+{
+ unsigned int c;
+ if (inb(0x64) & 1) {
+ c = inb(0x60);
+ switch (c) {
+ case 0xe0:
+ key_ext = 1;
+ return 0;
+ case 0x2a:
+ key_lshift = 1;
+ return 0;
+ case 0x36:
+ key_rshift = 1;
+ return 0;
+ case 0xaa:
+ key_lshift = 0;
+ return 0;
+ case 0xb6:
+ key_rshift = 0;
+ return 0;
+ case 0x3a:
+ if (key_caps) {
+ key_caps = 0;
+ pc_kbd_cmd(0xed, 0);
+ } else {
+ key_caps = 1;
+ pc_kbd_cmd(0xed, 4); /* set caps led */
+ }
+ return 0;
+ }
+
+ if (key_ext) {
+ // void printk(const char *format, ...);
+ printk("extended keycode: %x\n", c);
+
+ key_ext = 0;
+ return 0;
+ }
+
+ if (c & 0x80) /* unhandled key release */
+ return 0;
+
+ if (key_lshift || key_rshift)
+ return key_caps ? normal[c] : shifted[c];
+ else
+ return key_caps ? shifted[c] : normal[c];
+ }
+ return 0;
+}
+
+int pc_kbd_dataready(void)
+{
+ if (last_key)
+ return 1;
+
+ last_key = pc_kbd_poll();
+
+ return (last_key != 0);
+}
+
+unsigned char pc_kbd_readdata(void)
+{
+ char tmp;
+ while (!pc_kbd_dataready());
+ tmp = last_key;
+ last_key = 0;
+ return tmp;
+}
+
+/* ( addr len -- actual ) */
+static void
+pc_kbd_read(void)
+{
+ unsigned char *addr;
+ int len;
+
+ len = POP();
+ addr = (unsigned char *)POP();
+
+ if (len != 1)
+ printk("pc_kbd_read: bad len, addr %lx len %x\n", (unsigned long)addr, len);
+
+ if (pc_kbd_dataready()) {
+ *addr = pc_kbd_readdata();
+ PUSH(1);
+ } else {
+ PUSH(0);
+ }
+}
+
+static void
+pc_kbd_close(void)
+{
+}
+
+static void
+pc_kbd_open(unsigned long *address)
+{
+ int len;
+ phandle_t ph;
+ unsigned long *prop;
+
+ fword("my-self");
+ fword("ihandle>phandle");
+ ph = (phandle_t)POP();
+ prop = (unsigned long *)get_property(ph, "address", &len);
+ *address = *prop;
+
+ RET ( -1 );
+}
+
+DECLARE_UNNAMED_NODE(pc_kbd, INSTALL_OPEN, sizeof(unsigned long));
+
+NODE_METHODS(pc_kbd) = {
+ { "open", pc_kbd_open },
+ { "close", pc_kbd_close },
+ { "read", pc_kbd_read },
+};
+
+void
+ob_pc_kbd_init(const char *path, const char *dev_name, uint64_t base,
+ uint64_t offset, int intr)
+{
+ phandle_t chosen, aliases;
+ char nodebuff[128];
+
+ snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name);
+ REGISTER_NAMED_NODE(pc_kbd, nodebuff);
+
+ push_str(nodebuff);
+ fword("find-device");
+
+ push_str(dev_name);
+ fword("device-name");
+
+ push_str("serial");
+ fword("device-type");
+
+ PUSH(-1);
+ fword("encode-int");
+ push_str("keyboard");
+ fword("property");
+
+ PUSH((base + offset) >> 32);
+ fword("encode-int");
+ PUSH((base + offset) & 0xffffffff);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(SER_SIZE);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ PUSH(offset);
+ fword("encode-int");
+ push_str("address");
+ fword("property");
+
+ chosen = find_dev("/chosen");
+ push_str(nodebuff);
+ fword("open-dev");
+ set_int_property(chosen, "keyboard", POP());
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "keyboard", nodebuff, strlen(nodebuff) + 1);
+
+ pc_kbd_controller_cmd(0x60, 0x40); // Write mode command, translated mode
+}
diff --git a/roms/openbios/drivers/pc_serial.c b/roms/openbios/drivers/pc_serial.c
new file mode 100644
index 00000000..a638e1f9
--- /dev/null
+++ b/roms/openbios/drivers/pc_serial.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2003, 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "kernel/kernel.h"
+#include "drivers/drivers.h"
+#include "libc/vsprintf.h"
+
+/* ******************************************************************
+ * serial console functions
+ * ****************************************************************** */
+
+#define SER_SIZE 8
+
+#define RBR(x) x==2?0x2f8:0x3f8
+#define THR(x) x==2?0x2f8:0x3f8
+#define IER(x) x==2?0x2f9:0x3f9
+#define IIR(x) x==2?0x2fa:0x3fa
+#define LCR(x) x==2?0x2fb:0x3fb
+#define MCR(x) x==2?0x2fc:0x3fc
+#define LSR(x) x==2?0x2fd:0x3fd
+#define MSR(x) x==2?0x2fe:0x3fe
+#define SCR(x) x==2?0x2ff:0x3ff
+#define DLL(x) x==2?0x2f8:0x3f8
+#define DLM(x) x==2?0x2f9:0x3f9
+
+int uart_charav(int port)
+{
+ return ((inb(LSR(port)) & 1) != 0);
+}
+
+char uart_getchar(int port)
+{
+ while (!uart_charav(port));
+ return ((char) inb(RBR(port)) & 0177);
+}
+
+static void uart_port_putchar(int port, unsigned char c)
+{
+ if (c == '\n')
+ uart_port_putchar(port, '\r');
+ while (!(inb(LSR(port)) & 0x20));
+ outb(c, THR(port));
+}
+
+static void uart_init_line(int port, unsigned long baud)
+{
+ int i, baudconst;
+
+ switch (baud) {
+ case 115200:
+ baudconst = 1;
+ break;
+ case 57600:
+ baudconst = 2;
+ break;
+ case 38400:
+ baudconst = 3;
+ break;
+ case 19200:
+ baudconst = 6;
+ break;
+ case 9600:
+ default:
+ baudconst = 12;
+ break;
+ }
+
+ outb(0x87, LCR(port));
+ outb(0x00, DLM(port));
+ outb(baudconst, DLL(port));
+ outb(0x07, LCR(port));
+ outb(0x0f, MCR(port));
+
+ for (i = 10; i > 0; i--) {
+ if (inb(LSR(port)) == (unsigned int) 0)
+ break;
+ inb(RBR(port));
+ }
+}
+
+#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
+int uart_init(int port, unsigned long speed)
+{
+ uart_init_line(port, speed);
+ return -1;
+}
+
+void uart_putchar(int c)
+{
+ uart_port_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff));
+}
+#endif
+
+/* ( addr len -- actual ) */
+static void
+pc_serial_read(unsigned long *address)
+{
+ char *addr;
+ int len;
+
+ len = POP();
+ addr = (char *)POP();
+
+ if (len != 1)
+ printk("pc_serial_read: bad len, addr %lx len %x\n", (unsigned long)addr, len);
+
+ if (uart_charav(*address)) {
+ *addr = (char)uart_getchar(*address);
+ PUSH(1);
+ } else {
+ PUSH(0);
+ }
+}
+
+/* ( addr len -- actual ) */
+static void
+pc_serial_write(unsigned long *address)
+{
+ unsigned char *addr;
+ int i, len;
+
+ len = POP();
+ addr = (unsigned char *)POP();
+
+ for (i = 0; i < len; i++) {
+ uart_port_putchar(*address, addr[i]);
+ }
+ PUSH(len);
+}
+
+static void
+pc_serial_close(void)
+{
+}
+
+static void
+pc_serial_open(unsigned long *address)
+{
+ RET ( -1 );
+}
+
+static void
+pc_serial_init(unsigned long *address)
+{
+ *address = POP();
+}
+
+DECLARE_UNNAMED_NODE(pc_serial, INSTALL_OPEN, sizeof(unsigned long));
+
+NODE_METHODS(pc_serial) = {
+ { "init", pc_serial_init },
+ { "open", pc_serial_open },
+ { "close", pc_serial_close },
+ { "read", pc_serial_read },
+ { "write", pc_serial_write },
+};
+
+void
+ob_pc_serial_init(const char *path, const char *dev_name, uint64_t base,
+ uint64_t offset, int intr)
+{
+ phandle_t aliases;
+ char nodebuff[128];
+
+ snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name);
+ REGISTER_NAMED_NODE(pc_serial, nodebuff);
+
+ push_str(nodebuff);
+ fword("find-device");
+
+ PUSH(offset);
+ PUSH(find_package_method("init", get_cur_dev()));
+ fword("execute");
+
+ push_str("serial");
+ fword("device-type");
+
+ PUSH((base + offset) >> 32);
+ fword("encode-int");
+ PUSH((base + offset) & 0xffffffff);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(SER_SIZE);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+#if !defined(CONFIG_SPARC64)
+ PUSH(offset);
+ fword("encode-int");
+ push_str("address");
+ fword("property");
+#endif
+
+#if defined(CONFIG_SPARC64)
+ set_int_property(get_cur_dev(), "interrupts", 1);
+#endif
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "ttya", nodebuff, strlen(nodebuff) + 1);
+}
diff --git a/roms/openbios/drivers/pci.c b/roms/openbios/drivers/pci.c
new file mode 100644
index 00000000..366f4a17
--- /dev/null
+++ b/roms/openbios/drivers/pci.c
@@ -0,0 +1,1569 @@
+/*
+ * OpenBIOS pci driver
+ *
+ * This driver is compliant to the
+ * PCI bus binding to IEEE 1275-1994 Rev 2.1
+ *
+ * (C) 2004 Stefan Reinauer <stepan@openbios.org>
+ * (C) 2005 Ed Schouten <ed@fxq.nl>
+ *
+ * Some parts from OpenHackWare-0.4, Copyright (c) 2004-2005 Jocelyn Mayer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/ofmem.h"
+#include "kernel/kernel.h"
+#include "drivers/pci.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+
+#include "drivers/drivers.h"
+#include "drivers/vga.h"
+#include "packages/video.h"
+#include "libopenbios/video.h"
+#include "timer.h"
+#include "pci.h"
+#include "pci_database.h"
+#ifdef CONFIG_DRIVER_MACIO
+#include "cuda.h"
+#include "macio.h"
+#endif
+#ifdef CONFIG_DRIVER_USB
+#include "drivers/usb.h"
+#endif
+
+#if defined (CONFIG_DEBUG_PCI)
+# define PCI_DPRINTF(format, ...) printk(format, ## __VA_ARGS__)
+#else
+# define PCI_DPRINTF(format, ...) do { } while (0)
+#endif
+
+#define set_bool_property(ph, name) set_property(ph, name, NULL, 0);
+
+/* DECLARE data structures for the nodes. */
+
+DECLARE_UNNAMED_NODE( ob_pci_bus_node, INSTALL_OPEN, 2*sizeof(int) );
+DECLARE_UNNAMED_NODE( ob_pci_simple_node, INSTALL_OPEN, 2*sizeof(int) );
+DECLARE_UNNAMED_NODE( ob_pci_empty_node, 0, 2*sizeof(int) );
+
+const pci_arch_t *arch;
+
+#define IS_NOT_RELOCATABLE 0x80000000
+#define IS_PREFETCHABLE 0x40000000
+#define IS_ALIASED 0x20000000
+
+enum {
+ CONFIGURATION_SPACE = 0,
+ IO_SPACE = 1,
+ MEMORY_SPACE_32 = 2,
+ MEMORY_SPACE_64 = 3,
+};
+
+static int encode_int32_cells(int num_cells, u32 *prop, ucell val)
+{
+ int i = 0;
+
+ /* hi ... lo */
+ for (i=0; i < num_cells; ++i) {
+ prop[num_cells - i - 1] = val;
+ val >>= 16;
+ val >>= 16;
+ }
+
+ return num_cells;
+}
+
+static inline int pci_encode_phys_addr(u32 *phys, int flags, int space_code,
+ pci_addr dev, uint8_t reg, uint64_t addr)
+{
+
+ /* phys.hi */
+
+ phys[0] = flags | (space_code << 24) | dev | reg;
+
+ /* phys.mid */
+
+ phys[1] = addr >> 32;
+
+ /* phys.lo */
+
+ phys[2] = addr;
+
+ return 3;
+}
+
+static inline int pci_encode_size(u32 *prop, uint64_t size)
+{
+ return encode_int32_cells(2, prop, size);
+}
+
+static int host_address_cells(void)
+{
+ return get_int_property(find_dev("/"), "#address-cells", NULL);
+}
+
+static int host_encode_phys_addr(u32 *prop, ucell addr)
+{
+ return encode_int32_cells(host_address_cells(), prop, addr);
+}
+
+static int host_size_cells(void)
+{
+ return get_int_property(find_dev("/"), "#size-cells", NULL);
+}
+
+/*
+static int parent_address_cells(void)
+{
+ phandle_t parent_ph = ih_to_phandle(my_parent());
+ return get_int_property(parent_ph, "#address-cells", NULL);
+}
+
+static int parent_size_cells(void)
+{
+ phandle_t parent_ph = ih_to_phandle(my_parent());
+ return get_int_property(parent_ph, "#size-cells", NULL);
+}
+*/
+
+#if defined(CONFIG_DEBUG_PCI)
+static void dump_reg_property(const char* description, int nreg, u32 *reg)
+{
+ int i;
+ printk("%s reg", description);
+ for (i=0; i < nreg; ++i) {
+ printk(" %08X", reg[i]);
+ }
+ printk("\n");
+}
+#endif
+
+static unsigned long pci_bus_addr_to_host_addr(uint32_t ba)
+{
+ return arch->host_pci_base + (unsigned long)ba;
+}
+
+static void
+ob_pci_open(int *idx)
+{
+ int ret=1;
+ RET ( -ret );
+}
+
+static void
+ob_pci_close(int *idx)
+{
+}
+
+static void
+ob_pci_initialize(int *idx)
+{
+}
+
+/* ( str len -- phys.lo phys.mid phys.hi ) */
+
+static void
+ob_pci_decode_unit(int *idx)
+{
+ ucell hi, mid, lo;
+ const char *arg = pop_fstr_copy();
+ int dev, fn, reg, ss, n, p, t;
+ int bus = 0; /* no information */
+ char *ptr;
+
+ PCI_DPRINTF("ob_pci_decode_unit idx=%p\n", idx);
+
+ fn = 0;
+ reg = 0;
+ n = 0;
+ p = 0;
+ t = 0;
+
+ ptr = (char*)arg;
+ if (*ptr == 'n') {
+ n = IS_NOT_RELOCATABLE;
+ ptr++;
+ }
+ if (*ptr == 'i') {
+ ss = IO_SPACE;
+ ptr++;
+ if (*ptr == 't') {
+ t = IS_ALIASED;
+ ptr++;
+ }
+
+ /* DD,F,RR,NNNNNNNN */
+
+ dev = strtol(ptr, &ptr, 16);
+ ptr++;
+ fn = strtol(ptr, &ptr, 16);
+ ptr++;
+ reg = strtol(ptr, &ptr, 16);
+ ptr++;
+ lo = strtol(ptr, &ptr, 16);
+ mid = 0;
+
+ } else if (*ptr == 'm') {
+ ss = MEMORY_SPACE_32;
+ ptr++;
+ if (*ptr == 't') {
+ t = IS_ALIASED;
+ ptr++;
+ }
+ if (*ptr == 'p') {
+ p = IS_PREFETCHABLE;
+ ptr++;
+ }
+
+ /* DD,F,RR,NNNNNNNN */
+
+ dev = strtol(ptr, &ptr, 16);
+ ptr++;
+ fn = strtol(ptr, &ptr, 16);
+ ptr++;
+ reg = strtol(ptr, &ptr, 16);
+ ptr++;
+ lo = strtol(ptr, &ptr, 16);
+ mid = 0;
+
+ } else if (*ptr == 'x') {
+ unsigned long long addr64;
+ ss = MEMORY_SPACE_64;
+ ptr++;
+ if (*ptr == 'p') {
+ p = IS_PREFETCHABLE;
+ ptr++;
+ }
+
+ /* DD,F,RR,NNNNNNNNNNNNNNNN */
+
+ dev = strtol(ptr, &ptr, 16);
+ ptr++;
+ fn = strtol(ptr, &ptr, 16);
+ ptr++;
+ reg = strtol(ptr, &ptr, 16);
+ ptr++;
+ addr64 = strtoll(ptr, &ptr, 16);
+ lo = (ucell)addr64;
+ mid = addr64 >> 32;
+
+ } else {
+ ss = CONFIGURATION_SPACE;
+ /* "DD" or "DD,FF" */
+ dev = strtol(ptr, &ptr, 16);
+ if (*ptr == ',') {
+ ptr++;
+ fn = strtol(ptr, NULL, 16);
+ }
+ lo = 0;
+ mid = 0;
+ }
+ free((char*)arg);
+
+ hi = n | p | t | (ss << 24) | (bus << 16) | (dev << 11) | (fn << 8) | reg;
+
+ PUSH(lo);
+ PUSH(mid);
+ PUSH(hi);
+
+ PCI_DPRINTF("ob_pci_decode_unit idx=%p addr="
+ FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n",
+ idx, lo, mid, hi);
+}
+
+/* ( phys.lo phy.mid phys.hi -- str len ) */
+
+static void
+ob_pci_encode_unit(int *idx)
+{
+ char buf[28];
+ cell hi = POP();
+ cell mid = POP();
+ cell lo = POP();
+ int n, p, t, ss, dev, fn, reg;
+
+ n = hi & IS_NOT_RELOCATABLE;
+ p = hi & IS_PREFETCHABLE;
+ t = hi & IS_ALIASED;
+ ss = (hi >> 24) & 0x03;
+
+ dev = (hi >> 11) & 0x1F;
+ fn = (hi >> 8) & 0x07;
+ reg = hi & 0xFF;
+
+ switch(ss) {
+ case CONFIGURATION_SPACE:
+
+ if (fn == 0) /* DD */
+ snprintf(buf, sizeof(buf), "%x", dev);
+ else /* DD,F */
+ snprintf(buf, sizeof(buf), "%x,%x", dev, fn);
+ break;
+
+ case IO_SPACE:
+
+ /* [n]i[t]DD,F,RR,NNNNNNNN */
+ snprintf(buf, sizeof(buf), "%si%s%x,%x,%x," FMT_ucellx,
+ n ? "n" : "", /* relocatable */
+ t ? "t" : "", /* aliased */
+ dev, fn, reg, t ? lo & 0x03FF : lo);
+ break;
+
+ case MEMORY_SPACE_32:
+
+ /* [n]m[t][p]DD,F,RR,NNNNNNNN */
+ snprintf(buf, sizeof(buf), "%sm%s%s%x,%x,%x," FMT_ucellx,
+ n ? "n" : "", /* relocatable */
+ t ? "t" : "", /* aliased */
+ p ? "p" : "", /* prefetchable */
+ dev, fn, reg, lo );
+ break;
+
+ case MEMORY_SPACE_64:
+
+ /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN */
+ snprintf(buf, sizeof(buf), "%sx%s%x,%x,%x,%llx",
+ n ? "n" : "", /* relocatable */
+ p ? "p" : "", /* prefetchable */
+ dev, fn, reg, ((long long)mid << 32) | (long long)lo);
+ break;
+ }
+ push_str(buf);
+
+ PCI_DPRINTF("ob_pci_encode_unit space=%d dev=%d fn=%d buf=%s\n",
+ ss, dev, fn, buf);
+}
+
+/* ( pci-addr.lo pci-addr.hi size -- virt ) */
+
+static void
+ob_pci_map_in(int *idx)
+{
+ phys_addr_t phys;
+ uint32_t ba;
+ ucell size, virt;
+
+ PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx);
+
+ size = POP();
+ POP();
+ ba = POP();
+
+ phys = pci_bus_addr_to_host_addr(ba);
+
+#if defined(CONFIG_OFMEM)
+ ofmem_claim_phys(phys, size, 0);
+
+#if defined(CONFIG_PPC)
+ /* For some reason PPC gets upset when virt != phys for map-in... */
+ virt = ofmem_claim_virt(phys, size, 0);
+#else
+ virt = ofmem_claim_virt(-1, size, size);
+#endif
+
+ ofmem_map(phys, virt, size, ofmem_arch_io_translation_mode(phys));
+
+#else
+ virt = size; /* Keep compiler quiet */
+ virt = phys;
+#endif
+
+ PUSH(virt);
+}
+
+NODE_METHODS(ob_pci_bus_node) = {
+ { NULL, ob_pci_initialize },
+ { "open", ob_pci_open },
+ { "close", ob_pci_close },
+ { "decode-unit", ob_pci_decode_unit },
+ { "encode-unit", ob_pci_encode_unit },
+ { "pci-map-in", ob_pci_map_in },
+};
+
+NODE_METHODS(ob_pci_simple_node) = {
+ { NULL, ob_pci_initialize },
+ { "open", ob_pci_open },
+ { "close", ob_pci_close },
+};
+
+NODE_METHODS(ob_pci_empty_node) = {
+ { NULL, ob_pci_initialize }
+};
+
+static void pci_set_bus_range(const pci_config_t *config)
+{
+ phandle_t dev = find_dev(config->path);
+ u32 props[2];
+
+ props[0] = config->secondary_bus;
+ props[1] = config->subordinate_bus;
+
+ PCI_DPRINTF("setting bus range for %s PCI device, "
+ "package handle " FMT_ucellx " "
+ "bus primary=%d secondary=%d subordinate=%d\n",
+ config->path,
+ dev,
+ config->primary_bus,
+ config->secondary_bus,
+ config->subordinate_bus);
+
+
+ set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0]));
+}
+
+static void pci_host_set_reg(phandle_t phandle)
+{
+ phandle_t dev = phandle;
+
+ /* at most 2 integers for address and size */
+ u32 props[4];
+ int ncells = 0;
+
+ ncells += encode_int32_cells(host_address_cells(), props + ncells,
+ arch->cfg_base);
+
+ ncells += encode_int32_cells(host_size_cells(), props + ncells,
+ arch->cfg_len);
+
+ set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
+
+#if defined(CONFIG_DEBUG_PCI)
+ dump_reg_property("pci_host_set_reg", 4, props);
+#endif
+}
+
+/* child-phys : parent-phys : size */
+/* 3 cells for PCI : 2 cells for 64bit parent : 2 cells for PCI */
+
+static void pci_host_set_ranges(const pci_config_t *config)
+{
+ phandle_t dev = get_cur_dev();
+ u32 props[32];
+ int ncells;
+
+ ncells = 0;
+ /* first encode PCI configuration space */
+ {
+ ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
+ config->dev, 0, 0);
+ ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr);
+ ncells += pci_encode_size(props + ncells, arch->cfg_len);
+ }
+
+ if (arch->io_base) {
+ ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE,
+ config->dev, 0, 0);
+ ncells += host_encode_phys_addr(props + ncells, arch->io_base);
+ ncells += pci_encode_size(props + ncells, arch->io_len);
+ }
+ if (arch->rbase) {
+ ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
+ config->dev, 0, 0);
+ ncells += host_encode_phys_addr(props + ncells, arch->rbase);
+ ncells += pci_encode_size(props + ncells, arch->rlen);
+ }
+ if (arch->pci_mem_base) {
+ ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
+ config->dev, 0, arch->pci_mem_base);
+ ncells += host_encode_phys_addr(props + ncells, arch->host_pci_base +
+ arch->pci_mem_base);
+ ncells += pci_encode_size(props + ncells, arch->mem_len);
+ }
+ set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
+}
+
+int host_config_cb(const pci_config_t *config)
+{
+ //XXX this overrides "reg" property
+ pci_host_set_reg(get_cur_dev());
+ pci_host_set_ranges(config);
+
+ return 0;
+}
+
+static int sabre_configure(phandle_t dev)
+{
+ uint32_t props[28];
+
+ props[0] = 0xc0000000;
+ props[1] = 0x20000000;
+ set_property(dev, "virtual-dma", (char *)props, 2 * sizeof(props[0]));
+ props[0] = 1;
+ set_property(dev, "#virtual-dma-size-cells", (char *)props,
+ sizeof(props[0]));
+ set_property(dev, "#virtual-dma-addr-cells", (char *)props,
+ sizeof(props[0]));
+
+ set_property(dev, "no-streaming-cache", (char *)props, 0);
+
+ props[0] = 0x000007f0;
+ props[1] = 0x000007ee;
+ props[2] = 0x000007ef;
+ props[3] = 0x000007e5;
+ set_property(dev, "interrupts", (char *)props, 4 * sizeof(props[0]));
+ props[0] = 0x0000001f;
+ set_property(dev, "upa-portid", (char *)props, 1 * sizeof(props[0]));
+ return 0;
+}
+
+int sabre_config_cb(const pci_config_t *config)
+{
+ host_config_cb(config);
+
+ return sabre_configure(get_cur_dev());
+}
+
+int bridge_config_cb(const pci_config_t *config)
+{
+ phandle_t aliases;
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "bridge", config->path, strlen(config->path) + 1);
+
+ return 0;
+}
+
+int ide_config_cb2 (const pci_config_t *config)
+{
+ ob_ide_init(config->path,
+ config->assigned[0] & ~0x0000000F,
+ (config->assigned[1] & ~0x0000000F) + 2,
+ config->assigned[2] & ~0x0000000F,
+ (config->assigned[3] & ~0x0000000F) + 2);
+ return 0;
+}
+
+int eth_config_cb (const pci_config_t *config)
+{
+ phandle_t ph = get_cur_dev();
+
+ set_property(ph, "network-type", "ethernet", 9);
+ set_property(ph, "removable", "network", 8);
+ set_property(ph, "category", "net", 4);
+
+ return 0;
+}
+
+static inline void pci_decode_pci_addr(pci_addr addr, int *flags,
+ int *space_code, uint32_t *mask)
+{
+ *flags = 0;
+
+ if (addr & 0x01) {
+ *space_code = IO_SPACE;
+ *mask = 0x00000001;
+ } else {
+ if (addr & 0x04) {
+ *space_code = MEMORY_SPACE_64;
+ *flags |= IS_NOT_RELOCATABLE; /* XXX: why not relocatable? */
+ } else {
+ *space_code = MEMORY_SPACE_32;
+ }
+
+ if (addr & 0x08) {
+ *flags |= IS_PREFETCHABLE;
+ }
+
+ *mask = 0x0000000F;
+ }
+}
+
+/*
+ * "Designing PCI Cards and Drivers for Power Macintosh Computers", p. 454
+ *
+ * "AAPL,address" provides an array of 32-bit logical addresses
+ * Nth entry corresponding to Nth "assigned-address" base address entry.
+ */
+
+static void pci_set_AAPL_address(const pci_config_t *config)
+{
+ phandle_t dev = get_cur_dev();
+ cell props[7];
+ int ncells, i;
+
+ ncells = 0;
+ for (i = 0; i < 6; i++) {
+ if (!config->assigned[i] || !config->sizes[i])
+ continue;
+ props[ncells++] = config->assigned[i] & ~0x0000000F;
+ }
+ if (ncells)
+ set_property(dev, "AAPL,address", (char *)props,
+ ncells * sizeof(cell));
+}
+
+static void pci_set_assigned_addresses(phandle_t phandle,
+ const pci_config_t *config, int num_bars)
+{
+ phandle_t dev = phandle;
+ u32 props[32];
+ int ncells;
+ int i;
+ uint32_t mask;
+ int flags, space_code;
+
+ ncells = 0;
+ for (i = 0; i < num_bars; i++) {
+ /* consider only bars with non-zero region size */
+ if (!config->sizes[i])
+ continue;
+ pci_decode_pci_addr(config->assigned[i],
+ &flags, &space_code, &mask);
+
+ ncells += pci_encode_phys_addr(props + ncells,
+ flags, space_code, config->dev,
+ PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
+ config->assigned[i] & ~mask);
+
+ props[ncells++] = 0x00000000;
+ props[ncells++] = config->sizes[i];
+ }
+ if (ncells)
+ set_property(dev, "assigned-addresses", (char *)props,
+ ncells * sizeof(props[0]));
+}
+
+/* call after writing "reg" property to update config->path */
+static void ob_pci_reload_device_path(phandle_t phandle, pci_config_t *config)
+{
+ /* since "name" and "reg" are now assigned
+ we need to reload current node name */
+
+ PUSH(phandle);
+ fword("get-package-path");
+ char *new_path = pop_fstr_copy();
+ if (new_path) {
+ if (0 != strcmp(config->path, new_path)) {
+ PCI_DPRINTF("\n=== CHANGED === package path old=%s new=%s\n",
+ config->path, new_path);
+ strncpy(config->path, new_path, sizeof(config->path));
+ config->path[sizeof(config->path)-1] = '\0';
+ }
+ free(new_path);
+ } else {
+ PCI_DPRINTF("\n=== package path old=%s new=NULL\n", config->path);
+ }
+}
+
+static void pci_set_reg(phandle_t phandle,
+ pci_config_t *config, int num_bars)
+{
+ phandle_t dev = phandle;
+ u32 props[38];
+ int ncells;
+ int i;
+ uint32_t mask;
+ int space_code, flags;
+
+ ncells = 0;
+
+ /* first (addr, size) pair is the beginning of configuration address space */
+ ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
+ config->dev, 0, 0);
+
+ ncells += pci_encode_size(props + ncells, 0);
+
+ for (i = 0; i < num_bars; i++) {
+ /* consider only bars with non-zero region size */
+ if (!config->sizes[i])
+ continue;
+
+ pci_decode_pci_addr(config->regions[i],
+ &flags, &space_code, &mask);
+
+ ncells += pci_encode_phys_addr(props + ncells,
+ flags, space_code, config->dev,
+ PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
+ config->regions[i] & ~mask);
+
+ /* set size */
+ ncells += pci_encode_size(props + ncells, config->sizes[i]);
+ }
+
+ set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
+ ob_pci_reload_device_path(dev, config);
+
+#if defined(CONFIG_DEBUG_PCI)
+ dump_reg_property("pci_set_reg", ncells, props);
+#endif
+}
+
+
+static void pci_set_ranges(const pci_config_t *config)
+{
+ phandle_t dev = get_cur_dev();
+ u32 props[32];
+ int ncells;
+ int i;
+ uint32_t mask;
+ int flags;
+ int space_code;
+
+ ncells = 0;
+ for (i = 0; i < 6; i++) {
+ if (!config->assigned[i] || !config->sizes[i])
+ continue;
+
+ /* child address */
+
+ props[ncells++] = 0x00000000;
+
+ /* parent address */
+
+ pci_decode_pci_addr(config->assigned[i],
+ &flags, &space_code, &mask);
+ ncells += pci_encode_phys_addr(props + ncells, flags, space_code,
+ config->dev, 0x10 + i * 4,
+ config->assigned[i] & ~mask);
+
+ /* size */
+
+ props[ncells++] = config->sizes[i];
+ }
+ set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
+}
+
+int macio_heathrow_config_cb (const pci_config_t *config)
+{
+ pci_set_ranges(config);
+
+#ifdef CONFIG_DRIVER_MACIO
+ ob_macio_heathrow_init(config->path, config->assigned[0] & ~0x0000000F);
+#endif
+ return 0;
+}
+
+int macio_keylargo_config_cb (const pci_config_t *config)
+{
+ pci_set_ranges(config);
+
+#ifdef CONFIG_DRIVER_MACIO
+ ob_macio_keylargo_init(config->path, config->assigned[0] & ~0x0000000F);
+#endif
+ return 0;
+}
+
+int vga_config_cb (const pci_config_t *config)
+{
+ unsigned long rom;
+ uint32_t rom_size, size;
+ phandle_t ph;
+
+ if (config->assigned[0] != 0x00000000) {
+ setup_video();
+
+ rom = pci_bus_addr_to_host_addr(config->assigned[1] & ~0x0000000F);
+ rom_size = config->sizes[1];
+
+ ph = get_cur_dev();
+
+ if (rom_size >= 8) {
+ const char *p;
+
+ p = (const char *)rom;
+ if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') {
+ size = *(uint32_t*)(p + 4);
+ set_property(ph, "driver,AAPL,MacOS,PowerPC", p + 8, size);
+ }
+ }
+
+ /* Currently we don't read FCode from the hardware but execute it directly */
+ feval("['] vga-driver-fcode 2 cells + 1 byte-load");
+
+#ifdef CONFIG_MOL
+ /* Install special words for Mac On Linux */
+ molvideo_init();
+#endif
+
+ }
+
+ return 0;
+}
+
+int ebus_config_cb(const pci_config_t *config)
+{
+#ifdef CONFIG_DRIVER_EBUS
+ phandle_t dev = get_cur_dev();
+ uint32_t props[12];
+ int ncells;
+ int i;
+ uint32_t mask;
+ int flags, space_code;
+
+ props[0] = 0x14;
+ props[1] = 0x3f8;
+ props[2] = 1;
+ props[3] = find_dev("/");
+ props[4] = 0x2b;
+ set_property(dev, "interrupt-map", (char *)props, 5 * sizeof(props[0]));
+
+ props[0] = 0x000001ff;
+ props[1] = 0xffffffff;
+ props[2] = 3;
+ set_property(dev, "interrupt-map-mask", (char *)props, 3 * sizeof(props[0]));
+
+ /* Build ranges property from the BARs */
+ ncells = 0;
+ for (i = 0; i < 6; i++) {
+ /* consider only bars with non-zero region size */
+ if (!config->sizes[i])
+ continue;
+
+ pci_decode_pci_addr(config->assigned[i],
+ &flags, &space_code, &mask);
+
+ props[ncells++] = PCI_BASE_ADDR_0 + (i * sizeof(uint32_t));
+ props[ncells++] = 0x0;
+
+ ncells += pci_encode_phys_addr(props + ncells,
+ flags, space_code, config->dev,
+ PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
+ 0);
+
+ props[ncells++] = config->sizes[i];
+ }
+
+ set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
+
+ /* Build eeprom node */
+ fword("new-device");
+ PUSH(0x14);
+ fword("encode-int");
+ PUSH(0x2000);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x2000);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ push_str("mk48t59");
+ fword("model");
+
+ push_str("eeprom");
+ fword("device-name");
+ fword("finish-device");
+
+#ifdef CONFIG_DRIVER_FLOPPY
+ ob_floppy_init(config->path, "fdthree", 0x3f0ULL, 0);
+#endif
+#ifdef CONFIG_DRIVER_PC_SERIAL
+ ob_pc_serial_init(config->path, "su", (PCI_BASE_ADDR_1 | 0ULL) << 32, 0x3f8ULL, 0);
+#endif
+#ifdef CONFIG_DRIVER_PC_KBD
+ ob_pc_kbd_init(config->path, "kb_ps2", (PCI_BASE_ADDR_1 | 0ULL) << 32, 0x60ULL, 0);
+#endif
+#endif
+ return 0;
+}
+
+int i82378_config_cb(const pci_config_t *config)
+{
+#ifdef CONFIG_DRIVER_PC_SERIAL
+ ob_pc_serial_init(config->path, "serial", arch->io_base, 0x3f8ULL, 0);
+#endif
+#ifdef CONFIG_DRIVER_PC_KBD
+ ob_pc_kbd_init(config->path, "8042", arch->io_base, 0x60ULL, 0);
+#endif
+#ifdef CONFIG_DRIVER_IDE
+ ob_ide_init(config->path, 0x1f0, 0x3f6, 0x170, 0x376);
+#endif
+
+ return 0;
+}
+
+int usb_ohci_config_cb(const pci_config_t *config)
+{
+#ifdef CONFIG_DRIVER_USB
+ ob_usb_ohci_init(config->path, 0x80000000 | config->dev);
+#endif
+ return 0;
+}
+
+static void ob_pci_add_properties(phandle_t phandle,
+ pci_addr addr, const pci_dev_t *pci_dev,
+ const pci_config_t *config, int num_bars)
+{
+ /* cannot use get_cur_dev() path resolution since "name" and "reg"
+ properties are being changed */
+ phandle_t dev=phandle;
+ int status,id;
+ uint16_t vendor_id, device_id;
+ uint8_t rev;
+ uint8_t class_prog;
+ uint32_t class_code;
+
+ vendor_id = pci_config_read16(addr, PCI_VENDOR_ID);
+ device_id = pci_config_read16(addr, PCI_DEVICE_ID);
+ rev = pci_config_read8(addr, PCI_REVISION_ID);
+ class_prog = pci_config_read8(addr, PCI_CLASS_PROG);
+ class_code = pci_config_read16(addr, PCI_CLASS_DEVICE);
+
+ if (pci_dev) {
+ /**/
+ if (pci_dev->name) {
+ push_str(pci_dev->name);
+ fword("encode-string");
+ push_str("name");
+ fword("property");
+ } else {
+ char path[256];
+ snprintf(path, sizeof(path),
+ "pci%x,%x", vendor_id, device_id);
+ push_str(path);
+ fword("encode-string");
+ push_str("name");
+ fword("property");
+ }
+ } else {
+ PCI_DPRINTF("*** missing pci_dev\n");
+ }
+
+ /* create properties as described in 2.5 */
+
+ set_int_property(dev, "vendor-id", vendor_id);
+ set_int_property(dev, "device-id", device_id);
+ set_int_property(dev, "revision-id", rev);
+ set_int_property(dev, "class-code", class_code << 8 | class_prog);
+
+ if (config->irq_pin) {
+ OLDWORLD(set_int_property(dev, "AAPL,interrupts",
+ config->irq_line));
+#if defined(CONFIG_SPARC64)
+ set_int_property(dev, "interrupts", config->irq_pin);
+#else
+ NEWWORLD(set_int_property(dev, "interrupts", config->irq_pin));
+#endif
+ }
+
+ set_int_property(dev, "min-grant", pci_config_read8(addr, PCI_MIN_GNT));
+ set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT));
+
+ status=pci_config_read16(addr, PCI_STATUS);
+
+ set_int_property(dev, "devsel-speed",
+ (status&PCI_STATUS_DEVSEL_MASK)>>10);
+
+ if(status&PCI_STATUS_FAST_BACK)
+ set_bool_property(dev, "fast-back-to-back");
+ if(status&PCI_STATUS_66MHZ)
+ set_bool_property(dev, "66mhz-capable");
+ if(status&PCI_STATUS_UDF)
+ set_bool_property(dev, "udf-supported");
+
+ id=pci_config_read16(addr, PCI_SUBSYSTEM_VENDOR_ID);
+ if(id)
+ set_int_property(dev, "subsystem-vendor-id", id);
+ id=pci_config_read16(addr, PCI_SUBSYSTEM_ID);
+ if(id)
+ set_int_property(dev, "subsystem-id", id);
+
+ set_int_property(dev, "cache-line-size",
+ pci_config_read16(addr, PCI_CACHE_LINE_SIZE));
+
+ if (pci_dev) {
+ if (pci_dev->type) {
+ push_str(pci_dev->type);
+ fword("encode-string");
+ push_str("device_type");
+ fword("property");
+ }
+ if (pci_dev->model) {
+ push_str(pci_dev->model);
+ fword("encode-string");
+ push_str("model");
+ fword("property");
+ }
+ if (pci_dev->compat)
+ set_property(dev, "compatible",
+ pci_dev->compat, pci_compat_len(pci_dev));
+
+ if (pci_dev->acells)
+ set_int_property(dev, "#address-cells",
+ pci_dev->acells);
+ if (pci_dev->scells)
+ set_int_property(dev, "#size-cells",
+ pci_dev->scells);
+ if (pci_dev->icells)
+ set_int_property(dev, "#interrupt-cells",
+ pci_dev->icells);
+ }
+
+ pci_set_assigned_addresses(phandle, config, num_bars);
+ OLDWORLD(pci_set_AAPL_address(config));
+
+ PCI_DPRINTF("\n");
+}
+
+#ifdef CONFIG_XBOX
+static char pci_xbox_blacklisted (int bus, int devnum, int fn)
+{
+ /*
+ * The Xbox MCPX chipset is a derivative of the nForce 1
+ * chipset. It almost has the same bus layout; some devices
+ * cannot be used, because they have been removed.
+ */
+
+ /*
+ * Devices 00:00.1 and 00:00.2 used to be memory controllers on
+ * the nForce chipset, but on the Xbox, using them will lockup
+ * the chipset.
+ */
+ if ((bus == 0) && (devnum == 0) && ((fn == 1) || (fn == 2)))
+ return 1;
+
+ /*
+ * Bus 1 only contains a VGA controller at 01:00.0. When you try
+ * to probe beyond that device, you only get garbage, which
+ * could cause lockups.
+ */
+ if ((bus == 1) && ((devnum != 0) || (fn != 0)))
+ return 1;
+
+ /*
+ * Bus 2 used to contain the AGP controller, but the Xbox MCPX
+ * doesn't have one. Probing it can cause lockups.
+ */
+ if (bus >= 2)
+ return 1;
+
+ /*
+ * The device is not blacklisted.
+ */
+ return 0;
+}
+#endif
+
+static void ob_pci_configure_bar(pci_addr addr, pci_config_t *config,
+ int reg, int config_addr,
+ uint32_t *p_omask,
+ unsigned long *mem_base,
+ unsigned long *io_base)
+{
+ uint32_t smask, amask, size, reloc, min_align;
+ unsigned long base;
+
+ config->assigned[reg] = 0x00000000;
+ config->sizes[reg] = 0x00000000;
+
+ if ((*p_omask & 0x0000000f) == 0x4) {
+ /* 64 bits memory mapping */
+ PCI_DPRINTF("Skipping 64 bit BARs for %s\n", config->path);
+ return;
+ }
+
+ config->regions[reg] = pci_config_read32(addr, config_addr);
+
+ /* get region size */
+
+ pci_config_write32(addr, config_addr, 0xffffffff);
+ smask = pci_config_read32(addr, config_addr);
+ if (smask == 0x00000000 || smask == 0xffffffff)
+ return;
+
+ if (smask & 0x00000001 && reg != 6) {
+ /* I/O space */
+ base = *io_base;
+ min_align = 1 << 7;
+ amask = 0x00000001;
+ } else {
+ /* Memory Space */
+ base = *mem_base;
+ min_align = 1 << 16;
+ amask = 0x0000000F;
+ if (reg == 6) {
+ smask |= 1; /* ROM */
+ }
+ }
+ *p_omask = smask & amask;
+ smask &= ~amask;
+ size = (~smask) + 1;
+ config->sizes[reg] = size;
+ reloc = base;
+ if (size < min_align)
+ size = min_align;
+ reloc = (reloc + size -1) & ~(size - 1);
+ if (*io_base == base) {
+ PCI_DPRINTF("changing io_base from 0x%lx to 0x%x\n",
+ *io_base, reloc + size);
+ *io_base = reloc + size;
+ } else {
+ PCI_DPRINTF("changing mem_base from 0x%lx to 0x%x\n",
+ *mem_base, reloc + size);
+ *mem_base = reloc + size;
+ }
+ PCI_DPRINTF("Configuring BARs for %s: reloc 0x%x omask 0x%x "
+ "io_base 0x%lx mem_base 0x%lx size 0x%x\n",
+ config->path, reloc, *p_omask, *io_base, *mem_base, size);
+ pci_config_write32(addr, config_addr, reloc | *p_omask);
+ config->assigned[reg] = reloc | *p_omask;
+}
+
+static void ob_pci_configure_irq(pci_addr addr, pci_config_t *config)
+{
+ uint8_t irq_pin, irq_line;
+
+ irq_pin = pci_config_read8(addr, PCI_INTERRUPT_PIN);
+ if (irq_pin) {
+ config->irq_pin = irq_pin;
+ irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3;
+ irq_line = arch->irqs[irq_pin];
+ pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line);
+ config->irq_line = irq_line;
+ } else
+ config->irq_line = -1;
+}
+
+static void
+ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
+ unsigned long *mem_base, unsigned long *io_base)
+
+{
+ uint32_t omask;
+ uint16_t cmd;
+ int reg;
+ pci_addr config_addr;
+
+ ob_pci_configure_irq(addr, config);
+
+ omask = 0x00000000;
+ for (reg = 0; reg < num_regs; ++reg) {
+ config_addr = PCI_BASE_ADDR_0 + reg * 4;
+
+ ob_pci_configure_bar(addr, config, reg, config_addr,
+ &omask, mem_base,
+ io_base);
+ }
+
+ if (rom_bar) {
+ config_addr = rom_bar;
+ ob_pci_configure_bar(addr, config, reg, config_addr,
+ &omask, mem_base, io_base);
+ }
+ cmd = pci_config_read16(addr, PCI_COMMAND);
+ cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+ pci_config_write16(addr, PCI_COMMAND, cmd);
+}
+
+static void ob_configure_pci_device(const char* parent_path,
+ int *bus_num, unsigned long *mem_base, unsigned long *io_base,
+ int bus, int devnum, int fn, int *p_is_multi);
+
+static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base,
+ unsigned long *io_base, const char *path,
+ int bus)
+{
+ int devnum, fn, is_multi;
+
+ PCI_DPRINTF("\nScanning bus %d at %s...\n", bus, path);
+
+ for (devnum = 0; devnum < 32; devnum++) {
+ is_multi = 0;
+ for (fn = 0; fn==0 || (is_multi && fn<8); fn++) {
+ ob_configure_pci_device(path, bus_num, mem_base, io_base,
+ bus, devnum, fn, &is_multi);
+
+ }
+ }
+}
+
+static void ob_configure_pci_bridge(pci_addr addr,
+ int *bus_num, unsigned long *mem_base,
+ unsigned long *io_base,
+ int primary_bus, pci_config_t *config)
+{
+ config->primary_bus = primary_bus;
+ pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus);
+
+ config->secondary_bus = *bus_num;
+ pci_config_write8(addr, PCI_SECONDARY_BUS, config->secondary_bus);
+
+ config->subordinate_bus = 0xff;
+ pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
+
+ PCI_DPRINTF("scanning new pci bus %u under bridge %s\n",
+ config->secondary_bus, config->path);
+
+ /* make pci bridge parent device, prepare for recursion */
+
+ ob_scan_pci_bus(bus_num, mem_base, io_base,
+ config->path, config->secondary_bus);
+
+ /* bus scan updates *bus_num to last revealed pci bus number */
+ config->subordinate_bus = *bus_num;
+ pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
+
+ PCI_DPRINTF("bridge %s PCI bus primary=%d secondary=%d subordinate=%d\n",
+ config->path, config->primary_bus, config->secondary_bus,
+ config->subordinate_bus);
+
+ pci_set_bus_range(config);
+}
+
+static int ob_pci_read_identification(int bus, int devnum, int fn,
+ int *p_vid, int *p_did,
+ uint8_t *p_class, uint8_t *p_subclass)
+{
+ int vid, did;
+ uint32_t ccode;
+ pci_addr addr;
+
+#ifdef CONFIG_XBOX
+ if (pci_xbox_blacklisted (bus, devnum, fn))
+ return;
+#endif
+ addr = PCI_ADDR(bus, devnum, fn);
+ vid = pci_config_read16(addr, PCI_VENDOR_ID);
+ did = pci_config_read16(addr, PCI_DEVICE_ID);
+
+ if (vid==0xffff || vid==0) {
+ return 0;
+ }
+
+ if (p_vid) {
+ *p_vid = vid;
+ }
+
+ if (p_did) {
+ *p_did = did;
+ }
+
+ ccode = pci_config_read16(addr, PCI_CLASS_DEVICE);
+
+ if (p_class) {
+ *p_class = ccode >> 8;
+ }
+
+ if (p_subclass) {
+ *p_subclass = ccode;
+ }
+
+ return 1;
+}
+
+static void ob_configure_pci_device(const char* parent_path,
+ int *bus_num, unsigned long *mem_base, unsigned long *io_base,
+ int bus, int devnum, int fn, int *p_is_multi)
+{
+ int vid, did;
+ unsigned int htype;
+ pci_addr addr;
+ pci_config_t config = {};
+ const pci_dev_t *pci_dev;
+ uint8_t class, subclass, iface;
+ int num_bars, rom_bar;
+
+ phandle_t phandle = 0;
+ int is_host_bridge = 0;
+
+ if (!ob_pci_read_identification(bus, devnum, fn, &vid, &did, &class, &subclass)) {
+ return;
+ }
+
+ addr = PCI_ADDR(bus, devnum, fn);
+ iface = pci_config_read8(addr, PCI_CLASS_PROG);
+
+ pci_dev = pci_find_device(class, subclass, iface,
+ vid, did);
+
+ PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn,
+ vid, did);
+
+ htype = pci_config_read8(addr, PCI_HEADER_TYPE);
+
+ if (fn == 0) {
+ if (p_is_multi) {
+ *p_is_multi = htype & 0x80;
+ }
+ }
+
+ /* stop adding host bridge accessible from it's primary bus
+ PCI host bridge is to be added by host code
+ */
+ if (class == PCI_BASE_CLASS_BRIDGE &&
+ subclass == PCI_SUBCLASS_BRIDGE_HOST) {
+ is_host_bridge = 1;
+ }
+
+ if (is_host_bridge) {
+ /* reuse device tree node */
+ PCI_DPRINTF("host bridge found - ");
+ snprintf(config.path, sizeof(config.path),
+ "%s", parent_path);
+ } else if (pci_dev == NULL || pci_dev->name == NULL) {
+ snprintf(config.path, sizeof(config.path),
+ "%s/pci%x,%x", parent_path, vid, did);
+ }
+ else {
+ snprintf(config.path, sizeof(config.path),
+ "%s/%s", parent_path, pci_dev->name);
+ }
+
+ PCI_DPRINTF("%s - ", config.path);
+
+ config.dev = addr & 0x00FFFFFF;
+
+ switch (class) {
+ case PCI_BASE_CLASS_BRIDGE:
+ if (subclass != PCI_SUBCLASS_BRIDGE_HOST) {
+ REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle);
+ }
+ break;
+ case PCI_CLASS_DISPLAY:
+ REGISTER_NAMED_NODE_PHANDLE(ob_pci_empty_node, config.path, phandle);
+ break;
+ default:
+ REGISTER_NAMED_NODE_PHANDLE(ob_pci_simple_node, config.path, phandle);
+ break;
+ }
+
+ if (is_host_bridge) {
+ phandle = find_dev(config.path);
+
+ if (get_property(phandle, "vendor-id", NULL)) {
+ PCI_DPRINTF("host bridge already configured\n");
+ return;
+ }
+ }
+
+ activate_dev(phandle);
+
+ if (htype & PCI_HEADER_TYPE_BRIDGE) {
+ num_bars = 2;
+ rom_bar = PCI_ROM_ADDRESS1;
+ } else {
+ num_bars = 6;
+ rom_bar = PCI_ROM_ADDRESS;
+ }
+
+ ob_pci_configure(addr, &config, num_bars, rom_bar,
+ mem_base, io_base);
+
+ ob_pci_add_properties(phandle, addr, pci_dev, &config, num_bars);
+
+ if (!is_host_bridge) {
+ pci_set_reg(phandle, &config, num_bars);
+ }
+
+ /* call device-specific configuration callback */
+ if (pci_dev && pci_dev->config_cb) {
+ //activate_device(config.path);
+ pci_dev->config_cb(&config);
+ }
+
+ /* device is configured so we may move it out of scope */
+ device_end();
+
+ /* scan bus behind bridge device */
+ //if (htype & PCI_HEADER_TYPE_BRIDGE && class == PCI_BASE_CLASS_BRIDGE) {
+ if ( class == PCI_BASE_CLASS_BRIDGE &&
+ ( subclass == PCI_SUBCLASS_BRIDGE_PCI ||
+ subclass == PCI_SUBCLASS_BRIDGE_HOST ) ) {
+
+ if (subclass == PCI_SUBCLASS_BRIDGE_PCI) {
+ /* reserve next pci bus number for this PCI bridge */
+ ++(*bus_num);
+ }
+
+ ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config);
+ }
+}
+
+static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigned long io_base)
+{
+ /* Create an available property for both memory and IO space */
+ uint32_t props[10];
+ int ncells;
+
+ ncells = 0;
+ ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, 0, 0, mem_base);
+ ncells += pci_encode_size(props + ncells, arch->mem_len - mem_base);
+ ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, 0, 0, io_base);
+ ncells += pci_encode_size(props + ncells, arch->io_len - io_base);
+
+ set_property(host, "available", (char *)props, ncells * sizeof(props[0]));
+}
+
+/* Convert device/irq pin to interrupt property */
+#define SUN4U_INTERRUPT(dev, irq_pin) \
+ ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f)
+
+static void ob_pci_host_set_interrupt_map(phandle_t host)
+{
+ phandle_t dnode = 0;
+ u32 props[128];
+ int i;
+
+#if defined(CONFIG_PPC)
+ phandle_t target_node;
+
+ /* Oldworld macs do interrupt maps differently */
+ if (!is_newworld())
+ return;
+
+ dnode = dt_iterate_type(0, "open-pic");
+ if (dnode) {
+ /* patch in openpic interrupt-parent properties */
+ target_node = find_dev("/pci/mac-io");
+ set_int_property(target_node, "interrupt-parent", dnode);
+
+ target_node = find_dev("/pci/mac-io/escc/ch-a");
+ set_int_property(target_node, "interrupt-parent", dnode);
+
+ target_node = find_dev("/pci/mac-io/escc/ch-b");
+ set_int_property(target_node, "interrupt-parent", dnode);
+
+ /* QEMU only emulates 2 of the 3 ata buses currently */
+ /* On a new world Mac these are not numbered but named by the
+ * ATA version they support. Thus we have: ata-3, ata-3, ata-4
+ * On g3beige they all called just ide.
+ * We take ata-3 and ata-4 which seems to work for both
+ * at least for clients we care about */
+ target_node = find_dev("/pci/mac-io/ata-3");
+ set_int_property(target_node, "interrupt-parent", dnode);
+
+ target_node = find_dev("/pci/mac-io/ata-4");
+ set_int_property(target_node, "interrupt-parent", dnode);
+
+ target_node = find_dev("/pci/mac-io/via-cuda");
+ set_int_property(target_node, "interrupt-parent", dnode);
+
+ target_node = find_dev("/pci");
+ set_int_property(target_node, "interrupt-parent", dnode);
+
+ /* openpic interrupt mapping */
+ for (i = 0; i < (7*8); i += 7) {
+ props[i + PCI_INT_MAP_PCI0] = 0;
+ props[i + PCI_INT_MAP_PCI1] = 0;
+ props[i + PCI_INT_MAP_PCI2] = 0;
+ props[i + PCI_INT_MAP_PCI_INT] = (i / 7) + 1; // starts at PINA=1
+ props[i + PCI_INT_MAP_PIC_HANDLE] = dnode;
+ props[i + PCI_INT_MAP_PIC_INT] = arch->irqs[i / 7];
+ props[i + PCI_INT_MAP_PIC_POL] = 3;
+ }
+ set_property(host, "interrupt-map", (char *)props, 7 * 8 * sizeof(props[0]));
+
+ props[PCI_INT_MAP_PCI0] = 0;
+ props[PCI_INT_MAP_PCI1] = 0;
+ props[PCI_INT_MAP_PCI2] = 0;
+ props[PCI_INT_MAP_PCI_INT] = 0x7;
+
+ set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
+ }
+#elif defined(CONFIG_SPARC64)
+ int ncells, len;
+ u32 *val, addr;
+ char *reg;
+
+ /* Set interrupt-map for PCI devices with an interrupt pin present */
+ ncells = 0;
+
+ PUSH(host);
+ fword("child");
+ dnode = POP();
+ while (dnode) {
+ if (get_int_property(dnode, "interrupts", &len)) {
+ reg = get_property(dnode, "reg", &len);
+ if (reg) {
+ val = (u32 *)reg;
+
+ for (i = 0; i < (len / sizeof(u32)); i += 5) {
+ addr = val[i];
+
+ /* Device address is in 1st 32-bit word of encoded PCI address for config space */
+ if (!(addr & 0x03000000)) {
+ ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0);
+ props[ncells++] = 1; /* always interrupt pin 1 for QEMU */
+ props[ncells++] = host;
+ props[ncells++] = SUN4U_INTERRUPT(addr, 1);
+ }
+ }
+ }
+ }
+
+ PUSH(dnode);
+ fword("peer");
+ dnode = POP();
+ }
+ set_property(host, "interrupt-map", (char *)props, ncells * sizeof(props[0]));
+
+ props[0] = 0x0000f800;
+ props[1] = 0x0;
+ props[2] = 0x0;
+ props[3] = 7;
+ set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
+#endif
+}
+
+int ob_pci_init(void)
+{
+ int bus, devnum, fn;
+ uint8_t class, subclass;
+ unsigned long mem_base, io_base;
+
+ pci_config_t config = {}; /* host bridge */
+ phandle_t phandle_host = 0;
+
+ PCI_DPRINTF("Initializing PCI host bridge...\n");
+
+ activate_device("/");
+
+ /* Find all PCI bridges */
+
+ mem_base = arch->pci_mem_base;
+ /* I/O ports under 0x400 are used by devices mapped at fixed
+ location. */
+ io_base = 0x400;
+
+ bus = 0;
+
+ for (devnum = 0; devnum < 32; devnum++) {
+ /* scan only fn 0 */
+ fn = 0;
+
+ if (!ob_pci_read_identification(bus, devnum, fn,
+ 0, 0, &class, &subclass)) {
+ continue;
+ }
+
+ if (class != PCI_BASE_CLASS_BRIDGE || subclass != PCI_SUBCLASS_BRIDGE_HOST) {
+ continue;
+ }
+
+ /* create root node for host PCI bridge */
+
+ /* configure */
+ snprintf(config.path, sizeof(config.path), "/pci");
+
+ REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle_host);
+
+ pci_host_set_reg(phandle_host);
+
+ /* update device path after changing "reg" property */
+ ob_pci_reload_device_path(phandle_host, &config);
+
+ ob_configure_pci_device(config.path, &bus, &mem_base, &io_base,
+ bus, devnum, fn, 0);
+
+ /* we expect single host PCI bridge
+ but this may be machine-specific */
+ break;
+ }
+
+ /* create available attributes for the PCI bridge */
+ ob_pci_set_available(phandle_host, mem_base, io_base);
+
+ /* configure the host bridge interrupt map */
+ ob_pci_host_set_interrupt_map(phandle_host);
+
+ device_end();
+
+ return 0;
+}
diff --git a/roms/openbios/drivers/pci.fs b/roms/openbios/drivers/pci.fs
new file mode 100644
index 00000000..563b652a
--- /dev/null
+++ b/roms/openbios/drivers/pci.fs
@@ -0,0 +1,92 @@
+[IFDEF] CONFIG_DRIVER_PCI
+
+: pci-addr-encode ( addr.lo addr.mi addr.hi )
+ rot >r swap >r
+ encode-int
+ r> encode-int encode+
+ r> encode-int encode+
+ ;
+
+: pci-len-encode ( len.lo len.hi )
+ encode-int
+ rot encode-int encode+
+ ;
+
+\ Get region offset for BAR reg
+: pci-bar-offset@ ( bar-reg -- off.lo off.hi -1 | 0 )
+ " reg" active-package get-package-property 0= if
+ begin
+ decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi )
+ ff and 5 pick = if
+ >r >r 3drop r> r>
+ -1 exit
+ else
+ 2drop
+ then
+ \ Drop the size as we don't need it
+ decode-int drop decode-int drop
+ dup 0=
+ until
+ 3drop
+ 0 exit
+ else
+ 0
+ then
+ ;
+
+\ Get region size for BAR reg
+: pci-bar-size@ ( bar-reg -- size )
+ " reg" active-package get-package-property 0= if
+ begin
+ decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi )
+ ff and 5 pick = if
+ 2drop decode-int drop
+ decode-int
+ >r 3drop r>
+ exit
+ else
+ 2drop decode-int drop
+ decode-int drop
+ then
+ dup 0=
+ until
+ 3drop
+ 0 \ default size of 0 if BAR not found
+ then
+ ;
+
+\ Get base address for configured BAR reg
+: pci-bar-base@ ( bar-reg -- addr.lo addr.hi -1 | 0 )
+ " assigned-addresses" active-package get-package-property 0= if
+ begin
+ decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi )
+ ff and 5 pick = if
+ >r >r 3drop r> r>
+ -1 exit
+ else
+ 2drop
+ then
+ \ Drop the size as we don't need it
+ decode-int drop decode-int drop
+ dup 0=
+ until
+ 3drop
+ 0 exit
+ else
+ 0
+ then
+ ;
+
+\ Get PCI bus address and size for configured BAR reg
+: pci-bar>pci-region ( bar-reg -- addr.lo addr.hi size )
+ dup
+ >r pci-bar-offset@ if
+ swap r@ pci-bar-base@ if
+ swap d+
+ then
+ swap r@ pci-bar-size@
+ then
+ r> drop
+ ;
+
+[THEN]
diff --git a/roms/openbios/drivers/pci.h b/roms/openbios/drivers/pci.h
new file mode 100644
index 00000000..84a2b2cf
--- /dev/null
+++ b/roms/openbios/drivers/pci.h
@@ -0,0 +1,87 @@
+#ifndef PCI_H
+#define PCI_H
+
+#define PCI_VENDOR_ID 0x00
+#define PCI_DEVICE_ID 0x02
+
+#define PCI_COMMAND 0x04
+#define PCI_COMMAND_IO 0x01
+#define PCI_COMMAND_MEMORY 0x02
+#define PCI_COMMAND_BUS_MASTER 0x04
+
+#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features
+ [obsolete] */
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+
+#define PCI_REVISION_ID 0x08 /* Revision ID */
+#define PCI_CLASS_DISPLAY 0x03
+#define PCI_CLASS_PROG 0x09
+#define PCI_CLASS_DEVICE 0x0a
+#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
+#define PCI_HEADER_TYPE 0x0e
+#define PCI_HEADER_TYPE_NORMAL 0x00
+#define PCI_HEADER_TYPE_BRIDGE 0x01
+#define PCI_HEADER_TYPE_CARDBUS 0x02
+#define PCI_PRIMARY_BUS 0x18
+#define PCI_SECONDARY_BUS 0x19
+#define PCI_SUBORDINATE_BUS 0x1A
+#define PCI_BASE_ADDR_0 0x10
+#define PCI_BASE_ADDR_1 0x14
+#define PCI_BASE_ADDR_2 0x18
+#define PCI_BASE_ADDR_3 0x1c
+#define PCI_BASE_ADDR_4 0x20
+#define PCI_BASE_ADDR_5 0x24
+
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID 0x2e
+
+#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
+#define PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
+#define PCI_ROM_ADDRESS1 0x38 /* ROM_ADDRESS in bridge header */
+
+#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
+#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
+#define PCI_MIN_GNT 0x3e /* 8 bits */
+#define PCI_MAX_LAT 0x3f /* 8 bits */
+
+typedef struct {
+ u16 signature;
+ u8 reserved[0x16];
+ u16 dptr;
+} rom_header_t;
+
+typedef struct {
+ u32 signature;
+ u16 vendor;
+ u16 device;
+ u16 reserved_1;
+ u16 dlen;
+ u8 drevision;
+ u8 class_hi;
+ u16 class_lo;
+ u16 ilen;
+ u16 irevision;
+ u8 type;
+ u8 indicator;
+ u16 reserved_2;
+} pci_data_t;
+
+
+#include "asm/pci.h"
+
+#endif /* PCI_H */
diff --git a/roms/openbios/drivers/pci_database.c b/roms/openbios/drivers/pci_database.c
new file mode 100644
index 00000000..0070a78b
--- /dev/null
+++ b/roms/openbios/drivers/pci_database.c
@@ -0,0 +1,1275 @@
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "drivers/pci.h"
+#include "libc/vsprintf.h"
+
+#include "pci_database.h"
+
+/* PCI devices database */
+
+typedef struct pci_class_t pci_class_t;
+typedef struct pci_subclass_t pci_subclass_t;
+typedef struct pci_iface_t pci_iface_t;
+
+struct pci_iface_t {
+ uint8_t iface;
+ const char *name;
+ const char *type;
+ const pci_dev_t *devices;
+ int (*config_cb)(const pci_config_t *config);
+ const void *private;
+};
+
+struct pci_subclass_t {
+ uint8_t subclass;
+ const char *name;
+ const char *type;
+ const pci_dev_t *devices;
+ const pci_iface_t *iface;
+ int (*config_cb)(const pci_config_t *config);
+ const void *private;
+};
+
+struct pci_class_t {
+ const char *name;
+ const char *type;
+ const pci_subclass_t *subc;
+};
+
+/* Current machine description */
+
+static const pci_subclass_t undef_subclass[] = {
+ {
+ 0xFF, NULL, NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_dev_t scsi_devices[] = {
+ {
+ /* Virtio-block controller */
+ PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_BLOCK,
+ NULL, "virtio-blk", NULL,
+ "pci1af4,1001\0pci1af4,1001\0pciclass,01018f\0",
+ 0, 0, 0,
+ NULL, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_dev_t ide_devices[] = {
+ {
+ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, /* CMD646 IDE controller */
+ "pci-ide", "pci-ata", NULL,
+ "pci1095,646\0pci1095,646\0pciclass,01018f\0",
+ 0, 0, 0,
+ ide_config_cb2, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t mass_subclass[] = {
+ {
+ PCI_SUBCLASS_STORAGE_SCSI, "SCSI bus controller",
+ "scsi", scsi_devices, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_STORAGE_IDE, "IDE controller",
+ "ide", ide_devices, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_STORAGE_FLOPPY, "Floppy disk controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_STORAGE_IPI, "IPI bus controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_STORAGE_RAID, "RAID controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_STORAGE_ATA, "ATA controller",
+ "ata", NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_STORAGE_OTHER, "misc mass-storage controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_dev_t eth_devices[] = {
+ {
+ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_RTL8029,
+ NULL, "NE2000", "NE2000 PCI", NULL,
+ 0, 0, 0,
+ NULL, "ethernet",
+ },
+ {
+ /* Virtio-network controller */
+ PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_NET,
+ NULL, "virtio-net", NULL,
+ "pci1af4,1000\0pci1af4,1000\0pciclass,020000\0",
+ 0, 0, 0,
+ NULL, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t net_subclass[] = {
+ {
+ PCI_SUBCLASS_NETWORK_ETHERNET, "ethernet controller",
+ NULL, eth_devices, NULL,
+ eth_config_cb, "ethernet",
+ },
+ {
+ PCI_SUBCLASS_NETWORK_TOKEN_RING, "token ring controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_NETWORK_FDDI, "FDDI controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_NETWORK_ATM, "ATM controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_NETWORK_ISDN, "ISDN controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_NETWORK_WORDFIP, "WordFip controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_NETWORK_PICMG214, "PICMG 2.14 controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_NETWORK_OTHER, "misc network controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_dev_t vga_devices[] = {
+ {
+ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF,
+ NULL, "ATY", "ATY Rage128", "VGA\0",
+ 0, 0, 0,
+ NULL, NULL,
+ },
+ {
+ PCI_VENDOR_ID_QEMU, PCI_DEVICE_ID_QEMU_VGA,
+ NULL, "QEMU,VGA", "Qemu VGA", "VGA\0",
+ 0, 0, 0,
+ NULL, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const struct pci_iface_t vga_iface[] = {
+ {
+ 0x00, "VGA controller", NULL,
+ vga_devices, &vga_config_cb, NULL,
+ },
+ {
+ 0x01, "8514 compatible controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_subclass_t displ_subclass[] = {
+ {
+ PCI_SUBCLASS_DISPLAY_VGA, "display controller",
+ NULL, NULL, vga_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_DISPLAY_XGA, "XGA display controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_DISPLAY_3D, "3D display controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_DISPLAY_OTHER, "misc display controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t media_subclass[] = {
+ {
+ PCI_SUBCLASS_MULTIMEDIA_VIDEO, "video device",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_MULTIMEDIA_AUDIO, "audio device",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_MULTIMEDIA_PHONE, "computer telephony device",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_MULTIMEDIA_OTHER, "misc multimedia device",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t mem_subclass[] = {
+ {
+ PCI_SUBCLASS_MEMORY_RAM, "RAM controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_MEMORY_FLASH, "flash controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+
+static const pci_dev_t hbrg_devices[] = {
+ {
+ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_U3_AGP, NULL,
+ "pci", "AAPL,UniNorth", "u3-agp\0",
+ 3, 2, 1,
+ host_config_cb, NULL,
+ },
+ {
+ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_AGP, NULL,
+ "pci", "AAPL,UniNorth", "uni-north\0",
+ 3, 2, 1,
+ host_config_cb, NULL,
+ },
+ {
+ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI, NULL,
+ "pci", "AAPL,UniNorth", "uni-north\0",
+ 3, 2, 1,
+ host_config_cb, NULL,
+ },
+ {
+ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_I_PCI, NULL,
+ "pci", "AAPL,UniNorth", "uni-north\0",
+ 3, 2, 1,
+ NULL, NULL
+ },
+ {
+ PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC106, "pci",
+ "pci", "MOT,MPC106", "grackle\0",
+ 3, 2, 1,
+ host_config_cb, NULL
+ },
+ {
+ PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_RAVEN, NULL,
+ "pci", "PREP Host PCI Bridge - Motorola Raven", NULL,
+ 3, 2, 1,
+ host_config_cb, NULL,
+ },
+ {
+ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SABRE, NULL,
+ "pci", "SUNW,sabre", "pci108e,a000\0pciclass,0\0",
+ 3, 2, 1,
+ sabre_config_cb, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_dev_t PCIbrg_devices[] = {
+ {
+ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21154, NULL,
+ "pci-bridge", "DEV,21154", "DEV,21154\0pci-bridge\0",
+ 3, 2, 1,
+ bridge_config_cb, NULL,
+ },
+ {
+ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA, NULL,
+ "pci", "SUNW,simba", "pci108e,5000\0pciclass,060400\0",
+ 3, 2, 1,
+ bridge_config_cb, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_dev_t miscbrg_devices[] = {
+ {
+ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL,
+ "ebus", "ebus", "pci108e,1000\0pciclass,068000\0",
+ 2, 1, 1,
+ ebus_config_cb, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_dev_t isabrg_devices[] = {
+ {
+ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, NULL,
+ "isa", "isa", "pci8086,484\0",
+ 1, 1, 1,
+ i82378_config_cb, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t bridg_subclass[] = {
+ {
+ PCI_SUBCLASS_BRIDGE_HOST, "PCI host bridge",
+ "pci", hbrg_devices, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_ISA, "ISA bridge",
+ "isa", isabrg_devices, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_EISA, "EISA bridge",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_MC, "MCA bridge",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_PCI, "PCI-to-PCI bridge",
+ "pci", PCIbrg_devices, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_PCMCIA, "PCMCIA bridge",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_NUBUS, "NUBUS bridge",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_CARDBUS, "cardbus bridge",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_RACEWAY, "raceway bridge",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_PCI_SEMITP, "semi-transparent PCI-to-PCI bridge",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_IB_PCI, "infiniband-to-PCI bridge",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_BRIDGE_OTHER, "misc PCI bridge",
+ NULL, miscbrg_devices, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_iface_t serial_iface[] = {
+ {
+ 0x00, "XT serial controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x01, "16450 serial controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x02, "16550 serial controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x03, "16650 serial controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x04, "16750 serial controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x05, "16850 serial controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x06, "16950 serial controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_iface_t par_iface[] = {
+ {
+ 0x00, "parallel port", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x01, "bi-directional parallel port", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x02, "ECP 1.x parallel port", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x03, "IEEE 1284 controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFE, "IEEE 1284 device", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_iface_t modem_iface[] = {
+ {
+ 0x00, "generic modem", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x01, "Hayes 16450 modem", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x02, "Hayes 16550 modem", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x03, "Hayes 16650 modem", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x04, "Hayes 16750 modem", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_subclass_t comm_subclass[] = {
+ {
+ PCI_SUBCLASS_COMMUNICATION_SERIAL, "serial controller",
+ NULL, NULL, serial_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_COMMUNICATION_PARALLEL, "parallel port",
+ NULL, NULL, par_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_COMMUNICATION_MULTISERIAL, "multiport serial controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_COMMUNICATION_MODEM, "modem",
+ NULL, NULL, modem_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_COMMUNICATION_GPIB, "GPIB controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_COMMUNICATION_SC, "smart card",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_COMMUNICATION_OTHER, "misc communication device",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_iface_t pic_iface[] = {
+ {
+ 0x00, "8259 PIC", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x01, "ISA PIC", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x02, "EISA PIC", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x10, "I/O APIC", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x20, "I/O APIC", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_iface_t dma_iface[] = {
+ {
+ 0x00, "8237 DMA controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x01, "ISA DMA controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x02, "EISA DMA controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_iface_t tmr_iface[] = {
+ {
+ 0x00, "8254 system timer", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x01, "ISA system timer", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x02, "EISA system timer", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_iface_t rtc_iface[] = {
+ {
+ 0x00, "generic RTC controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x01, "ISA RTC controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_dev_t sys_devices[] = {
+ /* IBM MPIC controller */
+ {
+ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OPENPIC,
+ "open-pic", "MPIC", NULL, "chrp,open-pic\0",
+ 0, 0, 2,
+ NULL, NULL,
+ },
+ /* IBM MPIC2 controller */
+ {
+ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OPENPIC2,
+ "open-pic", "MPIC2", NULL, "chrp,open-pic\0",
+ 0, 0, 2,
+ NULL, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t sys_subclass[] = {
+ {
+ PCI_SUBCLASS_SYSTEM_PIC, "PIC",
+ NULL, NULL, pic_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SYSTEM_DMA, "DMA controller",
+ NULL, NULL, dma_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SYSTEM_TIMER, "system timer",
+ NULL, NULL, tmr_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SYSTEM_RTC, "RTC controller",
+ NULL, NULL, rtc_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SYSTEM_PCI_HOTPLUG, "PCI hotplug controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SYSTEM_OTHER, "misc system peripheral",
+ NULL, sys_devices, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t inp_subclass[] = {
+ {
+ PCI_SUBCLASS_INPUT_KEYBOARD, "keyboard controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_INPUT_PEN, "digitizer",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_INPUT_MOUSE, "mouse controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_INPUT_SCANNER, "scanner controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_INPUT_GAMEPORT, "gameport controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_INPUT_OTHER, "misc input device",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t dock_subclass[] = {
+ {
+ PCI_SUBCLASS_DOCKING_GENERIC, "generic docking station",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_DOCKING_OTHER, "misc docking station",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t cpu_subclass[] = {
+ {
+ PCI_SUBCLASS_PROCESSOR_386, "i386 processor",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_PROCESSOR_486, "i486 processor",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_PROCESSOR_PENTIUM, "pentium processor",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_PROCESSOR_ALPHA, "alpha processor",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_PROCESSOR_POWERPC, "PowerPC processor",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_PROCESSOR_MIPS, "MIPS processor",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_PROCESSOR_CO, "co-processor",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_dev_t usb_devices[] = {
+#if defined(CONFIG_QEMU)
+ {
+ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_KEYL_USB,
+ "usb", "usb", NULL,
+ "pci106b,3f\0pciclass,0c0310\0",
+ 1, 0, 0,
+ NULL, NULL,
+ },
+#endif
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+static const pci_iface_t usb_iface[] = {
+ {
+ 0x00, "UHCI USB controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x10, "OHCI USB controller", NULL,
+ usb_devices, &usb_ohci_config_cb, NULL,
+ },
+ {
+ 0x20, "EHCI USB controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x80, "misc USB controller", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFE, "USB device", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_iface_t ipmi_iface[] = {
+ {
+ 0x00, "IPMI SMIC interface", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x01, "IPMI keyboard interface", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0x02, "IPMI block transfer interface", NULL,
+ NULL, NULL, NULL,
+ },
+ {
+ 0xFF, NULL, NULL,
+ NULL, NULL, NULL,
+ },
+};
+
+static const pci_subclass_t ser_subclass[] = {
+ {
+ PCI_SUBCLASS_SERIAL_FIREWIRE, "Firewire bus controller",
+ "ieee1394", NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_ACCESS, "ACCESS bus controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_SSA, "SSA controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_USB, "USB controller",
+ "usb", NULL, usb_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_FIBER, "fibre channel controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_SMBUS, "SMBus controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_IB, "InfiniBand controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_IPMI, "IPMI interface",
+ NULL, NULL, ipmi_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_SERCOS, "SERCOS controller",
+ NULL, NULL, ipmi_iface,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SERIAL_CANBUS, "CANbus controller",
+ NULL, NULL, ipmi_iface,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t wrl_subclass[] = {
+ {
+ PCI_SUBCLASS_WIRELESS_IRDA, "IRDA controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_WIRELESS_CIR, "consumer IR controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_WIRELESS_RF_CONTROLLER, "RF controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_WIRELESS_BLUETOOTH, "bluetooth controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_WIRELESS_BROADBAND, "broadband controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_WIRELESS_OTHER, "misc wireless controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t sat_subclass[] = {
+ {
+ PCI_SUBCLASS_SATELLITE_TV, "satellite TV controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SATELLITE_AUDIO, "satellite audio controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SATELLITE_VOICE, "satellite voice controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SATELLITE_DATA, "satellite data controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t crypt_subclass[] = {
+ {
+ PCI_SUBCLASS_CRYPT_NETWORK, "cryptographic network controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_CRYPT_ENTERTAINMENT,
+ "cryptographic entertainment controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_CRYPT_OTHER, "misc cryptographic controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_subclass_t spc_subclass[] = {
+ {
+ PCI_SUBCLASS_SP_DPIO, "DPIO module",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SP_PERF, "performances counters",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SP_SYNCH, "communication synchronisation",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SP_MANAGEMENT, "management card",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ PCI_SUBCLASS_SP_OTHER, "misc signal processing controller",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+ {
+ 0xFF, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL,
+ },
+};
+
+static const pci_class_t pci_classes[] = {
+ /* 0x00 */
+ { "undefined", NULL, undef_subclass, },
+ /* 0x01 */
+ { "mass-storage controller", NULL, mass_subclass, },
+ /* 0x02 */
+ { "network controller", "network", net_subclass, },
+ /* 0x03 */
+ { "display controller", "display", displ_subclass, },
+ /* 0x04 */
+ { "multimedia device", NULL, media_subclass, },
+ /* 0x05 */
+ { "memory controller", "memory-controller", mem_subclass, },
+ /* 0x06 */
+ { "PCI bridge", NULL, bridg_subclass, },
+ /* 0x07 */
+ { "communication device", NULL, comm_subclass,},
+ /* 0x08 */
+ { "system peripheral", NULL, sys_subclass, },
+ /* 0x09 */
+ { "input device", NULL, inp_subclass, },
+ /* 0x0A */
+ { "docking station", NULL, dock_subclass, },
+ /* 0x0B */
+ { "processor", NULL, cpu_subclass, },
+ /* 0x0C */
+ { "serial bus controller", NULL, ser_subclass, },
+ /* 0x0D */
+ { "wireless controller", NULL, wrl_subclass, },
+ /* 0x0E */
+ { "intelligent I/O controller", NULL, NULL, },
+ /* 0x0F */
+ { "satellite communication controller", NULL, sat_subclass, },
+ /* 0x10 */
+ { "cryptographic controller", NULL, crypt_subclass, },
+ /* 0x11 */
+ { "signal processing controller", NULL, spc_subclass, },
+};
+
+static const pci_dev_t misc_pci[] = {
+ /* Heathrow Mac I/O */
+ {
+ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_343S1201,
+ "mac-io", "mac-io", "AAPL,343S1201", "heathrow\0",
+ 1, 1, 1,
+ &macio_heathrow_config_cb, NULL,
+ },
+ /* Paddington Mac I/O */
+ {
+ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_343S1211,
+ "mac-io", "mac-io", "AAPL,343S1211", "paddington\0heathrow\0",
+ 1, 1, 1,
+ &macio_heathrow_config_cb, NULL,
+ },
+ /* KeyLargo Mac I/O */
+ {
+ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_KEYL,
+ "mac-io", "mac-io", "AAPL,Keylargo", "Keylargo\0",
+ 1, 1, 1,
+ &macio_keylargo_config_cb, NULL,
+ },
+ {
+ 0xFFFF, 0xFFFF,
+ NULL, NULL, NULL, NULL,
+ -1, -1, -1,
+ NULL, NULL,
+ },
+};
+
+const pci_dev_t *pci_find_device (uint8_t class, uint8_t subclass,
+ uint8_t iface, uint16_t vendor,
+ uint16_t product)
+{
+ int (*config_cb)(const pci_config_t *config);
+ const pci_class_t *pclass;
+ const pci_subclass_t *psubclass;
+ const pci_iface_t *piface;
+ const pci_dev_t *dev;
+ const void *private;
+ pci_dev_t *new;
+ const char *name, *type;
+
+ name = "unknown";
+ type = "unknown";
+ config_cb = NULL;
+ private = NULL;
+
+ if (class == 0x00 && subclass == 0x01) {
+ /* Special hack for old style VGA devices */
+ class = 0x03;
+ subclass = 0x00;
+ } else if (class == 0xFF) {
+ /* Special case for misc devices */
+ dev = misc_pci;
+ goto find_device;
+ }
+ if (class > (sizeof(pci_classes) / sizeof(pci_class_t))) {
+ name = "invalid PCI device";
+ type = "invalid";
+ goto bad_device;
+ }
+ pclass = &pci_classes[class];
+ name = pclass->name;
+ type = pclass->type;
+ for (psubclass = pclass->subc; ; psubclass++) {
+ if (psubclass->subclass == 0xFF)
+ goto bad_device;
+ if (psubclass->subclass == subclass) {
+ if (psubclass->name != NULL)
+ name = psubclass->name;
+ if (psubclass->type != NULL)
+ type = psubclass->type;
+ if (psubclass->config_cb != NULL) {
+ config_cb = psubclass->config_cb;
+ }
+ if (psubclass->private != NULL)
+ private = psubclass->private;
+ if (psubclass->iface != NULL)
+ break;
+ dev = psubclass->devices;
+ goto find_device;
+ }
+ }
+ for (piface = psubclass->iface; ; piface++) {
+ if (piface->iface == 0xFF) {
+ dev = psubclass->devices;
+ break;
+ }
+ if (piface->iface == iface) {
+ if (piface->name != NULL)
+ name = piface->name;
+ if (piface->type != NULL)
+ type = piface->type;
+ if (piface->config_cb != NULL) {
+ config_cb = piface->config_cb;
+ }
+ if (piface->private != NULL)
+ private = piface->private;
+ dev = piface->devices;
+ break;
+ }
+ }
+find_device:
+ if (dev == NULL)
+ goto bad_device;
+ for (;; dev++) {
+ if (dev->vendor == 0xFFFF && dev->product == 0xFFFF) {
+ goto bad_device;
+ }
+ if (dev->vendor == vendor && dev->product == product) {
+ if (dev->name != NULL)
+ name = dev->name;
+ if (dev->type != NULL)
+ type = dev->type;
+ if (dev->config_cb != NULL) {
+ config_cb = dev->config_cb;
+ }
+ if (dev->private != NULL)
+ private = dev->private;
+ new = malloc(sizeof(pci_dev_t));
+ if (new == NULL)
+ return NULL;
+ new->vendor = vendor;
+ new->product = product;
+ new->type = type;
+ new->name = name;
+ new->model = dev->model;
+ new->compat = dev->compat;
+ new->acells = dev->acells;
+ new->scells = dev->scells;
+ new->icells = dev->icells;
+ new->config_cb = config_cb;
+ new->private = private;
+
+ return new;
+ }
+ }
+bad_device:
+ printk("Cannot manage '%s' PCI device type '%s':\n %x %x (%x %x %x)\n",
+ name, type, vendor, product, class, subclass, iface);
+
+ return NULL;
+}
diff --git a/roms/openbios/drivers/pci_database.h b/roms/openbios/drivers/pci_database.h
new file mode 100644
index 00000000..7f053d80
--- /dev/null
+++ b/roms/openbios/drivers/pci_database.h
@@ -0,0 +1,57 @@
+typedef struct pci_config_t pci_config_t;
+
+struct pci_config_t {
+ char path[256];
+ uint32_t dev; /* bus, dev, fn */
+ uint32_t regions[7];
+ uint32_t assigned[7];
+ uint32_t sizes[7];
+ int irq_pin;
+ int irq_line;
+ u32 primary_bus;
+ u32 secondary_bus;
+ u32 subordinate_bus;
+};
+
+typedef struct pci_dev_t pci_dev_t;
+struct pci_dev_t {
+ uint16_t vendor;
+ uint16_t product;
+ const char *type;
+ const char *name;
+ const char *model;
+ const char *compat;
+ int acells;
+ int scells;
+ int icells;
+ int (*config_cb)(const pci_config_t *config);
+ const void *private;
+};
+
+extern int ide_config_cb2(const pci_config_t *config);
+extern int eth_config_cb(const pci_config_t *config);
+extern int macio_heathrow_config_cb(const pci_config_t *config);
+extern int macio_keylargo_config_cb(const pci_config_t *config);
+extern int vga_config_cb(const pci_config_t *config);
+extern int host_config_cb(const pci_config_t *config);
+extern int sabre_config_cb(const pci_config_t *config);
+extern int bridge_config_cb(const pci_config_t *config);
+extern int ebus_config_cb(const pci_config_t *config);
+extern int i82378_config_cb(const pci_config_t *config);
+extern int usb_ohci_config_cb(const pci_config_t *config);
+
+static inline int pci_compat_len(const pci_dev_t *dev)
+{
+ int len, ret;
+ const char *path = dev->compat;
+ ret = 0;
+ while ((len = strlen(path)) != 0) {
+ ret += len + 1;
+ path += len + 1;
+ }
+ return ret;
+}
+
+extern const pci_dev_t *pci_find_device(uint8_t class, uint8_t subclass,
+ uint8_t iface, uint16_t vendor,
+ uint16_t product);
diff --git a/roms/openbios/drivers/sbus.c b/roms/openbios/drivers/sbus.c
new file mode 100644
index 00000000..a9b26c0a
--- /dev/null
+++ b/roms/openbios/drivers/sbus.c
@@ -0,0 +1,523 @@
+/*
+ * OpenBIOS SBus driver
+ *
+ * (C) 2004 Stefan Reinauer <stepan@openbios.org>
+ * (C) 2005 Ed Schouten <ed@fxq.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "kernel/kernel.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "drivers/drivers.h"
+#include "libopenbios/ofmem.h"
+#include "libopenbios/video.h"
+
+#define SBUS_REGS 0x28
+#define SBUS_SLOTS 16
+#define APC_REGS 0x10
+#define APC_OFFSET 0x0a000000ULL
+#define CS4231_REGS 0x40
+#define CS4231_OFFSET 0x0c000000ULL
+#define MACIO_ESPDMA 0x00400000ULL /* ESP DMA controller */
+#define MACIO_ESP 0x00800000ULL /* ESP SCSI */
+#define SS600MP_ESPDMA 0x00081000ULL
+#define SS600MP_ESP 0x00080000ULL
+#define SS600MP_LEBUFFER (SS600MP_ESPDMA + 0x10) // XXX should be 0x40000
+#define LEDMA_REGS 0x4
+#define LE_REGS 0x20
+
+#ifdef CONFIG_DEBUG_SBUS
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+typedef struct le_private {
+ uint32_t *dmaregs;
+ uint32_t *regs;
+} le_private_t;
+
+static void
+ob_sbus_node_init(uint64_t base)
+{
+ void *regs;
+
+ push_str("/iommu/sbus");
+ fword("find-device");
+
+ PUSH(base >> 32);
+ fword("encode-int");
+ PUSH(base & 0xffffffff);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(SBUS_REGS);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ regs = (void *)ofmem_map_io(base, SBUS_REGS);
+ PUSH((unsigned long)regs);
+ fword("encode-int");
+ push_str("address");
+ fword("property");
+}
+
+static void
+ob_le_init(unsigned int slot, uint64_t base, unsigned long leoffset, unsigned long dmaoffset)
+{
+ le_private_t *le;
+
+ le = malloc(sizeof(le_private_t));
+ if (!le) {
+ DPRINTF("Can't allocate LANCE private structure\n");
+ return;
+ }
+
+ /* Get the IO region for DMA registers */
+ le->dmaregs = (void *)ofmem_map_io(base + (uint64_t)dmaoffset, LEDMA_REGS);
+ if (le->dmaregs == NULL) {
+ DPRINTF("Can't map LANCE DMA registers\n");
+ return;
+ }
+
+ /* Now it appears that the Solaris kernel forgets to set up the LANCE DMA mapping
+ and so it must inherit the one from OpenBIOS. The symptom of this is that the
+ LANCE DMA base addr register is still zero, and so we start sending network
+ packets containing random areas of memory.
+
+ The correct fix for this should be to use dvma_alloc() to grab a section of
+ memory and point the LANCE DMA buffers to use that instead; this gets
+ slightly further but still crashes. Time-consuming investigation on various
+ hacked versions of QEMU seems to indicate that Solaris always assumes the LANCE
+ DMA base address is fixed 0xff000000 when setting up the IOMMU for the LANCE
+ card. Hence we imitate this behaviour here. */
+ le->dmaregs[3] = 0xff000000;
+
+ push_str("/iommu/sbus/ledma");
+ fword("find-device");
+ PUSH(slot);
+ fword("encode-int");
+ PUSH(dmaoffset);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x00000020);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ /* Get the IO region for Lance registers */
+ le->regs = (void *)ofmem_map_io(base + (uint64_t)leoffset, LE_REGS);
+ if (le->regs == NULL) {
+ DPRINTF("Can't map LANCE registers\n");
+ return;
+ }
+
+ push_str("/iommu/sbus/ledma/le");
+ fword("find-device");
+ PUSH(slot);
+ fword("encode-int");
+ PUSH(leoffset);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(0x00000004);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+}
+
+uint16_t graphic_depth;
+
+static void
+ob_tcx_init(unsigned int slot, const char *path)
+{
+ char buf[6];
+
+ printk("No display device located during SBus probe - falling back to internal TCX driver\n");
+
+ /* Make the sbus node the current instance and active package for probing */
+ feval("active-package my-self");
+ push_str("/iommu/sbus");
+ feval("2dup find-device open-dev to my-self");
+
+ fword("new-device");
+ PUSH(0);
+ PUSH(0);
+ snprintf(buf, 6, "%x,0", slot);
+ push_str(buf);
+ fword("set-args");
+ feval("['] tcx-driver-fcode 2 cells + 1 byte-load");
+ fword("finish-device");
+
+ /* Restore */
+ feval("to my-self active-package!");
+}
+
+static void
+ob_apc_init(unsigned int slot, unsigned long base)
+{
+ push_str("/iommu/sbus");
+ fword("find-device");
+ fword("new-device");
+
+ push_str("power-management");
+ fword("device-name");
+
+ PUSH(slot);
+ fword("encode-int");
+ PUSH(base);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(APC_REGS);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ fword("finish-device");
+}
+
+static void
+ob_cs4231_init(unsigned int slot)
+{
+ push_str("/iommu/sbus");
+ fword("find-device");
+ fword("new-device");
+
+ push_str("SUNW,CS4231");
+ fword("device-name");
+
+ push_str("serial");
+ fword("device-type");
+
+ PUSH(slot);
+ fword("encode-int");
+ PUSH(CS4231_OFFSET);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(CS4231_REGS);
+ fword("encode-int");
+ fword("encode+");
+ push_str("reg");
+ fword("property");
+
+ PUSH(5);
+ fword("encode-int");
+ PUSH(0);
+ fword("encode-int");
+ fword("encode+");
+ push_str("intr");
+ fword("property");
+
+ PUSH(5);
+ fword("encode-int");
+ push_str("interrupts");
+ fword("property");
+
+ push_str("audio");
+ fword("encode-string");
+ push_str("alias");
+ fword("property");
+
+ fword("finish-device");
+}
+
+static void
+ob_macio_init(unsigned int slot, uint64_t base, unsigned long offset)
+{
+ // All devices were integrated to NCR89C100, see
+ // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
+
+ // NCR 53c9x, aka ESP. See
+ // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
+#ifdef CONFIG_DRIVER_ESP
+ ob_esp_init(slot, base, offset + MACIO_ESP, offset + MACIO_ESPDMA);
+#endif
+
+ // NCR 92C990, Am7990, Lance. See http://www.amd.com
+ ob_le_init(slot, base, offset + 0x00c00000, offset + 0x00400010);
+
+ // Parallel port
+ //ob_bpp_init(base);
+}
+
+static void
+sbus_probe_self(unsigned int slot, unsigned long offset)
+{
+ /* Wrapper for calling probe-self in Forth. This is mainly because some
+ drivers don't handle properties correctly when the sbus node is set
+ as the current instance during probe. */
+ char buf[6];
+
+ printk("Probing SBus slot %d offset %ld\n", slot, offset);
+
+ /* Make the sbus node the current instance and active package for probing */
+ feval("active-package my-self");
+ push_str("/iommu/sbus");
+ feval("open-dev to my-self");
+
+ PUSH(0);
+ PUSH(0);
+ snprintf(buf, 6, "%x,%lx", slot, offset);
+ push_str(buf);
+ fword("2dup");
+ fword("probe-self-sbus");
+
+ /* Restore */
+ feval("to my-self active-package!");
+}
+
+static int
+sbus_probe_sucess(void)
+{
+ /* Return true if the last sbus_probe_self() resulted in
+ the successful detection and execution of FCode */
+ fword("probe-fcode?");
+ return POP();
+}
+
+static void
+sbus_probe_slot_ss5(unsigned int slot, uint64_t base)
+{
+ /* Probe the slot */
+ sbus_probe_self(slot, 0);
+
+ /* If the device was successfully created by FCode then do nothing */
+ if (sbus_probe_sucess()) {
+ return;
+ }
+
+ switch(slot) {
+ case 3: // SUNW,tcx
+ ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
+ break;
+ case 4:
+ // SUNW,CS4231
+ ob_cs4231_init(slot);
+ // Power management (APC)
+ ob_apc_init(slot, APC_OFFSET);
+ break;
+ case 5: // MACIO: le, esp, bpp
+ ob_macio_init(slot, base, 0x08000000);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+sbus_probe_slot_ss10(unsigned int slot, uint64_t base)
+{
+ /* Probe the slot */
+ sbus_probe_self(slot, 0);
+
+ /* If the device was successfully created by FCode then do nothing */
+ if (sbus_probe_sucess()) {
+ return;
+ }
+
+ switch(slot) {
+ case 2: // SUNW,tcx
+ ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
+ break;
+ case 0xf: // le, esp, bpp, power-management
+ ob_macio_init(slot, base, 0);
+ // Power management (APC) XXX should not exist
+ ob_apc_init(slot, APC_OFFSET);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+sbus_probe_slot_ss600mp(unsigned int slot, uint64_t base)
+{
+ /* Probe the slot */
+ sbus_probe_self(slot, 0);
+
+ /* If the device was successfully created by FCode then do nothing */
+ if (sbus_probe_sucess()) {
+ return;
+ }
+
+ switch(slot) {
+ case 2: // SUNW,tcx
+ ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
+ break;
+ case 0xf: // le, esp, bpp, power-management
+#ifdef CONFIG_DRIVER_ESP
+ ob_esp_init(slot, base, SS600MP_ESP, SS600MP_ESPDMA);
+#endif
+ // NCR 92C990, Am7990, Lance. See http://www.amd.com
+ ob_le_init(slot, base, 0x00060000, SS600MP_LEBUFFER);
+ // Power management (APC) XXX should not exist
+ ob_apc_init(slot, APC_OFFSET);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ob_sbus_open(void)
+{
+ int ret=1;
+ RET ( -ret );
+}
+
+static void
+ob_sbus_close(void)
+{
+ selfword("close-deblocker");
+}
+
+static void
+ob_sbus_initialize(void)
+{
+}
+
+
+NODE_METHODS(ob_sbus_node) = {
+ { NULL, ob_sbus_initialize },
+ { "open", ob_sbus_open },
+ { "close", ob_sbus_close },
+};
+
+struct sbus_offset {
+ int slot, type;
+ uint64_t base;
+ unsigned long size;
+};
+
+static const struct sbus_offset sbus_offsets_ss5[SBUS_SLOTS] = {
+ { 0, 0, 0x20000000, 0x10000000,},
+ { 1, 0, 0x30000000, 0x10000000,},
+ { 2, 0, 0x40000000, 0x10000000,},
+ { 3, 0, 0x50000000, 0x10000000,},
+ { 4, 0, 0x60000000, 0x10000000,},
+ { 5, 0, 0x70000000, 0x10000000,},
+};
+
+/* Shared with ss600mp */
+static const struct sbus_offset sbus_offsets_ss10[SBUS_SLOTS] = {
+ { 0, 0, 0xe00000000ULL, 0x10000000,},
+ { 1, 0, 0xe10000000ULL, 0x10000000,},
+ { 2, 0, 0xe20000000ULL, 0x10000000,},
+ { 3, 0, 0xe30000000ULL, 0x10000000,},
+ [0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,},
+};
+
+static void
+ob_add_sbus_range(const struct sbus_offset *range, int notfirst)
+{
+ if (!notfirst) {
+ push_str("/iommu/sbus");
+ fword("find-device");
+ }
+ PUSH(range->slot);
+ fword("encode-int");
+ if (notfirst)
+ fword("encode+");
+ PUSH(range->type);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(range->base >> 32);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(range->base & 0xffffffff);
+ fword("encode-int");
+ fword("encode+");
+ PUSH(range->size);
+ fword("encode-int");
+ fword("encode+");
+}
+
+static int
+ob_sbus_init_ss5(void)
+{
+ unsigned int slot;
+ int notfirst = 0;
+
+ for (slot = 0; slot < SBUS_SLOTS; slot++) {
+ if (sbus_offsets_ss5[slot].size > 0)
+ ob_add_sbus_range(&sbus_offsets_ss5[slot], notfirst++);
+ }
+ push_str("ranges");
+ fword("property");
+
+ for (slot = 0; slot < SBUS_SLOTS; slot++) {
+ if (sbus_offsets_ss5[slot].size > 0)
+ sbus_probe_slot_ss5(slot, sbus_offsets_ss5[slot].base);
+ }
+
+ return 0;
+}
+
+static int
+ob_sbus_init_ss10(void)
+{
+ unsigned int slot;
+ int notfirst = 0;
+
+ for (slot = 0; slot < SBUS_SLOTS; slot++) {
+ if (sbus_offsets_ss10[slot].size > 0)
+ ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++);
+ }
+ push_str("ranges");
+ fword("property");
+
+ for (slot = 0; slot < SBUS_SLOTS; slot++) {
+ if (sbus_offsets_ss10[slot].size > 0)
+ sbus_probe_slot_ss10(slot, sbus_offsets_ss10[slot].base);
+ }
+
+ return 0;
+}
+
+static int
+ob_sbus_init_ss600mp(void)
+{
+ unsigned int slot;
+ int notfirst = 0;
+
+ for (slot = 0; slot < SBUS_SLOTS; slot++) {
+ if (sbus_offsets_ss10[slot].size > 0)
+ ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++);
+ }
+ push_str("ranges");
+ fword("property");
+
+ for (slot = 0; slot < SBUS_SLOTS; slot++) {
+ if (sbus_offsets_ss10[slot].size > 0)
+ sbus_probe_slot_ss600mp(slot, sbus_offsets_ss10[slot].base);
+ }
+
+ return 0;
+}
+
+int ob_sbus_init(uint64_t base, int machine_id)
+{
+ ob_sbus_node_init(base);
+
+ switch (machine_id) {
+ case 66:
+ return ob_sbus_init_ss600mp();
+ case 64 ... 65:
+ return ob_sbus_init_ss10();
+ case 32 ... 63:
+ return ob_sbus_init_ss5();
+ default:
+ return -1;
+ }
+}
diff --git a/roms/openbios/drivers/sbus.fs b/roms/openbios/drivers/sbus.fs
new file mode 100644
index 00000000..b84a3ac7
--- /dev/null
+++ b/roms/openbios/drivers/sbus.fs
@@ -0,0 +1,94 @@
+\ -------------------------------------------------------------------------
+\ SBus encode/decode unit
+\ -------------------------------------------------------------------------
+
+: decode-unit-sbus ( str len -- id lun )
+ ascii , left-split
+ ( addr-R len-R addr-L len-L )
+ parse-hex
+ -rot parse-hex
+ swap
+;
+
+: encode-unit-sbus ( id lun -- str len)
+ swap
+ pocket tohexstr
+ " ," pocket tmpstrcat >r
+ rot pocket tohexstr r> tmpstrcat drop
+;
+
+\ Convert sbus unit (from decode-unit) to physical address using
+\ sbus node ranges property
+
+: sbus-unit>addr ( phys.lo phys.hi -- phys.lo phys.hi -1 | 0 )
+ " ranges" my-self ihandle>phandle
+ get-package-property 0= if ( phys.lo phys.hi prop prop-len )
+ begin
+ 2over swap drop 0 swap \ force phys.lo to zero for matching
+ 2swap ( unit.phys.lo unit.phys.hi 0 phys.hi res prop prop-len )
+ 0 -rot ( unit.phys.lo unit.phys.hi res prop prop-len )
+ 2 0 do
+ decode-int -rot >r >r ( unit.phys.lo unit.phys.hi res phys.x -- R: prop-len prop )
+ rot ( unit.phys.lo res phys.x phys.hi )
+ = if
+ 1+
+ then ( unit.phys.lo res )
+ r> r> ( unit.phys.lo res prop prop-len )
+ loop
+ rot ( prop prop-len res )
+ 2 = if \ did we match the unit address? if so, return the physical address
+ decode-phys 2swap 2drop 2swap ( unit.phys.lo unit.phys.hi phys.lo phys.hi )
+ drop 0 d+ \ force unit.phys.hi to zero and add address for final offset
+ -1 exit
+ else
+ decode-phys 2drop decode-int drop \ drop the size and carry on
+ then
+ dup 0= until
+ 2drop 2drop 0
+ then
+;
+
+: map-in-sbus ( phys.lo phys.hi size )
+ >r sbus-unit>addr if
+ r@ " map-in" $call-parent
+ then
+ r> drop
+;
+
+: map-out-sbus ( virt size )
+ " map-out" $call-parent
+;
+
+\ -------------------------------------------------------------------------
+\ SBus probe
+\ -------------------------------------------------------------------------
+
+: probe-self-sbus ( arg-adr arg-len reg-adr reg-len fcode-adr fcode-len -- )
+
+ 0 to probe-fcode?
+
+ ['] decode-unit-sbus catch if
+ 2drop 2drop 2drop 2drop
+ exit
+ then
+
+ h# 10000 map-in-sbus
+
+ dup cpeek if
+ dup h# f1 = swap h# fd = or if
+ new-device
+ >r set-args r>
+ dup 1 byte-load
+ finish-device
+
+ -1 to probe-fcode?
+ else
+ nip nip nip nip
+ ." Invalid FCode start byte" cr
+ then
+ else
+ nip nip nip nip
+ then
+
+ h# 10000 map-out-sbus
+;
diff --git a/roms/openbios/drivers/scsi.h b/roms/openbios/drivers/scsi.h
new file mode 100644
index 00000000..cb975fc7
--- /dev/null
+++ b/roms/openbios/drivers/scsi.h
@@ -0,0 +1,262 @@
+#ifndef _LINUX_SCSI_H
+#define _LINUX_SCSI_H
+
+/*
+ * This header file contains public constants and structures used by
+ * the scsi code for linux.
+ */
+
+/*
+ $Header: /usr/src/linux/include/linux/RCS/scsi.h,v 1.3 1993/09/24 12:20:33 drew Exp $
+
+ For documentation on the OPCODES, MESSAGES, and SENSE values,
+ please consult the SCSI standard.
+
+*/
+
+/*
+ * SCSI opcodes
+ */
+
+#define TEST_UNIT_READY 0x00
+#define REZERO_UNIT 0x01
+#define REQUEST_SENSE 0x03
+#define FORMAT_UNIT 0x04
+#define READ_BLOCK_LIMITS 0x05
+#define REASSIGN_BLOCKS 0x07
+#define READ_6 0x08
+#define WRITE_6 0x0a
+#define SEEK_6 0x0b
+#define READ_REVERSE 0x0f
+#define WRITE_FILEMARKS 0x10
+#define SPACE 0x11
+#define INQUIRY 0x12
+#define RECOVER_BUFFERED_DATA 0x14
+#define MODE_SELECT 0x15
+#define RESERVE 0x16
+#define RELEASE 0x17
+#define COPY 0x18
+#define ERASE 0x19
+#define MODE_SENSE 0x1a
+#define START_STOP 0x1b
+#define RECEIVE_DIAGNOSTIC 0x1c
+#define SEND_DIAGNOSTIC 0x1d
+#define ALLOW_MEDIUM_REMOVAL 0x1e
+
+#define SET_WINDOW 0x24
+#define READ_CAPACITY 0x25
+#define READ_10 0x28
+#define WRITE_10 0x2a
+#define SEEK_10 0x2b
+#define WRITE_VERIFY 0x2e
+#define VERIFY 0x2f
+#define SEARCH_HIGH 0x30
+#define SEARCH_EQUAL 0x31
+#define SEARCH_LOW 0x32
+#define SET_LIMITS 0x33
+#define PRE_FETCH 0x34
+#define READ_POSITION 0x34
+#define SYNCHRONIZE_CACHE 0x35
+#define LOCK_UNLOCK_CACHE 0x36
+#define READ_DEFECT_DATA 0x37
+#define MEDIUM_SCAN 0x38
+#define COMPARE 0x39
+#define COPY_VERIFY 0x3a
+#define WRITE_BUFFER 0x3b
+#define READ_BUFFER 0x3c
+#define UPDATE_BLOCK 0x3d
+#define READ_LONG 0x3e
+#define WRITE_LONG 0x3f
+#define CHANGE_DEFINITION 0x40
+#define WRITE_SAME 0x41
+#define READ_TOC 0x43
+#define LOG_SELECT 0x4c
+#define LOG_SENSE 0x4d
+#define MODE_SELECT_10 0x55
+#define RESERVE_10 0x56
+#define RELEASE_10 0x57
+#define MODE_SENSE_10 0x5a
+#define PERSISTENT_RESERVE_IN 0x5e
+#define PERSISTENT_RESERVE_OUT 0x5f
+#define REPORT_LUNS 0xa0
+#define MOVE_MEDIUM 0xa5
+#define READ_12 0xa8
+#define WRITE_12 0xaa
+#define WRITE_VERIFY_12 0xae
+#define SEARCH_HIGH_12 0xb0
+#define SEARCH_EQUAL_12 0xb1
+#define SEARCH_LOW_12 0xb2
+#define READ_ELEMENT_STATUS 0xb8
+#define SEND_VOLUME_TAG 0xb6
+#define WRITE_LONG_2 0xea
+#define READ_16 0x88
+#define WRITE_16 0x8a
+#define VERIFY_16 0x8f
+#define SERVICE_ACTION_IN 0x9e
+/* values for service action in */
+#define SAI_READ_CAPACITY_16 0x10
+
+#define SCSI_RETRY_10(c) ((c) == READ_6 || (c) == WRITE_6 || (c) == SEEK_6)
+
+/*
+ * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
+ * T10/1561-D Revision 4 Draft dated 7th November 2002.
+ */
+#define SAM_STAT_GOOD 0x00
+#define SAM_STAT_CHECK_CONDITION 0x02
+#define SAM_STAT_CONDITION_MET 0x04
+#define SAM_STAT_BUSY 0x08
+#define SAM_STAT_INTERMEDIATE 0x10
+#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14
+#define SAM_STAT_RESERVATION_CONFLICT 0x18
+#define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */
+#define SAM_STAT_TASK_SET_FULL 0x28
+#define SAM_STAT_ACA_ACTIVE 0x30
+#define SAM_STAT_TASK_ABORTED 0x40
+
+/*
+ * Status codes
+ */
+
+#define GOOD 0x00
+#define CHECK_CONDITION 0x01
+#define CONDITION_GOOD 0x02
+#define BUSY 0x04
+#define INTERMEDIATE_GOOD 0x08
+#define INTERMEDIATE_C_GOOD 0x0a
+#define RESERVATION_CONFLICT 0x0c
+#define COMMAND_TERMINATED 0x11
+#define QUEUE_FULL 0x14
+
+#define STATUS_MASK 0x3e
+
+/*
+ * SENSE KEYS
+ */
+
+#define NO_SENSE 0x00
+#define RECOVERED_ERROR 0x01
+#define NOT_READY 0x02
+#define MEDIUM_ERROR 0x03
+#define HARDWARE_ERROR 0x04
+#define ILLEGAL_REQUEST 0x05
+#define UNIT_ATTENTION 0x06
+#define DATA_PROTECT 0x07
+#define BLANK_CHECK 0x08
+#define COPY_ABORTED 0x0a
+#define ABORTED_COMMAND 0x0b
+#define VOLUME_OVERFLOW 0x0d
+#define MISCOMPARE 0x0e
+
+
+/*
+ * DEVICE TYPES
+ */
+
+#define TYPE_DISK 0x00
+#define TYPE_TAPE 0x01
+#define TYPE_PRINTER 0x02
+#define TYPE_PROCESSOR 0x03 /* HP scanners use this */
+#define TYPE_WORM 0x04 /* Treated as ROM by our system */
+#define TYPE_ROM 0x05
+#define TYPE_SCANNER 0x06
+#define TYPE_MOD 0x07 /* Magneto-optical disk -
+ * - treated as TYPE_DISK */
+#define TYPE_MEDIUM_CHANGER 0x08
+#define TYPE_COMM 0x09 /* Communications device */
+#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
+#define TYPE_NO_LUN 0x7f
+
+/*
+ * standard mode-select header prepended to all mode-select commands
+ *
+ * moved here from cdrom.h -- kraxel
+ */
+
+struct ccs_modesel_head
+{
+ uint8_t _r1; /* reserved */
+ uint8_t medium; /* device-specific medium type */
+ uint8_t _r2; /* reserved */
+ uint8_t block_desc_length; /* block descriptor length */
+ uint8_t density; /* device-specific density code */
+ uint8_t number_blocks_hi; /* number of blocks in this block desc */
+ uint8_t number_blocks_med;
+ uint8_t number_blocks_lo;
+ uint8_t _r3;
+ uint8_t block_length_hi; /* block length for blocks in this desc */
+ uint8_t block_length_med;
+ uint8_t block_length_lo;
+};
+
+/*
+ * MESSAGE CODES
+ */
+
+#define COMMAND_COMPLETE 0x00
+#define EXTENDED_MESSAGE 0x01
+#define EXTENDED_MODIFY_DATA_POINTER 0x00
+#define EXTENDED_SDTR 0x01
+#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */
+#define EXTENDED_WDTR 0x03
+#define SAVE_POINTERS 0x02
+#define RESTORE_POINTERS 0x03
+#define DISCONNECT 0x04
+#define INITIATOR_ERROR 0x05
+#define ABORT 0x06
+#define MESSAGE_REJECT 0x07
+#define NOP 0x08
+#define MSG_PARITY_ERROR 0x09
+#define LINKED_CMD_COMPLETE 0x0a
+#define LINKED_FLG_CMD_COMPLETE 0x0b
+#define BUS_DEVICE_RESET 0x0c
+
+#define INITIATE_RECOVERY 0x0f /* SCSI-II only */
+#define RELEASE_RECOVERY 0x10 /* SCSI-II only */
+
+#define SIMPLE_QUEUE_TAG 0x20
+#define HEAD_OF_QUEUE_TAG 0x21
+#define ORDERED_QUEUE_TAG 0x22
+
+/*
+ * Here are some scsi specific ioctl commands which are sometimes useful.
+ */
+/* These are a few other constants only used by scsi devices */
+/* Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395 */
+
+#define SCSI_IOCTL_GET_IDLUN 0x5382 /* conflicts with CDROMAUDIOBUFSIZ */
+
+/* Used to turn on and off tagged queuing for scsi devices */
+
+#define SCSI_IOCTL_TAGGED_ENABLE 0x5383
+#define SCSI_IOCTL_TAGGED_DISABLE 0x5384
+
+/* Used to obtain the host number of a device. */
+#define SCSI_IOCTL_PROBE_HOST 0x5385
+
+/* Used to get the bus number for a device */
+#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386
+
+/* Used to get the PCI location of a device */
+#define SCSI_IOCTL_GET_PCI 0x5387
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
+
+#endif
diff --git a/roms/openbios/drivers/tcx.fs b/roms/openbios/drivers/tcx.fs
new file mode 100644
index 00000000..af8991fd
--- /dev/null
+++ b/roms/openbios/drivers/tcx.fs
@@ -0,0 +1,280 @@
+\
+\ Fcode payload for QEMU TCX graphics card
+\
+\ This is the Forth source for an Fcode payload to initialise
+\ the QEMU TCX graphics card.
+\
+\ (C) Copyright 2013 Mark Cave-Ayland
+\
+
+fcode-version3
+
+\
+\ Instead of using fixed values for the framebuffer address and the width
+\ and height, grab the ones passed in by QEMU/generated by OpenBIOS
+\
+
+: (find-xt) \ ( str len -- xt | -1 )
+ $find if
+ exit
+ else
+ 2drop
+ -1
+ then
+;
+
+: (is-openbios) \ ( -- true | false )
+ " openbios-video-width" (find-xt) -1 <> if
+ -1
+ else
+ 0
+ then
+;
+
+" openbios-video-width" (find-xt) cell+ value openbios-video-width-xt
+" openbios-video-height" (find-xt) cell+ value openbios-video-height-xt
+" depth-bits" (find-xt) cell+ value depth-bits-xt
+" line-bytes" (find-xt) cell+ value line-bytes-xt
+
+: openbios-video-width
+ (is-openbios) if
+ openbios-video-width-xt @
+ else
+ h# 400
+ then
+;
+
+: openbios-video-height
+ (is-openbios) if
+ openbios-video-height-xt @
+ else
+ h# 300
+ then
+;
+
+: depth-bits
+ (is-openbios) if
+ depth-bits-xt @
+ else
+ h# 8
+ then
+;
+
+: line-bytes
+ (is-openbios) if
+ line-bytes-xt @
+ else
+ h# 400
+ then
+;
+
+\
+\ Registers
+\
+
+h# 0 constant tcx-off-rom
+h# 10000 constant /tcx-off-rom
+
+h# 200000 constant tcx-off-cmap
+h# 4000 constant /tcx-off-cmap-24
+h# 4 constant /tcx-off-cmap-8
+
+h# 240000 constant tcx-off-dhc
+h# 4000 constant /tcx-off-dhc-24
+h# 4 constant /tcx-off-dhc-8
+
+h# 280000 constant tcx-off-alt
+h# 8000 constant /tcx-off-alt-24
+h# 1 constant /tcx-off-alt-8
+
+h# 301000 constant tcx-off-thc-24
+h# 300000 constant tcx-off-thc-8
+h# 1000 constant /tcx-off-thc-24
+h# 81c constant /tcx-off-thc-8
+
+h# 701000 constant tcx-off-tec
+h# 1000 constant /tcx-off-tec
+
+h# 800000 constant tcx-off-dfb8
+h# 100000 constant /tcx-off-dfb8
+
+h# 2000000 constant tcx-off-dfb24
+h# 400000 constant /tcx-off-dfb24-24
+h# 1 constant /tcx-off-dfb24-8
+
+h# 4000000 constant tcx-off-stip
+h# 800000 constant /tcx-off-stip
+
+h# 6000000 constant tcx-off-blit
+h# 800000 constant /tcx-off-blit
+
+h# a000000 constant tcx-off-rdfb32
+h# 400000 constant /tcx-off-rdfb32-24
+h# 1 constant /tcx-off-rdfb32-8
+
+h# c000000 constant tcx-off-rstip
+h# 800000 constant /tcx-off-rstip-24
+h# 1 constant /tcx-off-rstip-8
+
+h# e000000 constant tcx-off-rblit
+h# 800000 constant /tcx-off-rblit-24
+h# 1 constant /tcx-off-rblit-8
+
+: >tcx-reg-spec ( offset size -- encoded-reg )
+ >r 0 my-address d+ my-space encode-phys r> encode-int encode+
+;
+
+: tcx-8bit-reg
+ \ WARNING: order is important (at least to Solaris)
+ tcx-off-dfb8 /tcx-off-dfb8 >tcx-reg-spec
+ tcx-off-dfb24 /tcx-off-dfb24-8 >tcx-reg-spec encode+
+ tcx-off-stip /tcx-off-stip >tcx-reg-spec encode+
+ tcx-off-blit /tcx-off-blit >tcx-reg-spec encode+
+ tcx-off-rdfb32 /tcx-off-rdfb32-8 >tcx-reg-spec encode+
+ tcx-off-rstip /tcx-off-rstip-8 >tcx-reg-spec encode+
+ tcx-off-rblit /tcx-off-rblit-8 >tcx-reg-spec encode+
+ tcx-off-tec /tcx-off-tec >tcx-reg-spec encode+
+ tcx-off-cmap /tcx-off-cmap-8 >tcx-reg-spec encode+
+ tcx-off-thc-8 /tcx-off-thc-8 >tcx-reg-spec encode+
+ tcx-off-rom /tcx-off-rom >tcx-reg-spec encode+
+ tcx-off-dhc /tcx-off-dhc-8 >tcx-reg-spec encode+
+ tcx-off-alt /tcx-off-alt-8 >tcx-reg-spec encode+
+ " reg" property
+;
+
+: tcx-24bit-reg
+ \ WARNING: order is important (at least to Solaris)
+ tcx-off-dfb8 /tcx-off-dfb8 >tcx-reg-spec
+ tcx-off-dfb24 /tcx-off-dfb24-24 >tcx-reg-spec encode+
+ tcx-off-stip /tcx-off-stip >tcx-reg-spec encode+
+ tcx-off-blit /tcx-off-blit >tcx-reg-spec encode+
+ tcx-off-rdfb32 /tcx-off-rdfb32-24 >tcx-reg-spec encode+
+ tcx-off-rstip /tcx-off-rstip-24 >tcx-reg-spec encode+
+ tcx-off-rblit /tcx-off-rblit-24 >tcx-reg-spec encode+
+ tcx-off-tec /tcx-off-tec >tcx-reg-spec encode+
+ tcx-off-cmap /tcx-off-cmap-24 >tcx-reg-spec encode+
+ tcx-off-thc-24 /tcx-off-thc-24 >tcx-reg-spec encode+
+ tcx-off-rom /tcx-off-rom >tcx-reg-spec encode+
+ tcx-off-dhc /tcx-off-dhc-24 >tcx-reg-spec encode+
+ tcx-off-alt /tcx-off-alt-24 >tcx-reg-spec encode+
+ " reg" property
+;
+
+: do-map-in ( offset size -- virt )
+ >r my-space r> " map-in" $call-parent
+;
+
+: do-map-out ( virt size )
+ " map-out" $call-parent
+;
+
+\
+\ DAC
+\
+
+-1 value tcx-dac
+-1 value /tcx-dac
+-1 value fb-addr
+
+: dac! ( data reg# -- )
+ >r dup 2dup bljoin r> tcx-dac + l!
+;
+
+external
+
+: color! ( r g b c# -- )
+ 0 dac! ( r g b )
+ swap rot ( b g r )
+ 4 dac! ( b g )
+ 4 dac! ( b )
+ 4 dac! ( )
+;
+
+headerless
+
+\
+\ Mapping
+\
+
+: dac-map
+ tcx-off-cmap /tcx-dac do-map-in to tcx-dac
+;
+
+: fb-map
+ tcx-off-dfb8 h# c0000 do-map-in to fb-addr
+;
+
+: map-regs
+ dac-map fb-map
+;
+
+\
+\ Installation
+\
+
+" SUNW,tcx" device-name
+" display" device-type
+
+: qemu-tcx-driver-install ( -- )
+ tcx-dac -1 = if
+ map-regs
+
+ \ Initial pallette taken from Sun's "Writing FCode Programs"
+ h# ff h# ff h# ff h# 0 color! \ Background white
+ h# 0 h# 0 h# 0 h# ff color! \ Foreground black
+ h# 64 h# 41 h# b4 h# 1 color! \ SUN-blue logo
+
+ fb-addr to frame-buffer-adr
+ default-font set-font
+
+ \ Sun TCX adapters don't have an address property, but it is useful for
+ \ OpenBIOS developers. Unfortunately NetBSD SPARC32 has a bug that causes
+ \ it to fail initialising TCX if the address property is present; so work
+ \ around this by adding an underscore prefix
+ frame-buffer-adr encode-int " _address" property
+
+ openbios-video-width openbios-video-height over char-width / over char-height /
+ fb8-install
+ then
+;
+
+: qemu-tcx-driver-init
+
+ \ Handle differences between 8-bit/24-bit mode
+ depth-bits 8 = if
+ tcx-8bit-reg
+ /tcx-off-cmap-8 to /tcx-dac
+ " true" encode-string " tcx-8-bit" property
+ else
+ tcx-24bit-reg
+ /tcx-off-cmap-24 to /tcx-dac
+
+ \ Even with a 24-bit enabled TCX card, the control plane is
+ \ used in 8-bit mode. So force the video subsystem into 8-bit
+ \ mode before initialisation.
+ 8 depth-bits-xt !
+ openbios-video-width line-bytes-xt !
+ then
+
+ h# 1d encode-int " vbporch" property
+ h# a0 encode-int " hbporch" property
+ h# 06 encode-int " vsync" property
+ h# 88 encode-int " hsync" property
+ h# 03 encode-int " vfporch" property
+ h# 18 encode-int " hfporch" property
+ h# 03dfd240 encode-int " pixfreq" property
+ h# 3c encode-int " vfreq" property
+
+ openbios-video-height encode-int " height" property
+ openbios-video-width encode-int " width" property
+ line-bytes encode-int " linebytes" property
+
+ h# 39 encode-int 0 encode-int encode+ " intr" property
+ 5 encode-int " interrupts" property
+
+ ['] qemu-tcx-driver-install is-install
+;
+
+qemu-tcx-driver-init
+
+end0
diff --git a/roms/openbios/drivers/timer.c b/roms/openbios/drivers/timer.c
new file mode 100644
index 00000000..d6794ae9
--- /dev/null
+++ b/roms/openbios/drivers/timer.c
@@ -0,0 +1,100 @@
+/*
+ * OpenBIOS native timer driver
+ *
+ * (C) 2004 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "drivers/drivers.h"
+#include "timer.h"
+#include "asm/io.h"
+
+#if defined(CONFIG_X86) || defined(CONFIG_AMD64)
+
+void setup_timers(void)
+{
+ /* nothing to do */
+}
+
+static void load_timer2(unsigned int ticks)
+{
+ /* Set up the timer gate, turn off the speaker */
+ outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
+ outb(TIMER2_SEL | WORD_ACCESS | MODE0 | BINARY_COUNT,
+ TIMER_MODE_PORT);
+ outb(ticks & 0xFF, TIMER2_PORT);
+ outb(ticks >> 8, TIMER2_PORT);
+}
+
+void udelay(unsigned int usecs)
+{
+ load_timer2((usecs * TICKS_PER_MS) / 1000);
+ while ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
+}
+
+unsigned long currticks(void)
+{
+ static unsigned long totticks = 0UL; /* High resolution */
+ unsigned long ticks = 0;
+ unsigned char portb = inb(PPC_PORTB);
+
+ /*
+ * Read the timer, and hope it hasn't wrapped around
+ * (call this again within 54ms), then restart it
+ */
+ outb(TIMER2_SEL | LATCH_COUNT, TIMER_MODE_PORT);
+ ticks = inb(TIMER2_PORT);
+ ticks |= inb(TIMER2_PORT) << 8;
+ outb(TIMER2_SEL | WORD_ACCESS | MODE0 | BINARY_COUNT,
+ TIMER_MODE_PORT);
+ outb(0, TIMER2_PORT);
+ outb(0, TIMER2_PORT);
+
+ /*
+ * Check if the timer was running. If not,
+ * result is rubbish and need to start it
+ */
+ if (portb & PPCB_T2GATE) {
+ totticks += (0x10000 - ticks);
+ } else {
+ /* Set up the timer gate, turn off the speaker */
+ outb((portb & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
+ }
+ return totticks / TICKS_PER_MS;
+}
+#endif
+
+#ifdef CONFIG_PPC
+
+void setup_timers(void)
+{
+ /* nothing to do */
+}
+
+/*
+ * TODO: pass via lb table
+ */
+unsigned long timer_freq = 10000000 / 4;
+
+void udelay(unsigned int usecs)
+{
+ unsigned long ticksperusec = timer_freq / 1000000;
+ _wait_ticks(ticksperusec * usecs);
+}
+
+#endif
+
+void ndelay(unsigned int nsecs)
+{
+ udelay((nsecs + 999) / 1000);
+}
+
+void mdelay(unsigned int msecs)
+{
+ udelay(msecs * 1000);
+}
diff --git a/roms/openbios/drivers/timer.h b/roms/openbios/drivers/timer.h
new file mode 100644
index 00000000..7e86db3f
--- /dev/null
+++ b/roms/openbios/drivers/timer.h
@@ -0,0 +1,62 @@
+/* Taken from Etherboot */
+/* Defines for routines to implement a low-overhead timer for drivers */
+
+ /*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+/* Ports for the 8254 timer chip */
+#define TIMER2_PORT 0x42
+#define TIMER_MODE_PORT 0x43
+
+/* Meaning of the mode bits */
+#define TIMER0_SEL 0x00
+#define TIMER1_SEL 0x40
+#define TIMER2_SEL 0x80
+#define READBACK_SEL 0xC0
+
+#define LATCH_COUNT 0x00
+#define LOBYTE_ACCESS 0x10
+#define HIBYTE_ACCESS 0x20
+#define WORD_ACCESS 0x30
+
+#define MODE0 0x00
+#define MODE1 0x02
+#define MODE2 0x04
+#define MODE3 0x06
+#define MODE4 0x08
+#define MODE5 0x0A
+
+#define BINARY_COUNT 0x00
+#define BCD_COUNT 0x01
+
+/* Timers tick over at this rate */
+#define CLOCK_TICK_RATE 1193180U
+#define TICKS_PER_MS (CLOCK_TICK_RATE/1000)
+
+/* Parallel Peripheral Controller Port B */
+#define PPC_PORTB 0x61
+
+/* Meaning of the port bits */
+#define PPCB_T2OUT 0x20 /* Bit 5 */
+#define PPCB_SPKR 0x02 /* Bit 1 */
+#define PPCB_T2GATE 0x01 /* Bit 0 */
+
+extern void ndelay(unsigned int nsecs);
+extern void udelay(unsigned int usecs);
+extern void mdelay(unsigned int msecs);
+extern unsigned long currticks(void);
+extern unsigned long get_timer_freq(void);
+
+/* arch/ppc/timebase.S */
+void _wait_ticks(unsigned long nticks);
+
+#define TICKS_PER_SEC 1000
+
+#endif /* TIMER_H */
diff --git a/roms/openbios/drivers/usb.c b/roms/openbios/drivers/usb.c
new file mode 100644
index 00000000..c6e37174
--- /dev/null
+++ b/roms/openbios/drivers/usb.c
@@ -0,0 +1,587 @@
+/*
+ * Driver for USB ported from CoreBoot
+ *
+ * Copyright (C) 2014 BALATON Zoltan
+ *
+ * This file was part of the libpayload project.
+ *
+ * Copyright (C) 2008-2010 coresystems GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "drivers/usb.h"
+#include "usb.h"
+#include "timer.h"
+#include "libc/byteorder.h"
+
+hci_t *usb_hcs = 0;
+
+static void usb_nop_init (usbdev_t *dev);
+
+static void
+usb_nop_destroy (usbdev_t *dev)
+{
+ if (dev->descriptor != 0)
+ free (dev->descriptor);
+ usb_nop_init (dev);
+ dev->address = -1;
+ dev->hub = -1;
+ dev->port = -1;
+}
+
+static void
+usb_nop_poll (usbdev_t *dev)
+{
+ return;
+}
+
+static void
+usb_nop_init (usbdev_t *dev)
+{
+ dev->descriptor = 0;
+ dev->destroy = usb_nop_destroy;
+ dev->poll = usb_nop_poll;
+}
+
+hci_t *
+new_controller (void)
+{
+ hci_t *controller = malloc (sizeof (hci_t));
+
+ if (controller) {
+ /* atomic */
+ controller->next = usb_hcs;
+ usb_hcs = controller;
+ /* atomic end */
+ }
+
+ return controller;
+}
+
+void
+detach_controller (hci_t *controller)
+{
+ if (controller == NULL)
+ return;
+ if (usb_hcs == controller) {
+ usb_hcs = controller->next;
+ } else {
+ hci_t *it = usb_hcs;
+ while (it != NULL) {
+ if (it->next == controller) {
+ it->next = controller->next;
+ return;
+ }
+ it = it->next;
+ }
+ }
+}
+
+/**
+ * Shut down all controllers
+ */
+int
+usb_exit (void)
+{
+ while (usb_hcs != NULL) {
+ usb_hcs->shutdown(usb_hcs);
+ }
+ return 0;
+}
+
+/**
+ * Polls all hubs on all USB controllers, to find out about device changes
+ */
+void
+usb_poll (void)
+{
+ if (usb_hcs == 0)
+ return;
+ hci_t *controller = usb_hcs;
+ while (controller != NULL) {
+ int i;
+ for (i = 0; i < 128; i++) {
+ if (controller->devices[i] != 0) {
+ controller->devices[i]->poll (controller->devices[i]);
+ }
+ }
+ controller = controller->next;
+ }
+}
+
+void
+init_device_entry (hci_t *controller, int i)
+{
+ if (controller->devices[i] != 0)
+ usb_debug("warning: device %d reassigned?\n", i);
+ controller->devices[i] = malloc(sizeof(usbdev_t));
+ controller->devices[i]->controller = controller;
+ controller->devices[i]->address = -1;
+ controller->devices[i]->hub = -1;
+ controller->devices[i]->port = -1;
+ controller->devices[i]->init = usb_nop_init;
+ controller->devices[i]->init (controller->devices[i]);
+}
+
+void
+set_feature (usbdev_t *dev, int endp, int feature, int rtype)
+{
+ dev_req_t dr;
+
+ dr.bmRequestType = rtype;
+ dr.data_dir = host_to_device;
+ dr.bRequest = SET_FEATURE;
+ dr.wValue = __cpu_to_le16(feature);
+ dr.wIndex = __cpu_to_le16(endp);
+ dr.wLength = 0;
+ dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
+}
+
+void
+get_status (usbdev_t *dev, int intf, int rtype, int len, void *data)
+{
+ dev_req_t dr;
+
+ dr.bmRequestType = rtype;
+ dr.data_dir = device_to_host;
+ dr.bRequest = GET_STATUS;
+ dr.wValue = 0;
+ dr.wIndex = __cpu_to_le16(intf);
+ dr.wLength = __cpu_to_le16(len);
+ dev->controller->control (dev, IN, sizeof (dr), &dr, len, data);
+}
+
+u8 *
+get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType,
+ int descIdx, int langID)
+{
+ u8 buf[8];
+ u8 *result;
+ dev_req_t dr;
+ int size;
+
+ dr.bmRequestType = bmRequestType;
+ dr.data_dir = device_to_host; // always like this for descriptors
+ dr.bRequest = GET_DESCRIPTOR;
+ dr.wValue = __cpu_to_le16((descType << 8) | descIdx);
+ dr.wIndex = __cpu_to_le16(langID);
+ dr.wLength = __cpu_to_le16(8);
+ if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) {
+ usb_debug ("getting descriptor size (type %x) failed\n",
+ descType);
+ }
+
+ if (descType == 1) {
+ device_descriptor_t *dd = (device_descriptor_t *) buf;
+ usb_debug ("maxPacketSize0: %x\n", dd->bMaxPacketSize0);
+ if (dd->bMaxPacketSize0 != 0)
+ dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0;
+ }
+
+ /* special case for configuration descriptors: they carry all their
+ subsequent descriptors with them, and keep the entire size at a
+ different location */
+ size = buf[0];
+ if (buf[1] == 2) {
+ int realsize = __le16_to_cpu(((unsigned short *) (buf + 2))[0]);
+ size = realsize;
+ }
+ result = malloc (size);
+ memset (result, 0, size);
+ dr.wLength = __cpu_to_le16(size);
+ if (dev->controller->
+ control (dev, IN, sizeof (dr), &dr, size, result)) {
+ usb_debug ("getting descriptor (type %x, size %x) failed\n",
+ descType, size);
+ }
+
+ return result;
+}
+
+void
+set_configuration (usbdev_t *dev)
+{
+ dev_req_t dr;
+
+ dr.bmRequestType = 0;
+ dr.bRequest = SET_CONFIGURATION;
+ dr.wValue = __cpu_to_le16(dev->configuration[5]);
+ dr.wIndex = 0;
+ dr.wLength = 0;
+ dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
+}
+
+int
+clear_feature (usbdev_t *dev, int endp, int feature, int rtype)
+{
+ dev_req_t dr;
+
+ dr.bmRequestType = rtype;
+ dr.data_dir = host_to_device;
+ dr.bRequest = CLEAR_FEATURE;
+ dr.wValue = __cpu_to_le16(feature);
+ dr.wIndex = __cpu_to_le16(endp);
+ dr.wLength = 0;
+ return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
+}
+
+int
+clear_stall (endpoint_t *ep)
+{
+ usbdev_t *dev = ep->dev;
+ int endp = ep->endpoint;
+ int rtype = gen_bmRequestType (host_to_device, standard_type,
+ endp ? endp_recp : dev_recp);
+
+ int ret = clear_feature (dev, endp, ENDPOINT_HALT, rtype);
+ ep->toggle = 0;
+ return ret;
+}
+
+/* returns free address or -1 */
+static int
+get_free_address (hci_t *controller)
+{
+ int i;
+ for (i = 1; i < 128; i++) {
+ if (controller->devices[i] == 0)
+ return i;
+ }
+ usb_debug ("no free address found\n");
+ return -1; // no free address
+}
+
+int
+generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr)
+{
+ int adr = get_free_address (controller); // address to set
+ dev_req_t dr;
+
+ memset (&dr, 0, sizeof (dr));
+ dr.data_dir = host_to_device;
+ dr.req_type = standard_type;
+ dr.req_recp = dev_recp;
+ dr.bRequest = SET_ADDRESS;
+ dr.wValue = __cpu_to_le16(adr);
+ dr.wIndex = 0;
+ dr.wLength = 0;
+
+ init_device_entry(controller, adr);
+ usbdev_t *dev = controller->devices[adr];
+ // dummy values for registering the address
+ dev->address = 0;
+ dev->hub = hubaddr;
+ dev->port = hubport;
+ dev->speed = speed;
+ dev->endpoints[0].dev = dev;
+ dev->endpoints[0].endpoint = 0;
+ dev->endpoints[0].maxpacketsize = 8;
+ dev->endpoints[0].toggle = 0;
+ dev->endpoints[0].direction = SETUP;
+ mdelay (50);
+ if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) {
+ return -1;
+ }
+ mdelay (50);
+
+ return adr;
+}
+
+/* Normalize bInterval to log2 of microframes */
+static int
+usb_decode_interval(const int speed, const endpoint_type type, const unsigned char bInterval)
+{
+#define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1)
+ switch (speed) {
+ case LOW_SPEED:
+ switch (type) {
+ case ISOCHRONOUS: case INTERRUPT:
+ return LOG2(bInterval) + 3;
+ default:
+ return 0;
+ }
+ case FULL_SPEED:
+ switch (type) {
+ case ISOCHRONOUS:
+ return (bInterval - 1) + 3;
+ case INTERRUPT:
+ return LOG2(bInterval) + 3;
+ default:
+ return 0;
+ }
+ case HIGH_SPEED:
+ switch (type) {
+ case ISOCHRONOUS: case INTERRUPT:
+ return bInterval - 1;
+ default:
+ return LOG2(bInterval);
+ }
+ case SUPER_SPEED:
+ switch (type) {
+ case ISOCHRONOUS: case INTERRUPT:
+ return bInterval - 1;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+#undef LOG2
+}
+
+static int
+set_address (hci_t *controller, int speed, int hubport, int hubaddr)
+{
+ int adr = controller->set_address(controller, speed, hubport, hubaddr);
+ if (adr < 0 || !controller->devices[adr]) {
+ usb_debug ("set_address failed\n");
+ return -1;
+ }
+ configuration_descriptor_t *cd;
+ device_descriptor_t *dd;
+
+ usbdev_t *dev = controller->devices[adr];
+ dev->address = adr;
+ dev->hub = hubaddr;
+ dev->port = hubport;
+ dev->speed = speed;
+ dev->descriptor = get_descriptor (dev, gen_bmRequestType
+ (device_to_host, standard_type, dev_recp), 1, 0, 0);
+ dd = (device_descriptor_t *) dev->descriptor;
+
+ usb_debug ("* found device (0x%04x:0x%04x, USB %x.%x)",
+ __le16_to_cpu(dd->idVendor), __le16_to_cpu(dd->idProduct),
+ __le16_to_cpu(dd->bcdUSB) >> 8, __le16_to_cpu(dd->bcdUSB) & 0xff);
+ dev->quirks = USB_QUIRK_NONE;
+
+ usb_debug ("\ndevice has %x configurations\n", dd->bNumConfigurations);
+ if (dd->bNumConfigurations == 0) {
+ /* device isn't usable */
+ usb_debug ("... no usable configuration!\n");
+ dev->address = 0;
+ return -1;
+ }
+
+ dev->configuration = get_descriptor (dev, gen_bmRequestType
+ (device_to_host, standard_type, dev_recp), 2, 0, 0);
+ cd = (configuration_descriptor_t *) dev->configuration;
+ interface_descriptor_t *interface =
+ (interface_descriptor_t *) (((char *) cd) + cd->bLength);
+ {
+ int i;
+ int num = cd->bNumInterfaces;
+ interface_descriptor_t *current = interface;
+ usb_debug ("device has %x interfaces\n", num);
+ if (num > 1) {
+ usb_debug ("\nNOTICE: This driver defaults to using the first interface.\n"
+ "This might be the wrong choice and lead to limited functionality\n"
+ "of the device.\n");
+ /* we limit to the first interface, as there was no need to
+ * implement something else for the time being. If you need
+ * it, see the SetInterface and GetInterface functions in
+ * the USB specification, and adapt appropriately.
+ */
+ num = (num > 1) ? 1 : num;
+ }
+ for (i = 0; i < num; i++) {
+ int j;
+ usb_debug (" #%x has %x endpoints, interface %x:%x, protocol %x\n",
+ current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol);
+ endpoint_descriptor_t *endp =
+ (endpoint_descriptor_t *) (((char *) current)
+ + current->bLength);
+ /* Skip any non-endpoint descriptor */
+ if (endp->bDescriptorType != 0x05)
+ endp = (endpoint_descriptor_t *)(((char *)endp) + ((char *)endp)[0]);
+
+ memset (dev->endpoints, 0, sizeof (dev->endpoints));
+ dev->num_endp = 1; // 0 always exists
+ dev->endpoints[0].dev = dev;
+ dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0;
+ dev->endpoints[0].direction = SETUP;
+ dev->endpoints[0].type = CONTROL;
+ dev->endpoints[0].interval = usb_decode_interval(dev->speed, CONTROL, endp->bInterval);
+ for (j = 1; j <= current->bNumEndpoints; j++) {
+#ifdef CONFIG_DEBUG_USB
+ static const char *transfertypes[4] = {
+ "control", "isochronous", "bulk", "interrupt"
+ };
+ usb_debug (" #%x: Endpoint %x (%s), max packet size %x, type %s\n", j, endp->bEndpointAddress & 0x7f, ((endp->bEndpointAddress & 0x80) != 0) ? "in" : "out", __le16_to_cpu(endp->wMaxPacketSize), transfertypes[endp->bmAttributes]);
+#endif
+ endpoint_t *ep =
+ &dev->endpoints[dev->num_endp++];
+ ep->dev = dev;
+ ep->endpoint = endp->bEndpointAddress;
+ ep->toggle = 0;
+ ep->maxpacketsize = __le16_to_cpu(endp->wMaxPacketSize);
+ ep->direction =
+ ((endp->bEndpointAddress & 0x80) ==
+ 0) ? OUT : IN;
+ ep->type = endp->bmAttributes;
+ ep->interval = usb_decode_interval(dev->speed, ep->type, endp->bInterval);
+ endp = (endpoint_descriptor_t
+ *) (((char *) endp) + endp->bLength);
+ }
+ current = (interface_descriptor_t *) endp;
+ }
+ }
+
+ if (controller->finish_device_config &&
+ controller->finish_device_config(dev))
+ return adr; /* Device isn't configured correctly,
+ only control transfers may work. */
+
+ set_configuration(dev);
+
+ int class = dd->bDeviceClass;
+ if (class == 0)
+ class = interface->bInterfaceClass;
+
+ usb_debug(", class: ");
+ switch (class) {
+ case audio_device:
+ usb_debug("audio\n");
+ break;
+ case comm_device:
+ usb_debug("communication\n");
+ break;
+ case hid_device:
+ usb_debug ("HID\n");
+#ifdef CONFIG_USB_HID
+ controller->devices[adr]->init = usb_hid_init;
+ return adr;
+#else
+ usb_debug ("NOTICE: USB HID support not compiled in\n");
+#endif
+ break;
+ case physical_device:
+ usb_debug("physical\n");
+ break;
+ case imaging_device:
+ usb_debug("camera\n");
+ break;
+ case printer_device:
+ usb_debug("printer\n");
+ break;
+ case msc_device:
+ usb_debug ("MSC\n");
+#ifdef CONFIG_USB_MSC
+ controller->devices[adr]->init = usb_msc_init;
+ return adr;
+#else
+ usb_debug ("NOTICE: USB MSC support not compiled in\n");
+#endif
+ break;
+ case hub_device:
+ usb_debug ("hub\n");
+#ifdef CONFIG_USB_HUB
+ controller->devices[adr]->init = usb_hub_init;
+ return adr;
+#else
+ usb_debug ("NOTICE: USB hub support not compiled in.\n");
+#endif
+ break;
+ case cdc_device:
+ usb_debug("CDC\n");
+ break;
+ case ccid_device:
+ usb_debug("smartcard / CCID\n");
+ break;
+ case security_device:
+ usb_debug("content security\n");
+ break;
+ case video_device:
+ usb_debug("video\n");
+ break;
+ case healthcare_device:
+ usb_debug("healthcare\n");
+ break;
+ case diagnostic_device:
+ usb_debug("diagnostic\n");
+ break;
+ case wireless_device:
+ usb_debug("wireless\n");
+ break;
+ default:
+ usb_debug("unsupported class %x\n", class);
+ break;
+ }
+ controller->devices[adr]->init = usb_generic_init;
+ return adr;
+}
+
+/*
+ * Should be called by the hub drivers whenever a physical detach occurs
+ * and can be called by usb class drivers if they are unsatisfied with a
+ * malfunctioning device.
+ */
+void
+usb_detach_device(hci_t *controller, int devno)
+{
+ /* check if device exists, as we may have
+ been called yet by the usb class driver */
+ if (controller->devices[devno]) {
+ controller->devices[devno]->destroy (controller->devices[devno]);
+ free(controller->devices[devno]);
+ controller->devices[devno] = NULL;
+ if (controller->destroy_device)
+ controller->destroy_device(controller, devno);
+ }
+}
+
+int
+usb_attach_device(hci_t *controller, int hubaddress, int port, int speed)
+{
+#ifdef CONFIG_USB_DEBUG
+ static const char* speeds[] = { "full", "low", "high" };
+ usb_debug ("%sspeed device\n", (speed <= 2) ? speeds[speed] : "invalid value - no");
+#endif
+ int newdev = set_address (controller, speed, port, hubaddress);
+ if (newdev == -1)
+ return -1;
+ usbdev_t *newdev_t = controller->devices[newdev];
+ // determine responsible driver - current done in set_address
+ newdev_t->init (newdev_t);
+ /* init() may have called usb_detach_device() yet, so check */
+ return controller->devices[newdev] ? newdev : -1;
+}
+
+static void
+usb_generic_destroy (usbdev_t *dev)
+{
+ if (usb_generic_remove)
+ usb_generic_remove(dev);
+}
+
+void
+usb_generic_init (usbdev_t *dev)
+{
+ dev->data = NULL;
+ dev->destroy = usb_generic_destroy;
+
+ if (usb_generic_create)
+ usb_generic_create(dev);
+}
diff --git a/roms/openbios/drivers/usb.h b/roms/openbios/drivers/usb.h
new file mode 100644
index 00000000..2e23a137
--- /dev/null
+++ b/roms/openbios/drivers/usb.h
@@ -0,0 +1,357 @@
+/*
+ * Driver for USB ported from CoreBoot
+ *
+ * Copyright (C) 2014 BALATON Zoltan
+ *
+ * This file was part of the libpayload project.
+ *
+ * Copyright (C) 2008 coresystems GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __USB_H
+#define __USB_H
+#include <drivers/pci.h>
+
+typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir;
+typedef enum { standard_type = 0, class_type = 1, vendor_type =
+ 2, reserved_type = 3
+} dev_req_type;
+typedef enum { dev_recp = 0, iface_recp = 1, endp_recp = 2, other_recp = 3
+} dev_req_recp;
+
+typedef enum {
+ GET_STATUS = 0,
+ CLEAR_FEATURE = 1,
+ SET_FEATURE = 3,
+ SET_ADDRESS = 5,
+ GET_DESCRIPTOR = 6,
+ SET_DESCRIPTOR = 7,
+ GET_CONFIGURATION = 8,
+ SET_CONFIGURATION = 9,
+ GET_INTERFACE = 10,
+ SET_INTERFACE = 11,
+ SYNCH_FRAME = 12
+} bRequest_Codes;
+
+typedef enum {
+ ENDPOINT_HALT = 0,
+ DEVICE_REMOTE_WAKEUP = 1,
+ TEST_MODE = 2
+} feature_selectors;
+
+enum {
+ audio_device = 0x01,
+ comm_device = 0x02,
+ hid_device = 0x03,
+ physical_device = 0x05,
+ imaging_device = 0x06,
+ printer_device = 0x07,
+ msc_device = 0x08,
+ hub_device = 0x09,
+ cdc_device = 0x0a,
+ ccid_device = 0x0b,
+ security_device = 0x0d,
+ video_device = 0x0e,
+ healthcare_device = 0x0f,
+ diagnostic_device = 0xdc,
+ wireless_device = 0xe0,
+ misc_device = 0xef,
+};
+
+enum { hid_subclass_none = 0, hid_subclass_boot = 1 };
+
+enum {
+ hid_boot_proto_none = 0,
+ hid_boot_proto_keyboard = 1,
+ hid_boot_proto_mouse = 2
+};
+
+typedef struct {
+ union {
+ struct {
+#ifdef CONFIG_BIG_ENDIAN
+ dev_req_dir data_dir:1;
+ dev_req_type req_type:2;
+ dev_req_recp req_recp:5;
+#else
+ dev_req_recp req_recp:5;
+ dev_req_type req_type:2;
+ dev_req_dir data_dir:1;
+#endif
+ } __attribute__ ((packed));
+ unsigned char bmRequestType;
+ } __attribute__ ((packed));
+ unsigned char bRequest;
+ unsigned short wValue;
+ unsigned short wIndex;
+ unsigned short wLength;
+} __attribute__ ((packed)) dev_req_t;
+
+struct usbdev_hc;
+typedef struct usbdev_hc hci_t;
+
+struct usbdev;
+typedef struct usbdev usbdev_t;
+
+typedef enum { SETUP, IN, OUT } direction_t;
+typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3
+} endpoint_type;
+
+typedef struct {
+ usbdev_t *dev;
+ int endpoint;
+ direction_t direction;
+ int toggle;
+ int maxpacketsize;
+ endpoint_type type;
+ int interval; /* expressed as binary logarithm of the number
+ of microframes (i.e. t = 125us * 2^interval) */
+} endpoint_t;
+
+enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 };
+
+struct usbdev {
+ hci_t *controller;
+ endpoint_t endpoints[32];
+ int num_endp;
+ int address; // usb address
+ int hub; // hub, device is attached to
+ int port; // port where device is attached
+ int speed; // 1: lowspeed, 0: fullspeed, 2: highspeed
+ u32 quirks; // quirks field. got to love usb
+ void *data;
+ u8 *descriptor;
+ u8 *configuration;
+ void (*init) (usbdev_t *dev);
+ void (*destroy) (usbdev_t *dev);
+ void (*poll) (usbdev_t *dev);
+};
+
+typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type;
+
+struct usbdev_hc {
+ hci_t *next;
+ u32 reg_base;
+ hc_type type;
+ usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable
+
+ /* start(): Resume operation. */
+ void (*start) (hci_t *controller);
+ /* stop(): Stop operation but keep controller initialized. */
+ void (*stop) (hci_t *controller);
+ /* reset(): Perform a controller reset. The controller needs to
+ be (re)initialized afterwards to work (again). */
+ void (*reset) (hci_t *controller);
+ /* init(): Initialize a (previously reset) controller
+ to a working state. */
+ void (*init) (hci_t *controller);
+ /* shutdown(): Stop operation, detach host controller and shutdown
+ this driver instance. After calling shutdown() any
+ other usage of this hci_t* is invalid. */
+ void (*shutdown) (hci_t *controller);
+
+ int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize);
+ int (*control) (usbdev_t *dev, direction_t pid, int dr_length,
+ void *devreq, int data_length, u8 *data);
+ void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
+ void (*destroy_intr_queue) (endpoint_t *ep, void *queue);
+ u8* (*poll_intr_queue) (void *queue);
+ void *instance;
+
+ /* set_address(): Tell the usb device its address and
+ return it. xHCI controllers want to
+ do this by themself. Also, the usbdev
+ structure has to be allocated and
+ initialized. */
+ int (*set_address) (hci_t *controller, int speed, int hubport, int hubaddr);
+ /* finish_device_config(): Another hook for xHCI,
+ returns 0 on success. */
+ int (*finish_device_config) (usbdev_t *dev);
+ /* destroy_device(): Finally, destroy all structures that
+ were allocated during set_address()
+ and finish_device_config(). */
+ void (*destroy_device) (hci_t *controller, int devaddr);
+};
+
+typedef struct {
+ unsigned char bDescLength;
+ unsigned char bDescriptorType;
+ unsigned char bNbrPorts;
+ union {
+ struct {
+#ifdef CONFIG_BIG_ENDIAN
+ unsigned long:8;
+ unsigned long arePortIndicatorsSupported:1;
+ unsigned long ttThinkTime:2;
+ unsigned long overcurrentProtectionMode:2;
+ unsigned long isCompoundDevice:1;
+ unsigned long logicalPowerSwitchingMode:2;
+#else
+ unsigned long logicalPowerSwitchingMode:2;
+ unsigned long isCompoundDevice:1;
+ unsigned long overcurrentProtectionMode:2;
+ unsigned long ttThinkTime:2;
+ unsigned long arePortIndicatorsSupported:1;
+ unsigned long:8;
+#endif
+ } __attribute__ ((packed));
+ unsigned short wHubCharacteristics;
+ } __attribute__ ((packed));
+ unsigned char bPowerOn2PwrGood;
+ unsigned char bHubContrCurrent;
+ char DeviceRemovable[];
+} __attribute__ ((packed)) hub_descriptor_t;
+
+typedef struct {
+ unsigned char bLength;
+ unsigned char bDescriptorType;
+ unsigned short bcdUSB;
+ unsigned char bDeviceClass;
+ unsigned char bDeviceSubClass;
+ unsigned char bDeviceProtocol;
+ unsigned char bMaxPacketSize0;
+ unsigned short idVendor;
+ unsigned short idProduct;
+ unsigned short bcdDevice;
+ unsigned char iManufacturer;
+ unsigned char iProduct;
+ unsigned char iSerialNumber;
+ unsigned char bNumConfigurations;
+} __attribute__ ((packed)) device_descriptor_t;
+
+typedef struct {
+ unsigned char bLength;
+ unsigned char bDescriptorType;
+ unsigned short wTotalLength;
+ unsigned char bNumInterfaces;
+ unsigned char bConfigurationValue;
+ unsigned char iConfiguration;
+ unsigned char bmAttributes;
+ unsigned char bMaxPower;
+} __attribute__ ((packed)) configuration_descriptor_t;
+
+typedef struct {
+ unsigned char bLength;
+ unsigned char bDescriptorType;
+ unsigned char bInterfaceNumber;
+ unsigned char bAlternateSetting;
+ unsigned char bNumEndpoints;
+ unsigned char bInterfaceClass;
+ unsigned char bInterfaceSubClass;
+ unsigned char bInterfaceProtocol;
+ unsigned char iInterface;
+} __attribute__ ((packed)) interface_descriptor_t;
+
+typedef struct {
+ unsigned char bLength;
+ unsigned char bDescriptorType;
+ unsigned char bEndpointAddress;
+ unsigned char bmAttributes;
+ unsigned short wMaxPacketSize;
+ unsigned char bInterval;
+} __attribute__ ((packed)) endpoint_descriptor_t;
+
+typedef struct {
+ unsigned char bLength;
+ unsigned char bDescriptorType;
+ unsigned short bcdHID;
+ unsigned char bCountryCode;
+ unsigned char bNumDescriptors;
+ unsigned char bReportDescriptorType;
+ unsigned short wReportDescriptorLength;
+} __attribute__ ((packed)) hid_descriptor_t;
+
+hci_t *new_controller (void);
+void detach_controller (hci_t *controller);
+void usb_poll (void);
+void init_device_entry (hci_t *controller, int num);
+
+void set_feature (usbdev_t *dev, int endp, int feature, int rtype);
+void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data);
+void set_configuration (usbdev_t *dev);
+int clear_feature (usbdev_t *dev, int endp, int feature, int rtype);
+int clear_stall (endpoint_t *ep);
+
+void usb_hub_init (usbdev_t *dev);
+void usb_hid_init (usbdev_t *dev);
+void usb_msc_init (usbdev_t *dev);
+void usb_generic_init (usbdev_t *dev);
+
+u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType,
+ int descType, int descIdx, int langID);
+
+static inline unsigned char
+gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp)
+{
+ return (dir << 7) | (type << 5) | recp;
+}
+
+/* default "set address" handler */
+int generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr);
+
+void usb_detach_device(hci_t *controller, int devno);
+int usb_attach_device(hci_t *controller, int hubaddress, int port, int speed);
+
+u32 usb_quirk_check(u16 vendor, u16 device);
+int usb_interface_check(u16 vendor, u16 device);
+
+#define USB_QUIRK_MSC_FORCE_PROTO_SCSI (1 << 0)
+#define USB_QUIRK_MSC_FORCE_PROTO_ATAPI (1 << 1)
+#define USB_QUIRK_MSC_FORCE_PROTO_UFI (1 << 2)
+#define USB_QUIRK_MSC_FORCE_PROTO_RBC (1 << 3)
+#define USB_QUIRK_MSC_FORCE_TRANS_BBB (1 << 4)
+#define USB_QUIRK_MSC_FORCE_TRANS_CBI (1 << 5)
+#define USB_QUIRK_MSC_FORCE_TRANS_CBI_I (1 << 6)
+#define USB_QUIRK_MSC_NO_TEST_UNIT_READY (1 << 7)
+#define USB_QUIRK_MSC_SHORT_INQUIRY (1 << 8)
+#define USB_QUIRK_TEST (1 << 31)
+#define USB_QUIRK_NONE 0
+
+#ifdef CONFIG_DEBUG_USB
+#define usb_debug(fmt, args...) do { printk(fmt , ##args); } while (0)
+#else
+#define usb_debug(fmt, args...)
+#endif
+
+/**
+ * To be implemented by libpayload-client. It's called by the USB stack
+ * when a new USB device is found which isn't claimed by a built in driver,
+ * so the client has the chance to know about it.
+ *
+ * @param dev descriptor for the USB device
+ */
+void __attribute__((weak)) usb_generic_create (usbdev_t *dev);
+
+/**
+ * To be implemented by libpayload-client. It's called by the USB stack
+ * when it finds out that a USB device is removed which wasn't claimed by a
+ * built in driver.
+ *
+ * @param dev descriptor for the USB device
+ */
+void __attribute__((weak)) usb_generic_remove (usbdev_t *dev);
+
+#endif
diff --git a/roms/openbios/drivers/usbhid.c b/roms/openbios/drivers/usbhid.c
new file mode 100644
index 00000000..a423278a
--- /dev/null
+++ b/roms/openbios/drivers/usbhid.c
@@ -0,0 +1,579 @@
+/*
+ * Driver for HID devices ported from CoreBoot
+ *
+ * Copyright (C) 2014 BALATON Zoltan
+ *
+ * This file was part of the libpayload project.
+ *
+ * Copyright (C) 2008-2010 coresystems GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include <libc/string.h>
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "drivers/usb.h"
+#include "usb.h"
+
+DECLARE_UNNAMED_NODE(usb_kbd, INSTALL_OPEN, sizeof(int));
+
+static void
+keyboard_open(int *idx)
+{
+ RET(-1);
+}
+
+static void
+keyboard_close(int *idx)
+{
+}
+
+static void keyboard_read(void);
+
+NODE_METHODS( usb_kbd ) = {
+ { "open", keyboard_open },
+ { "close", keyboard_close },
+ { "read", keyboard_read },
+};
+
+#ifdef CONFIG_USB_DEBUG
+static const char *boot_protos[3] = { "(none)", "keyboard", "mouse" };
+#endif
+typedef enum { hid_proto_boot = 0, hid_proto_report = 1 } hid_proto;
+enum { GET_REPORT = 0x1, GET_IDLE = 0x2, GET_PROTOCOL = 0x3, SET_REPORT =
+ 0x9, SET_IDLE = 0xa, SET_PROTOCOL = 0xb
+};
+
+typedef union {
+ struct {
+ u8 modifiers;
+ u8 repeats;
+ u8 keys[6];
+ };
+ u8 buffer[8];
+} usb_hid_keyboard_event_t;
+
+typedef struct {
+ void* queue;
+ hid_descriptor_t *descriptor;
+
+ usb_hid_keyboard_event_t previous;
+ int lastkeypress;
+ int repeat_delay;
+} usbhid_inst_t;
+
+#define HID_INST(dev) ((usbhid_inst_t*)(dev)->data)
+
+static void
+usb_hid_destroy (usbdev_t *dev)
+{
+ if (HID_INST(dev)->queue) {
+ int i;
+ for (i = 0; i <= dev->num_endp; i++) {
+ if (dev->endpoints[i].endpoint == 0)
+ continue;
+ if (dev->endpoints[i].type != INTERRUPT)
+ continue;
+ if (dev->endpoints[i].direction != IN)
+ continue;
+ break;
+ }
+ dev->controller->destroy_intr_queue(
+ &dev->endpoints[i], HID_INST(dev)->queue);
+ HID_INST(dev)->queue = NULL;
+ }
+ free (dev->data);
+}
+
+/* keybuffer is global to all USB keyboards */
+static int keycount;
+#define KEYBOARD_BUFFER_SIZE 16
+static short keybuffer[KEYBOARD_BUFFER_SIZE];
+
+const char *countries[36][2] = {
+ { "unknown", "us" },
+ { "Arabic", "ae" },
+ { "Belgian", "be" },
+ { "Canadian-Bilingual", "ca" },
+ { "Canadian-French", "ca" },
+ { "Czech Republic", "cz" },
+ { "Danish", "dk" },
+ { "Finnish", "fi" },
+ { "French", "fr" },
+ { "German", "de" },
+ { "Greek", "gr" },
+ { "Hebrew", "il" },
+ { "Hungary", "hu" },
+ { "International (ISO)", "iso" },
+ { "Italian", "it" },
+ { "Japan (Katakana)", "jp" },
+ { "Korean", "us" },
+ { "Latin American", "us" },
+ { "Netherlands/Dutch", "nl" },
+ { "Norwegian", "no" },
+ { "Persian (Farsi)", "ir" },
+ { "Poland", "pl" },
+ { "Portuguese", "pt" },
+ { "Russia", "ru" },
+ { "Slovakia", "sl" },
+ { "Spanish", "es" },
+ { "Swedish", "se" },
+ { "Swiss/French", "ch" },
+ { "Swiss/German", "ch" },
+ { "Switzerland", "ch" },
+ { "Taiwan", "tw" },
+ { "Turkish-Q", "tr" },
+ { "UK", "uk" },
+ { "US", "us" },
+ { "Yugoslavia", "yu" },
+ { "Turkish-F", "tr" },
+ /* 36 - 255: Reserved */
+};
+
+
+
+struct layout_maps {
+ const char *country;
+ const short map[4][0x80];
+};
+
+static const struct layout_maps *map;
+
+#define KEY_BREAK 0x101 /* Not on PC KBD */
+#define KEY_DOWN 0x102 /* Down arrow key */
+#define KEY_UP 0x103 /* Up arrow key */
+#define KEY_LEFT 0x104 /* Left arrow key */
+#define KEY_RIGHT 0x105 /* Right arrow key */
+#define KEY_HOME 0x106 /* home key */
+#define KEY_BACKSPACE 0x107 /* not on pc */
+#define KEY_F0 0x108 /* function keys; 64 reserved */
+#define KEY_F(n) (KEY_F0 + (n))
+
+#define KEY_DC 0x14a /* delete character */
+#define KEY_IC 0x14b /* insert char or enter ins mode */
+
+#define KEY_NPAGE 0x152 /* next page */
+#define KEY_PPAGE 0x153 /* previous page */
+
+#define KEY_ENTER 0x157 /* enter or send (unreliable) */
+
+#define KEY_PRINT 0x15a /* print/copy */
+
+#define KEY_END 0x166 /* end key */
+
+static const struct layout_maps keyboard_layouts[] = {
+// #ifdef CONFIG_PC_KEYBOARD_LAYOUT_US
+{ .country = "us", .map = {
+ { /* No modifier */
+ -1, -1, -1, -1, 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ /* 0x10 */
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
+ /* 0x20 */
+ '3', '4', '5', '6', '7', '8', '9', '0',
+ '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
+ /* 0x30 */
+ ']', '\\', -1, ';', '\'', '`', ',', '.',
+ '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
+ /* 0x40 */
+ KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */,
+ KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
+ /* 50 */
+ KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+',
+ KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
+ /* 60 */
+ KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 70 */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* Shift modifier */
+ -1, -1, -1, -1, 'A', 'B', 'C', 'D',
+ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ /* 0x10 */
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
+ /* 0x20 */
+ '#', '$', '%', '^', '&', '*', '(', ')',
+ '\n', '\e', '\b', '\t', ' ', '_', '+', '{',
+ /* 0x30 */
+ '}', '|', -1, ':', '"', '~', '<', '>',
+ '?', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
+ /* 0x40 */
+ KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */,
+ KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
+ /* 50 */
+ KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+',
+ KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
+ /* 60 */
+ KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 70 */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* Alt */
+ -1, -1, -1, -1, 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ /* 0x10 */
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
+ /* 0x20 */
+ '3', '4', '5', '6', '7', '8', '9', '0',
+ '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
+ /* 0x30 */
+ ']', '\\', -1, ';', '\'', '`', ',', '.',
+ '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
+ /* 0x40 */
+ KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */,
+ KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
+ /* 50 */
+ KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+',
+ KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
+ /* 60 */
+ KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 70 */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* Shift+Alt modifier */
+ -1, -1, -1, -1, 'A', 'B', 'C', 'D',
+ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ /* 0x10 */
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
+ /* 0x20 */
+ '#', '$', '%', '^', '&', '*', '(', ')',
+ '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
+ /* 0x30 */
+ ']', '\\', -1, ':', '\'', '`', ',', '.',
+ '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
+ /* 0x40 */
+ KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */,
+ KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
+ /* 50 */
+ KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+',
+ KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
+ /* 60 */
+ KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 70 */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ }
+}},
+//#endif
+};
+
+#define MOD_SHIFT (1 << 0)
+#define MOD_ALT (1 << 1)
+#define MOD_CTRL (1 << 2)
+
+static void usb_hid_keyboard_queue(int ch) {
+ /* ignore key presses if buffer full */
+ if (keycount < KEYBOARD_BUFFER_SIZE)
+ keybuffer[keycount++] = ch;
+}
+
+#define KEYBOARD_REPEAT_MS 30
+#define INITIAL_REPEAT_DELAY 10
+#define REPEAT_DELAY 2
+
+static void
+usb_hid_process_keyboard_event(usbhid_inst_t *const inst,
+ const usb_hid_keyboard_event_t *const current)
+{
+ const usb_hid_keyboard_event_t *const previous = &inst->previous;
+
+ int i, keypress = 0, modifiers = 0;
+
+ if (current->modifiers & 0x01) /* Left-Ctrl */ modifiers |= MOD_CTRL;
+ if (current->modifiers & 0x02) /* Left-Shift */ modifiers |= MOD_SHIFT;
+ if (current->modifiers & 0x04) /* Left-Alt */ modifiers |= MOD_ALT;
+ if (current->modifiers & 0x08) /* Left-GUI */ ;
+ if (current->modifiers & 0x10) /* Right-Ctrl */ modifiers |= MOD_CTRL;
+ if (current->modifiers & 0x20) /* Right-Shift */ modifiers |= MOD_SHIFT;
+ if (current->modifiers & 0x40) /* Right-AltGr */ modifiers |= MOD_ALT;
+ if (current->modifiers & 0x80) /* Right-GUI */ ;
+
+ /* Did the event change at all? */
+ if (inst->lastkeypress &&
+ !memcmp(current, previous, sizeof(*current))) {
+ /* No. Then it's a key repeat event. */
+ if (inst->repeat_delay) {
+ inst->repeat_delay--;
+ } else {
+ usb_hid_keyboard_queue(inst->lastkeypress);
+ inst->repeat_delay = REPEAT_DELAY;
+ }
+
+ return;
+ }
+
+ inst->lastkeypress = 0;
+
+ for (i=0; i<6; i++) {
+ int j;
+ int skip = 0;
+ // No more keys? skip
+ if (current->keys[i] == 0)
+ return;
+
+ for (j=0; j<6; j++) {
+ if (current->keys[i] == previous->keys[j]) {
+ skip = 1;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+
+
+ /* Mask off MOD_CTRL */
+ keypress = map->map[modifiers & 0x03][current->keys[i]];
+
+ if (modifiers & MOD_CTRL) {
+ switch (keypress) {
+ case 'a' ... 'z':
+ keypress &= 0x1f;
+ break;
+ default:
+ continue;
+ }
+ }
+
+ if (keypress == -1) {
+ /* Debug: Print unknown keys */
+ usb_debug ("usbhid: <%x> %x [ %x %x %x %x %x %x ] %d\n",
+ current->modifiers, current->repeats,
+ current->keys[0], current->keys[1],
+ current->keys[2], current->keys[3],
+ current->keys[4], current->keys[5], i);
+
+ /* Unknown key? Try next one in the queue */
+ continue;
+ }
+
+ usb_hid_keyboard_queue(keypress);
+
+ /* Remember for authentic key repeat */
+ inst->lastkeypress = keypress;
+ inst->repeat_delay = INITIAL_REPEAT_DELAY;
+ }
+}
+
+static void
+usb_hid_poll (usbdev_t *dev)
+{
+ usb_hid_keyboard_event_t current;
+ const u8 *buf;
+
+ while ((buf=dev->controller->poll_intr_queue (HID_INST(dev)->queue))) {
+ memcpy(&current.buffer, buf, 8);
+ usb_hid_process_keyboard_event(HID_INST(dev), &current);
+ HID_INST(dev)->previous = current;
+ }
+}
+
+static void
+usb_hid_set_idle (usbdev_t *dev, interface_descriptor_t *interface, u16 duration)
+{
+ dev_req_t dr;
+ dr.data_dir = host_to_device;
+ dr.req_type = class_type;
+ dr.req_recp = iface_recp;
+ dr.bRequest = SET_IDLE;
+ dr.wValue = __cpu_to_le16((duration >> 2) << 8);
+ dr.wIndex = __cpu_to_le16(interface->bInterfaceNumber);
+ dr.wLength = 0;
+ dev->controller->control (dev, OUT, sizeof (dev_req_t), &dr, 0, 0);
+}
+
+static void
+usb_hid_set_protocol (usbdev_t *dev, interface_descriptor_t *interface, hid_proto proto)
+{
+ dev_req_t dr;
+ dr.data_dir = host_to_device;
+ dr.req_type = class_type;
+ dr.req_recp = iface_recp;
+ dr.bRequest = SET_PROTOCOL;
+ dr.wValue = __cpu_to_le16(proto);
+ dr.wIndex = __cpu_to_le16(interface->bInterfaceNumber);
+ dr.wLength = 0;
+ dev->controller->control (dev, OUT, sizeof (dev_req_t), &dr, 0, 0);
+}
+
+static int usb_hid_set_layout (const char *country)
+{
+ /* FIXME should be per keyboard */
+ int i;
+
+ for (i=0; i<sizeof(keyboard_layouts)/sizeof(keyboard_layouts[0]); i++) {
+ if (strncmp(keyboard_layouts[i].country, country,
+ strlen(keyboard_layouts[i].country)))
+ continue;
+
+ /* Found, changing keyboard layout */
+ map = &keyboard_layouts[i];
+ usb_debug(" Keyboard layout '%s'\n", map->country);
+ return 0;
+ }
+
+ usb_debug(" Keyboard layout '%s' not found, using '%s'\n",
+ country, map->country);
+
+ /* Nothing found, not changed */
+ return -1;
+}
+
+void
+usb_hid_init (usbdev_t *dev)
+{
+ configuration_descriptor_t *cd = (configuration_descriptor_t*)dev->configuration;
+ interface_descriptor_t *interface = (interface_descriptor_t*)(((char *) cd) + cd->bLength);
+
+ if (interface->bInterfaceSubClass == hid_subclass_boot) {
+ u8 countrycode = 0;
+ usb_debug (" supports boot interface..\n");
+ usb_debug (" it's a %s\n",
+ boot_protos[interface->bInterfaceProtocol]);
+ switch (interface->bInterfaceProtocol) {
+ case hid_boot_proto_keyboard:
+ dev->data = malloc (sizeof (usbhid_inst_t));
+ if (!dev->data) {
+ printk("Not enough memory for USB HID device.\n");
+ return;
+ }
+ memset(&HID_INST(dev)->previous, 0x00,
+ sizeof(HID_INST(dev)->previous));
+ usb_debug (" configuring...\n");
+ usb_hid_set_protocol(dev, interface, hid_proto_boot);
+ usb_hid_set_idle(dev, interface, KEYBOARD_REPEAT_MS);
+ usb_debug (" activating...\n");
+#if 0
+ HID_INST (dev)->descriptor =
+ (hid_descriptor_t *)
+ get_descriptor(dev, gen_bmRequestType
+ (device_to_host, standard_type, iface_recp),
+ 0x21, 0, 0);
+ countrycode = HID_INST(dev)->descriptor->bCountryCode;
+#endif
+ /* 35 countries defined: */
+ if (countrycode > 35)
+ countrycode = 0;
+ usb_debug (" Keyboard has %s layout (country code %02x)\n",
+ countries[countrycode][0], countrycode);
+
+ /* Set keyboard layout accordingly */
+ usb_hid_set_layout(countries[countrycode][1]);
+
+ // only add here, because we only support boot-keyboard HID devices
+ dev->destroy = usb_hid_destroy;
+ dev->poll = usb_hid_poll;
+ int i;
+ for (i = 0; i <= dev->num_endp; i++) {
+ if (dev->endpoints[i].endpoint == 0)
+ continue;
+ if (dev->endpoints[i].type != INTERRUPT)
+ continue;
+ if (dev->endpoints[i].direction != IN)
+ continue;
+ break;
+ }
+ usb_debug (" found endpoint %x for interrupt-in\n", i);
+ /* 20 buffers of 8 bytes, for every 10 msecs */
+ HID_INST(dev)->queue = dev->controller->create_intr_queue (&dev->endpoints[i], 8, 20, 10);
+ keycount = 0;
+ usb_debug (" configuration done.\n");
+ break;
+ default:
+ usb_debug("NOTICE: HID interface protocol %d%s not supported.\n",
+ interface->bInterfaceProtocol,
+ (interface->bInterfaceProtocol == hid_boot_proto_mouse ?
+ " (USB mouse)" : ""));
+ break;
+ }
+ }
+}
+
+static int usbhid_havechar (void)
+{
+ return (keycount != 0);
+}
+
+static int usbhid_getchar (void)
+{
+ short ret;
+
+ if (keycount == 0)
+ return 0;
+ ret = keybuffer[0];
+ memmove(keybuffer, keybuffer + 1, --keycount);
+
+ return (int)ret;
+}
+
+/* ( addr len -- actual ) */
+static void keyboard_read(void)
+{
+ char *addr;
+ int len, key, i;
+
+ usb_poll();
+ len=POP();
+ addr=(char *)cell2pointer(POP());
+
+ for (i = 0; i < len; i++) {
+ if (!usbhid_havechar())
+ break;
+ key = usbhid_getchar();
+ *addr++ = (char)key;
+ }
+ PUSH(i);
+}
+
+void ob_usb_hid_add_keyboard(const char *path)
+{
+ char name[128];
+ phandle_t aliases;
+
+ snprintf(name, sizeof(name), "%s/keyboard", path);
+ usb_debug("Found keyboard at %s\n", name);
+ REGISTER_NAMED_NODE(usb_kbd, name);
+
+ push_str(name);
+ fword("find-device");
+
+ push_str("keyboard");
+ fword("device-type");
+
+ aliases = find_dev("/aliases");
+ set_property(aliases, "adb-keyboard", name, strlen(name) + 1);
+}
diff --git a/roms/openbios/drivers/usbohci.c b/roms/openbios/drivers/usbohci.c
new file mode 100644
index 00000000..774164b0
--- /dev/null
+++ b/roms/openbios/drivers/usbohci.c
@@ -0,0 +1,926 @@
+/*
+ * Driver for USB OHCI ported from CoreBoot
+ *
+ * Copyright (C) 2014 BALATON Zoltan
+ *
+ * This file was part of the libpayload project.
+ *
+ * Copyright (C) 2010 Patrick Georgi
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+//#define USB_DEBUG_ED
+
+#include "config.h"
+#include <asm/io.h>
+#include <libopenbios/ofmem.h>
+#include "timer.h"
+#include "drivers/pci.h"
+#include "pci.h"
+#include <drivers/usb.h>
+#include "usbohci_private.h"
+#include "usbohci.h"
+
+static void ohci_start (hci_t *controller);
+static void ohci_stop (hci_t *controller);
+static void ohci_reset (hci_t *controller);
+static void ohci_shutdown (hci_t *controller);
+static int ohci_bulk (endpoint_t *ep, int size, u8 *data, int finalize);
+static int ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq,
+ int dalen, u8 *data);
+static void* ohci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
+static void ohci_destroy_intr_queue (endpoint_t *ep, void *queue);
+static u8* ohci_poll_intr_queue (void *queue);
+static void ohci_process_done_queue(ohci_t *ohci, int spew_debug);
+
+#ifdef USB_DEBUG_ED
+static void
+dump_td (td_t *cur)
+{
+ usb_debug("+---------------------------------------------------+\n");
+ if (((__le32_to_cpu(cur->config) & (3UL << 19)) >> 19) == 0)
+ usb_debug("|..[SETUP]..........................................|\n");
+ else if (((__le32_to_cpu(cur->config) & (3UL << 8)) >> 8) == 2)
+ usb_debug("|..[IN].............................................|\n");
+ else if (((__le32_to_cpu(cur->config) & (3UL << 8)) >> 8) == 1)
+ usb_debug("|..[OUT]............................................|\n");
+ else
+ usb_debug("|..[]...............................................|\n");
+ usb_debug("|:|============ OHCI TD at [0x%08lx] ==========|:|\n", virt_to_phys(cur));
+ usb_debug("|:| ERRORS = [%ld] | CONFIG = [0x%08x] | |:|\n",
+ 3 - ((__le32_to_cpu(cur->config) & (3UL << 26)) >> 26), __le32_to_cpu(cur->config));
+ usb_debug("|:+-----------------------------------------------+:|\n");
+ usb_debug("|:| C | Condition Code | [%02ld] |:|\n",
+ (__le32_to_cpu(cur->config) & (0xFUL << 28)) >> 28);
+ usb_debug("|:| O | Direction/PID | [%ld] |:|\n",
+ (__le32_to_cpu(cur->config) & (3UL << 19)) >> 19);
+ usb_debug("|:| N | Buffer Rounding | [%ld] |:|\n",
+ (__le32_to_cpu(cur->config) & (1UL << 18)) >> 18);
+ usb_debug("|:| F | Delay Intterrupt | [%ld] |:|\n",
+ (__le32_to_cpu(cur->config) & (7UL << 21)) >> 21);
+ usb_debug("|:| I | Data Toggle | [%ld] |:|\n",
+ (__le32_to_cpu(cur->config) & (3UL << 24)) >> 24);
+ usb_debug("|:| G | Error Count | [%ld] |:|\n",
+ (__le32_to_cpu(cur->config) & (3UL << 26)) >> 26);
+ usb_debug("|:+-----------------------------------------------+:|\n");
+ usb_debug("|:| Current Buffer Pointer [0x%08x] |:|\n", __le32_to_cpu(cur->current_buffer_pointer));
+ usb_debug("|:+-----------------------------------------------+:|\n");
+ usb_debug("|:| Next TD [0x%08x] |:|\n", __le32_to_cpu(cur->next_td));
+ usb_debug("|:+-----------------------------------------------+:|\n");
+ usb_debug("|:| Current Buffer End [0x%08x] |:|\n", __le32_to_cpu(cur->buffer_end));
+ usb_debug("|:|-----------------------------------------------|:|\n");
+ usb_debug("|...................................................|\n");
+ usb_debug("+---------------------------------------------------+\n");
+}
+
+static void
+dump_ed (ed_t *cur)
+{
+ td_t *tmp_td = NULL;
+ usb_debug("+===================================================+\n");
+ usb_debug("| ############# OHCI ED at [0x%08lx] ########### |\n", virt_to_phys(cur));
+ usb_debug("+---------------------------------------------------+\n");
+ usb_debug("| Next Endpoint Descriptor [0x%08lx] |\n", __le32_to_cpu(cur->next_ed) & ~0xFUL);
+ usb_debug("+---------------------------------------------------+\n");
+ usb_debug("| | @ 0x%08x : |\n", __le32_to_cpu(cur->config));
+ usb_debug("| C | Maximum Packet Length | [%04ld] |\n",
+ ((__le32_to_cpu(cur->config) & (0x3fffUL << 16)) >> 16));
+ usb_debug("| O | Function Address | [%04d] |\n",
+ __le32_to_cpu(cur->config) & 0x7F);
+ usb_debug("| N | Endpoint Number | [%02ld] |\n",
+ (__le32_to_cpu(cur->config) & (0xFUL << 7)) >> 7);
+ usb_debug("| F | Endpoint Direction | [%ld] |\n",
+ ((__le32_to_cpu(cur->config) & (3UL << 11)) >> 11));
+ usb_debug("| I | Endpoint Speed | [%ld] |\n",
+ ((__le32_to_cpu(cur->config) & (1UL << 13)) >> 13));
+ usb_debug("| G | Skip | [%ld] |\n",
+ ((__le32_to_cpu(cur->config) & (1UL << 14)) >> 14));
+ usb_debug("| | Format | [%ld] |\n",
+ ((__le32_to_cpu(cur->config) & (1UL << 15)) >> 15));
+ usb_debug("+---------------------------------------------------+\n");
+ usb_debug("| TD Queue Tail Pointer [0x%08lx] |\n",
+ __le32_to_cpu(cur->tail_pointer) & ~0xFUL);
+ usb_debug("+---------------------------------------------------+\n");
+ usb_debug("| TD Queue Head Pointer [0x%08lx] |\n",
+ __le32_to_cpu(cur->head_pointer) & ~0xFUL);
+ usb_debug("| CarryToggleBit [%d] Halted [%d] |\n",
+ (u16)(__le32_to_cpu(cur->head_pointer) & 0x2UL)>>1, (u16)(__le32_to_cpu(cur->head_pointer) & 0x1UL));
+
+ tmp_td = (td_t *)phys_to_virt((__le32_to_cpu(cur->head_pointer) & ~0xFUL));
+ if ((__le32_to_cpu(cur->head_pointer) & ~0xFUL) != (__le32_to_cpu(cur->tail_pointer) & ~0xFUL)) {
+ usb_debug("|:::::::::::::::::: OHCI TD CHAIN ::::::::::::::::::|\n");
+ while (virt_to_phys(tmp_td) != (__le32_to_cpu(cur->tail_pointer) & ~0xFUL))
+ {
+ dump_td(tmp_td);
+ tmp_td = (td_t *)phys_to_virt((__le32_to_cpu(tmp_td->next_td) & ~0xFUL));
+ }
+ usb_debug("|:::::::::::::::: EOF OHCI TD CHAIN ::::::::::::::::|\n");
+ usb_debug("+---------------------------------------------------+\n");
+ } else {
+ usb_debug("+---------------------------------------------------+\n");
+ }
+}
+#endif
+
+static void
+ohci_reset (hci_t *controller)
+{
+ if (controller == NULL)
+ return;
+
+ OHCI_INST(controller)->opreg->HcCommandStatus = __cpu_to_le32(HostControllerReset);
+ mdelay(2); /* wait 2ms */
+ OHCI_INST(controller)->opreg->HcControl = 0;
+ mdelay(10); /* wait 10ms */
+}
+
+static void
+ohci_reinit (hci_t *controller)
+{
+}
+
+hci_t *
+ohci_init (void *bar)
+{
+ int i;
+
+ hci_t *controller = new_controller ();
+
+ if (!controller) {
+ printk("Could not create USB controller instance.\n");
+ return NULL;
+ }
+
+ controller->instance = malloc (sizeof (ohci_t));
+ if(!controller->instance) {
+ printk("Not enough memory creating USB controller instance.\n");
+ return NULL;
+ }
+
+ controller->type = OHCI;
+
+ controller->start = ohci_start;
+ controller->stop = ohci_stop;
+ controller->reset = ohci_reset;
+ controller->init = ohci_reinit;
+ controller->shutdown = ohci_shutdown;
+ controller->bulk = ohci_bulk;
+ controller->control = ohci_control;
+ controller->set_address = generic_set_address;
+ controller->finish_device_config = NULL;
+ controller->destroy_device = NULL;
+ controller->create_intr_queue = ohci_create_intr_queue;
+ controller->destroy_intr_queue = ohci_destroy_intr_queue;
+ controller->poll_intr_queue = ohci_poll_intr_queue;
+ for (i = 0; i < 128; i++) {
+ controller->devices[i] = 0;
+ }
+ init_device_entry (controller, 0);
+ OHCI_INST (controller)->roothub = controller->devices[0];
+
+ controller->reg_base = (u32)(unsigned long)bar;
+ OHCI_INST (controller)->opreg = (opreg_t*)phys_to_virt(controller->reg_base);
+ usb_debug("OHCI Version %x.%x\n",
+ (READ_OPREG(OHCI_INST(controller), HcRevision) >> 4) & 0xf,
+ READ_OPREG(OHCI_INST(controller), HcRevision) & 0xf);
+
+ if ((READ_OPREG(OHCI_INST(controller), HcControl) & HostControllerFunctionalStateMask) == USBReset) {
+ /* cold boot */
+ OHCI_INST (controller)->opreg->HcControl &= __cpu_to_le32(~RemoteWakeupConnected);
+ OHCI_INST (controller)->opreg->HcFmInterval =
+ __cpu_to_le32((11999 * FrameInterval) | ((((11999 - 210)*6)/7) * FSLargestDataPacket));
+ /* TODO: right value for PowerOnToPowerGoodTime ? */
+ OHCI_INST (controller)->opreg->HcRhDescriptorA =
+ __cpu_to_le32(NoPowerSwitching | NoOverCurrentProtection | (10 * PowerOnToPowerGoodTime));
+ OHCI_INST (controller)->opreg->HcRhDescriptorB = __cpu_to_le32(0 * DeviceRemovable);
+ udelay(100); /* TODO: reset asserting according to USB spec */
+ } else if ((READ_OPREG(OHCI_INST(controller), HcControl) & HostControllerFunctionalStateMask) != USBOperational) {
+ OHCI_INST (controller)->opreg->HcControl =
+ __cpu_to_le32((READ_OPREG(OHCI_INST(controller), HcControl) & ~HostControllerFunctionalStateMask)
+ | USBResume);
+ udelay(100); /* TODO: resume time according to USB spec */
+ }
+ int interval = OHCI_INST (controller)->opreg->HcFmInterval;
+
+ OHCI_INST (controller)->opreg->HcCommandStatus = __cpu_to_le32(HostControllerReset);
+ udelay (10); /* at most 10us for reset to complete. State must be set to Operational within 2ms (5.1.1.4) */
+ OHCI_INST (controller)->opreg->HcFmInterval = interval;
+ ofmem_posix_memalign((void **)&(OHCI_INST (controller)->hcca), 256, 256);
+ memset((void*)OHCI_INST (controller)->hcca, 0, 256);
+
+ usb_debug("HCCA addr %p\n", OHCI_INST(controller)->hcca);
+ /* Initialize interrupt table. */
+ u32 *const intr_table = OHCI_INST(controller)->hcca->HccaInterruptTable;
+ ed_t *const periodic_ed;
+ ofmem_posix_memalign((void **)&periodic_ed, sizeof(ed_t), sizeof(ed_t));
+ memset((void *)periodic_ed, 0, sizeof(*periodic_ed));
+ for (i = 0; i < 32; ++i)
+ intr_table[i] = __cpu_to_le32(virt_to_phys(periodic_ed));
+ OHCI_INST (controller)->periodic_ed = periodic_ed;
+
+ OHCI_INST (controller)->opreg->HcHCCA = __cpu_to_le32(virt_to_phys(OHCI_INST(controller)->hcca));
+ /* Make sure periodic schedule is enabled. */
+ OHCI_INST (controller)->opreg->HcControl |= __cpu_to_le32(PeriodicListEnable);
+ OHCI_INST (controller)->opreg->HcControl &= __cpu_to_le32(~IsochronousEnable); // unused by this driver
+ // disable everything, contrary to what OHCI spec says in 5.1.1.4, as we don't need IRQs
+ OHCI_INST (controller)->opreg->HcInterruptEnable = __cpu_to_le32(1<<31);
+ OHCI_INST (controller)->opreg->HcInterruptDisable = __cpu_to_le32(~(1<<31));
+ OHCI_INST (controller)->opreg->HcInterruptStatus = __cpu_to_le32(~0);
+ OHCI_INST (controller)->opreg->HcPeriodicStart =
+ __cpu_to_le32((READ_OPREG(OHCI_INST(controller), HcFmInterval) & FrameIntervalMask) / 10 * 9);
+ OHCI_INST (controller)->opreg->HcControl = __cpu_to_le32((READ_OPREG(OHCI_INST(controller), HcControl)
+ & ~HostControllerFunctionalStateMask) | USBOperational);
+
+ mdelay(100);
+
+ controller->devices[0]->controller = controller;
+ controller->devices[0]->init = ohci_rh_init;
+ controller->devices[0]->init (controller->devices[0]);
+ return controller;
+}
+
+hci_t *
+ohci_pci_init (pci_addr addr)
+{
+ u32 reg_base;
+ uint16_t cmd;
+
+ cmd = pci_config_read16(addr, PCI_COMMAND);
+ cmd |= PCI_COMMAND_BUS_MASTER;
+ pci_config_write16(addr, PCI_COMMAND, cmd);
+
+ /* regarding OHCI spec, Appendix A, BAR_OHCI register description, Table A-4
+ * BASE ADDRESS only [31-12] bits. All other usually 0, but not all.
+ * OHCI mandates MMIO, so bit 0 is clear */
+ reg_base = pci_config_read32 (addr, PCI_BASE_ADDR_0) & 0xfffff000;
+
+ return ohci_init((void *)(unsigned long)reg_base);
+}
+
+static void
+ohci_shutdown (hci_t *controller)
+{
+ if (controller == 0)
+ return;
+ detach_controller (controller);
+ ohci_stop(controller);
+ OHCI_INST (controller)->roothub->destroy (OHCI_INST (controller)->
+ roothub);
+ controller->reset (controller);
+ free ((void *)OHCI_INST (controller)->periodic_ed);
+ free (OHCI_INST (controller));
+ free (controller);
+}
+
+static void
+ohci_start (hci_t *controller)
+{
+// TODO: turn on all operation of OHCI, but assume that it's initialized.
+}
+
+static void
+ohci_stop (hci_t *controller)
+{
+// TODO: turn off all operation of OHCI
+}
+
+static int
+wait_for_ed(usbdev_t *dev, ed_t *head, int pages)
+{
+ usb_debug("Waiting for %d pages on dev %p with head %p\n", pages, dev, head);
+ /* wait for results */
+ /* TOTEST: how long to wait?
+ * give 2s per TD (2 pages) plus another 2s for now
+ */
+ int timeout = pages*1000 + 2000;
+ while (((__le32_to_cpu(head->head_pointer) & ~3) != __le32_to_cpu(head->tail_pointer)) &&
+ !(__le32_to_cpu(head->head_pointer) & 1) &&
+ ((__le32_to_cpu((((td_t*)phys_to_virt(__le32_to_cpu(head->head_pointer) & ~3)))->config)
+ & TD_CC_MASK) >= TD_CC_NOACCESS) && timeout--) {
+ /* don't log every ms */
+ if (!(timeout % 100))
+ usb_debug("intst: %x; ctrl: %x; cmdst: %x; head: %x -> %x, tail: %x, condition: %x\n",
+ READ_OPREG(OHCI_INST(dev->controller), HcInterruptStatus),
+ READ_OPREG(OHCI_INST(dev->controller), HcControl),
+ READ_OPREG(OHCI_INST(dev->controller), HcCommandStatus),
+ __le32_to_cpu(head->head_pointer),
+ __le32_to_cpu(((td_t*)phys_to_virt(__le32_to_cpu(head->head_pointer) & ~3))->next_td),
+ __le32_to_cpu(head->tail_pointer),
+ (__le32_to_cpu(((td_t*)phys_to_virt(__le32_to_cpu(head->head_pointer) & ~3))->config) & TD_CC_MASK) >> TD_CC_SHIFT);
+ mdelay(1);
+ }
+ if (timeout < 0)
+ usb_debug("Error: ohci: endpoint "
+ "descriptor processing timed out.\n");
+ /* Clear the done queue. */
+ ohci_process_done_queue(OHCI_INST(dev->controller), 1);
+
+ if (__le32_to_cpu(head->head_pointer) & 1) {
+ usb_debug("HALTED!\n");
+ return 1;
+ }
+ return 0;
+}
+
+static void
+ohci_free_ed (ed_t *const head)
+{
+ /* In case the transfer canceled, we have to free unprocessed TDs. */
+ while ((__le32_to_cpu(head->head_pointer) & ~0x3) != __le32_to_cpu(head->tail_pointer)) {
+ /* Save current TD pointer. */
+ td_t *const cur_td =
+ (td_t*)phys_to_virt(__le32_to_cpu(head->head_pointer) & ~0x3);
+ /* Advance head pointer. */
+ head->head_pointer = cur_td->next_td;
+ /* Free current TD. */
+ free((void *)cur_td);
+ }
+
+ /* Always free the dummy TD */
+ if ((__le32_to_cpu(head->head_pointer) & ~0x3) == __le32_to_cpu(head->tail_pointer))
+ free(phys_to_virt(__le32_to_cpu(head->head_pointer) & ~0x3));
+ /* and the ED. */
+ free((void *)head);
+}
+
+static int
+ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen,
+ unsigned char *data)
+{
+ td_t *cur;
+
+ // pages are specified as 4K in OHCI, so don't use getpagesize()
+ int first_page = (unsigned long)data / 4096;
+ int last_page = (unsigned long)(data+dalen-1)/4096;
+ if (last_page < first_page) last_page = first_page;
+ int pages = (dalen==0)?0:(last_page - first_page + 1);
+
+ /* First TD. */
+ td_t *const first_td;
+ ofmem_posix_memalign((void **)&first_td, sizeof(td_t), sizeof(td_t));
+ memset((void *)first_td, 0, sizeof(*first_td));
+ cur = first_td;
+
+ cur->config = __cpu_to_le32(TD_DIRECTION_SETUP |
+ TD_DELAY_INTERRUPT_NOINTR |
+ TD_TOGGLE_FROM_TD |
+ TD_TOGGLE_DATA0 |
+ TD_CC_NOACCESS);
+ cur->current_buffer_pointer = __cpu_to_le32(virt_to_phys(devreq));
+ cur->buffer_end = __cpu_to_le32(virt_to_phys((char *)devreq + drlen - 1));
+
+ while (pages > 0) {
+ /* One more TD. */
+ td_t *const next;
+ ofmem_posix_memalign((void **)&next, sizeof(td_t), sizeof(td_t));
+ memset((void *)next, 0, sizeof(*next));
+ /* Linked to the previous. */
+ cur->next_td = __cpu_to_le32(virt_to_phys(next));
+ /* Advance to the new TD. */
+ cur = next;
+
+ cur->config = __cpu_to_le32((dir == IN ? TD_DIRECTION_IN : TD_DIRECTION_OUT) |
+ TD_DELAY_INTERRUPT_NOINTR |
+ TD_TOGGLE_FROM_ED |
+ TD_CC_NOACCESS);
+ cur->current_buffer_pointer = __cpu_to_le32(virt_to_phys(data));
+ pages--;
+ int consumed = (4096 - ((unsigned long)data % 4096));
+ if (consumed >= dalen) {
+ // end of data is within same page
+ cur->buffer_end = __cpu_to_le32(virt_to_phys(data + dalen - 1));
+ dalen = 0;
+ /* assert(pages == 0); */
+ } else {
+ dalen -= consumed;
+ data += consumed;
+ pages--;
+ int second_page_size = dalen;
+ if (dalen > 4096) {
+ second_page_size = 4096;
+ }
+ cur->buffer_end = __cpu_to_le32(virt_to_phys(data + second_page_size - 1));
+ dalen -= second_page_size;
+ data += second_page_size;
+ }
+ }
+
+ /* One more TD. */
+ td_t *const next_td;
+ ofmem_posix_memalign((void **)&next_td, sizeof(td_t), sizeof(td_t));
+ memset((void *)next_td, 0, sizeof(*next_td));
+ /* Linked to the previous. */
+ cur->next_td = __cpu_to_le32(virt_to_phys(next_td));
+ /* Advance to the new TD. */
+ cur = next_td;
+ cur->config = __cpu_to_le32((dir == IN ? TD_DIRECTION_OUT : TD_DIRECTION_IN) |
+ TD_DELAY_INTERRUPT_ZERO | /* Write done head after this TD. */
+ TD_TOGGLE_FROM_TD |
+ TD_TOGGLE_DATA1 |
+ TD_CC_NOACCESS);
+ cur->current_buffer_pointer = 0;
+ cur->buffer_end = 0;
+
+ /* Final dummy TD. */
+ td_t *const final_td;
+ ofmem_posix_memalign((void **)&final_td, sizeof(td_t), sizeof(td_t));
+ memset((void *)final_td, 0, sizeof(*final_td));
+ /* Linked to the previous. */
+ cur->next_td = __cpu_to_le32(virt_to_phys(final_td));
+
+ /* Data structures */
+ ed_t *head;
+ ofmem_posix_memalign((void **)&head, sizeof(ed_t), sizeof(ed_t));
+ memset((void*)head, 0, sizeof(*head));
+ head->config = __cpu_to_le32((dev->address << ED_FUNC_SHIFT) |
+ (0 << ED_EP_SHIFT) |
+ (OHCI_FROM_TD << ED_DIR_SHIFT) |
+ (dev->speed?ED_LOWSPEED:0) |
+ (dev->endpoints[0].maxpacketsize << ED_MPS_SHIFT));
+ head->tail_pointer = __cpu_to_le32(virt_to_phys(final_td));
+ head->head_pointer = __cpu_to_le32(virt_to_phys(first_td));
+
+ usb_debug("ohci_control(): doing transfer with %x. first_td at %x\n",
+ __le32_to_cpu(head->config) & ED_FUNC_MASK, __le32_to_cpu(head->head_pointer));
+#ifdef USB_DEBUG_ED
+ dump_ed(head);
+#endif
+
+ /* activate schedule */
+ OHCI_INST(dev->controller)->opreg->HcControlHeadED = __cpu_to_le32(virt_to_phys(head));
+ OHCI_INST(dev->controller)->opreg->HcControl |= __cpu_to_le32(ControlListEnable);
+ OHCI_INST(dev->controller)->opreg->HcCommandStatus = __cpu_to_le32(ControlListFilled);
+
+ int failure = wait_for_ed(dev, head,
+ (dalen==0)?0:(last_page - first_page + 1));
+ /* Wait some frames before and one after disabling list access. */
+ mdelay(4);
+ OHCI_INST(dev->controller)->opreg->HcControl &= __cpu_to_le32(~ControlListEnable);
+ mdelay(1);
+
+ /* free memory */
+ ohci_free_ed(head);
+
+ return failure;
+}
+
+/* finalize == 1: if data is of packet aligned size, add a zero length packet */
+static int
+ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize)
+{
+ int i;
+ usb_debug("bulk: %x bytes from %p, finalize: %x, maxpacketsize: %x\n", dalen, data, finalize, ep->maxpacketsize);
+
+ td_t *cur, *next;
+
+ // pages are specified as 4K in OHCI, so don't use getpagesize()
+ int first_page = (unsigned long)data / 4096;
+ int last_page = (unsigned long)(data+dalen-1)/4096;
+ if (last_page < first_page) last_page = first_page;
+ int pages = (dalen==0)?0:(last_page - first_page + 1);
+ int td_count = (pages+1)/2;
+
+ if (finalize && ((dalen % ep->maxpacketsize) == 0)) {
+ td_count++;
+ }
+
+ /* First TD. */
+ td_t *const first_td;
+ ofmem_posix_memalign((void **)&first_td, sizeof(td_t), sizeof(td_t));
+ memset((void *)first_td, 0, sizeof(*first_td));
+ cur = next = first_td;
+
+ for (i = 0; i < td_count; ++i) {
+ /* Advance to next TD. */
+ cur = next;
+ cur->config = __cpu_to_le32((ep->direction == IN ? TD_DIRECTION_IN : TD_DIRECTION_OUT) |
+ TD_DELAY_INTERRUPT_NOINTR |
+ TD_TOGGLE_FROM_ED |
+ TD_CC_NOACCESS);
+ cur->current_buffer_pointer = __cpu_to_le32(virt_to_phys(data));
+ pages--;
+ if (dalen == 0) {
+ /* magic TD for empty packet transfer */
+ cur->current_buffer_pointer = 0;
+ cur->buffer_end = 0;
+ /* assert((pages == 0) && finalize); */
+ }
+ int consumed = (4096 - ((unsigned long)data % 4096));
+ if (consumed >= dalen) {
+ // end of data is within same page
+ cur->buffer_end = __cpu_to_le32(virt_to_phys(data + dalen - 1));
+ dalen = 0;
+ /* assert(pages == finalize); */
+ } else {
+ dalen -= consumed;
+ data += consumed;
+ pages--;
+ int second_page_size = dalen;
+ if (dalen > 4096) {
+ second_page_size = 4096;
+ }
+ cur->buffer_end = __cpu_to_le32(virt_to_phys(data + second_page_size - 1));
+ dalen -= second_page_size;
+ data += second_page_size;
+ }
+ /* One more TD. */
+ ofmem_posix_memalign((void **)&next, sizeof(td_t), sizeof(td_t));
+ memset((void *)next, 0, sizeof(*next));
+ /* Linked to the previous. */
+ cur->next_td = __cpu_to_le32(virt_to_phys(next));
+ }
+
+ /* Write done head after last TD. */
+ cur->config &= __cpu_to_le32(~TD_DELAY_INTERRUPT_MASK);
+ /* Advance to final, dummy TD. */
+ cur = next;
+
+ /* Data structures */
+ ed_t *head;
+ ofmem_posix_memalign((void **)&head, sizeof(ed_t), sizeof(ed_t));
+ memset((void*)head, 0, sizeof(*head));
+ head->config = __cpu_to_le32((ep->dev->address << ED_FUNC_SHIFT) |
+ ((ep->endpoint & 0xf) << ED_EP_SHIFT) |
+ (((ep->direction==IN)?OHCI_IN:OHCI_OUT) << ED_DIR_SHIFT) |
+ (ep->dev->speed?ED_LOWSPEED:0) |
+ (ep->maxpacketsize << ED_MPS_SHIFT));
+ head->tail_pointer = __cpu_to_le32(virt_to_phys(cur));
+ head->head_pointer = __cpu_to_le32(virt_to_phys(first_td) | (ep->toggle?ED_TOGGLE:0));
+
+ usb_debug("doing bulk transfer with %x(%x). first_td at %lx, last %lx\n",
+ __le32_to_cpu(head->config) & ED_FUNC_MASK,
+ (__le32_to_cpu(head->config) & ED_EP_MASK) >> ED_EP_SHIFT,
+ virt_to_phys(first_td), virt_to_phys(cur));
+
+ /* activate schedule */
+ OHCI_INST(ep->dev->controller)->opreg->HcBulkHeadED = __cpu_to_le32(virt_to_phys(head));
+ OHCI_INST(ep->dev->controller)->opreg->HcControl |= __cpu_to_le32(BulkListEnable);
+ OHCI_INST(ep->dev->controller)->opreg->HcCommandStatus = __cpu_to_le32(BulkListFilled);
+
+ int failure = wait_for_ed(ep->dev, head,
+ (dalen==0)?0:(last_page - first_page + 1));
+ /* Wait some frames before and one after disabling list access. */
+ mdelay(4);
+ OHCI_INST(ep->dev->controller)->opreg->HcControl &= __cpu_to_le32(~BulkListEnable);
+ mdelay(1);
+
+ ep->toggle = __le32_to_cpu(head->head_pointer) & ED_TOGGLE;
+
+ /* free memory */
+ ohci_free_ed(head);
+
+ if (failure) {
+ /* try cleanup */
+ clear_stall(ep);
+ }
+
+ return failure;
+}
+
+
+struct _intr_queue;
+
+struct _intrq_td {
+ volatile td_t td;
+ u8 *data;
+ struct _intrq_td *next;
+ struct _intr_queue *intrq;
+};
+
+struct _intr_queue {
+ volatile ed_t ed;
+ struct _intrq_td *head;
+ struct _intrq_td *tail;
+ u8 *data;
+ int reqsize;
+ endpoint_t *endp;
+ unsigned int remaining_tds;
+ int destroy;
+};
+
+typedef struct _intrq_td intrq_td_t;
+typedef struct _intr_queue intr_queue_t;
+
+#define INTRQ_TD_FROM_TD(x) ((intrq_td_t *)x)
+
+static void
+ohci_fill_intrq_td(intrq_td_t *const td, intr_queue_t *const intrq,
+ u8 *const data)
+{
+ memset(td, 0, sizeof(*td));
+ td->td.config = __cpu_to_le32(TD_QUEUETYPE_INTR |
+ (intrq->endp->direction == IN ? TD_DIRECTION_IN : TD_DIRECTION_OUT) |
+ TD_DELAY_INTERRUPT_ZERO |
+ TD_TOGGLE_FROM_ED |
+ TD_CC_NOACCESS);
+ td->td.current_buffer_pointer = __cpu_to_le32(virt_to_phys(data));
+ td->td.buffer_end = __cpu_to_le32(virt_to_phys(data) + intrq->reqsize - 1);
+ td->intrq = intrq;
+ td->data = data;
+}
+
+/* create and hook-up an intr queue into device schedule */
+static void *
+ohci_create_intr_queue(endpoint_t *const ep, const int reqsize,
+ const int reqcount, const int reqtiming)
+{
+ int i;
+ intrq_td_t *first_td = NULL, *last_td = NULL;
+
+ if (reqsize > 4096)
+ return NULL;
+
+ intr_queue_t *const intrq;
+ ofmem_posix_memalign((void **)&intrq, sizeof(intrq->ed), sizeof(*intrq));
+ memset(intrq, 0, sizeof(*intrq));
+ intrq->data = (u8 *)malloc(reqcount * reqsize);
+ intrq->reqsize = reqsize;
+ intrq->endp = ep;
+
+ /* Create #reqcount TDs. */
+ u8 *cur_data = intrq->data;
+ for (i = 0; i < reqcount; ++i) {
+ intrq_td_t *const td;
+ ofmem_posix_memalign((void **)&td, sizeof(td->td), sizeof(*td));
+ ++intrq->remaining_tds;
+ ohci_fill_intrq_td(td, intrq, cur_data);
+ cur_data += reqsize;
+ if (!first_td)
+ first_td = td;
+ else
+ last_td->td.next_td = __cpu_to_le32(virt_to_phys(&td->td));
+ last_td = td;
+ }
+
+ /* Create last, dummy TD. */
+ intrq_td_t *dummy_td;
+ ofmem_posix_memalign((void **)&dummy_td, sizeof(dummy_td->td), sizeof(*dummy_td));
+ memset(dummy_td, 0, sizeof(*dummy_td));
+ dummy_td->intrq = intrq;
+ if (last_td)
+ last_td->td.next_td = __cpu_to_le32(virt_to_phys(&dummy_td->td));
+ last_td = dummy_td;
+
+ /* Initialize ED. */
+ intrq->ed.config = __cpu_to_le32((ep->dev->address << ED_FUNC_SHIFT) |
+ ((ep->endpoint & 0xf) << ED_EP_SHIFT) |
+ (((ep->direction == IN) ? OHCI_IN : OHCI_OUT) << ED_DIR_SHIFT) |
+ (ep->dev->speed ? ED_LOWSPEED : 0) |
+ (ep->maxpacketsize << ED_MPS_SHIFT));
+ intrq->ed.tail_pointer = __cpu_to_le32(virt_to_phys(last_td));
+ intrq->ed.head_pointer = __cpu_to_le32(virt_to_phys(first_td) | (ep->toggle ? ED_TOGGLE : 0));
+
+#ifdef USB_DEBUG_ED
+ dump_ed(&intrq->ed);
+#endif
+ /* Insert ED into periodic table. */
+ int nothing_placed = 1;
+ ohci_t *const ohci = OHCI_INST(ep->dev->controller);
+ u32 *const intr_table = ohci->hcca->HccaInterruptTable;
+ const u32 dummy_ptr = __cpu_to_le32(virt_to_phys(ohci->periodic_ed));
+ for (i = 0; i < 32; i += reqtiming) {
+ /* Advance to the next free position. */
+ while ((i < 32) && (intr_table[i] != dummy_ptr)) ++i;
+ if (i < 32) {
+ usb_debug("Placed endpoint %lx to %d\n", virt_to_phys(&intrq->ed), i);
+ intr_table[i] = __cpu_to_le32(virt_to_phys(&intrq->ed));
+ nothing_placed = 0;
+ }
+ }
+ if (nothing_placed) {
+ usb_debug("Error: Failed to place ohci interrupt endpoint "
+ "descriptor into periodic table: no space left\n");
+ ohci_destroy_intr_queue(ep, intrq);
+ return NULL;
+ }
+
+ return intrq;
+}
+
+/* remove queue from device schedule, dropping all data that came in */
+static void
+ohci_destroy_intr_queue(endpoint_t *const ep, void *const q_)
+{
+ intr_queue_t *const intrq = (intr_queue_t *)q_;
+
+ int i;
+
+ /* Remove interrupt queue from periodic table. */
+ ohci_t *const ohci = OHCI_INST(ep->dev->controller);
+ u32 *const intr_table = ohci->hcca->HccaInterruptTable;
+ for (i=0; i < 32; ++i) {
+ if (intr_table[i] == __cpu_to_le32(virt_to_phys(intrq)))
+ intr_table[i] = __cpu_to_le32(virt_to_phys(ohci->periodic_ed));
+ }
+ /* Wait for frame to finish. */
+ mdelay(1);
+
+ /* Free unprocessed TDs. */
+ while ((__le32_to_cpu(intrq->ed.head_pointer) & ~0x3) != __le32_to_cpu(intrq->ed.tail_pointer)) {
+ td_t *const cur_td = (td_t *)phys_to_virt(__le32_to_cpu(intrq->ed.head_pointer) & ~0x3);
+ intrq->ed.head_pointer = cur_td->next_td;
+ free(INTRQ_TD_FROM_TD(cur_td));
+ --intrq->remaining_tds;
+ }
+ /* Free final, dummy TD. */
+ free(phys_to_virt(__le32_to_cpu(intrq->ed.head_pointer) & ~0x3));
+ /* Free data buffer. */
+ free(intrq->data);
+
+ /* Free TDs already fetched from the done queue. */
+ ohci_process_done_queue(ohci, 1);
+ while (intrq->head) {
+ intrq_td_t *const cur_td = (intrq_td_t *const )__le32_to_cpu(intrq->head);
+ intrq->head = intrq->head->next;
+ free(cur_td);
+ --intrq->remaining_tds;
+ }
+
+ /* Mark interrupt queue to be destroyed.
+ ohci_process_done_queue() will free the remaining TDs
+ and finish the interrupt queue off once all TDs are gone. */
+ intrq->destroy = 1;
+
+ /* Save data toggle. */
+ ep->toggle = __le32_to_cpu(intrq->ed.head_pointer) & ED_TOGGLE;
+}
+
+/* read one intr-packet from queue, if available. extend the queue for new input.
+ return NULL if nothing new available.
+ Recommended use: while (data=poll_intr_queue(q)) process(data);
+ */
+static u8 *
+ohci_poll_intr_queue(void *const q_)
+{
+ intr_queue_t *const intrq = (intr_queue_t *)q_;
+
+ u8 *data = NULL;
+
+ /* Process done queue first, then check if we have work to do. */
+ ohci_process_done_queue(OHCI_INST(intrq->endp->dev->controller), 0);
+
+ if (intrq->head) {
+ /* Save pointer to processed TD and advance. */
+ intrq_td_t *const cur_td = intrq->head;
+ intrq->head = cur_td->next;
+
+ /* Return data buffer of this TD. */
+ data = cur_td->data;
+
+ /* Requeue this TD (i.e. copy to dummy and requeue as dummy). */
+ intrq_td_t *const dummy_td =
+ INTRQ_TD_FROM_TD(phys_to_virt(__le32_to_cpu(intrq->ed.tail_pointer)));
+ ohci_fill_intrq_td(dummy_td, intrq, data);
+ /* Reset all but intrq pointer (i.e. init as dummy). */
+ memset(cur_td, 0, sizeof(*cur_td));
+ cur_td->intrq = intrq;
+ /* Insert into interrupt queue as dummy. */
+ dummy_td->td.next_td = __le32_to_cpu(virt_to_phys(&cur_td->td));
+ intrq->ed.tail_pointer = __le32_to_cpu(virt_to_phys(&cur_td->td));
+ }
+
+ return data;
+}
+
+static void
+ohci_process_done_queue(ohci_t *const ohci, const int spew_debug)
+{
+ int i, j;
+
+ /* Temporary queue of interrupt queue TDs (to reverse order). */
+ intrq_td_t *temp_tdq = NULL;
+
+ /* Check if done head has been written. */
+ if (!(READ_OPREG(ohci, HcInterruptStatus) & WritebackDoneHead))
+ return;
+ /* Fetch current done head.
+ Lsb is only interesting for hw interrupts. */
+ u32 phys_done_queue = __le32_to_cpu(ohci->hcca->HccaDoneHead) & ~1;
+ /* Tell host controller, he may overwrite the done head pointer. */
+ ohci->opreg->HcInterruptStatus = __cpu_to_le32(WritebackDoneHead);
+
+ i = 0;
+ /* Process done queue (it's in reversed order). */
+ while (phys_done_queue) {
+ td_t *const done_td = (td_t *)phys_to_virt(phys_done_queue);
+
+ /* Advance pointer to next TD. */
+ phys_done_queue = __le32_to_cpu(done_td->next_td);
+
+ switch (__le32_to_cpu(done_td->config) & TD_QUEUETYPE_MASK) {
+ case TD_QUEUETYPE_ASYNC:
+ /* Free processed async TDs. */
+ free((void *)done_td);
+ break;
+ case TD_QUEUETYPE_INTR: {
+ intrq_td_t *const td = INTRQ_TD_FROM_TD(done_td);
+ intr_queue_t *const intrq = td->intrq;
+ /* Check if the corresponding interrupt
+ queue is still beeing processed. */
+ if (intrq->destroy) {
+ /* Free this TD, and */
+ free(td);
+ --intrq->remaining_tds;
+ /* the interrupt queue if it has no more TDs. */
+ if (!intrq->remaining_tds)
+ free(intrq);
+ usb_debug("Freed TD from orphaned interrupt "
+ "queue, %d TDs remain.\n",
+ intrq->remaining_tds);
+ } else {
+ /* Save done TD to be processed. */
+ td->next = temp_tdq;
+ temp_tdq = td;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ ++i;
+ }
+ if (spew_debug)
+ usb_debug("Processed %d done TDs.\n", i);
+
+ j = 0;
+ /* Process interrupt queue TDs in right order. */
+ while (temp_tdq) {
+ /* Save pointer of current TD and advance. */
+ intrq_td_t *const cur_td = temp_tdq;
+ temp_tdq = temp_tdq->next;
+
+ /* The interrupt queue for the current TD. */
+ intr_queue_t *const intrq = cur_td->intrq;
+ /* Append to interrupt queue. */
+ if (!intrq->head) {
+ /* First element. */
+ intrq->head = intrq->tail = cur_td;
+ } else {
+ /* Insert at tail. */
+ intrq->tail->next = cur_td;
+ intrq->tail = cur_td;
+ }
+ /* It's always the last element. */
+ cur_td->next = NULL;
+ ++j;
+ }
+ if (spew_debug)
+ usb_debug("processed %d done tds, %d intr tds thereof.\n", i, j);
+}
+
+int ob_usb_ohci_init (const char *path, uint32_t addr)
+{
+ hci_t *ctrl;
+ int i;
+
+ usb_debug("ohci_init: %s addr = %x\n", path, addr);
+ ctrl = ohci_pci_init(addr);
+ if (!ctrl)
+ return 0;
+
+ /* Init ports */
+ usb_poll();
+
+ /* Look for a keyboard */
+ for (i = 0; i < 128; i++) {
+ if (ctrl->devices[i] && ctrl->devices[i]->configuration) {
+ configuration_descriptor_t *cd;
+ interface_descriptor_t *intf;
+
+ cd = (configuration_descriptor_t *)ctrl->devices[i]->configuration;
+ intf = (interface_descriptor_t *)(ctrl->devices[i]->configuration + cd->bLength);
+ usb_debug("Device at port %d is class %d\n", i, intf->bInterfaceClass);
+ if (intf->bInterfaceClass == hid_device &&
+ intf->bInterfaceSubClass == hid_subclass_boot &&
+ intf->bInterfaceProtocol == hid_boot_proto_keyboard ) {
+ break;
+ }
+ }
+ }
+ if ( i < 128 )
+ ob_usb_hid_add_keyboard(path);
+
+ return 1;
+}
diff --git a/roms/openbios/drivers/usbohci.h b/roms/openbios/drivers/usbohci.h
new file mode 100644
index 00000000..69033287
--- /dev/null
+++ b/roms/openbios/drivers/usbohci.h
@@ -0,0 +1,45 @@
+/*
+ * Driver for USB OHCI ported from CoreBoot
+ *
+ * Copyright (C) 2014 BALATON Zoltan
+ *
+ * This file was part of the libpayload project.
+ *
+ * Copyright (C) 2010 Patrick Georgi
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __OHCI_H
+#define __OHCI_H
+
+#include "config.h"
+#include "usbohci_private.h"
+
+hci_t *ohci_pci_init (u32 addr);
+hci_t *ohci_init (void *bar);
+
+void ohci_rh_init (usbdev_t *dev);
+
+#endif
diff --git a/roms/openbios/drivers/usbohci_private.h b/roms/openbios/drivers/usbohci_private.h
new file mode 100644
index 00000000..b3a723e2
--- /dev/null
+++ b/roms/openbios/drivers/usbohci_private.h
@@ -0,0 +1,270 @@
+/*
+ * Driver for USB OHCI ported from CoreBoot
+ *
+ * Copyright (C) 2014 BALATON Zoltan
+ *
+ * This file was part of the libpayload project.
+ *
+ * Copyright (C) 2010 Patrick Georgi
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __OHCI_PRIVATE_H
+#define __OHCI_PRIVATE_H
+
+#include "libc/byteorder.h"
+#include "usb.h"
+
+#define READ_OPREG(ohci, field) (__le32_to_cpu((ohci)->opreg->field))
+#define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit))
+
+ // FIXME: fake
+ typedef enum { CMD} reg;
+
+ enum {
+ NumberDownstreamPorts = 1<<0,
+ PowerSwitchingMode = 1<<8,
+ NoPowerSwitching = 1<<9,
+ DeviceType = 1<<10,
+ OverCurrentProtectionMode = 1<<11,
+ NoOverCurrentProtection = 1<<12,
+ PowerOnToPowerGoodTime = 1<<24
+ } HcRhDescriptorAReg;
+
+ enum {
+ NumberDownstreamPortsMask = MASK(0, 8),
+ PowerOnToPowerGoodTimeMask = MASK(24, 8)
+ } HcRhDescriptorAMask;
+
+ enum {
+ DeviceRemovable = 1<<0,
+ PortPowerControlMask = 1<<16
+ } HcRhDescriptorBReg;
+
+ enum {
+ CurrentConnectStatus = 1<<0,
+ PortEnableStatus = 1<<1,
+ PortSuspendStatus = 1<<2,
+ PortOverCurrentIndicator = 1<<3,
+ PortResetStatus = 1<<4,
+ PortPowerStatus = 1<<8,
+ LowSpeedDeviceAttached = 1<<9,
+ ConnectStatusChange = 1<<16,
+ PortEnableStatusChange = 1<<17,
+ PortSuspendStatusChange = 1<<18,
+ PortOverCurrentIndicatorChange = 1<<19,
+ PortResetStatusChange = 1<<20
+ } HcRhPortStatusRead;
+ enum {
+ ClearPortEnable = 1<<0,
+ SetPortEnable = 1<<1,
+ SetPortSuspend = 1<<2,
+ ClearSuspendStatus = 1<<3,
+ SetPortReset = 1<<4,
+ SetPortPower = 1<<8,
+ ClearPortPower = 1<<9,
+ } HcRhPortStatusSet;
+
+ enum {
+ LocalPowerStatus = 1<<0,
+ OverCurrentIndicator = 1<<1,
+ DeviceRemoteWakeupEnable = 1<<15,
+ LocalPowerStatusChange = 1<<16,
+ OverCurrentIndicatorChange = 1<<17,
+ ClearRemoteWakeupEnable = 1<<31
+ } HcRhStatusReg;
+
+ enum {
+ FrameInterval = 1<<0,
+ FSLargestDataPacket = 1<<16,
+ FrameIntervalToggle = 1<<31
+ } HcFmIntervalOffset;
+ enum {
+ FrameIntervalMask = MASK(0, 14),
+ FSLargestDataPacketMask = MASK(16, 15),
+ FrameIntervalToggleMask = MASK(31, 1)
+ } HcFmIntervalMask;
+
+ enum {
+ ControlBulkServiceRatio = 1<<0,
+ PeriodicListEnable = 1<<2,
+ IsochronousEnable = 1<<3,
+ ControlListEnable = 1<<4,
+ BulkListEnable = 1<<5,
+ HostControllerFunctionalState = 1<<6,
+ InterruptRouting = 1<<8,
+ RemoteWakeupConnected = 1<<9,
+ RemoteWakeupEnable = 1<<10
+ } HcControlReg;
+
+ enum {
+ ControlBulkServiceRatioMask = MASK(0, 2),
+ HostControllerFunctionalStateMask = MASK(6, 2)
+ } HcControlMask;
+
+ enum {
+ USBReset = 0*HostControllerFunctionalState,
+ USBResume = 1*HostControllerFunctionalState,
+ USBOperational = 2*HostControllerFunctionalState,
+ USBSuspend = 3*HostControllerFunctionalState
+ };
+
+ enum {
+ HostControllerReset = 1<<0,
+ ControlListFilled = 1<<1,
+ BulkListFilled = 1<<2,
+ OwnershipChangeRequest = 1<<3,
+ SchedulingOverrunCount = 1<<16
+ } HcCommandStatusReg;
+
+ enum {
+ SchedulingOverrunCountMask = MASK(16, 2)
+ } HcCommandStatusMask;
+
+ enum {
+ FrameRemaining = 1<<0,
+ FrameRemainingToggle = 1<<31
+ } HcFmRemainingReg;
+
+ enum {
+ SchedulingOverrung = 1<<0,
+ WritebackDoneHead = 1<<1,
+ StartofFrame = 1<<2,
+ ResumeDetected = 1<<3,
+ UnrecoverableError = 1<<4,
+ FrameNumberOverflow = 1<<5,
+ RootHubStatusChange = 1<<6,
+ OwnershipChange = 1<<30
+ } HcInterruptStatusReg;
+
+ typedef struct {
+ // Control and Status Partition
+ volatile u32 HcRevision;
+ volatile u32 HcControl;
+ volatile u32 HcCommandStatus;
+ volatile u32 HcInterruptStatus;
+ volatile u32 HcInterruptEnable;
+ volatile u32 HcInterruptDisable;
+
+ // Memory Pointer Partition
+ volatile u32 HcHCCA;
+ volatile u32 HcPeriodCurrentED;
+ volatile u32 HcControlHeadED;
+ volatile u32 HcControlCurrentED;
+ volatile u32 HcBulkHeadED;
+ volatile u32 HcBulkCurrentED;
+ volatile u32 HcDoneHead;
+
+ // Frame Counter Partition
+ volatile u32 HcFmInterval;
+ volatile u32 HcFmRemaining;
+ volatile u32 HcFmNumber;
+ volatile u32 HcPeriodicStart;
+ volatile u32 HcLSThreshold;
+
+ // Root Hub Partition
+ volatile u32 HcRhDescriptorA;
+ volatile u32 HcRhDescriptorB;
+ volatile u32 HcRhStatus;
+ /* all bits in HcRhPortStatus registers are R/WC, so
+ _DO NOT_ use |= to set the bits,
+ this clears the entire state */
+ volatile u32 HcRhPortStatus[];
+ } __attribute__ ((packed)) opreg_t;
+
+ typedef struct { /* should be 256 bytes according to spec */
+ u32 HccaInterruptTable[32];
+ volatile u16 HccaFrameNumber;
+ volatile u16 HccaPad1;
+ volatile u32 HccaDoneHead;
+ u8 reserved[116]; /* pad according to spec */
+ u8 what[4]; /* really pad to 256 as spec only covers 252 */
+ } __attribute__ ((packed)) hcca_t;
+
+ typedef volatile struct {
+ u32 config;
+ u32 tail_pointer;
+ u32 head_pointer;
+ u32 next_ed;
+ } __attribute__ ((packed)) ed_t;
+#define ED_HALTED 1
+#define ED_TOGGLE 2
+
+#define ED_FUNC_SHIFT 0
+#define ED_FUNC_MASK MASK(0, 7)
+#define ED_EP_SHIFT 7
+#define ED_EP_MASK MASK(7, 4)
+#define ED_DIR_SHIFT 11
+#define ED_DIR_MASK MASK(11, 2)
+#define ED_LOWSPEED (1 << 13)
+#define ED_MPS_SHIFT 16
+
+ typedef volatile struct {
+ u32 config;
+ u32 current_buffer_pointer;
+ u32 next_td;
+ u32 buffer_end;
+ } __attribute__ ((packed)) td_t;
+/*
+ * Bits 0 through 17 of .config won't be interpreted by the host controller
+ * (HC) and, after processing the TD, the HC has to ensure those bits have
+ * the same state as before. So we are free to use those bits for our own
+ * purpose.
+ */
+#define TD_QUEUETYPE_SHIFT 0
+#define TD_QUEUETYPE_MASK MASK(TD_QUEUETYPE_SHIFT, 2)
+#define TD_QUEUETYPE_ASYNC (0 << TD_QUEUETYPE_SHIFT)
+#define TD_QUEUETYPE_INTR (1 << TD_QUEUETYPE_SHIFT)
+
+#define TD_DIRECTION_SHIFT 19
+#define TD_DIRECTION_MASK MASK(TD_DIRECTION_SHIFT, 2)
+#define TD_DIRECTION_SETUP OHCI_SETUP << TD_DIRECTION_SHIFT
+#define TD_DIRECTION_IN OHCI_IN << TD_DIRECTION_SHIFT
+#define TD_DIRECTION_OUT OHCI_OUT << TD_DIRECTION_SHIFT
+#define TD_DELAY_INTERRUPT_SHIFT 21
+#define TD_DELAY_INTERRUPT_MASK MASK(TD_DELAY_INTERRUPT_SHIFT, 3)
+#define TD_DELAY_INTERRUPT_ZERO 0
+#define TD_DELAY_INTERRUPT_NOINTR (7 << TD_DELAY_INTERRUPT_SHIFT)
+#define TD_TOGGLE_DATA0 0
+#define TD_TOGGLE_DATA1 (1 << 24)
+#define TD_TOGGLE_FROM_ED 0
+#define TD_TOGGLE_FROM_TD (1 << 25)
+#define TD_CC_SHIFT 28
+#define TD_CC_MASK MASK(TD_CC_SHIFT, 4)
+#define TD_CC_NOERR 0
+#define TD_CC_NOACCESS (14 << TD_CC_SHIFT) /* the lower of the two values, so "no access" can be tested with >= */
+
+#define OHCI_INST(controller) ((ohci_t*)((controller)->instance))
+
+ typedef struct ohci {
+ opreg_t *opreg;
+ hcca_t *hcca;
+ usbdev_t *roothub;
+ ed_t *periodic_ed;
+ } ohci_t;
+
+ typedef enum { OHCI_SETUP=0, OHCI_OUT=1, OHCI_IN=2, OHCI_FROM_TD=3 } ohci_pid_t;
+
+#endif
diff --git a/roms/openbios/drivers/usbohci_rh.c b/roms/openbios/drivers/usbohci_rh.c
new file mode 100644
index 00000000..55503be6
--- /dev/null
+++ b/roms/openbios/drivers/usbohci_rh.c
@@ -0,0 +1,212 @@
+/*
+ * Driver for USB OHCI Root Hubs ported from CoreBoot
+ *
+ * Copyright (C) 2014 BALATON Zoltan
+ *
+ * This file was part of the libpayload project.
+ *
+ * Copyright (C) 2010 Patrick Georgi
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "timer.h"
+#include "usbohci_private.h"
+#include "usbohci.h"
+
+typedef struct {
+ int numports;
+ int *port;
+} rh_inst_t;
+
+#define RH_INST(dev) ((rh_inst_t*)(dev)->data)
+
+static void
+ohci_rh_enable_port (usbdev_t *dev, int port)
+{
+ /* Reset RH port should hold 50ms with pulses of at least 10ms and
+ * gaps of at most 3ms (usb20 spec 7.1.7.5).
+ * After reset, the port will be enabled automatically (ohci spec
+ * 7.4.4).
+ */
+ int total_delay = 100; /* 100 * 500us == 50ms */
+ while (total_delay > 0) {
+ if (!(READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port])
+ & CurrentConnectStatus))
+ return;
+
+ /* start reset */
+ OHCI_INST (dev->controller)->opreg->HcRhPortStatus[port] =
+ __cpu_to_le32(SetPortReset);
+ int timeout = 200; /* timeout after 200 * 500us == 100ms */
+ while ((READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port])
+ & PortResetStatus)
+ && timeout--) {
+ udelay(500); total_delay--;
+ }
+ if (READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port])
+ & PortResetStatus) {
+ usb_debug("Warning: root-hub port reset timed out.\n");
+ break;
+ }
+ if ((200-timeout) < 20) {
+ usb_debug("Warning: port reset too short: %dms; "
+ "should be at least 10ms.\n",
+ (200-timeout)/2);
+ total_delay = 0; /* can happen on QEMU */
+ }
+ /* clear reset status change */
+ OHCI_INST(dev->controller)->opreg->HcRhPortStatus[port] =
+ __cpu_to_le32(PortResetStatusChange);
+ usb_debug ("rh port reset finished after %dms.\n", (200-timeout)/2);
+ }
+}
+
+/* disable root hub */
+static void
+ohci_rh_disable_port (usbdev_t *dev, int port)
+{
+ OHCI_INST (dev->controller)->opreg->HcRhPortStatus[port] =
+ __cpu_to_le32(ClearPortEnable); // disable port
+ int timeout = 50; /* timeout after 50 * 100us == 5ms */
+ while ((READ_OPREG(OHCI_INST (dev->controller), HcRhPortStatus[port])
+ & PortEnableStatus)
+ && timeout--) {
+ udelay(100);
+ }
+}
+
+static void
+ohci_rh_scanport (usbdev_t *dev, int port)
+{
+ if (port >= RH_INST(dev)->numports) {
+ usb_debug("Invalid port %d\n", port);
+ return;
+ }
+
+ /* device registered, and device change logged, so something must have happened */
+ if (RH_INST (dev)->port[port] != -1) {
+ usb_detach_device(dev->controller, RH_INST (dev)->port[port]);
+ RH_INST (dev)->port[port] = -1;
+ }
+
+ /* no device attached
+ previously registered devices are detached, nothing left to do */
+ if (!(READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) & CurrentConnectStatus))
+ return;
+
+ // clear port state change
+ OHCI_INST(dev->controller)->opreg->HcRhPortStatus[port] = __cpu_to_le32(ConnectStatusChange);
+ ohci_rh_enable_port (dev, port);
+
+ mdelay(100); // wait for signal to stabilize
+
+ if (!(READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) & PortEnableStatus)) {
+ usb_debug ("port enable failed\n");
+ return;
+ }
+
+ int speed = (READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) & LowSpeedDeviceAttached) != 0;
+ RH_INST (dev)->port[port] = usb_attach_device(dev->controller, dev->address, port, speed);
+}
+
+static int
+ohci_rh_report_port_changes (usbdev_t *dev)
+{
+ ohci_t *const ohcic = OHCI_INST (dev->controller);
+
+ int i;
+
+ for (i = 0; i < RH_INST(dev)->numports; i++) {
+ // maybe detach+attach happened between two scans?
+ if (READ_OPREG(ohcic, HcRhPortStatus[i]) & ConnectStatusChange) {
+ ohcic->opreg->HcRhPortStatus[i] = __cpu_to_le32(ConnectStatusChange);
+ usb_debug("attachment change on port %d\n", i);
+ return i;
+ }
+ }
+
+ // no change
+ return -1;
+}
+
+static void
+ohci_rh_destroy (usbdev_t *dev)
+{
+ int i;
+ for (i = 0; i < RH_INST (dev)->numports; i++)
+ ohci_rh_disable_port (dev, i);
+ free (RH_INST (dev));
+}
+
+static void
+ohci_rh_poll (usbdev_t *dev)
+{
+ ohci_t *const ohcic = OHCI_INST (dev->controller);
+
+ int port;
+
+ /* Check if anything changed. */
+ if (!(READ_OPREG(ohcic, HcInterruptStatus) & RootHubStatusChange))
+ return;
+ ohcic->opreg->HcInterruptStatus = __cpu_to_le32(RootHubStatusChange);
+ usb_debug("root hub status change\n");
+
+ /* Scan ports with changed connection status. */
+ while ((port = ohci_rh_report_port_changes (dev)) != -1)
+ ohci_rh_scanport (dev, port);
+}
+
+void
+ohci_rh_init (usbdev_t *dev)
+{
+ int i;
+
+ dev->destroy = ohci_rh_destroy;
+ dev->poll = ohci_rh_poll;
+
+ dev->data = malloc (sizeof (rh_inst_t));
+ if (!dev->data) {
+ printk("Not enough memory for OHCI RH.\n");
+ return;
+ }
+
+ RH_INST (dev)->numports = READ_OPREG(OHCI_INST(dev->controller), HcRhDescriptorA) & NumberDownstreamPortsMask;
+ RH_INST (dev)->port = malloc(sizeof(int) * RH_INST (dev)->numports);
+ usb_debug("%d ports registered\n", RH_INST (dev)->numports);
+
+ for (i = 0; i < RH_INST (dev)->numports; i++) {
+ ohci_rh_enable_port (dev, i);
+ RH_INST (dev)->port[i] = -1;
+ }
+
+ /* we can set them here because a root hub _really_ shouldn't
+ appear elsewhere */
+ dev->address = 0;
+ dev->hub = -1;
+ dev->port = -1;
+
+ usb_debug("rh init done\n");
+}
diff --git a/roms/openbios/drivers/vga.fs b/roms/openbios/drivers/vga.fs
new file mode 100644
index 00000000..ec4c6c5f
--- /dev/null
+++ b/roms/openbios/drivers/vga.fs
@@ -0,0 +1,204 @@
+\
+\ Fcode payload for QEMU VGA graphics card
+\
+\ This is the Forth source for an Fcode payload to initialise
+\ the QEMU VGA graphics card.
+\
+\ (C) Copyright 2013 Mark Cave-Ayland
+\
+
+fcode-version3
+
+\
+\ Dictionary lookups for words that don't have an FCode
+\
+
+: (find-xt) \ ( str len -- xt | -1 )
+ $find if
+ exit
+ else
+ -1
+ then
+;
+
+" openbios-video-width" (find-xt) cell+ value openbios-video-width-xt
+" openbios-video-height" (find-xt) cell+ value openbios-video-height-xt
+" depth-bits" (find-xt) cell+ value depth-bits-xt
+" line-bytes" (find-xt) cell+ value line-bytes-xt
+
+: openbios-video-width openbios-video-width-xt @ ;
+: openbios-video-height openbios-video-height-xt @ ;
+: depth-bits depth-bits-xt @ ;
+: line-bytes line-bytes-xt @ ;
+
+" fb8-fillrect" (find-xt) value fb8-fillrect-xt
+: fb8-fillrect fb8-fillrect-xt execute ;
+
+\
+\ IO port words
+\
+
+" ioc!" (find-xt) value ioc!-xt
+" iow!" (find-xt) value iow!-xt
+
+: ioc! ioc!-xt execute ;
+: iow! iow!-xt execute ;
+
+\
+\ VGA registers
+\
+
+h# 3c0 constant vga-addr
+h# 3c8 constant dac-write-addr
+h# 3c9 constant dac-data-addr
+
+: vga-color! ( r g b index -- )
+ \ Set the VGA colour registers
+ dac-write-addr ioc! rot
+ 2 >> dac-data-addr ioc! swap
+ 2 >> dac-data-addr ioc!
+ 2 >> dac-data-addr ioc!
+;
+
+\
+\ VBE registers
+\
+
+h# 0 constant VBE_DISPI_INDEX_ID
+h# 1 constant VBE_DISPI_INDEX_XRES
+h# 2 constant VBE_DISPI_INDEX_YRES
+h# 3 constant VBE_DISPI_INDEX_BPP
+h# 4 constant VBE_DISPI_INDEX_ENABLE
+h# 5 constant VBE_DISPI_INDEX_BANK
+h# 6 constant VBE_DISPI_INDEX_VIRT_WIDTH
+h# 7 constant VBE_DISPI_INDEX_VIRT_HEIGHT
+h# 8 constant VBE_DISPI_INDEX_X_OFFSET
+h# 9 constant VBE_DISPI_INDEX_Y_OFFSET
+h# a constant VBE_DISPI_INDEX_NB
+
+h# 0 constant VBE_DISPI_DISABLED
+h# 1 constant VBE_DISPI_ENABLED
+
+\
+\ Bochs VBE register writes
+\
+
+: vbe-iow! ( val addr -- )
+ h# 1ce iow!
+ h# 1d0 iow!
+;
+
+\
+\ Initialise Bochs VBE mode
+\
+
+: vbe-init ( -- )
+ h# 0 vga-addr ioc! \ Enable blanking
+ VBE_DISPI_DISABLED VBE_DISPI_INDEX_ENABLE vbe-iow!
+ h# 0 VBE_DISPI_INDEX_X_OFFSET vbe-iow!
+ h# 0 VBE_DISPI_INDEX_Y_OFFSET vbe-iow!
+ openbios-video-width VBE_DISPI_INDEX_XRES vbe-iow!
+ openbios-video-height VBE_DISPI_INDEX_YRES vbe-iow!
+ depth-bits VBE_DISPI_INDEX_BPP vbe-iow!
+ VBE_DISPI_ENABLED VBE_DISPI_INDEX_ENABLE vbe-iow!
+ h# 0 vga-addr ioc!
+ h# 20 vga-addr ioc! \ Disable blanking
+;
+
+\
+\ PCI
+\
+
+" pci-bar>pci-region" (find-xt) value pci-bar>pci-region-xt
+: pci-bar>pci-region pci-bar>pci-region-xt execute ;
+
+h# 10 constant cfg-bar0 \ Framebuffer BAR
+-1 value fb-addr
+
+: map-fb ( -- )
+ cfg-bar0 pci-bar>pci-region \ ( pci-addr.lo pci-addr.hi size )
+ " pci-map-in" $call-parent
+ to fb-addr
+;
+
+\
+\ Publically visible words
+\
+
+external
+
+[IFDEF] CONFIG_MOL
+defer mol-color!
+
+\ Hook for MOL (see packages/molvideo.c)
+\
+\ Perhaps for neatness this there should be a separate molvga.fs
+\ but let's leave it here for now.
+
+: color! ( r g b index -- )
+ mol-color!
+;
+
+[ELSE]
+
+\ Standard VGA
+
+: color! ( r g b index -- )
+ vga-color!
+;
+
+[THEN]
+
+: fill-rectangle ( color_ind x y width height -- )
+ fb8-fillrect
+;
+
+: dimensions ( -- width height )
+ openbios-video-width
+ openbios-video-height
+;
+
+: set-colors ( table start count -- )
+ 0 do
+ over dup \ ( table start table table )
+ c@ swap 1+ \ ( table start r table-g )
+ dup c@ swap 1+ \ ( table start r g table-b )
+ c@ 3 pick \ ( table start r g b index )
+ color! \ ( table start )
+ 1+
+ swap 3 + swap \ ( table+3 start+1 )
+ loop
+;
+
+headerless
+
+\
+\ Installation
+\
+
+: qemu-vga-driver-install ( -- )
+ fb-addr -1 = if
+ map-fb fb-addr to frame-buffer-adr
+ default-font set-font
+
+ frame-buffer-adr encode-int " address" property
+
+ openbios-video-width openbios-video-height over char-width / over char-height /
+ fb8-install
+ then
+;
+
+: qemu-vga-driver-init
+
+ vbe-init
+ openbios-video-width encode-int " width" property
+ openbios-video-height encode-int " height" property
+ depth-bits encode-int " depth" property
+ line-bytes encode-int " linebytes" property
+
+ ['] qemu-vga-driver-install is-install
+;
+
+qemu-vga-driver-init
+
+end0
diff --git a/roms/openbios/drivers/vga.h b/roms/openbios/drivers/vga.h
new file mode 100644
index 00000000..a37e66e6
--- /dev/null
+++ b/roms/openbios/drivers/vga.h
@@ -0,0 +1,231 @@
+/*
+ *
+ * modified
+ * by Steve M. Gehlbach <steve@kesa.com>
+ *
+ * Originally from linux/drivers/video/vga16.c by
+ * Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
+ * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#ifndef VGA_H_INCL
+#define VGA_H_INCL 1
+
+#include "drivers/vga.h"
+
+//#include <cpu/p5/io.h>
+
+#define u8 unsigned char
+#define u16 unsigned short
+#define u32 unsigned int
+#define __u32 u32
+
+#define VERROR -1
+#define CHAR_HEIGHT 16
+#define LINES 25
+#define COLS 80
+
+// macros for writing to vga regs
+#define write_crtc(data,addr) outb(addr,CRT_IC); outb(data,CRT_DC)
+#define write_att(data,addr) inb(IS1_RC); inb(0x80); outb(addr,ATT_IW); inb(0x80); outb(data,ATT_IW); inb(0x80)
+#define write_seq(data,addr) outb(addr,SEQ_I); outb(data,SEQ_D)
+#define write_gra(data,addr) outb(addr,GRA_I); outb(data,GRA_D)
+u8 read_seq_b(u16 addr);
+u8 read_gra_b(u16 addr);
+u8 read_crtc_b(u16 addr);
+u8 read_att_b(u16 addr);
+
+
+#ifdef VGA_HARDWARE_FIXUP
+void vga_hardware_fixup(void);
+#else
+#define vga_hardware_fixup() do{} while(0)
+#endif
+
+#define SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
+#define SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
+#define SYNC_EXT 4 /* external sync */
+#define SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
+#define SYNC_BROADCAST 16 /* broadcast video timings */
+ /* vtotal = 144d/288n/576i => PAL */
+ /* vtotal = 121d/242n/484i => NTSC */
+
+#define SYNC_ON_GREEN 32 /* sync on green */
+
+#define VMODE_NONINTERLACED 0 /* non interlaced */
+#define VMODE_INTERLACED 1 /* interlaced */
+#define VMODE_DOUBLE 2 /* double scan */
+#define VMODE_MASK 255
+
+#define VMODE_YWRAP 256 /* ywrap instead of panning */
+#define VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
+#define VMODE_CONUPDATE 512 /* don't update x/yoffset */
+
+/* VGA data register ports */
+#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */
+#define CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */
+#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */
+#define GRA_D 0x3CF /* Graphics Controller Data Register */
+#define SEQ_D 0x3C5 /* Sequencer Data Register */
+
+#define MIS_R 0x3CC // Misc Output Read Register
+#define MIS_W 0x3C2 // Misc Output Write Register
+
+#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */
+#define IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */
+#define PEL_D 0x3C9 /* PEL Data Register */
+#define PEL_MSK 0x3C6 /* PEL mask register */
+
+/* EGA-specific registers */
+#define GRA_E0 0x3CC /* Graphics enable processor 0 */
+#define GRA_E1 0x3CA /* Graphics enable processor 1 */
+
+
+/* VGA index register ports */
+#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */
+#define CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */
+#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */
+#define GRA_I 0x3CE /* Graphics Controller Index */
+#define SEQ_I 0x3C4 /* Sequencer Index */
+#define PEL_IW 0x3C8 /* PEL Write Index */
+#define PEL_IR 0x3C7 /* PEL Read Index */
+#define DAC_REG 0x3C8 /* DAC register */
+#define DAC_VAL 0x3C9 /* DAC value */
+
+/* standard VGA indexes max counts */
+#define CRTC_C 25 /* 25 CRT Controller Registers sequentially set*/
+ // the remainder are not in the par array
+#define ATT_C 21 /* 21 Attribute Controller Registers */
+#define GRA_C 9 /* 9 Graphics Controller Registers */
+#define SEQ_C 5 /* 5 Sequencer Registers */
+#define MIS_C 1 /* 1 Misc Output Register */
+
+#define CRTC_H_TOTAL 0
+#define CRTC_H_DISP 1
+#define CRTC_H_BLANK_START 2
+#define CRTC_H_BLANK_END 3
+#define CRTC_H_SYNC_START 4
+#define CRTC_H_SYNC_END 5
+#define CRTC_V_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define CRTC_PRESET_ROW 8
+#define CRTC_MAX_SCAN 9
+#define CRTC_CURSOR_START 0x0A
+#define CRTC_CURSOR_END 0x0B
+#define CRTC_START_HI 0x0C
+#define CRTC_START_LO 0x0D
+#define CRTC_CURSOR_HI 0x0E
+#define CRTC_CURSOR_LO 0x0F
+#define CRTC_V_SYNC_START 0x10
+#define CRTC_V_SYNC_END 0x11
+#define CRTC_V_DISP_END 0x12
+#define CRTC_OFFSET 0x13
+#define CRTC_UNDERLINE 0x14
+#define CRTC_V_BLANK_START 0x15
+#define CRTC_V_BLANK_END 0x16
+#define CRTC_MODE 0x17
+#define CRTC_LINE_COMPARE 0x18
+
+#define ATC_MODE 0x10
+#define ATC_OVERSCAN 0x11
+#define ATC_PLANE_ENABLE 0x12
+#define ATC_PEL 0x13
+#define ATC_COLOR_PAGE 0x14
+
+#define SEQ_CLOCK_MODE 0x01
+#define SEQ_PLANE_WRITE 0x02
+#define SEQ_CHARACTER_MAP 0x03
+#define SEQ_MEMORY_MODE 0x04
+
+#define GDC_SR_VALUE 0x00
+#define GDC_SR_ENABLE 0x01
+#define GDC_COMPARE_VALUE 0x02
+#define GDC_DATA_ROTATE 0x03
+#define GDC_PLANE_READ 0x04
+#define GDC_MODE 0x05
+#define GDC_MISC 0x06
+#define GDC_COMPARE_MASK 0x07
+#define GDC_BIT_MASK 0x08
+
+// text attributes
+#define VGA_ATTR_CLR_RED 0x4
+#define VGA_ATTR_CLR_GRN 0x2
+#define VGA_ATTR_CLR_BLU 0x1
+#define VGA_ATTR_CLR_YEL (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN)
+#define VGA_ATTR_CLR_CYN (VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU)
+#define VGA_ATTR_CLR_MAG (VGA_ATTR_CLR_BLU | VGA_ATTR_CLR_RED)
+#define VGA_ATTR_CLR_BLK 0
+#define VGA_ATTR_CLR_WHT (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU)
+#define VGA_ATTR_BNK 0x80
+#define VGA_ATTR_ITN 0x08
+
+/*
+ * vga register parameters
+ * these are copied to the
+ * registers.
+ *
+ */
+struct vga_par {
+ u8 crtc[CRTC_C];
+ u8 atc[ATT_C];
+ u8 gdc[GRA_C];
+ u8 seq[SEQ_C];
+ u8 misc; // the misc register, MIS_W
+ u8 vss;
+};
+
+
+/* Interpretation of offset for color fields: All offsets are from the right,
+ * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
+ * can use the offset as right argument to <<). A pixel afterwards is a bit
+ * stream and is written to video memory as that unmodified. This implies
+ * big-endian byte order if bits_per_pixel is greater than 8.
+ */
+struct fb_bitfield {
+ __u32 offset; /* beginning of bitfield */
+ __u32 length; /* length of bitfield */
+ __u32 msb_right; /* != 0 : Most significant bit is */
+ /* right */
+};
+
+struct screeninfo {
+ __u32 xres; /* visible resolution */
+ __u32 yres;
+ __u32 xres_virtual; /* virtual resolution */
+ __u32 yres_virtual;
+ __u32 xoffset; /* offset from virtual to visible */
+ __u32 yoffset; /* resolution */
+
+ __u32 bits_per_pixel; /* guess what */
+ __u32 grayscale; /* != 0 Graylevels instead of colors */
+
+ struct fb_bitfield red; /* bitfield in fb mem if true color, */
+ struct fb_bitfield green; /* else only length is significant */
+ struct fb_bitfield blue;
+ struct fb_bitfield transp; /* transparency */
+
+ __u32 nonstd; /* != 0 Non standard pixel format */
+
+ __u32 activate; /* see FB_ACTIVATE_* */
+
+ __u32 height; /* height of picture in mm */
+ __u32 width; /* width of picture in mm */
+
+ __u32 accel_flags; /* acceleration flags (hints) */
+
+ /* Timing: All values in pixclocks, except pixclock (of course) */
+ __u32 pixclock; /* pixel clock in ps (pico seconds) */
+ __u32 left_margin; /* time from sync to picture */
+ __u32 right_margin; /* time from picture to sync */
+ __u32 upper_margin; /* time from sync to picture */
+ __u32 lower_margin;
+ __u32 hsync_len; /* length of horizontal sync */
+ __u32 vsync_len; /* length of vertical sync */
+ __u32 sync; /* sync polarity */
+ __u32 vmode; /* interlaced etc */
+ __u32 reserved[6]; /* Reserved for future compatibility */
+};
+#endif
diff --git a/roms/openbios/drivers/vga_load_regs.c b/roms/openbios/drivers/vga_load_regs.c
new file mode 100644
index 00000000..dda6b798
--- /dev/null
+++ b/roms/openbios/drivers/vga_load_regs.c
@@ -0,0 +1,496 @@
+#include "asm/io.h"
+#include "drivers/vga.h"
+#include "vga.h"
+
+/*
+ * $Id$
+ * $Source$
+ *
+ * from the Linux kernel code base.
+ * orig by Ben Pfaff and Petr Vandrovec.
+ *
+ * modified by
+ * Steve M. Gehlbach <steve@kesa.com>
+ *
+ * NOTE: to change the horiz and vertical pixels,
+ * change the xres,yres,xres_virt,yres_virt setting
+ * in the screeninfo structure below. You may also need
+ * to change the border settings as well.
+ *
+ * Convert the screeninfo structure to data for
+ * writing to the vga registers
+ *
+ */
+
+// prototypes
+static int vga_decode_var(const struct screeninfo *var, struct vga_par *par);
+static int vga_set_regs(const struct vga_par *par);
+
+u8 read_seq_b(u16 addr) {
+ outb(addr,SEQ_I);
+ return inb(SEQ_D);
+}
+u8 read_gra_b(u16 addr) {
+ outb(addr,GRA_I);
+ return inb(GRA_D);
+}
+u8 read_crtc_b(u16 addr) {
+ outb(addr,CRT_IC);
+ return inb(CRT_DC);
+}
+u8 read_att_b(u16 addr) {
+ inb(IS1_RC);
+ inb(0x80);
+ outb(addr,ATT_IW);
+ return inb(ATT_R);
+}
+
+
+/*
+From: The Frame Buffer Device
+by Geert Uytterhoeven <geert@linux-m68k.org>
+in the linux kernel docs.
+
+The following picture summarizes all timings. The horizontal retrace time is
+the sum of the left margin, the right margin and the hsync length, while the
+vertical retrace time is the sum of the upper margin, the lower margin and the
+vsync length.
+
+ +----------+---------------------------------------------+----------+-------+
+ | | ^ | | |
+ | | |upper_margin | | |
+ | | | | | |
+ +----------###############################################----------+-------+
+ | # ^ # | |
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ | left # | # right | hsync |
+ | margin # | xres # margin | len |
+ |<-------->#<---------------+--------------------------->#<-------->|<----->|
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ | # |yres # | |
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ | # | # | |
+ +----------###############################################----------+-------+
+ | | ^ | | |
+ | | |lower_margin | | |
+ | | | | | |
+ +----------+---------------------------------------------+----------+-------+
+ | | ^ | | |
+ | | |vsync_len | | |
+ | | | | | |
+ +----------+---------------------------------------------+----------+-------+
+
+All horizontal timings are in number of dotclocks
+(in picoseconds, 1E-12 s), and vertical timings in number of scanlines.
+
+The vga uses the following fields:
+
+ - pixclock: pixel clock in ps (pico seconds)
+ - xres,yres,xres_v,yres_v
+ - left_margin: time from sync to picture
+ - right_margin: time from picture to sync
+ - upper_margin: time from sync to picture
+ - lower_margin: time from picture to sync
+ - hsync_len: length of horizontal sync
+ - vsync_len: length of vertical sync
+
+*/
+
+/* our display parameters per the above */
+
+static const struct screeninfo vga_settings = {
+ 640,400,640,400,/* xres,yres,xres_virt,yres_virt */
+ 0,0, /* xoffset,yoffset */
+ 4, /* bits_per_pixel NOT USED*/
+ 0, /* greyscale ? */
+ {0,0,0}, /* R */
+ {0,0,0}, /* G */
+ {0,0,0}, /* B */
+ {0,0,0}, /* transparency */
+ 0, /* standard pixel format */
+ 0, // activate now
+ -1,-1, // height and width in mm
+ 0, // accel flags
+ 39721, // pixclock: 79442 -> 12.587 Mhz (NOT USED)
+ // 70616 -> 14.161
+ // 39721 -> 25.175
+ // 35308 -> 28.322
+
+ 48, 16, 39, 8, // margins left,right,upper,lower
+ 96, // hsync length
+ 2, // vsync length
+ 0, // sync polarity
+ 0, // non interlaced, single mode
+ {0,0,0,0,0,0} // compatibility
+};
+
+// ALPHA-MODE
+// Hard coded to BIOS VGA mode 3 (alpha color text)
+// screen size settable in screeninfo structure
+
+static int vga_decode_var(const struct screeninfo *var,
+ struct vga_par *par)
+{
+ u8 VgaAttributeTable[16] =
+ { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x014, 0x007, 0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x03F};
+
+ u32 xres, right, hslen, left, xtotal;
+ u32 yres, lower, vslen, upper, ytotal;
+ u32 vxres, xoffset, vyres, yoffset;
+ u32 pos;
+ u8 r7, rMode;
+ int i;
+
+ xres = (var->xres + 7) & ~7;
+ vxres = (var->xres_virtual + 0xF) & ~0xF;
+ xoffset = (var->xoffset + 7) & ~7;
+ left = (var->left_margin + 7) & ~7;
+ right = (var->right_margin + 7) & ~7;
+ hslen = (var->hsync_len + 7) & ~7;
+
+ if (vxres < xres)
+ vxres = xres;
+ if (xres + xoffset > vxres)
+ xoffset = vxres - xres;
+
+ xres >>= 3;
+ right >>= 3;
+ hslen >>= 3;
+ left >>= 3;
+ vxres >>= 3;
+ xtotal = xres + right + hslen + left;
+ if (xtotal >= 256)
+ return VERROR; //xtotal too big
+ if (hslen > 32)
+ return VERROR; //hslen too big
+ if (right + hslen + left > 64)
+ return VERROR; //hblank too big
+ par->crtc[CRTC_H_TOTAL] = xtotal - 5;
+ par->crtc[CRTC_H_BLANK_START] = xres - 1;
+ par->crtc[CRTC_H_DISP] = xres - 1;
+ pos = xres + right;
+ par->crtc[CRTC_H_SYNC_START] = pos;
+ pos += hslen;
+ par->crtc[CRTC_H_SYNC_END] = (pos & 0x1F) | 0x20 ; //<--- stpc text mode p178
+ pos += left - 2; /* blank_end + 2 <= total + 5 */
+ par->crtc[CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
+ if (pos & 0x20)
+ par->crtc[CRTC_H_SYNC_END] |= 0x80;
+
+ yres = var->yres;
+ lower = var->lower_margin;
+ vslen = var->vsync_len;
+ upper = var->upper_margin;
+ vyres = var->yres_virtual;
+ yoffset = var->yoffset;
+
+ if (yres > vyres)
+ vyres = yres;
+ if (vxres * vyres > 65536) {
+ vyres = 65536 / vxres;
+ if (vyres < yres)
+ return VERROR; // out of memory
+ }
+ if (yoffset + yres > vyres)
+ yoffset = vyres - yres;
+
+ if (var->vmode & VMODE_DOUBLE) {
+ yres <<= 1;
+ lower <<= 1;
+ vslen <<= 1;
+ upper <<= 1;
+ }
+ ytotal = yres + lower + vslen + upper;
+ if (ytotal > 1024) {
+ ytotal >>= 1;
+ yres >>= 1;
+ lower >>= 1;
+ vslen >>= 1;
+ upper >>= 1;
+ rMode = 0x04;
+ } else
+ rMode = 0x00;
+ if (ytotal > 1024)
+ return VERROR; //ytotal too big
+ if (vslen > 16)
+ return VERROR; //vslen too big
+ par->crtc[CRTC_V_TOTAL] = ytotal - 2;
+ r7 = 0x10; /* disable linecompare */
+ if (ytotal & 0x100) r7 |= 0x01;
+ if (ytotal & 0x200) r7 |= 0x20;
+ par->crtc[CRTC_PRESET_ROW] = 0;
+
+
+// GMODE <--> ALPHA-MODE
+// default using alpha mode so we need to set char rows= CHAR_HEIGHT-1
+ par->crtc[CRTC_MAX_SCAN] = 0x40 | (CHAR_HEIGHT-1); /* 16 scanlines, linecmp max*/
+
+ if (var->vmode & VMODE_DOUBLE)
+ par->crtc[CRTC_MAX_SCAN] |= 0x80;
+ par->crtc[CRTC_CURSOR_START] = 0x00; // curs enabled, start line = 0
+ par->crtc[CRTC_CURSOR_END] = CHAR_HEIGHT-1; // end line = 12
+ pos = yoffset * vxres + (xoffset >> 3);
+ par->crtc[CRTC_START_HI] = pos >> 8;
+ par->crtc[CRTC_START_LO] = pos & 0xFF;
+ par->crtc[CRTC_CURSOR_HI] = 0x00;
+ par->crtc[CRTC_CURSOR_LO] = 0x00;
+ pos = yres - 1;
+ par->crtc[CRTC_V_DISP_END] = pos & 0xFF;
+ par->crtc[CRTC_V_BLANK_START] = pos & 0xFF;
+ if (pos & 0x100)
+ r7 |= 0x0A; /* 0x02 -> DISP_END, 0x08 -> BLANK_START */
+ if (pos & 0x200) {
+ r7 |= 0x40; /* 0x40 -> DISP_END */
+ par->crtc[CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
+ }
+ pos += lower;
+ par->crtc[CRTC_V_SYNC_START] = pos & 0xFF;
+ if (pos & 0x100)
+ r7 |= 0x04;
+ if (pos & 0x200)
+ r7 |= 0x80;
+ pos += vslen;
+ par->crtc[CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled reg write prot, IRQ */
+ pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
+ par->crtc[CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
+ but some SVGA chips requires all 8 bits to set */
+ if (vxres >= 512)
+ return VERROR; //vxres too long
+ par->crtc[CRTC_OFFSET] = vxres >> 1;
+
+ // put the underline off of the character, necessary in alpha color mode
+ par->crtc[CRTC_UNDERLINE] = 0x1f;
+
+ par->crtc[CRTC_MODE] = rMode | 0xA3; // word mode
+ par->crtc[CRTC_LINE_COMPARE] = 0xFF;
+ par->crtc[CRTC_OVERFLOW] = r7;
+
+
+ // not used ??
+ par->vss = 0x00; /* 3DA */
+
+ for (i = 0x00; i < 0x10; i++) {
+ par->atc[i] = VgaAttributeTable[i];
+ }
+ // GMODE <--> ALPHA-MODE
+ par->atc[ATC_MODE] = 0x0c; // text mode
+
+ par->atc[ATC_OVERSCAN] = 0x00; // no border
+ par->atc[ATC_PLANE_ENABLE] = 0x0F;
+ par->atc[ATC_PEL] = xoffset & 7;
+ par->atc[ATC_COLOR_PAGE] = 0x00;
+
+ par->misc = 0x67; /* enable CPU, ports 0x3Dx, positive sync*/
+ if (var->sync & SYNC_HOR_HIGH_ACT)
+ par->misc &= ~0x40;
+ if (var->sync & SYNC_VERT_HIGH_ACT)
+ par->misc &= ~0x80;
+
+ par->seq[SEQ_CLOCK_MODE] = 0x01; //8-bit char; 0x01=alpha mode
+ par->seq[SEQ_PLANE_WRITE] = 0x03; // just char/attr plane
+ par->seq[SEQ_CHARACTER_MAP] = 0x00;
+ par->seq[SEQ_MEMORY_MODE] = 0x02; // A/G bit not used in stpc; O/E on, C4 off
+
+ par->gdc[GDC_SR_VALUE] = 0x00;
+ // bits set in the SR_EN regs will enable set/reset action
+ // based on the bit settings in the SR_VAL register
+ par->gdc[GDC_SR_ENABLE] = 0x00;
+ par->gdc[GDC_COMPARE_VALUE] = 0x00;
+ par->gdc[GDC_DATA_ROTATE] = 0x00;
+ par->gdc[GDC_PLANE_READ] = 0;
+ par->gdc[GDC_MODE] = 0x10; //Okay
+
+ // GMODE <--> ALPHA-MMODE
+ par->gdc[GDC_MISC] = 0x0e; // b0=0 ->alpha mode; memory at 0xb8000
+
+ par->gdc[GDC_COMPARE_MASK] = 0x00;
+ par->gdc[GDC_BIT_MASK] = 0xFF;
+
+ return 0;
+}
+
+//
+// originally from the stpc web site
+//
+static const unsigned char VgaLookupTable[3 * 0x3f + 3] = {
+ // Red Green Blue
+ 0x000, 0x000, 0x000, // 00h
+ 0x000, 0x000, 0x02A, // 01h
+ 0x000, 0x02A, 0x000, // 02h
+ 0x000, 0x02A, 0x02A, // 03h
+ 0x02A, 0x000, 0x000, // 04h
+ 0x02A, 0x000, 0x02A, // 05h
+ 0x02A, 0x02A, 0x000, // 06h
+ 0x02A, 0x02A, 0x02A, // 07h
+ 0x000, 0x000, 0x015, // 08h
+ 0x000, 0x000, 0x03F, // 09h
+ 0x000, 0x02A, 0x015, // 0Ah
+ 0x000, 0x02A, 0x03F, // 0Bh
+ 0x02A, 0x000, 0x015, // 0Ch
+ 0x02A, 0x000, 0x03F, // 0Dh
+ 0x02A, 0x02A, 0x015, // 0Eh
+ 0x02A, 0x02A, 0x03F, // 0Fh
+ 0x000, 0x015, 0x000, // 10h
+ 0x000, 0x015, 0x02A, // 11h
+ 0x000, 0x03F, 0x000, // 12h
+ 0x000, 0x03F, 0x02A, // 13h
+ 0x02A, 0x015, 0x000, // 14h
+ 0x02A, 0x015, 0x02A, // 15h
+ 0x02A, 0x03F, 0x000, // 16h
+ 0x02A, 0x03F, 0x02A, // 17h
+ 0x000, 0x015, 0x015, // 18h
+ 0x000, 0x015, 0x03F, // 19h
+ 0x000, 0x03F, 0x015, // 1Ah
+ 0x000, 0x03F, 0x03F, // 1Bh
+ 0x02A, 0x015, 0x015, // 1Ch
+ 0x02A, 0x015, 0x03F, // 1Dh
+ 0x02A, 0x03F, 0x015, // 1Eh
+ 0x02A, 0x03F, 0x03F, // 1Fh
+ 0x015, 0x000, 0x000, // 20h
+ 0x015, 0x000, 0x02A, // 21h
+ 0x015, 0x02A, 0x000, // 22h
+ 0x015, 0x02A, 0x02A, // 23h
+ 0x03F, 0x000, 0x000, // 24h
+ 0x03F, 0x000, 0x02A, // 25h
+ 0x03F, 0x02A, 0x000, // 26h
+ 0x03F, 0x02A, 0x02A, // 27h
+ 0x015, 0x000, 0x015, // 28h
+ 0x015, 0x000, 0x03F, // 29h
+ 0x015, 0x02A, 0x015, // 2Ah
+ 0x015, 0x02A, 0x03F, // 2Bh
+ 0x03F, 0x000, 0x015, // 2Ch
+ 0x03F, 0x000, 0x03F, // 2Dh
+ 0x03F, 0x02A, 0x015, // 2Eh
+ 0x03F, 0x02A, 0x03F, // 2Fh
+ 0x015, 0x015, 0x000, // 30h
+ 0x015, 0x015, 0x02A, // 31h
+ 0x015, 0x03F, 0x000, // 32h
+ 0x015, 0x03F, 0x02A, // 33h
+ 0x03F, 0x015, 0x000, // 34h
+ 0x03F, 0x015, 0x02A, // 35h
+ 0x03F, 0x03F, 0x000, // 36h
+ 0x03F, 0x03F, 0x02A, // 37h
+ 0x015, 0x015, 0x015, // 38h
+ 0x015, 0x015, 0x03F, // 39h
+ 0x015, 0x03F, 0x015, // 3Ah
+ 0x015, 0x03F, 0x03F, // 3Bh
+ 0x03F, 0x015, 0x015, // 3Ch
+ 0x03F, 0x015, 0x03F, // 3Dh
+ 0x03F, 0x03F, 0x015, // 3Eh
+ 0x03F, 0x03F, 0x03F, // 3Fh
+};
+
+/*
+ * From the Linux kernel.
+ * orig by Ben Pfaff and Petr Vandrovec.
+ * see the note in the vga.h for attribution.
+ *
+ * modified by
+ * Steve M. Gehlbach <steve@kesa.com>
+ * for the linuxbios project
+ *
+ * Write the data in the vga parameter structure
+ * to the vga registers, along with other default
+ * settings.
+ *
+ */
+static int vga_set_regs(const struct vga_par *par)
+{
+ int i;
+
+ /* update misc output register */
+ outb(par->misc, MIS_W);
+
+ /* synchronous reset on */
+ outb(0x00, SEQ_I);
+ outb(0x00, SEQ_D);
+
+ /* write sequencer registers */
+ outb(1, SEQ_I);
+ outb(par->seq[1] | 0x20, SEQ_D); // blank display
+ for (i = 2; i < SEQ_C; i++) {
+ outb(i, SEQ_I);
+ outb(par->seq[i], SEQ_D);
+ }
+
+ /* synchronous reset off */
+ outb(0x00, SEQ_I);
+ outb(0x03, SEQ_D);
+
+ /* deprotect CRT registers 0-7 */
+ outb(0x11, CRT_IC);
+ outb(par->crtc[0x11], CRT_DC);
+
+ /* write CRT registers */
+ for (i = 0; i < CRTC_C; i++) {
+ outb(i, CRT_IC);
+ outb(par->crtc[i], CRT_DC);
+ }
+ /* write graphics controller registers */
+ for (i = 0; i < GRA_C; i++) {
+ outb(i, GRA_I);
+ outb(par->gdc[i], GRA_D);
+ }
+
+ /* write attribute controller registers */
+ for (i = 0; i < ATT_C; i++) {
+ inb(IS1_RC); /* reset flip-flop */
+ inb(0x80); //delay
+ outb(i, ATT_IW);
+ inb(0x80); //delay
+
+ outb(par->atc[i], ATT_IW);
+ inb(0x80); //delay
+ }
+
+ // initialize the color table
+ outb(0, PEL_IW);
+ i = 0;
+ // length is a magic number right now
+ while ( i < (0x3f*3 + 3) ) {
+ outb(VgaLookupTable[i++], PEL_D);
+ outb(VgaLookupTable[i++], PEL_D);
+ outb(VgaLookupTable[i++], PEL_D);
+ }
+
+ outb(0x0ff, PEL_MSK); // palette mask
+
+ // very important
+ // turn on video, disable palette access
+ inb(IS1_RC); /* reset flip-flop */
+ inb(0x80); //delay
+ outb(0x20, ATT_IW);
+
+ /* Wait for screen to stabilize. */
+ //for(i=0;i<1000;i++) { inb(0x80); }
+
+ outb(0x01, SEQ_I); // unblank display
+ outb(par->seq[1], SEQ_D);
+
+// turn on display, disable access to attr palette
+ inb(IS1_RC);
+ outb(0x20, ATT_IW);
+
+return 0;
+}
+
+void
+vga_load_regs(void)
+{
+ struct vga_par par;
+
+ if (vga_decode_var(&vga_settings, &par) == 0) {
+ vga_set_regs(&par);
+ }
+}
diff --git a/roms/openbios/drivers/vga_set_mode.c b/roms/openbios/drivers/vga_set_mode.c
new file mode 100644
index 00000000..339ad296
--- /dev/null
+++ b/roms/openbios/drivers/vga_set_mode.c
@@ -0,0 +1,148 @@
+/*
+ * $Id$
+ * $Source$
+ *
+ * by
+ * Steve M. Gehlbach <steve@kesa.com>
+ *
+ * These routines set graphics mode and alpha mode
+ * for switching back and forth.
+ *
+ * Register settings are
+ * more or less as follows:
+ *
+ * Register Graphics Alpha
+ * 16 color
+ * ------------------------------------------------
+ * GDC_MODE 0x00 0x10
+ * GDC_MISC 0x05 0x0e
+ * SEQ_MEMORY_MODE 0x06 0x02
+ * SEQ_PLANE_WRITE 0x0f 0x03
+ * CRTC_CURSOR_START 0x20 0x00
+ * CRTC_CURSOR_END 0x00 CHAR_HEIGHT-1
+ * CRTC_MODE 0xe3 0xa3
+ * CRTC_MAX_SCAN 0x40 0x40 | CHAR_HEIGHT-1
+ * ATC_MODE 0x01 0x0c
+ *
+ */
+
+#include "asm/io.h"
+#include "vga.h"
+
+void vga_set_gmode (void) {
+ u8 byte;
+
+ byte = read_att_b(ATC_MODE) & ~0x0f;
+ write_att(byte|0x1, ATC_MODE);
+//
+// display is off at this point
+
+ byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf;
+ write_seq(byte|0xf,SEQ_PLANE_WRITE); // all planes
+ byte = read_seq_b(SEQ_MEMORY_MODE);
+ write_seq(byte|4,SEQ_MEMORY_MODE);
+
+ byte = read_gra_b(GDC_MODE) & ~0x10;
+ write_gra(byte,GDC_MODE);
+ write_gra(0x05, GDC_MISC);
+
+ write_crtc(0x20, CRTC_CURSOR_START);
+ write_crtc(0x00, CRTC_CURSOR_END);
+ byte = read_crtc_b(CRTC_MODE) & ~0xe0;
+ write_crtc(byte|0xe0, CRTC_MODE);
+ byte = read_crtc_b(CRTC_MAX_SCAN) & ~0x01f;
+ write_crtc(byte, CRTC_MAX_SCAN);
+
+ byte = inb(MIS_R); // get 3c2 value by reading 3cc
+ outb(byte & ~0xc,MIS_W); // clear last bits to set 25Mhz clock and low page
+
+
+// turn on display, disable access to attr palette
+ inb(IS1_RC);
+ outb(0x20, ATT_IW);
+}
+
+void vga_set_amode (void) {
+ u8 byte;
+ write_att(0x0c, ATC_MODE);
+
+ //reset palette to normal in the case it was changed
+ write_att(0x0, ATC_COLOR_PAGE);
+//
+// display is off at this point
+
+ write_seq(0x3,SEQ_PLANE_WRITE); // planes 0 & 1
+ byte = read_seq_b(SEQ_MEMORY_MODE) & ~0x04;
+ write_seq(byte,SEQ_MEMORY_MODE);
+
+ byte = read_gra_b(GDC_MODE) & ~0x60;
+ write_gra(byte|0x10,GDC_MODE);
+
+ write_gra(0x0e, GDC_MISC);
+
+ write_crtc(0x00, CRTC_CURSOR_START);
+ write_crtc(CHAR_HEIGHT-1, CRTC_CURSOR_END);
+
+ byte = read_crtc_b(CRTC_MODE) & ~0xe0;
+ write_crtc(byte|0xa0, CRTC_MODE);
+ byte = read_crtc_b(CRTC_MAX_SCAN) & ~0x01f;
+ write_crtc(byte | (CHAR_HEIGHT-1), CRTC_MAX_SCAN);
+
+
+// turn on display, disable access to attr palette
+ inb(IS1_RC);
+ outb(0x20, ATT_IW);
+}
+
+/*
+ * by Steve M. Gehlbach, Ph.D. <steve@kesa.com>
+ *
+ * vga_font_load loads a font into font memory. It
+ * assumes alpha mode has been set.
+ *
+ * The font load code follows technique used
+ * in the tiara project, which came from
+ * the Universal Talkware Boot Loader,
+ * http://www.talkware.net.
+ */
+
+void vga_font_load(unsigned char *vidmem, const unsigned char *font, int height, int num_chars) {
+
+/* Note: the font table is 'height' long but the font storage area
+ * is 32 bytes long.
+ */
+
+ int i,j;
+ u8 byte;
+
+ // set sequencer map 2, odd/even off
+ byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf;
+ write_seq(byte|4,SEQ_PLANE_WRITE);
+ byte = read_seq_b(SEQ_MEMORY_MODE);
+ write_seq(byte|4,SEQ_MEMORY_MODE);
+
+ // select graphics map 2, odd/even off, map starts at 0xa0000
+ write_gra(2,GDC_PLANE_READ);
+ byte = read_gra_b(GDC_MODE) & ~0x10;
+ write_gra(byte,GDC_MODE);
+ write_gra(0,GDC_MISC);
+
+ for (i = 0 ; i < num_chars ; i++) {
+ for (j = 0 ; j < height ; j++) {
+ vidmem[i*32+j] = font[i*16+j];
+ }
+ }
+
+ // set sequencer back to maps 0,1, odd/even on
+ byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf;
+ write_seq(byte|3,SEQ_PLANE_WRITE);
+ byte = read_seq_b(SEQ_MEMORY_MODE) & ~0x4;
+ write_seq(byte,SEQ_MEMORY_MODE);
+
+ // select graphics back to map 0,1, odd/even on
+ write_gra(0,GDC_PLANE_READ);
+ byte = read_gra_b(GDC_MODE);
+ write_gra(byte|0x10,GDC_MODE);
+ write_gra(0xe,GDC_MISC);
+
+}
diff --git a/roms/openbios/forth/Kconfig b/roms/openbios/forth/Kconfig
new file mode 100644
index 00000000..87ff1917
--- /dev/null
+++ b/roms/openbios/forth/Kconfig
@@ -0,0 +1,9 @@
+#
+#
+#
+
+#menu "Packages"
+#
+#source "forth/packages/Kconfig"
+#
+#endmenu
diff --git a/roms/openbios/forth/admin/README b/roms/openbios/forth/admin/README
new file mode 100644
index 00000000..711f7e0e
--- /dev/null
+++ b/roms/openbios/forth/admin/README
@@ -0,0 +1,3 @@
+\ This directory contains code that implements
+\ the Administration command group
+\ (Chapter 7.4 in the IEEE 1275-1994)
diff --git a/roms/openbios/forth/admin/banner.fs b/roms/openbios/forth/admin/banner.fs
new file mode 100644
index 00000000..5439fc08
--- /dev/null
+++ b/roms/openbios/forth/admin/banner.fs
@@ -0,0 +1,49 @@
+\ 7.4.10 Banner
+
+defer builtin-logo
+defer builtin-banner
+0 value suppress-banner?
+
+:noname
+ 0 0
+; to builtin-logo
+
+:noname
+ builddate s" built on " version s" Welcome to OpenBIOS v" pocket
+ tmpstrcat tmpstrcat tmpstrcat drop
+; to builtin-banner
+
+: suppress-banner ( -- )
+ 1 to suppress-banner?
+;
+
+: banner ( -- )
+ suppress-banner
+ stdout @ ?dup 0= if exit then
+
+ \ draw logo if stdout is a "display" node
+ dup ihandle>phandle " device_type" rot get-package-property if 0 0 then
+ " display" strcmp if
+ drop
+ else
+ \ draw logo ( ihandle )
+ dup ihandle>phandle " draw-logo" rot find-method if
+ ( ihandle xt )
+ swap >r >r
+ 0 \ line #
+ oem-logo? if oem-logo else builtin-logo then
+ ( 0 addr logo-len )
+ 200 = if
+ d# 64 d# 64
+ r> r> call-package
+ else
+ r> r> 2drop 2drop
+ then
+ else
+ drop
+ then
+ then
+
+ oem-banner? if oem-banner else builtin-banner then
+ type cr
+;
diff --git a/roms/openbios/forth/admin/build.xml b/roms/openbios/forth/admin/build.xml
new file mode 100644
index 00000000..66544967
--- /dev/null
+++ b/roms/openbios/forth/admin/build.xml
@@ -0,0 +1,25 @@
+<build>
+
+ <!--
+ build description for forth administrative command group
+
+ Copyright (C) 2003-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="openbios" target="forth">
+ <object source="devices.fs"/>
+ <object source="nvram.fs"/>
+ <object source="callback.fs"/>
+ <object source="help.fs"/>
+ <object source="iocontrol.fs"/>
+ <object source="banner.fs"/>
+ <object source="reset.fs"/>
+ <object source="script.fs"/>
+ <object source="security.fs"/>
+ <object source="selftest.fs"/>
+ <object source="userboot.fs"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/forth/admin/callback.fs b/roms/openbios/forth/admin/callback.fs
new file mode 100644
index 00000000..e318af23
--- /dev/null
+++ b/roms/openbios/forth/admin/callback.fs
@@ -0,0 +1,10 @@
+\ 7.4.9 Client program callback
+
+: callback ( "service-name< >" "arguments<cr>" -- )
+ ;
+
+: $callback ( argn ... arg1 nargs addr len -- retn ... ret2 Nreturns-1 )
+ ;
+
+: sync ( -- )
+ ;
diff --git a/roms/openbios/forth/admin/devices.fs b/roms/openbios/forth/admin/devices.fs
new file mode 100644
index 00000000..6f9e8efb
--- /dev/null
+++ b/roms/openbios/forth/admin/devices.fs
@@ -0,0 +1,515 @@
+\ tag: device tree administration
+\
+\ this code implements IEEE 1275-1994
+\
+\ Copyright (C) 2003 Samuel Rydh
+\ Copyright (C) 2003-2006 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+
+\ 7.4.11.1 Device alias
+
+: devalias ( "{alias-name}< >{device-specifier}<cr>" -- )
+ ;
+
+: nvalias ( "alias-name< >device-specifier<cr>" -- )
+ ;
+
+: $nvalias ( name-str name-len dev-str dev-len -- )
+ ;
+
+: nvunalias ( "alias-name< >" -- )
+ ;
+
+: $nvunalias ( name-str name-len -- )
+ ;
+
+
+\ 7.4.11.2 Device tree browsing
+
+: dev ( "<spaces>device-specifier" -- )
+ bl parse
+ find-device
+;
+
+: cd
+ dev
+;
+
+\ find-device ( dev-str dev-len -- )
+\ implemented in pathres.fs
+
+: device-end ( -- )
+ 0 active-package!
+ ;
+
+\ Open selected device node and make it the current instance
+\ section H.8 errata: pre OpenFirmware, but Sun OBP compatible
+: select-dev ( -- )
+ open-dev dup 0= abort" failed opening parent."
+ dup to my-self
+ ihandle>phandle active-package!
+;
+
+\ Close current node, deselect active package and current instance,
+\ leaving no instance selected
+\ section H.8 errata: pre OpenFirmware, but Sun OBP compatible
+: unselect-dev ( -- )
+ my-self close-dev
+ device-end
+ 0 to my-self
+;
+
+: begin-package ( arg-str arg-len reg-str reg-len dev-str dev-len -- )
+ select-dev
+ new-device
+ set-args
+;
+
+: end-package ( -- )
+ finish-device
+ unselect-dev
+;
+
+: ?active-package ( -- phandle )
+ active-package dup 0= abort" no active device"
+;
+
+\ -------------------------------------------------------
+\ path handling
+\ -------------------------------------------------------
+
+\ used if parent lacks an encode-unit method
+: def-encode-unit ( unitaddr ... )
+ pocket tohexstr
+;
+
+: get-encode-unit-xt ( phandle.parent -- xt )
+ >dn.parent @
+ " encode-unit" rot find-method
+ 0= if ['] def-encode-unit then
+;
+
+: get-nodename ( phandle -- str len )
+ " name" rot get-package-property if " <noname>" else 1- then
+;
+
+\ helper, return the node name in the format 'cpus@addr'
+: pnodename ( phandle -- str len )
+ dup get-nodename rot
+ dup " reg" rot get-package-property if drop exit then rot
+
+ \ set active-package and clear my-self (decode-phys needs this)
+ my-self >r 0 to my-self
+ active-package >r
+ dup active-package!
+
+ ( name len prop len phandle )
+ get-encode-unit-xt
+
+ ( name len prop len xt )
+ depth >r >r
+ decode-phys r> execute
+ r> -rot >r >r depth! 3drop
+
+ ( name len R: len str )
+ r> r> " @"
+ here 20 + \ abuse dictionary for temporary storage
+ tmpstrcat >r
+ 2swap r> tmpstrcat drop
+ pocket tmpstrcpy drop
+
+ r> active-package!
+ r> to my-self
+;
+
+: inodename ( ihandle -- str len )
+ my-self over to my-self >r
+ ihandle>phandle get-nodename
+
+ \ nonzero unit number?
+ false >r
+ depth >r my-unit r> 1+
+ begin depth over > while
+ swap 0<> if r> drop true >r then
+ repeat
+ drop
+
+ \ if not... check for presence of "reg" property
+ r> ?dup 0= if
+ " reg" my-self ihandle>phandle get-package-property
+ if false else 2drop true then
+ then
+
+ ( name len print-unit-flag )
+ if
+ my-self ihandle>phandle get-encode-unit-xt
+
+ ( name len xt )
+ depth >r >r
+ my-unit r> execute
+ r> -rot >r >r depth! drop
+ r> r>
+ ( name len str len )
+ here 20 + tmpstrcpy
+ " @" rot tmpstrcat drop
+ 2swap pocket tmpstrcat drop
+ then
+
+ \ add :arguments
+ my-args dup if
+ " :" pocket tmpstrcat drop
+ 2swap pocket tmpstrcat drop
+ else
+ 2drop
+ then
+
+ r> to my-self
+;
+
+\ helper, also used by client interface (package-to-path)
+: get-package-path ( phandle -- str len )
+ ?dup 0= if 0 0 then
+
+ dup >dn.parent @ 0= if drop " /" exit then
+ \ dictionary abused for temporary storage
+ >r 0 0 here 40 +
+ begin r> dup >dn.parent @ dup >r while
+ ( path len tempbuf phandle R: phandle.parent )
+ pnodename rot tmpstrcat
+ " /" rot tmpstrcat
+ repeat
+ r> 3drop
+ pocket tmpstrcpy drop
+;
+
+\ used by client interface (instance-to-path)
+: get-instance-path ( ihandle -- str len )
+ ?dup 0= if 0 0 then
+
+ dup ihandle>phandle >dn.parent @ 0= if drop " /" exit then
+
+ \ dictionary abused for temporary storage
+ >r 0 0 here 40 +
+ begin r> dup >in.my-parent @ dup >r while
+ ( path len tempbuf ihandle R: ihandle.parent )
+ dup >in.interposed @ 0= if
+ inodename rot tmpstrcat
+ " /" rot tmpstrcat
+ else
+ drop
+ then
+ repeat
+ r> 3drop
+ pocket tmpstrcpy drop
+;
+
+\ used by client interface (instance-to-interposed-path)
+: get-instance-interposed-path ( ihandle -- str len )
+ ?dup 0= if 0 0 then
+
+ dup ihandle>phandle >dn.parent @ 0= if drop " /" exit then
+
+ \ dictionary abused for temporary storage
+ >r 0 0 here 40 +
+ begin r> dup >in.my-parent @ dup >r while
+ ( path len tempbuf ihandle R: ihandle.parent )
+ dup >r inodename rot tmpstrcat
+ r> >in.interposed @ if " /%" else " /" then
+ rot tmpstrcat
+ repeat
+ r> 3drop
+ pocket tmpstrcpy drop
+;
+
+: pwd ( -- )
+ ?active-package get-package-path type
+;
+
+: ls ( -- )
+ cr
+ ?active-package >dn.child @
+ begin dup while
+ dup u. dup pnodename type cr
+ >dn.peer @
+ repeat
+ drop
+;
+
+
+\ -------------------------------------------
+\ property printing
+\ -------------------------------------------
+
+: .p-string? ( data len -- true | data len false )
+ \ no trailing zero?
+ 2dup + 1- c@ if 0 exit then
+
+ swap >r 0
+ \ count zeros and detect unprintable characters?
+ over 1- begin 1- dup 0>= while
+ dup r@ + c@
+ ( len zerocnt n ch )
+
+ ?dup 0= if
+ swap 1+ swap
+ else
+ dup 1b <= swap 80 >= or
+ if 2drop r> swap 0 exit then
+ then
+ repeat drop r> -rot
+ ( data len zerocnt )
+
+ \ simple string
+ 0= if
+ ascii " emit 1- type ascii " emit true exit
+ then
+
+ \ make sure there are no double zeros (except possibly at the end)
+ 2dup over + swap
+ ( data len end ptr )
+ begin 2dup <> while
+ dup c@ 0= if
+ 2dup 1+ <> if 2drop false exit then
+ then
+ dup cstrlen 1+ +
+ repeat
+ 2drop
+
+ ." {"
+ 0 -rot over + swap
+ \ multistring ( cnt end ptr )
+ begin 2dup <> while
+ rot dup if ." , " then 1+ -rot
+ dup cstrlen 2dup
+ ascii " emit type ascii " emit
+ 1+ +
+ repeat
+ ." }"
+ 3drop true
+;
+
+: .p-int? ( data len -- 1 | data len 0 )
+ dup 4 <> if false exit then
+ decode-int -rot 2drop true swap
+ dup 0>= if . exit then
+ dup -ff < if u. exit then
+ .
+;
+
+\ Print a number zero-padded
+: 0.r ( u minlen -- )
+ 0 swap <# 1 ?do # loop #s #> type
+;
+
+: .p-bytes? ( data len -- 1 | data len 0 )
+ ." -- " dup . ." : "
+ swap >r 0
+ begin 2dup > while
+ dup r@ + c@
+ ( len n ch )
+
+ 2 0.r space
+ 1+
+ repeat
+ 2drop r> drop 1
+;
+
+\ this function tries to heuristically determine the data format
+: (.property) ( data len -- )
+ dup 0= if 2drop ." <empty>" exit then
+
+ .p-string? if exit then
+ .p-int? if exit then
+ .p-bytes? if exit then
+ 2drop ." <unimplemented type>"
+;
+
+\ Print the value of a property in "reg" format
+: .p-reg ( #acells #scells data len -- )
+ 2dup + -rot ( #acells #scells data+len data len )
+ >r >r -rot ( data+len #acells #scells R: len data )
+ 4 * swap 4 * dup r> r> ( data+len #sbytes #abytes #abytes data len )
+ bounds ( data+len #sbytes #abytes #abytes data+len data ) ?do
+ dup 0= if 2 spaces then \ start of "size" part
+ 2dup <> if \ non-first byte in row
+ dup 3 and 0= if space then \ make numbers more readable
+ then
+ i c@ 2 0.r \ print byte
+ 1- 3dup nip + 0= if \ end of row
+ 3 pick i 1+ > if \ non-last byte
+ cr \ start new line
+ d# 26 spaces \ indentation
+ then
+ drop dup \ update counter
+ then
+ loop
+ 3drop drop
+;
+
+\ Return the number of cells per physical address
+: .p-translations-#pacells ( -- #cells )
+ " /" find-package if
+ " #address-cells" rot get-package-property if
+ 1
+ else
+ decode-int nip nip 1 max
+ then
+ else
+ 1
+ then
+;
+
+\ Return the number of cells per translation entry
+: .p-translations-#cells ( -- #cells )
+ [IFDEF] CONFIG_PPC
+ my-#acells 3 *
+ .p-translations-#pacells +
+ [ELSE]
+ my-#acells 3 *
+ [THEN]
+;
+
+\ Set up column offsets
+: .p-translations-cols ( -- col1 ... coln #cols )
+ .p-translations-#cells 4 *
+ [IFDEF] CONFIG_PPC
+ 4 -
+ dup 4 -
+ dup .p-translations-#pacells 4 * -
+ 3
+ [ELSE]
+ my-#acells 4 * -
+ dup my-#scells 4 * -
+ 2
+ [THEN]
+;
+
+\ Print the value of the MMU translations property
+: .p-translations ( data len -- )
+ >r >r .p-translations-cols r> r> ( col1 ... coln #cols data len )
+ 2dup + -rot ( col1 ... coln #cols data+len data len )
+ >r >r .p-translations-#cells 4 * dup r> r>
+ ( col1 ... coln #cols data+len #bytes #bytes len data )
+ bounds ( col1 ... coln #cols data+len #bytes #bytes data+len data ) ?do
+ 3 pick 4 + 4 ?do \ check all defined columns
+ i pick over = if
+ 2 spaces \ start new column
+ then
+ loop
+ 2dup <> if \ non-first byte in row
+ dup 3 and 0= if space then \ make numbers more readable
+ then
+ i c@ 2 0.r \ print byte
+ 1- dup 0= if \ end of row
+ 2 pick i 1+ > if \ non-last byte
+ cr \ start new line
+ d# 26 spaces \ indentation
+ then
+ drop dup \ update counter
+ then
+ loop
+ 2drop drop 0 ?do drop loop
+;
+
+\ This function hardwires data formats to particular node properties
+: (.property-by-name) ( name-str name-len data len -- )
+ 2over " reg" strcmp 0= if
+ my-#acells my-#scells 2swap .p-reg
+ 2drop exit
+ then
+
+ active-package get-nodename " memory" strcmp 0= if
+ 2over " available" strcmp 0= if
+ my-#acells my-#scells 2swap .p-reg
+ 2drop exit
+ then
+ then
+ " /chosen" find-dev if
+ " mmu" rot get-package-property 0= if
+ decode-int nip nip ihandle>phandle active-package = if
+ 2over " available" strcmp 0= if
+ my-#acells my-#scells 1 max 2swap .p-reg
+ 2drop exit
+ then
+ 2over " translations" strcmp 0= if
+ .p-translations
+ 2drop exit
+ then
+ then
+ then
+ then
+
+ 2swap 2drop ( data len )
+ (.property)
+;
+
+: .properties ( -- )
+ ?active-package dup >r if
+ 0 0
+ begin
+ r@ next-property
+ while
+ cr 2dup dup -rot type
+ begin ." " 1+ dup d# 26 >= until drop
+ 2dup
+ 2dup active-package get-package-property drop
+ ( name-str name-len data len )
+ (.property-by-name)
+ repeat
+ then
+ r> drop
+ cr
+;
+
+
+\ 7.4.11 Device tree
+
+: print-dev ( phandle -- phandle )
+ dup u.
+ dup get-package-path type
+ dup " device_type" rot get-package-property if
+ cr
+ else
+ ." (" decode-string type ." )" cr 2drop
+ then
+ ;
+
+: show-sub-devs ( subtree-phandle -- )
+ print-dev
+ >dn.child @
+ begin dup while
+ dup recurse
+ >dn.peer @
+ repeat
+ drop
+ ;
+
+: show-all-devs ( -- )
+ active-package
+ cr " /" find-device
+ ?active-package show-sub-devs
+ active-package!
+ ;
+
+
+: show-devs ( "{device-specifier}<cr>" -- )
+ active-package
+ cr " /" find-device
+ linefeed parse find-device
+ ?active-package show-sub-devs
+ active-package!
+ ;
+
+
+
+\ 7.4.11.3 Device probing
+
+\ Set to true if the last probe-self was successful
+0 value probe-fcode?
+
+: probe-all ( -- )
+ ;
diff --git a/roms/openbios/forth/admin/help.fs b/roms/openbios/forth/admin/help.fs
new file mode 100644
index 00000000..e6e624b2
--- /dev/null
+++ b/roms/openbios/forth/admin/help.fs
@@ -0,0 +1,51 @@
+\ tag: firmware help
+\
+\ this code implements IEEE 1275-1994 ch. 7.4.1
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+hex
+
+: (help-generic)
+ ." Enter 'help command-name' or 'help category-name' for more help" cr
+ ." (Use ONLY the first word of a category description)" cr
+ ." Examples: help select -or- help line" cr cr
+ ." Categories:" cr
+ ." boot (Load and execute a client program)" cr
+ ." diag (Diagnostic routines)" cr
+ ;
+
+: (help-diag)
+ ." test <device> Run the selftest method for specified device" cr
+ ." test-all Execute test for all devices using selftest method" cr
+ ;
+
+: (help-boot)
+ ." boot [<device-specifier>:<device-arguments>] [boot-arguments]" cr
+ ." Examples:" cr
+ ." boot Default boot (values specified in nvram variables)" cr
+ ." boot disk1:a Boot from disk1 partition a" cr
+ ." boot hd:1,\boot\vmlinuz root=/dev/hda1" cr
+ ;
+
+: help ( "{name}<cr>" -- )
+ \ Provide information for category or specific command.
+ linefeed parse cr
+ dup 0= if
+ (help-generic)
+ 2drop
+ else
+ 2dup " diag" rot min comp not if
+ (help-diag) 2drop exit
+ then
+ 2dup " boot" rot min comp not if
+ (help-boot) 2drop exit
+ then
+ ." No help available for " type cr
+ then
+ ;
+
diff --git a/roms/openbios/forth/admin/iocontrol.fs b/roms/openbios/forth/admin/iocontrol.fs
new file mode 100644
index 00000000..b0f578f4
--- /dev/null
+++ b/roms/openbios/forth/admin/iocontrol.fs
@@ -0,0 +1,168 @@
+\ tag: stdin/stdout handling
+\
+\ Copyright (C) 2003 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ 7.4.5 I/O control
+
+variable stdout
+variable stdin
+
+: input ( dev-str dev-len -- )
+ 2dup find-dev 0= if
+ ." Input device " type ." not found." cr exit
+ then
+
+ " read" rot find-method 0= if
+ type ." has no read method." cr exit
+ then
+ drop
+
+ \ open stdin device
+ 2dup open-dev ?dup 0= if
+ ." Opening " type ." failed." cr exit
+ then
+ -rot 2drop
+
+ \ call install-abort if present
+ dup " install-abort" rot ['] $call-method catch if 3drop then
+
+ \ close old stdin
+ stdin @ ?dup if
+ dup " remove-abort" rot ['] $call-method catch if 3drop then
+ close-dev
+ then
+ stdin !
+
+ \ update /chosen
+ " /chosen" find-package if
+ >r stdin @ encode-int " stdin" r> (property)
+ then
+
+[IFDEF] CONFIG_SPARC32
+ \ update stdin-path properties
+ \ (this isn't part of the IEEE1275 spec but needed by older Solaris)
+ " /" find-package if
+ >r stdin @ get-instance-path encode-string " stdin-path" r> (property)
+ then
+[THEN]
+;
+
+: output ( dev-str dev-len -- )
+ 2dup find-dev 0= if
+ ." Output device " type ." not found." cr exit
+ then
+
+ " write" rot find-method 0= if
+ type ." has no write method." cr exit
+ then
+ drop
+
+ \ open stdin device
+ 2dup open-dev ?dup 0= if
+ ." Opening " type ." failed." cr exit
+ then
+ -rot 2drop
+
+ \ close old stdout
+ stdout @ ?dup if close-dev then
+ stdout !
+
+ \ update /chosen
+ " /chosen" find-package if
+ >r stdout @ encode-int " stdout" r> (property)
+ then
+
+[IFDEF] CONFIG_SPARC32
+ \ update stdout-path properties
+ \ (this isn't part of the IEEE1275 spec but needed by older Solaris)
+ " /" find-package if
+ >r stdout @ get-instance-path encode-string " stdout-path" r> (property)
+ then
+[THEN]
+;
+
+: io ( dev-str dev-len -- )
+ 2dup input output
+;
+
+\ key?, key and emit implementation
+variable io-char
+variable io-out-char
+
+: io-key? ( -- available? )
+ io-char @ -1 <> if true exit then
+ io-char 1 " read" stdin @ $call-method
+ 1 =
+;
+
+: io-key ( -- key )
+ \ poll for key
+ begin io-key? until
+ io-char c@ -1 to io-char
+;
+
+: io-emit ( char -- )
+ stdout @ if
+ io-out-char c!
+ io-out-char 1 " write" stdout @ $call-method
+ then
+ drop
+;
+
+variable CONSOLE-IN-list
+variable CONSOLE-OUT-list
+
+: CONSOLE-IN-initializer ( xt -- )
+ CONSOLE-IN-list list-add ,
+;
+: CONSOLE-OUT-initializer ( xt -- )
+ CONSOLE-OUT-list list-add ,
+;
+
+: install-console ( -- )
+
+ \ create screen alias
+ " /aliases" find-package if
+ >r
+ " screen" find-package if drop else
+ \ bad (or missing) screen alias
+ 0 " display" iterate-device-type ?dup if
+ ( display-ph R: alias-ph )
+ get-package-path encode-string " screen" r@ (property)
+ then
+ then
+ r> drop
+ then
+
+ output-device output
+ input-device input
+
+ \ let arch determine a useful output device
+ CONSOLE-OUT-list begin list-get while
+ stdout @ if drop else @ execute then
+ repeat
+
+ \ let arch determine a useful input device
+ CONSOLE-IN-list begin list-get while
+ stdin @ if drop else @ execute then
+ repeat
+
+ \ activate console
+ stdout @ if
+ ['] io-emit to emit
+ then
+
+ stdin @ if
+ -1 to io-char
+ ['] io-key? to key?
+ ['] io-key to key
+ then
+;
+
+:noname
+ " screen" output
+; CONSOLE-OUT-initializer
diff --git a/roms/openbios/forth/admin/nvram.fs b/roms/openbios/forth/admin/nvram.fs
new file mode 100644
index 00000000..20f6462b
--- /dev/null
+++ b/roms/openbios/forth/admin/nvram.fs
@@ -0,0 +1,385 @@
+\ tag: nvram config handling
+\
+\ this code implements IEEE 1275-1994
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+struct ( config )
+ 2 cells field >cf.name
+ 2 cells field >cf.default \ 0 -1 if no default
+ /n field >cf.check-xt
+ /n field >cf.exec-xt
+ /n field >cf.next
+constant config-info.size
+
+0 value config-root
+
+\ --------------------------------------------------------
+\ config handling
+\ --------------------------------------------------------
+
+: find-config ( name-str len -- 0|configptr )
+ config-root
+ begin ?dup while
+ -rot
+ 2dup 4 pick >cf.name 2@
+ strcmp 0= if
+ 2drop exit
+ then
+ rot >cf.next @
+ repeat
+ 2drop 0
+;
+
+: is-config-word ( configp -- )
+ dup >cf.name 2@ $create ,
+ does> @
+ dup >cf.name 2@
+ s" /options" find-dev if
+ get-package-property if 0 -1 then
+ ( configp prop-str prop-len )
+ \ drop trailing zero
+ ?dup if 1- then
+ else
+ 2drop 0 -1
+ then
+ \ use default value if property is missing
+ dup 0< if 2drop dup >cf.default 2@ then
+ \ no default value, use empty string
+ dup 0< if 2drop 0 0 then
+
+ rot >cf.exec-xt @ execute
+;
+
+: new-config ( name-str name-len -- configp )
+ 2dup find-config ?dup if
+ nip nip
+ 0 0 2 pick >cf.default 2!
+ else
+ dict-strdup
+ here config-info.size allot
+ dup config-info.size 0 fill
+ config-root over >cf.next !
+ dup to config-root
+ dup >r >cf.name 2! r>
+ dup is-config-word
+ then
+ ( configp )
+;
+
+: config-default ( str len configp -- )
+ -rot
+ dup 0> if dict-strdup then
+ rot >cf.default 2!
+;
+
+: no-conf-def ( configp -- )
+ 0 -1
+;
+
+\ --------------------------------------------------------
+\ config types
+\ --------------------------------------------------------
+
+: exec-str-conf ( str len -- str len )
+ \ trivial
+;
+: check-str-conf ( str len -- str len valid? )
+ \ nothing
+ true
+;
+
+: str-config ( def-str len name len -- configp )
+ new-config >r
+ ['] exec-str-conf r@ >cf.exec-xt !
+ ['] check-str-conf r@ >cf.check-xt !
+ r> config-default
+;
+
+\ ------------------------------------------------------------
+
+: exec-int-conf ( str len -- value )
+ \ fixme
+ parse-hex
+;
+: check-int-conf ( str len -- str len valid? )
+ true
+;
+
+: int-config ( def-str len name len -- configp )
+ new-config >r
+ ['] exec-int-conf r@ >cf.exec-xt !
+ ['] check-int-conf r@ >cf.check-xt !
+ r> config-default
+;
+
+\ ------------------------------------------------------------
+
+: exec-secmode-conf ( str len -- n )
+ 2dup s" command" strcmp 0= if 2drop 1 exit then
+ 2dup s" full" strcmp 0= if 2drop 2 exit then
+ 2drop 0
+;
+: check-secmode-conf ( str len -- str len valid? )
+ 2dup s" none" strcmp 0= if true exit then
+ 2dup s" command" strcmp 0= if true exit then
+ 2dup s" full" strcmp 0= if true exit then
+ false
+;
+
+: secmode-config ( def-str len name len -- configp )
+ new-config >r
+ ['] exec-secmode-conf r@ >cf.exec-xt !
+ ['] check-secmode-conf r@ >cf.check-xt !
+ r> config-default
+;
+
+\ ------------------------------------------------------------
+
+: exec-bool-conf ( str len -- value )
+ 2dup s" true" strcmp 0= if 2drop true exit then
+ 2dup s" false" strcmp 0= if 2drop false exit then
+ 2dup s" TRUE" strcmp 0= if 2drop false exit then
+ 2dup s" FALSE" strcmp 0= if 2drop false exit then
+ parse-hex 0<>
+;
+
+: check-bool-conf ( name len -- str len valid? )
+ 2dup s" true" strcmp 0= if true exit then
+ 2dup s" false" strcmp 0= if true exit then
+ 2dup s" TRUE" strcmp 0= if 2drop s" true" true exit then
+ 2dup s" FALSE" strcmp 0= if 2drop s" false" true exit then
+ false
+;
+
+: bool-config ( configp -- configp )
+ new-config >r
+ ['] exec-bool-conf r@ >cf.exec-xt !
+ ['] check-bool-conf r@ >cf.check-xt !
+ r> config-default
+;
+
+
+\ --------------------------------------------------------
+\ 7.4.4 Nonvolatile memory
+\ --------------------------------------------------------
+
+: $setenv ( data-addr data-len name-str name-len -- )
+ 2dup find-config ?dup if
+ >r 2swap r>
+ ( name len data len configptr )
+ >cf.check-xt @ execute
+ 0= abort" Invalid value."
+ 2swap
+ else
+ \ create string config type
+ 2dup no-conf-def 2swap str-config
+ then
+
+ 2swap encode-string 2swap
+ s" /options" find-package drop
+ encode-property
+;
+
+: setenv ( "nv-param< >new-value<eol>" -- )
+ parse-word
+ \ XXX drop blanks
+ dup if linefeed parse else 0 0 then
+
+ dup 0= abort" Invalid value."
+ 2swap $setenv
+;
+
+: printenv ( "{param-name}<eol>" -- )
+ \ XXX temporary implementation
+ linefeed parse 2drop
+
+ active-package
+ s" /options" find-device
+ .properties
+ active-package!
+;
+
+: (set-default) ( configptr -- )
+ dup >cf.default 2@ dup 0>= if
+ rot >cf.name 2@ $setenv
+ else
+ \ no default value
+ 3drop
+ then
+;
+
+: set-default ( "param-name<eol>" -- )
+ linefeed parse
+ find-config ?dup if
+ (set-default)
+ else
+ ." No such parameter." -2 throw
+ then
+;
+
+: set-defaults ( -- )
+ config-root
+ begin ?dup while
+ dup (set-default)
+ >cf.next @
+ repeat
+;
+
+( maxlen "new-name< >" -- ) ( E: -- addr len )
+: nodefault-bytes
+ ;
+
+
+\ --------------------------------------------------------
+\ initialize config from nvram
+\ --------------------------------------------------------
+
+\ CHRP format (array of null-terminated strings, "variable=value")
+: nvram-load-configs ( data len -- )
+ \ XXX: no len checking performed...
+ drop
+ begin dup c@ while
+ ( data )
+ dup cstrlen 2dup + 1+ -rot
+ ( next str len )
+ ascii = left-split ( next val len name str )
+ ['] $setenv catch if
+ 2drop 2drop
+ then
+ repeat drop
+;
+
+: (nvram-store-one) ( buf len str len -- buf len success? )
+ swap >r
+ 2dup < if r> 2drop 2drop false exit then
+ ( buf len strlen R: str )
+ swap over - r> swap >r -rot
+ ( str buf strlen R: res_len )
+ 2dup + >r move r> r> true
+;
+
+: (make-configstr) ( configptr ph -- str len )
+ >r
+ >cf.name 2@
+ 2dup r> get-package-property if
+ 2drop 0 0 exit
+ else
+ dup if 1- then
+ then
+ ( name len value-str len )
+ 2swap s" =" 2swap
+ pocket tmpstrcat tmpstrcat drop
+ 2dup + 0 swap c!
+ 1+
+;
+
+: nvram-store-configs ( data len -- )
+ 2 - \ make room for two trailing zeros
+
+ s" /options" find-dev 0= if 2drop exit then
+ >r
+ config-root
+ ( data len configptr R: phandle )
+ begin ?dup while
+ r@ over >r (make-configstr)
+ ( buf len val len R: configptr phandle )
+ (nvram-store-one) drop
+ r> >cf.next @
+ repeat
+ \ null terminate
+ 2 + 0 fill
+ r> drop
+;
+
+
+\ --------------------------------------------------------
+\ NVRAM variables
+\ --------------------------------------------------------
+\ fcode-debug? input-device output-device
+s" true" s" auto-boot?" bool-config \ 7.4.3.5
+s" boot" s" boot-command" str-config \ 7.4.3.5
+s" " s" boot-file" str-config \ 7.4.3.5
+s" false" s" diag-switch?" bool-config \ 7.4.3.5
+no-conf-def s" diag-device" str-config \ 7.4.3.5
+no-conf-def s" diag-file" str-config \ 7.4.3.5
+s" false" s" fcode-debug?" bool-config \ 7.7
+s" " s" nvramrc" str-config \ 7.4.4.2
+s" false" s" oem-banner?" bool-config
+s" " s" oem-banner" str-config
+s" false" s" oem-logo?" bool-config
+no-conf-def s" oem-logo" str-config
+s" false" s" use-nvramrc?" bool-config \ 7.4.4.2
+s" keyboard" s" input-device" str-config \ 7.4.5
+s" screen" s" output-device" str-config \ 7.4.5
+s" 80" s" screen-#columns" int-config \ 7.4.5
+s" 24" s" screen-#rows" int-config \ 7.4.5
+s" 0" s" selftest-#megs" int-config
+no-conf-def s" security-mode" secmode-config
+
+\ --- devices ---
+s" -1" s" pci-probe-mask" int-config
+s" false" s" default-mac-address" bool-config
+s" false" s" skip-netboot?" bool-config
+s" true" s" scroll-lock" bool-config
+
+[IFDEF] CONFIG_PPC
+\ ---- PPC ----
+s" false" s" little-endian?" bool-config
+s" false" s" real-mode?" bool-config
+s" -1" s" real-base" int-config
+s" -1" s" real-size" int-config
+s" 4000000" s" load-base" int-config
+s" -1" s" virt-base" int-config
+s" -1" s" virt-size" int-config
+[THEN]
+
+[IFDEF] CONFIG_X86
+\ ---- X86 ----
+s" true" s" little-endian?" bool-config
+[THEN]
+
+[IFDEF] CONFIG_SPARC32
+\ ---- SPARC32 ----
+s" 4000" s" load-base" int-config
+s" true" s" tpe-link-test?" bool-config
+s" 9600,8,n,1,-" s" ttya-mode" str-config
+s" true" s" ttya-ignore-cd" bool-config
+s" false" s" ttya-rts-dtr-off" bool-config
+s" 9600,8,n,1,-" s" ttyb-mode" str-config
+s" true" s" ttyb-ignore-cd" bool-config
+s" false" s" ttyb-rts-dtr-off" bool-config
+[THEN]
+
+[IFDEF] CONFIG_SPARC64
+\ ---- SPARC64 ----
+s" 4000" s" load-base" int-config
+s" false" s" little-endian?" bool-config
+[THEN]
+
+\ --- ??? ---
+s" " s" boot-screen" str-config
+s" " s" boot-script" str-config
+s" false" s" use-generic?" bool-config
+s" disk" s" boot-device" str-config \ 7.4.3.5
+s" " s" boot-args" str-config \ ???
+
+\ defers
+['] fcode-debug? to _fcode-debug?
+['] diag-switch? to _diag-switch?
+
+\ Hack for load-base: it seems that some Sun bootloaders try
+\ and execute "<value> to load-base" which will only work if
+\ load-base is value. Hence we redefine load-base here as a
+\ value using its normal default.
+[IFDEF] CONFIG_SPARC64
+load-base value load-base
+[THEN]
+
+: release-load-area
+ drop
+;
diff --git a/roms/openbios/forth/admin/reset.fs b/roms/openbios/forth/admin/reset.fs
new file mode 100644
index 00000000..56569265
--- /dev/null
+++ b/roms/openbios/forth/admin/reset.fs
@@ -0,0 +1,12 @@
+\ 7.4.7 Reset
+
+defer reset-all ( -- )
+
+: no-reset-all
+ s" reset-all is not available on this platform." type cr
+ ;
+
+' no-reset-all to reset-all
+
+\ OpenBOOT knows reset as well.
+: reset reset-all ;
diff --git a/roms/openbios/forth/admin/script.fs b/roms/openbios/forth/admin/script.fs
new file mode 100644
index 00000000..a65adb20
--- /dev/null
+++ b/roms/openbios/forth/admin/script.fs
@@ -0,0 +1,16 @@
+\ 7.4.4.2 The script
+
+: nvedit ( -- )
+ ;
+
+: nvstore ( -- )
+ ;
+
+: nvquit ( -- )
+ ;
+
+: nvrecover ( -- )
+ ;
+
+: nvrun ( -- )
+ ;
diff --git a/roms/openbios/forth/admin/security.fs b/roms/openbios/forth/admin/security.fs
new file mode 100644
index 00000000..ef2ec30b
--- /dev/null
+++ b/roms/openbios/forth/admin/security.fs
@@ -0,0 +1,10 @@
+\ 7.4.6 Security
+
+: password ( -- )
+ ;
+
+: security-password ( -- password-str password-len )
+ ;
+
+: security-#badlogins ( -- n )
+ ;
diff --git a/roms/openbios/forth/admin/selftest.fs b/roms/openbios/forth/admin/selftest.fs
new file mode 100644
index 00000000..20c0c963
--- /dev/null
+++ b/roms/openbios/forth/admin/selftest.fs
@@ -0,0 +1,49 @@
+\ tag: self-test
+\
+\ this code implements IEEE 1275-1994 ch. 7.4.8
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\
+\ 7.4.8 Self-test
+\
+
+: $test ( devname-addr devname-len -- )
+ 2dup ." Testing device " type ." : "
+ find-dev if
+ s" self-test" rot find-method if
+ execute
+ else
+ ." no self-test method."
+ then
+ else
+ ." no such device."
+ then
+ cr
+;
+
+: test ( "device-specifier<cr>"-- )
+ linefeed parse cr $test
+ ;
+
+: test-sub-devs
+ >dn.child @
+ begin dup while
+ dup get-package-path $test
+ dup recurse
+ >dn.peer @
+ repeat
+ drop
+;
+
+: test-all ( "{device-specifier}<cr>" -- )
+ active-package
+ cr " /" find-device
+ linefeed parse find-device
+ ?active-package test-sub-devs
+ active-package!
+ ;
diff --git a/roms/openbios/forth/admin/userboot.fs b/roms/openbios/forth/admin/userboot.fs
new file mode 100644
index 00000000..3ae899c2
--- /dev/null
+++ b/roms/openbios/forth/admin/userboot.fs
@@ -0,0 +1,29 @@
+\ 7.4.3.5 User commands for booting
+
+: boot ( "{param-text}<cr>" -- )
+ linefeed parse
+
+ \ Copy NVRAM parameters from boot-file to bootargs in case any parameters have
+ \ been specified for the platform-specific boot code
+ s" boot-file" $find drop execute
+ encode-string
+ " /chosen" (find-dev) if
+ " bootargs" rot (property)
+ then
+
+ \ Execute platform-specific boot code, e.g. kernel
+ s" platform-boot" $find if
+ execute
+ then
+
+ (find-bootdevice) \ Setup bootargs
+ $load \ load and go
+ go
+;
+
+
+\ : diagnostic-mode? ( -- diag? )
+\ ;
+
+\ : diag-switch? ( -- diag? )
+\ ;
diff --git a/roms/openbios/forth/bootstrap/bootstrap.fs b/roms/openbios/forth/bootstrap/bootstrap.fs
new file mode 100644
index 00000000..0668cf7d
--- /dev/null
+++ b/roms/openbios/forth/bootstrap/bootstrap.fs
@@ -0,0 +1,1590 @@
+\ tag: bootstrap of basic forth words
+\
+\ Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\
+\ this file contains almost all forth words described
+\ by the open firmware user interface. Some more complex
+\ parts are found in seperate files (memory management,
+\ vocabulary support)
+\
+
+\
+\ often used constants (reduces dictionary size)
+\
+
+1 constant 1
+2 constant 2
+3 constant 3
+-1 constant -1
+0 constant 0
+
+0 value my-self
+
+\
+\ 7.3.5.1 Numeric-base control
+\
+
+: decimal 10 base ! ;
+: hex 16 base ! ;
+: octal 8 base ! ;
+hex
+
+\
+\ vocabulary words
+\
+
+variable current forth-last current !
+
+: last
+ current @
+ ;
+
+variable #order 0 #order !
+
+defer context
+0 value vocabularies?
+
+defer locals-end
+0 value locals-dict
+variable locals-dict-buf
+
+\
+\ 7.3.7 Flag constants
+\
+
+1 1 = constant true
+0 1 = constant false
+
+\
+\ 7.3.9.2.2 Immediate words (part 1)
+\
+
+: (immediate) ( xt -- )
+ 1 - dup c@ 1 or swap c!
+ ;
+
+: (compile-only)
+ 1 - dup c@ 2 or swap c!
+ ;
+
+: immediate
+ last @ (immediate)
+ ;
+
+: compile-only
+ last @ (compile-only)
+ ;
+
+: flags? ( xt -- flags )
+ /n /c + - c@ 7f and
+ ;
+
+: immediate? ( xt -- true|false )
+ flags? 1 and 1 =
+ ;
+
+: compile-only? ( xt -- true|false )
+ flags? 2 and 2 =
+ ;
+
+: [ 0 state ! ; compile-only
+: ] -1 state ! ;
+
+
+
+\
+\ 7.3.9.2.1 Data space allocation
+\
+
+: allot here + here! ;
+: , here /n allot ! ;
+: c, here /c allot c! ;
+
+: align
+ /n here /n 1 - and - \ how many bytes to next alignment
+ /n 1 - and allot \ mask out everything that is bigger
+ ; \ than cellsize-1
+
+: null-align
+ here dup align here swap - 0 fill
+ ;
+
+: w,
+ here 1 and allot \ if here is not even, we have to align.
+ here /w allot w!
+ ;
+
+: l,
+ /l here /l 1 - and - \ same as in align, with /l
+ /l 1 - and \ if it's /l we are already aligned.
+ allot
+ here /l allot l!
+ ;
+
+
+\
+\ 7.3.6 comparison operators (part 1)
+\
+
+: <> = invert ;
+
+
+\
+\ 7.3.9.2.4 Miscellaneous dictionary (part 1)
+\
+
+: (to) ( xt-new xt-defer -- )
+ /n + !
+ ;
+
+: >body ( xt -- a-addr ) /n 1 lshift + ;
+: body> ( a-addr -- xt ) /n 1 lshift - ;
+
+: reveal latest @ last ! ;
+: recursive reveal ; immediate
+: recurse latest @ /n + , ; immediate
+
+: noop ;
+
+defer environment?
+: no-environment?
+ 2drop false
+ ;
+
+['] no-environment? ['] environment? (to)
+
+
+\
+\ 7.3.8.1 Conditional branches
+\
+
+\ A control stack entry is implemented using 2 data stack items
+\ of the form ( addr type ). type can be one of the
+\ following:
+\ 0 - orig
+\ 1 - dest
+\ 2 - do-sys
+
+: resolve-orig here nip over /n + - swap ! ;
+: (if) ['] do?branch , here 0 0 , ; compile-only
+: (then) resolve-orig ; compile-only
+
+variable tmp-comp-depth -1 tmp-comp-depth !
+variable tmp-comp-buf 0 tmp-comp-buf !
+
+: setup-tmp-comp ( -- )
+ state @ 0 = (if)
+ here tmp-comp-buf @ here! , \ save here and switch to tmp directory
+ 1 , \ DOCOL
+ depth tmp-comp-depth ! \ save control depth
+ ]
+ (then)
+;
+
+: execute-tmp-comp ( -- )
+ depth tmp-comp-depth @ =
+ (if)
+ -1 tmp-comp-depth !
+ ['] (semis) ,
+ tmp-comp-buf @
+ dup @ here!
+ 0 state !
+ /n + execute
+ (then)
+;
+
+: if setup-tmp-comp ['] do?branch , here 0 0 , ; immediate
+: then resolve-orig execute-tmp-comp ; compile-only
+: else ['] dobranch , here 0 0 , 2swap resolve-orig ; compile-only
+
+\
+\ 7.3.8.3 Conditional loops
+\
+
+\ some dummy words for see
+: (begin) ;
+: (again) ;
+: (until) ;
+: (while) ;
+: (repeat) ;
+
+\ resolve-dest requires a loop...
+: (resolve-dest) here /n + nip - , ;
+: (resolve-begin) setup-tmp-comp ['] (begin) , here 1 ; immediate
+: (resolve-until) ['] (until) , ['] do?branch , (resolve-dest) execute-tmp-comp ; compile-only
+
+: resolve-dest ( dest origN ... orig )
+ 2 >r
+ (resolve-begin)
+ \ Find topmost control stack entry with a type of 1 (dest)
+ r> dup dup pick 1 = if
+ \ Move it to the top
+ roll
+ swap 1 - roll
+ \ Resolve it
+ (resolve-dest)
+ 1 \ force exit
+ else
+ drop
+ 2 + >r
+ 0
+ then
+ (resolve-until)
+;
+
+: begin
+ setup-tmp-comp
+ ['] (begin) ,
+ here
+ 1
+ ; immediate
+
+: again
+ ['] (again) ,
+ ['] dobranch ,
+ resolve-dest
+ execute-tmp-comp
+ ; compile-only
+
+: until
+ ['] (until) ,
+ ['] do?branch ,
+ resolve-dest
+ execute-tmp-comp
+ ; compile-only
+
+: while
+ setup-tmp-comp
+ ['] (while) ,
+ ['] do?branch ,
+ here 0 0 , 2swap
+ ; immediate
+
+: repeat
+ ['] (repeat) ,
+ ['] dobranch ,
+ resolve-dest resolve-orig
+ execute-tmp-comp
+ ; compile-only
+
+
+\
+\ 7.3.8.4 Counted loops
+\
+
+variable leaves 0 leaves !
+
+: resolve-loop
+ leaves @
+ begin
+ ?dup
+ while
+ dup @ \ leaves -- leaves *leaves )
+ swap \ -- *leaves leaves )
+ here over - \ -- *leaves leaves here-leaves
+ swap ! \ -- *leaves
+ repeat
+ here nip - ,
+ leaves !
+ ;
+
+: do
+ setup-tmp-comp
+ leaves @
+ here 2
+ ['] (do) ,
+ 0 leaves !
+ ; immediate
+
+: ?do
+ setup-tmp-comp
+ leaves @
+ ['] (?do) ,
+ here 2
+ here leaves !
+ 0 ,
+ ; immediate
+
+: loop
+ ['] (loop) ,
+ resolve-loop
+ execute-tmp-comp
+ ; immediate
+
+: +loop
+ ['] (+loop) ,
+ resolve-loop
+ execute-tmp-comp
+ ; immediate
+
+
+\ Using primitive versions of i and j
+\ speeds up loops by 300%
+\ : i r> r@ swap >r ;
+\ : j r> r> r> r@ -rot >r >r swap >r ;
+
+: unloop r> r> r> 2drop >r ;
+
+: leave
+ ['] unloop ,
+ ['] dobranch ,
+ leaves @
+ here leaves !
+ ,
+ ; immediate
+
+: ?leave if leave then ;
+
+\
+\ 7.3.8.2 Case statement
+\
+
+: case
+ setup-tmp-comp
+ 0
+; immediate
+
+: endcase
+ ['] drop ,
+ 0 ?do
+ ['] then execute
+ loop
+ execute-tmp-comp
+; immediate
+
+: of
+ 1 + >r
+ ['] over ,
+ ['] = ,
+ ['] if execute
+ ['] drop ,
+ r>
+ ; immediate
+
+: endof
+ >r
+ ['] else execute
+ r>
+ ; immediate
+
+\
+\ 7.3.8.5 Other control flow commands
+\
+
+: exit r> drop ;
+
+
+\
+\ 7.3.4.3 ASCII constants (part 1)
+\
+
+20 constant bl
+07 constant bell
+08 constant bs
+0d constant carret
+0a constant linefeed
+
+
+\
+\ 7.3.1.1 - stack duplication
+\
+: tuck swap over ;
+: 3dup 2 pick 2 pick 2 pick ;
+
+\
+\ 7.3.1.2 - stack removal
+\
+: clear 0 depth! ;
+: 3drop 2drop drop ;
+
+\
+\ 7.3.1.3 - stack rearrangement
+\
+
+: 2rot >r >r 2swap r> r> 2swap ;
+
+\
+\ 7.3.1.4 - return stack
+\
+
+\ Note: these words are not part of the official OF specification, however
+\ they are part of the ANSI DPANS94 core extensions (see section 6.2) and
+\ so this seems an appropriate place for them.
+: 2>r r> -rot swap >r >r >r ;
+: 2r> r> r> r> rot >r swap ;
+: 2r@ r> r> r> 2dup >r >r rot >r swap ;
+
+\
+\ 7.3.2.1 - single precision integer arithmetic (part 1)
+\
+
+: u/mod 0 swap mu/mod drop ;
+: 1+ 1 + ;
+: 1- 1 - ;
+: 2+ 2 + ;
+: 2- 2 - ;
+: even 1+ -2 and ;
+: bounds over + swap ;
+
+\
+\ 7.3.2.2 bitwise logical operators
+\
+: << lshift ;
+: >> rshift ;
+: 2* 1 lshift ;
+: u2/ 1 rshift ;
+: 2/ 1 >>a ;
+: not invert ;
+
+\
+\ 7.3.2.3 double number arithmetic
+\
+
+: s>d dup 0 < ;
+: dnegate 0 0 2swap d- ;
+: dabs dup 0 < if dnegate then ;
+: um/mod mu/mod drop ;
+
+\ symmetric division
+: sm/rem ( d n -- rem quot )
+ over >r >r dabs r@ abs um/mod r> 0 <
+ if
+ negate
+ then
+ r> 0 < if
+ negate swap negate swap
+ then
+ ;
+
+\ floored division
+: fm/mod ( d n -- rem quot )
+ dup >r 2dup xor 0 < >r sm/rem over 0 <> r> and if
+ 1 - swap r> + swap exit
+ then
+ r> drop
+ ;
+
+\
+\ 7.3.2.1 - single precision integer arithmetic (part 2)
+\
+
+: */mod ( n1 n2 n3 -- quot rem ) >r m* r> fm/mod ;
+: */ ( n1 n2 n3 -- n1*n2/n3 ) */mod nip ;
+: /mod >r s>d r> fm/mod ;
+: mod /mod drop ;
+: / /mod nip ;
+
+
+\
+\ 7.3.2.4 Data type conversion
+\
+
+: lwsplit ( quad -- w.lo w.hi )
+ dup ffff and swap 10 rshift ffff and
+;
+
+: wbsplit ( word -- b.lo b.hi )
+ dup ff and swap 8 rshift ff and
+;
+
+: lbsplit ( quad -- b.lo b2 b3 b.hi )
+ lwsplit swap wbsplit rot wbsplit
+;
+
+: bwjoin ( b.lo b.hi -- word )
+ ff and 8 lshift swap ff and or
+;
+
+: wljoin ( w.lo w.hi -- quad )
+ ffff and 10 lshift swap ffff and or
+;
+
+: bljoin ( b.lo b2 b3 b.hi -- quad )
+ bwjoin -rot bwjoin swap wljoin
+;
+
+: wbflip ( word -- word ) \ flips bytes in a word
+ dup 8 rshift ff and swap ff and bwjoin
+;
+
+: lwflip ( q1 -- q2 )
+ dup 10 rshift ffff and swap ffff and wljoin
+;
+
+: lbflip ( q1 -- q2 )
+ dup 10 rshift ffff and wbflip swap ffff and wbflip wljoin
+;
+
+\
+\ 7.3.2.5 address arithmetic
+\
+
+: /c* /c * ;
+: /w* /w * ;
+: /l* /l * ;
+: /n* /n * ;
+: ca+ /c* + ;
+: wa+ /w* + ;
+: la+ /l* + ;
+: na+ /n* + ;
+: ca1+ /c + ;
+: wa1+ /w + ;
+: la1+ /l + ;
+: na1+ /n + ;
+: aligned /n 1- + /n negate and ;
+: char+ ca1+ ;
+: cell+ na1+ ;
+: chars /c* ;
+: cells /n* ;
+/n constant cell
+
+\
+\ 7.3.6 Comparison operators
+\
+
+: <= > not ;
+: >= < not ;
+: 0= 0 = ;
+: 0<= 0 <= ;
+: 0< 0 < ;
+: 0<> 0 <> ;
+: 0> 0 > ;
+: 0>= 0 >= ;
+: u<= u> not ;
+: u>= u< not ;
+: within >r over > swap r> >= or not ;
+: between 1 + within ;
+
+\
+\ 7.3.3.1 Memory access
+\
+
+: 2@ dup cell+ @ swap @ ;
+: 2! dup >r ! r> cell+ ! ;
+
+: <w@ w@ dup 8000 >= if 10000 - then ;
+
+: comp ( str1 str2 len -- 0|1|-1 )
+ >r 0 -rot r>
+ bounds ?do
+ dup c@ i c@ - dup if
+ < if 1 else -1 then swap leave
+ then
+ drop ca1+
+ loop
+ drop
+;
+
+\ compare two string
+
+: $= ( str1 len1 str2 len2 -- true|false )
+ rot ( str1 str2 len2 len1 )
+ over ( str1 str2 len2 len1 len2 )
+ <> if ( str1 str2 len2 )
+ 3drop
+ false
+ else ( str1 str2 len2 )
+ comp
+ 0=
+ then
+;
+
+\ : +! tuck @ + swap ! ;
+: off false swap ! ;
+: on true swap ! ;
+: blank bl fill ;
+: erase 0 fill ;
+: wbflips ( waddr len -- )
+ bounds do i w@ wbflip i w! /w +loop
+;
+
+: lwflips ( qaddr len -- )
+ bounds do i l@ lwflip i l! /l +loop
+;
+
+: lbflips ( qaddr len -- )
+ bounds do i l@ lbflip i l! /l +loop
+;
+
+
+\
+\ 7.3.8.6 Error handling (part 1)
+\
+
+variable catchframe
+0 catchframe !
+
+: catch
+ my-self >r
+ depth >r
+ catchframe @ >r
+ rdepth catchframe !
+ execute
+ r> catchframe !
+ r> r> 2drop 0
+ ;
+
+: throw
+ ?dup if
+ catchframe @ rdepth!
+ r> catchframe !
+ r> swap >r depth!
+ drop r>
+ r> ['] my-self (to)
+ then
+ ;
+
+\
+\ 7.3.3.2 memory allocation
+\
+
+include memory.fs
+
+
+\
+\ 7.3.4.4 Console output (part 1)
+\
+
+defer emit
+
+: type bounds ?do i c@ emit loop ;
+
+\ this one obviously only works when called
+\ with a forth string as count fetches addr-1.
+\ openfirmware has no such req. therefore it has to go:
+
+\ : type 0 do count emit loop drop ;
+
+: debug-type bounds ?do i c@ (emit) loop ;
+
+\
+\ 7.3.4.1 Text Input
+\
+
+0 value source-id
+0 value ib
+variable #ib 0 #ib !
+variable >in 0 >in !
+
+: source ( -- addr len )
+ ib #ib @
+ ;
+
+: /string ( c-addr1 u1 n -- c-addr2 u2 )
+ tuck - -rot + swap
+;
+
+
+\
+\ pockets implementation for 7.3.4.1
+
+100 constant pocketsize
+4 constant numpockets
+variable pockets 0 pockets !
+variable whichpocket 0 whichpocket !
+
+\ allocate 4 pockets to begin with
+: init-pockets ( -- )
+ pocketsize numpockets * alloc-mem pockets !
+ ;
+
+: pocket ( ?? -- ?? )
+ pocketsize whichpocket @ *
+ pockets @ +
+ whichpocket @ 1 + numpockets mod
+ whichpocket !
+ ;
+
+\ span variable from 7.3.4.2
+variable span 0 span !
+
+\ if char is bl then any control character is matched
+: findchar ( str len char -- offs true | false )
+ swap 0 do
+ over i + c@
+ over dup bl = if <= else = then if
+ 2drop i dup dup leave
+ \ i nip nip true exit \ replaces above
+ then
+ loop
+ =
+ \ drop drop false
+ ;
+
+: parse ( delim text<delim> -- str len )
+ >r \ save delimiter
+ ib >in @ +
+ span @ >in @ - \ ib+offs len-offset.
+ dup 0 < if \ if we are already at the end of the string, return an empty string
+ + 0 \ move to end of input string
+ r> drop
+ exit
+ then
+ 2dup r> \ ib+offs len-offset ib+offs len-offset delim
+ findchar if \ look for the delimiter.
+ nip dup 1+
+ else
+ dup
+ then
+ >in +!
+ \ dup -1 = if drop 0 then \ workaround for negative length
+ ;
+
+: skipws ( -- )
+ ib span @ ( -- ib recvchars )
+ begin
+ dup >in @ > if ( -- recvchars>offs )
+ over >in @ +
+ c@ bl <=
+ else
+ false
+ then
+ while
+ 1 >in +!
+ repeat
+ 2drop
+ ;
+
+: parse-word ( < >text< > -- str len )
+ skipws bl parse
+ ;
+
+: word ( delim <delims>text<delim> -- pstr )
+ pocket >r parse dup r@ c! bounds r> dup 2swap
+ do
+ char+ i c@ over c!
+ loop
+ drop
+ ;
+
+: ( 29 parse 2drop ; immediate
+: \ span @ >in ! ; immediate
+
+
+
+\
+\ 7.3.4.7 String literals
+\
+
+: ",
+ bounds ?do
+ i c@ c,
+ loop
+ ;
+
+: (") ( -- addr len )
+ r> dup
+ 2 cells + ( r-addr addr )
+ over cell+ @ ( r-addr addr len )
+ rot over + aligned cell+ >r ( addr len R: r-addr )
+ ;
+
+: handle-text ( temp-addr len -- addr len )
+ state @ if
+ ['] (") , dup , ", null-align
+ else
+ pocket swap
+ dup >r
+ 0 ?do
+ over i + c@ over i + c!
+ loop
+ nip r>
+ then
+ ;
+
+: s"
+ 22 parse handle-text
+ ; immediate
+
+
+
+\
+\ 7.3.4.4 Console output (part 2)
+\
+
+: ."
+ 22 parse handle-text
+ ['] type
+ state @ if
+ ,
+ else
+ execute
+ then
+ ; immediate
+
+: .(
+ 29 parse handle-text
+ ['] type
+ state @ if
+ ,
+ else
+ execute
+ then
+ ; immediate
+
+
+
+\
+\ 7.3.4.8 String manipulation
+\
+
+: count ( pstr -- str len ) 1+ dup 1- c@ ;
+
+: pack ( str len addr -- pstr )
+ 2dup c! \ store len
+ 1+ swap 0 ?do
+ over i + c@ over i + c!
+ loop nip 1-
+ ;
+
+: lcc ( char1 -- char2 ) dup 41 5a between if 20 + then ;
+: upc ( char1 -- char2 ) dup 61 7a between if 20 - then ;
+
+: -trailing ( str len1 -- str len2 )
+ begin
+ dup 0<> if \ len != 0 ?
+ 2dup 1- +
+ c@ bl =
+ else
+ false
+ then
+ while
+ 1-
+ repeat
+ ;
+
+
+\
+\ 7.3.4.5 Output formatting
+\
+
+: cr linefeed emit ;
+: debug-cr linefeed (emit) ;
+: (cr carret emit ;
+: space bl emit ;
+: spaces 0 ?do space loop ;
+variable #line 0 #line !
+variable #out 0 #out !
+
+
+\
+\ 7.3.9.2.3 Dictionary search
+\
+
+\ helper functions
+
+: lfa2name ( lfa -- name len )
+ 1- \ skip flag byte
+ begin \ skip 0 padding
+ 1- dup c@ ?dup
+ until
+ 7f and \ clear high bit in length
+
+ tuck - swap ( ptr-to-len len - name len )
+ ;
+
+: comp-nocase ( str1 str2 len -- true|false )
+ 0 do
+ 2dup i + c@ upc ( str1 str2 byteX )
+ swap i + c@ upc ( str1 str2 byte1 byte2 )
+ <> if
+ 0 leave
+ then
+ loop
+ if -1 else drop 0 then
+ swap drop
+ ;
+
+: comp-word ( b-str len lfa -- true | false )
+ lfa2name ( str len str len -- )
+ >r swap r> ( str str len len )
+ over = if ( str str len )
+ comp-nocase
+ else
+ drop drop drop false \ if len does not match, string does not match
+ then
+;
+
+\ $find is an fcode word, but we place it here since we use it for find.
+
+: find-wordlist ( name-str name-len last -- xt true | name-str name-len false )
+
+ @ >r
+
+ begin
+ 2dup r@ dup if comp-word dup false = then
+ while
+ r> @ >r drop
+ repeat
+
+ r@ if \ successful?
+ -rot 2drop r> cell+ swap
+ else
+ r> drop drop drop false
+ then
+
+ ;
+
+: $find ( name-str name-len -- xt true | name-str name-len false )
+ locals-dict 0<> if
+ locals-dict-buf @ find-wordlist ?dup if
+ exit
+ then
+ then
+ vocabularies? if
+ #order @ 0 ?do
+ i cells context + @
+ find-wordlist
+ ?dup if
+ unloop exit
+ then
+ loop
+ false
+ else
+ forth-last find-wordlist
+ then
+ ;
+
+\ look up a word in the current wordlist
+: $find1 ( name-str name-len -- xt true | name-str name-len false )
+ vocabularies? if
+ current @
+ else
+ forth-last
+ then
+ find-wordlist
+ ;
+
+
+: '
+ parse-word $find 0= if
+ type 3a emit -13 throw
+ then
+ ;
+
+: [']
+ parse-word $find 0= if
+ type 3a emit -13 throw
+ then
+ state @ if
+ ['] (lit) , ,
+ then
+ ; immediate
+
+: find ( pstr -- xt n | pstr false )
+ dup count $find \ pstr xt true | pstr name-str name-len false
+ if
+ nip true
+ over immediate? if
+ negate \ immediate returns 1
+ then
+ else
+ 2drop false
+ then
+ ;
+
+
+\
+\ 7.3.9.2.2 Immediate words (part 2)
+\
+
+: literal ['] (lit) , , ; immediate
+: compile, , ; immediate
+: compile r> cell+ dup @ , >r ;
+: [compile] ['] ' execute , ; immediate
+
+: postpone
+ parse-word $find if
+ dup immediate? not if
+ ['] (lit) , , ['] ,
+ then
+ ,
+ else
+ s" undefined word " type type cr
+ then
+ ; immediate
+
+
+\
+\ 7.3.9.2.4 Miscellaneous dictionary (part 2)
+\
+
+variable #instance
+
+: instance ( -- )
+ true #instance !
+;
+
+: #instance-base
+ my-self dup if @ then
+;
+
+: #instance-offs
+ my-self dup if na1+ then
+;
+
+\ the following instance words are used internally
+\ to implement variable instantiation.
+
+: instance-cfa? ( cfa -- true | false )
+ b e within \ b,c and d are instance defining words
+;
+
+: behavior ( xt-defer -- xt )
+ dup @ instance-cfa? if
+ #instance-base ?dup if
+ swap na1+ @ + @
+ else
+ 3 /n* + @
+ then
+ else
+ na1+ @
+ then
+;
+
+: (ito) ( xt-new xt-defer -- )
+ #instance-base ?dup if
+ swap na1+ @ + !
+ else
+ 3 /n* + !
+ then
+;
+
+: (to-xt) ( xt -- )
+ dup @ instance-cfa?
+ state @ if
+ swap ['] (lit) , , if ['] (ito) else ['] (to) then ,
+ else
+ if (ito) else /n + ! then
+ then
+;
+
+: to
+ ['] ' execute
+ (to-xt)
+ ; immediate
+
+: is ( xt "wordname<>" -- )
+ parse-word $find if
+ (to)
+ else
+ s" could not find " type type
+ then
+ ;
+
+\
+\ 7.3.4.2 Console Input
+\
+
+defer key?
+defer key
+
+: accept ( addr len -- len2 )
+ tuck 0 do
+ key
+ dup linefeed = if
+ space drop drop drop i 0 leave
+ then
+ dup emit over c! 1 +
+ loop
+ drop ( cr )
+ ;
+
+: expect ( addr len -- )
+ accept span !
+ ;
+
+
+\
+\ 7.3.4.3 ASCII constants (part 2)
+\
+
+: handle-lit
+ state @ if
+ 2 = if
+ ['] (lit) , ,
+ then
+ ['] (lit) , ,
+ else
+ drop
+ then
+ ;
+
+: char
+ parse-word 0<> if c@ else s" Unexpected EOL." type cr then ;
+ ;
+
+: ascii char 1 handle-lit ; immediate
+: [char] char 1 handle-lit ; immediate
+
+: control
+ char bl 1- and 1 handle-lit
+; immediate
+
+
+
+\
+\ 7.3.8.6 Error handling (part 2)
+\
+
+: abort
+ -1 throw
+ ;
+
+: abort"
+ ['] if execute
+ 22 parse handle-text
+ ['] type ,
+ ['] (lit) ,
+ -2 ,
+ ['] throw ,
+ ['] then execute
+ ; compile-only
+
+\
+\ 7.5.3.1 Dictionary search
+\
+
+\ this does not belong here, but its nice for testing
+
+: words ( -- )
+ last
+ begin @
+ ?dup while
+ dup lfa2name
+
+ \ Don't print spaces for headerless words
+ dup if
+ type space
+ else
+ type
+ then
+
+ repeat
+ cr
+ ;
+
+\
+\ 7.3.5.4 Numeric output primitives
+\
+
+false value capital-hex?
+
+: pad ( -- addr ) here 100 + aligned ;
+
+: todigit ( num -- ascii )
+ dup 9 > if
+ capital-hex? not if
+ 20 +
+ then
+ 7 +
+ then
+ 30 +
+ ;
+
+: <# pad dup ! ;
+: hold pad dup @ 1- tuck swap ! c! ;
+: sign
+ 0< if
+ 2d hold
+ then
+ ;
+
+: # base @ mu/mod rot todigit hold ;
+: #s begin # 2dup or 0= until ;
+: #> 2drop pad dup @ tuck - ;
+: (.) <# dup >r abs 0 #s r> sign #> ;
+
+: u# base @ u/mod swap todigit hold ;
+: u#s begin u# dup 0= until ;
+: u#> 0 #> ;
+: (u.) <# u#s u#> ;
+
+\
+\ 7.3.5.3 Numeric output
+\
+
+: . (.) type space ;
+: s. . ;
+: u. (u.) type space ;
+: .r swap (.) rot 2dup < if over - spaces else drop then type ;
+: u.r swap (u.) rot 2dup < if over - spaces else drop then type ;
+: .d base @ swap decimal . base ! ;
+: .h base @ swap hex . base ! ;
+
+: .s
+ 3c emit depth dup (.) type 3e emit space
+ 0
+ ?do
+ depth i - 1- pick .
+ loop
+ cr
+ ;
+
+\
+\ 7.3.5.2 Numeric input
+\
+
+: digit ( char base -- n true | char false )
+ swap dup upc dup
+ 41 5a ( A - Z ) between if
+ 7 -
+ else
+ dup 39 > if \ protect from : and ;
+ -rot 2drop false exit
+ then
+ then
+
+ 30 ( number 0 ) - rot over swap 0 swap within if
+ nip true
+ else
+ drop false
+ then
+ ;
+
+: >number
+ begin
+ dup
+ while
+ over c@ base @ digit 0= if
+ drop exit
+ then >r 2swap r> swap base @ um* drop rot base @ um* d+ 2swap
+ 1 /string
+ repeat
+ ;
+
+: numdelim?
+ dup 2e = swap 2c = or
+;
+
+
+: $dnumber?
+ 0 0 2swap dup 0= if
+ 2drop 2drop 0 exit
+ then over c@ 2d = dup >r negate /string begin
+ >number dup 1 >
+ while
+ over c@ numdelim? 0= if
+ 2drop 2drop r> drop 0 exit
+ then 1 /string
+ repeat if
+ c@ 2e = if
+ true
+ else
+ 2drop r> drop 0 exit
+ then
+ else
+ drop false
+ then over or if
+ r> if
+ dnegate
+ then 2
+ else
+ drop r> if
+ negate
+ then 1
+ then
+;
+
+
+: $number ( )
+ $dnumber?
+ case
+ 0 of true endof
+ 1 of false endof
+ 2 of drop false endof
+ endcase
+;
+
+: d#
+ parse-word
+ base @ >r
+
+ decimal
+
+ $number if
+ s" illegal number" type cr 0
+ then
+ r> base !
+ 1 handle-lit
+ ; immediate
+
+: h#
+ parse-word
+ base @ >r
+
+ hex
+
+ $number if
+ s" illegal number" type cr 0
+ then
+ r> base !
+ 1 handle-lit
+ ; immediate
+
+: o#
+ parse-word
+ base @ >r
+
+ octal
+
+ $number if
+ s" illegal number" type cr 0
+ then
+ r> base !
+ 1 handle-lit
+ ; immediate
+
+
+\
+\ 7.3.4.7 String Literals (part 2)
+\
+
+: "
+ pocket dup
+ begin
+ span @ >in @ > if
+ 22 parse >r ( pocket pocket str R: len )
+ over r@ move \ copy string
+ r> + ( pocket nextdest )
+ ib >in @ + c@ ( pocket nextdest nexchar )
+ 1 >in +!
+ 28 = \ is nextchar a parenthesis?
+ span @ >in @ > \ more input?
+ and
+ else
+ false
+ then
+ while
+ 29 parse \ parse everything up to the next ')'
+ bounds ?do
+ i c@ 10 digit if
+ i 1+ c@ 10 digit if
+ swap 4 lshift or
+ else
+ drop
+ then
+ over c! 1+
+ 2
+ else
+ drop 1
+ then
+ +loop
+ repeat
+ over -
+ handle-text
+; immediate
+
+
+\
+\ 7.3.3.1 Memory Access (part 2)
+\
+
+: dump ( addr len -- )
+ over + swap
+ cr
+ do i u. space
+ 10 0 do
+ j i + c@
+ dup 10 / todigit emit
+ 10 mod todigit emit
+ space
+ i 7 = if space then
+ loop
+ 3 spaces
+ 10 0 do
+ j i + c@
+ dup 20 < if drop 2e then \ non-printables as dots?
+ emit
+ loop
+ cr
+ 10 +loop
+;
+
+
+
+\
+\ 7.3.9.1 Defining words
+\
+
+: header ( name len -- )
+ dup if \ might be a noname...
+ 2dup $find1 if
+ drop 2dup type s" isn't unique." type cr
+ else
+ 2drop
+ then
+ then
+ null-align
+ dup -rot ", 80 or c, \ write name and len
+ here /n 1- and 0= if 0 c, then \ pad and space for flags
+ null-align
+ 80 here 1- c! \ write flags byte
+ here last @ , latest ! \ write backlink and set latest
+ ;
+
+
+: :
+ parse-word header
+ 1 , ]
+ ;
+
+: :noname
+ 0 0 header
+ here
+ 1 , ]
+ ;
+
+: ;
+ locals-dict 0<> if
+ 0 ['] locals-dict /n + !
+ ['] locals-end ,
+ then
+ ['] (semis) , reveal ['] [ execute
+ ; immediate
+
+: constant
+ parse-word header
+ 3 , , \ compile DOCON and value
+ reveal
+ ;
+
+0 value active-package
+: instance, ( size -- )
+ \ first word of the device node holds the instance size
+ dup active-package @ dup rot + active-package !
+ , , \ offset size
+;
+
+: instance? ( -- flag )
+ #instance @ dup if
+ false #instance !
+ then
+;
+
+: value
+ parse-word header
+ instance? if
+ /n b , instance, , \ DOIVAL
+ else
+ 3 , ,
+ then
+ reveal
+ ;
+
+: variable
+ parse-word header
+ instance? if
+ /n c , instance, 0 ,
+ else
+ 4 , 0 ,
+ then
+ reveal
+ ;
+
+: $buffer: ( size str len -- where )
+ header
+ instance? if
+ /n over /n 1- and - /n 1- and + \ align buffer size
+ dup c , instance, \ DOIVAR
+ else
+ 4 ,
+ then
+ here swap
+ 2dup 0 fill \ zerofill
+ allot
+ reveal
+;
+
+: buffer: ( size -- )
+ parse-word $buffer: drop
+;
+
+: (undefined-defer) ( -- )
+ \ XXX: this does not work with behavior ... execute
+ r@ 2 cells - lfa2name
+ s" undefined defer word " type type cr ;
+
+: (undefined-idefer) ( -- )
+ s" undefined idefer word " type cr ;
+
+: defer ( new-name< > -- )
+ parse-word header
+ instance? if
+ 2 /n* d , instance, \ DOIDEFER
+ ['] (undefined-idefer)
+ else
+ 5 ,
+ ['] (undefined-defer)
+ then
+ ,
+ ['] (semis) ,
+ reveal
+ ;
+
+: alias ( new-name< >old-name< > -- )
+ parse-word
+ parse-word $find if
+ -rot \ move xt behind.
+ header
+ 1 , \ fixme we want our own cfa here.
+ , \ compile old name xt
+ ['] (semis) ,
+ reveal
+ else
+ s" undefined word " type type space
+ 2drop
+ then
+ ;
+
+: $create
+ header 6 ,
+ ['] noop ,
+ reveal
+ ;
+
+: create
+ parse-word $create
+ ;
+
+: (does>)
+ r> cell+ \ get address of code to execute
+ latest @ \ backlink of just "create"d word
+ cell+ cell+ ! \ write code to execute after the
+ \ new word's CFA
+ ;
+
+: does>
+ ['] (does>) , \ compile does handling
+ 1 , \ compile docol
+ ; immediate
+
+0 constant struct
+
+: field
+ create
+ over ,
+ +
+ does>
+ @ +
+ ;
+
+: 2constant
+ create , ,
+ does> 2@ reveal
+ ;
+
+\
+\ initializer for the temporary compile buffer
+\
+
+: init-tmp-comp
+ here 200 allot tmp-comp-buf !
+;
+
+\ the end
diff --git a/roms/openbios/forth/bootstrap/build.xml b/roms/openbios/forth/bootstrap/build.xml
new file mode 100644
index 00000000..d950a46d
--- /dev/null
+++ b/roms/openbios/forth/bootstrap/build.xml
@@ -0,0 +1,16 @@
+<build>
+ <!--
+ build description for openbios forth bootstrap
+
+ Copyright (C) 2004-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="bootstrap">
+ <object source="start.fs" target="forth"/>
+ </dictionary>
+
+ <dictionary name="openbios" init="bootstrap"/>
+
+</build>
diff --git a/roms/openbios/forth/bootstrap/builtin.fs b/roms/openbios/forth/bootstrap/builtin.fs
new file mode 100644
index 00000000..03f5fde1
--- /dev/null
+++ b/roms/openbios/forth/bootstrap/builtin.fs
@@ -0,0 +1,28 @@
+\ tag: initialize builtin functionality
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+
+
+: init-builtin-terminal ( -- )
+
+ \ define key, key? and emit
+ ['] (key) ['] key (to)
+ ['] (key?) ['] key? (to)
+ ['] (emit) ['] emit (to)
+
+ \ 2 bytes band guard on each side
+ 100 #ib !
+ #ib @ dup ( -- ibs ibs )
+ cell+ alloc-mem ( -- ibs addr )
+ dup -rot ( -- addr ibs addr )
+
+ /w + ['] ib (to) \ assign input buffer
+ 0 fill \ erase tib
+ 0 ['] source-id (to) \ builtin terminal has id 0
+
+ ;
diff --git a/roms/openbios/forth/bootstrap/hayes.fs b/roms/openbios/forth/bootstrap/hayes.fs
new file mode 100644
index 00000000..e5a46f40
--- /dev/null
+++ b/roms/openbios/forth/bootstrap/hayes.fs
@@ -0,0 +1,1064 @@
+\ From: John Hayes S1I
+\ Subject: tester.fr
+\ Date: Mon, 27 Nov 95 13:10:09 PST
+
+\ (C) 1995 JOHNS HOPKINS UNIVERSITY / APPLIED PHYSICS LABORATORY
+\ MAY BE DISTRIBUTED FREELY AS LONG AS THIS COPYRIGHT NOTICE REMAINS.
+\ VERSION 1.1
+
+HEX
+
+\ switch output of hex values to capital letters
+true to capital-hex?
+
+
+\ SET THE FOLLOWING FLAG TO TRUE FOR MORE VERBOSE OUTPUT; THIS MAY
+\ ALLOW YOU TO TELL WHICH TEST CAUSED YOUR SYSTEM TO HANG.
+
+VARIABLE VERBOSE
+ FALSE VERBOSE !
+
+: EMPTY-STACK \ ( ... -- ) EMPTY STACK: HANDLES UNDERFLOWED STACK TOO.
+ DEPTH ?DUP IF DUP 0< IF NEGATE 0 DO 0 LOOP ELSE 0 DO DROP LOOP THEN THEN ;
+
+: ERROR \ ( C-ADDR U -- ) DISPLAY AN ERROR MESSAGE FOLLOWED BY
+ \ THE LINE THAT HAD THE ERROR.
+ \ TYPE SOURCE TYPE CR \ DISPLAY LINE CORRESPONDING TO ERROR
+
+ \ FIXME beginagain wants the following for output:
+ TYPE SOURCE drop span @ TYPE CR \ DISPLAY LINE CORRESPONDING TO ERROR
+ EMPTY-STACK \ THROW AWAY EVERY THING ELSE
+ -99 SYS-DEBUG \ MAKE BEGINAGAIN BOOTSTRAP FAIL.
+;
+
+VARIABLE ACTUAL-DEPTH \ STACK RECORD
+CREATE ACTUAL-RESULTS 20 CELLS ALLOT
+
+: { \ ( -- ) SYNTACTIC SUGAR.
+ ;
+
+: -> \ ( ... -- ) RECORD DEPTH AND CONTENT OF STACK.
+ DEPTH DUP ACTUAL-DEPTH ! \ RECORD DEPTH
+ ?DUP IF \ IF THERE IS SOMETHING ON STACK
+ 0 DO ACTUAL-RESULTS I CELLS + ! LOOP \ SAVE THEM
+ THEN ;
+
+: } \ ( ... -- ) COMPARE STACK (EXPECTED) CONTENTS WITH SAVED
+ \ (ACTUAL) CONTENTS.
+ DEPTH ACTUAL-DEPTH @ = IF \ IF DEPTHS MATCH
+ DEPTH ?DUP IF \ IF THERE IS SOMETHING ON THE STACK
+ 0 DO \ FOR EACH STACK ITEM
+ ACTUAL-RESULTS I CELLS + @ \ COMPARE ACTUAL WITH EXPECTED
+ <> IF S" INCORRECT RESULT: " ERROR LEAVE THEN
+ LOOP
+ THEN
+ ELSE \ DEPTH MISMATCH
+ S" WRONG NUMBER OF RESULTS: " ERROR
+ THEN ;
+
+: TESTING \ ( -- ) TALKING COMMENT.
+ SOURCE VERBOSE @
+ IF DUP >R TYPE CR R> >IN !
+ ELSE >IN ! DROP
+ THEN
+ ;
+
+\ From: John Hayes S1I
+\ Subject: core.fr
+\ Date: Mon, 27 Nov 95 13:10
+
+\ (C) 1995 JOHNS HOPKINS UNIVERSITY / APPLIED PHYSICS LABORATORY
+\ MAY BE DISTRIBUTED FREELY AS LONG AS THIS COPYRIGHT NOTICE REMAINS.
+\ VERSION 1.2
+\ THIS PROGRAM TESTS THE CORE WORDS OF AN ANS FORTH SYSTEM.
+\ THE PROGRAM ASSUMES A TWO'S COMPLEMENT IMPLEMENTATION WHERE
+\ THE RANGE OF SIGNED NUMBERS IS -2^(N-1) ... 2^(N-1)-1 AND
+\ THE RANGE OF UNSIGNED NUMBERS IS 0 ... 2^(N)-1.
+\ I HAVEN'T FIGURED OUT HOW TO TEST KEY, QUIT, ABORT, OR ABORT"...
+\ I ALSO HAVEN'T THOUGHT OF A WAY TO TEST ENVIRONMENT?...
+
+TESTING CORE WORDS
+HEX
+
+\ ------------------------------------------------------------------------
+TESTING BASIC ASSUMPTIONS
+
+{ -> } \ START WITH CLEAN SLATE
+( TEST IF ANY BITS ARE SET; ANSWER IN BASE 1 )
+{ : BITSSET? IF 0 0 ELSE 0 THEN ; -> }
+{ 0 BITSSET? -> 0 } ( ZERO IS ALL BITS CLEAR )
+{ 1 BITSSET? -> 0 0 } ( OTHER NUMBER HAVE AT LEAST ONE BIT )
+{ -1 BITSSET? -> 0 0 }
+
+\ ------------------------------------------------------------------------
+TESTING BOOLEANS: INVERT AND OR XOR
+
+{ 0 0 AND -> 0 }
+{ 0 1 AND -> 0 }
+{ 1 0 AND -> 0 }
+{ 1 1 AND -> 1 }
+
+{ 0 INVERT 1 AND -> 1 }
+{ 1 INVERT 1 AND -> 0 }
+
+0 CONSTANT 0S
+0 INVERT CONSTANT 1S
+
+{ 0S INVERT -> 1S }
+{ 1S INVERT -> 0S }
+
+{ 0S 0S AND -> 0S }
+{ 0S 1S AND -> 0S }
+{ 1S 0S AND -> 0S }
+{ 1S 1S AND -> 1S }
+
+{ 0S 0S OR -> 0S }
+{ 0S 1S OR -> 1S }
+{ 1S 0S OR -> 1S }
+{ 1S 1S OR -> 1S }
+
+{ 0S 0S XOR -> 0S }
+{ 0S 1S XOR -> 1S }
+{ 1S 0S XOR -> 1S }
+{ 1S 1S XOR -> 0S }
+
+\ ------------------------------------------------------------------------
+TESTING 2* 2/ LSHIFT RSHIFT
+
+( WE TRUST 1S, INVERT, AND BITSSET?; WE WILL CONFIRM RSHIFT LATER )
+1S 1 RSHIFT INVERT CONSTANT MSB
+{ MSB BITSSET? -> 0 0 }
+
+{ 0S 2* -> 0S }
+{ 1 2* -> 2 }
+{ 4000 2* -> 8000 }
+{ 1S 2* 1 XOR -> 1S }
+{ MSB 2* -> 0S }
+
+{ 0S 2/ -> 0S }
+{ 1 2/ -> 0 }
+{ 4000 2/ -> 2000 }
+{ 1S 2/ -> 1S } \ MSB PROPOGATED
+{ 1S 1 XOR 2/ -> 1S }
+{ MSB 2/ MSB AND -> MSB }
+
+{ 1 0 LSHIFT -> 1 }
+{ 1 1 LSHIFT -> 2 }
+{ 1 2 LSHIFT -> 4 }
+{ 1 F LSHIFT -> 8000 } \ BIGGEST GUARANTEED SHIFT
+{ 1S 1 LSHIFT 1 XOR -> 1S }
+{ MSB 1 LSHIFT -> 0 }
+
+{ 1 0 RSHIFT -> 1 }
+{ 1 1 RSHIFT -> 0 }
+{ 2 1 RSHIFT -> 1 }
+{ 4 2 RSHIFT -> 1 }
+{ 8000 F RSHIFT -> 1 } \ BIGGEST
+{ MSB 1 RSHIFT MSB AND -> 0 } \ RSHIFT ZERO FILLS MSBS
+{ MSB 1 RSHIFT 2* -> MSB }
+
+\ ------------------------------------------------------------------------
+TESTING COMPARISONS: 0= = 0< < > U< MIN MAX
+0 INVERT CONSTANT MAX-UINT
+0 INVERT 1 RSHIFT CONSTANT MAX-INT
+0 INVERT 1 RSHIFT INVERT CONSTANT MIN-INT
+0 INVERT 1 RSHIFT CONSTANT MID-UINT
+0 INVERT 1 RSHIFT INVERT CONSTANT MID-UINT+1
+
+0S CONSTANT <FALSE>
+1S CONSTANT <TRUE>
+
+{ 0 0= -> <TRUE> }
+{ 1 0= -> <FALSE> }
+{ 2 0= -> <FALSE> }
+{ -1 0= -> <FALSE> }
+{ MAX-UINT 0= -> <FALSE> }
+{ MIN-INT 0= -> <FALSE> }
+{ MAX-INT 0= -> <FALSE> }
+
+{ 0 0 = -> <TRUE> }
+{ 1 1 = -> <TRUE> }
+{ -1 -1 = -> <TRUE> }
+{ 1 0 = -> <FALSE> }
+{ -1 0 = -> <FALSE> }
+{ 0 1 = -> <FALSE> }
+{ 0 -1 = -> <FALSE> }
+
+{ 0 0< -> <FALSE> }
+{ -1 0< -> <TRUE> }
+{ MIN-INT 0< -> <TRUE> }
+{ 1 0< -> <FALSE> }
+{ MAX-INT 0< -> <FALSE> }
+
+{ 0 1 < -> <TRUE> }
+{ 1 2 < -> <TRUE> }
+{ -1 0 < -> <TRUE> }
+{ -1 1 < -> <TRUE> }
+{ MIN-INT 0 < -> <TRUE> }
+{ MIN-INT MAX-INT < -> <TRUE> }
+{ 0 MAX-INT < -> <TRUE> }
+{ 0 0 < -> <FALSE> }
+{ 1 1 < -> <FALSE> }
+{ 1 0 < -> <FALSE> }
+{ 2 1 < -> <FALSE> }
+{ 0 -1 < -> <FALSE> }
+{ 1 -1 < -> <FALSE> }
+{ 0 MIN-INT < -> <FALSE> }
+{ MAX-INT MIN-INT < -> <FALSE> }
+{ MAX-INT 0 < -> <FALSE> }
+
+{ 0 1 > -> <FALSE> }
+{ 1 2 > -> <FALSE> }
+{ -1 0 > -> <FALSE> }
+{ -1 1 > -> <FALSE> }
+{ MIN-INT 0 > -> <FALSE> }
+{ MIN-INT MAX-INT > -> <FALSE> }
+{ 0 MAX-INT > -> <FALSE> }
+{ 0 0 > -> <FALSE> }
+{ 1 1 > -> <FALSE> }
+{ 1 0 > -> <TRUE> }
+{ 2 1 > -> <TRUE> }
+{ 0 -1 > -> <TRUE> }
+{ 1 -1 > -> <TRUE> }
+{ 0 MIN-INT > -> <TRUE> }
+{ MAX-INT MIN-INT > -> <TRUE> }
+{ MAX-INT 0 > -> <TRUE> }
+
+{ 0 1 U< -> <TRUE> }
+{ 1 2 U< -> <TRUE> }
+{ 0 MID-UINT U< -> <TRUE> }
+{ 0 MAX-UINT U< -> <TRUE> }
+{ MID-UINT MAX-UINT U< -> <TRUE> }
+{ 0 0 U< -> <FALSE> }
+{ 1 1 U< -> <FALSE> }
+{ 1 0 U< -> <FALSE> }
+{ 2 1 U< -> <FALSE> }
+{ MID-UINT 0 U< -> <FALSE> }
+{ MAX-UINT 0 U< -> <FALSE> }
+{ MAX-UINT MID-UINT U< -> <FALSE> }
+
+{ 0 1 MIN -> 0 }
+{ 1 2 MIN -> 1 }
+{ -1 0 MIN -> -1 }
+{ -1 1 MIN -> -1 }
+{ MIN-INT 0 MIN -> MIN-INT }
+{ MIN-INT MAX-INT MIN -> MIN-INT }
+{ 0 MAX-INT MIN -> 0 }
+{ 0 0 MIN -> 0 }
+{ 1 1 MIN -> 1 }
+{ 1 0 MIN -> 0 }
+{ 2 1 MIN -> 1 }
+{ 0 -1 MIN -> -1 }
+{ 1 -1 MIN -> -1 }
+{ 0 MIN-INT MIN -> MIN-INT }
+{ MAX-INT MIN-INT MIN -> MIN-INT }
+{ MAX-INT 0 MIN -> 0 }
+
+{ 0 1 MAX -> 1 }
+{ 1 2 MAX -> 2 }
+{ -1 0 MAX -> 0 }
+{ -1 1 MAX -> 1 }
+{ MIN-INT 0 MAX -> 0 }
+{ MIN-INT MAX-INT MAX -> MAX-INT }
+{ 0 MAX-INT MAX -> MAX-INT }
+{ 0 0 MAX -> 0 }
+{ 1 1 MAX -> 1 }
+{ 1 0 MAX -> 1 }
+{ 2 1 MAX -> 2 }
+{ 0 -1 MAX -> 0 }
+{ 1 -1 MAX -> 1 }
+{ 0 MIN-INT MAX -> 0 }
+{ MAX-INT MIN-INT MAX -> MAX-INT }
+{ MAX-INT 0 MAX -> MAX-INT }
+
+\ ------------------------------------------------------------------------
+TESTING STACK OPS: 2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP
+
+{ 1 2 2DROP -> }
+{ 1 2 2DUP -> 1 2 1 2 }
+{ 1 2 3 4 2OVER -> 1 2 3 4 1 2 }
+{ 1 2 3 4 2SWAP -> 3 4 1 2 }
+{ 0 ?DUP -> 0 }
+{ 1 ?DUP -> 1 1 }
+{ -1 ?DUP -> -1 -1 }
+{ DEPTH -> 0 }
+{ 0 DEPTH -> 0 1 }
+{ 0 1 DEPTH -> 0 1 2 }
+{ 0 DROP -> }
+{ 1 2 DROP -> 1 }
+{ 1 DUP -> 1 1 }
+{ 1 2 OVER -> 1 2 1 }
+{ 1 2 3 ROT -> 2 3 1 }
+{ 1 2 SWAP -> 2 1 }
+
+\ ------------------------------------------------------------------------
+TESTING >R R> R@
+
+{ : GR1 >R R> ; -> }
+{ : GR2 >R R@ R> DROP ; -> }
+{ 123 GR1 -> 123 }
+{ 123 GR2 -> 123 }
+{ 1S GR1 -> 1S } ( RETURN STACK HOLDS CELLS )
+
+\ ------------------------------------------------------------------------
+TESTING ADD/SUBTRACT: + - 1+ 1- ABS NEGATE
+
+{ 0 5 + -> 5 }
+{ 5 0 + -> 5 }
+{ 0 -5 + -> -5 }
+{ -5 0 + -> -5 }
+{ 1 2 + -> 3 }
+{ 1 -2 + -> -1 }
+{ -1 2 + -> 1 }
+{ -1 -2 + -> -3 }
+{ -1 1 + -> 0 }
+{ MID-UINT 1 + -> MID-UINT+1 }
+
+{ 0 5 - -> -5 }
+{ 5 0 - -> 5 }
+{ 0 -5 - -> 5 }
+{ -5 0 - -> -5 }
+{ 1 2 - -> -1 }
+{ 1 -2 - -> 3 }
+{ -1 2 - -> -3 }
+{ -1 -2 - -> 1 }
+{ 0 1 - -> -1 }
+{ MID-UINT+1 1 - -> MID-UINT }
+
+{ 0 1+ -> 1 }
+{ -1 1+ -> 0 }
+{ 1 1+ -> 2 }
+{ MID-UINT 1+ -> MID-UINT+1 }
+
+{ 2 1- -> 1 }
+{ 1 1- -> 0 }
+{ 0 1- -> -1 }
+{ MID-UINT+1 1- -> MID-UINT }
+
+{ 0 NEGATE -> 0 }
+{ 1 NEGATE -> -1 }
+{ -1 NEGATE -> 1 }
+{ 2 NEGATE -> -2 }
+{ -2 NEGATE -> 2 }
+
+{ 0 ABS -> 0 }
+{ 1 ABS -> 1 }
+{ -1 ABS -> 1 }
+{ MIN-INT ABS -> MID-UINT+1 }
+
+\ ------------------------------------------------------------------------
+TESTING MULTIPLY: S>D * M* UM*
+
+{ 0 S>D -> 0 0 }
+{ 1 S>D -> 1 0 }
+{ 2 S>D -> 2 0 }
+{ -1 S>D -> -1 -1 }
+{ -2 S>D -> -2 -1 }
+{ MIN-INT S>D -> MIN-INT -1 }
+{ MAX-INT S>D -> MAX-INT 0 }
+
+{ 0 0 M* -> 0 S>D }
+{ 0 1 M* -> 0 S>D }
+{ 1 0 M* -> 0 S>D }
+{ 1 2 M* -> 2 S>D }
+{ 2 1 M* -> 2 S>D }
+{ 3 3 M* -> 9 S>D }
+{ -3 3 M* -> -9 S>D }
+{ 3 -3 M* -> -9 S>D }
+{ -3 -3 M* -> 9 S>D }
+{ 0 MIN-INT M* -> 0 S>D }
+{ 1 MIN-INT M* -> MIN-INT S>D }
+{ 2 MIN-INT M* -> 0 1S }
+{ 0 MAX-INT M* -> 0 S>D }
+{ 1 MAX-INT M* -> MAX-INT S>D }
+{ 2 MAX-INT M* -> MAX-INT 1 LSHIFT 0 }
+{ MIN-INT MIN-INT M* -> 0 MSB 1 RSHIFT }
+{ MAX-INT MIN-INT M* -> MSB MSB 2/ }
+{ MAX-INT MAX-INT M* -> 1 MSB 2/ INVERT }
+
+{ 0 0 * -> 0 } \ TEST IDENTITIES
+{ 0 1 * -> 0 }
+{ 1 0 * -> 0 }
+{ 1 2 * -> 2 }
+{ 2 1 * -> 2 }
+{ 3 3 * -> 9 }
+{ -3 3 * -> -9 }
+{ 3 -3 * -> -9 }
+{ -3 -3 * -> 9 }
+
+{ MID-UINT+1 1 RSHIFT 2 * -> MID-UINT+1 }
+{ MID-UINT+1 2 RSHIFT 4 * -> MID-UINT+1 }
+{ MID-UINT+1 1 RSHIFT MID-UINT+1 OR 2 * -> MID-UINT+1 }
+
+{ 0 0 UM* -> 0 0 }
+{ 0 1 UM* -> 0 0 }
+{ 1 0 UM* -> 0 0 }
+{ 1 2 UM* -> 2 0 }
+{ 2 1 UM* -> 2 0 }
+{ 3 3 UM* -> 9 0 }
+
+{ MID-UINT+1 1 RSHIFT 2 UM* -> MID-UINT+1 0 }
+{ MID-UINT+1 2 UM* -> 0 1 }
+{ MID-UINT+1 4 UM* -> 0 2 }
+{ 1S 2 UM* -> 1S 1 LSHIFT 1 }
+{ MAX-UINT MAX-UINT UM* -> 1 1 INVERT }
+
+\ ------------------------------------------------------------------------
+TESTING DIVIDE: FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD
+
+{ 0 S>D 1 FM/MOD -> 0 0 }
+{ 1 S>D 1 FM/MOD -> 0 1 }
+{ 2 S>D 1 FM/MOD -> 0 2 }
+{ -1 S>D 1 FM/MOD -> 0 -1 }
+{ -2 S>D 1 FM/MOD -> 0 -2 }
+{ 0 S>D -1 FM/MOD -> 0 0 }
+{ 1 S>D -1 FM/MOD -> 0 -1 }
+{ 2 S>D -1 FM/MOD -> 0 -2 }
+{ -1 S>D -1 FM/MOD -> 0 1 }
+{ -2 S>D -1 FM/MOD -> 0 2 }
+{ 2 S>D 2 FM/MOD -> 0 1 }
+{ -1 S>D -1 FM/MOD -> 0 1 }
+{ -2 S>D -2 FM/MOD -> 0 1 }
+{ 7 S>D 3 FM/MOD -> 1 2 }
+{ 7 S>D -3 FM/MOD -> -2 -3 }
+{ -7 S>D 3 FM/MOD -> 2 -3 }
+{ -7 S>D -3 FM/MOD -> -1 2 }
+{ MAX-INT S>D 1 FM/MOD -> 0 MAX-INT }
+{ MIN-INT S>D 1 FM/MOD -> 0 MIN-INT }
+{ MAX-INT S>D MAX-INT FM/MOD -> 0 1 }
+{ MIN-INT S>D MIN-INT FM/MOD -> 0 1 }
+{ 1S 1 4 FM/MOD -> 3 MAX-INT }
+{ 1 MIN-INT M* 1 FM/MOD -> 0 MIN-INT }
+{ 1 MIN-INT M* MIN-INT FM/MOD -> 0 1 }
+{ 2 MIN-INT M* 2 FM/MOD -> 0 MIN-INT }
+{ 2 MIN-INT M* MIN-INT FM/MOD -> 0 2 }
+{ 1 MAX-INT M* 1 FM/MOD -> 0 MAX-INT }
+{ 1 MAX-INT M* MAX-INT FM/MOD -> 0 1 }
+{ 2 MAX-INT M* 2 FM/MOD -> 0 MAX-INT }
+{ 2 MAX-INT M* MAX-INT FM/MOD -> 0 2 }
+{ MIN-INT MIN-INT M* MIN-INT FM/MOD -> 0 MIN-INT }
+{ MIN-INT MAX-INT M* MIN-INT FM/MOD -> 0 MAX-INT }
+{ MIN-INT MAX-INT M* MAX-INT FM/MOD -> 0 MIN-INT }
+{ MAX-INT MAX-INT M* MAX-INT FM/MOD -> 0 MAX-INT }
+
+{ 0 S>D 1 SM/REM -> 0 0 }
+{ 1 S>D 1 SM/REM -> 0 1 }
+{ 2 S>D 1 SM/REM -> 0 2 }
+{ -1 S>D 1 SM/REM -> 0 -1 }
+{ -2 S>D 1 SM/REM -> 0 -2 }
+{ 0 S>D -1 SM/REM -> 0 0 }
+{ 1 S>D -1 SM/REM -> 0 -1 }
+{ 2 S>D -1 SM/REM -> 0 -2 }
+{ -1 S>D -1 SM/REM -> 0 1 }
+{ -2 S>D -1 SM/REM -> 0 2 }
+{ 2 S>D 2 SM/REM -> 0 1 }
+{ -1 S>D -1 SM/REM -> 0 1 }
+{ -2 S>D -2 SM/REM -> 0 1 }
+{ 7 S>D 3 SM/REM -> 1 2 }
+{ 7 S>D -3 SM/REM -> 1 -2 }
+{ -7 S>D 3 SM/REM -> -1 -2 }
+{ -7 S>D -3 SM/REM -> -1 2 }
+{ MAX-INT S>D 1 SM/REM -> 0 MAX-INT }
+{ MIN-INT S>D 1 SM/REM -> 0 MIN-INT }
+{ MAX-INT S>D MAX-INT SM/REM -> 0 1 }
+{ MIN-INT S>D MIN-INT SM/REM -> 0 1 }
+{ 1S 1 4 SM/REM -> 3 MAX-INT }
+{ 2 MIN-INT M* 2 SM/REM -> 0 MIN-INT }
+{ 2 MIN-INT M* MIN-INT SM/REM -> 0 2 }
+{ 2 MAX-INT M* 2 SM/REM -> 0 MAX-INT }
+{ 2 MAX-INT M* MAX-INT SM/REM -> 0 2 }
+{ MIN-INT MIN-INT M* MIN-INT SM/REM -> 0 MIN-INT }
+{ MIN-INT MAX-INT M* MIN-INT SM/REM -> 0 MAX-INT }
+{ MIN-INT MAX-INT M* MAX-INT SM/REM -> 0 MIN-INT }
+{ MAX-INT MAX-INT M* MAX-INT SM/REM -> 0 MAX-INT }
+
+{ 0 0 1 UM/MOD -> 0 0 }
+{ 1 0 1 UM/MOD -> 0 1 }
+{ 1 0 2 UM/MOD -> 1 0 }
+{ 3 0 2 UM/MOD -> 1 1 }
+{ MAX-UINT 2 UM* 2 UM/MOD -> 0 MAX-UINT }
+{ MAX-UINT 2 UM* MAX-UINT UM/MOD -> 0 2 }
+{ MAX-UINT MAX-UINT UM* MAX-UINT UM/MOD -> 0 MAX-UINT }
+
+: IFFLOORED
+ [ -3 2 / -2 = INVERT ] LITERAL IF POSTPONE \ THEN ;
+: IFSYM
+ [ -3 2 / -1 = INVERT ] LITERAL IF POSTPONE \ THEN ;
+
+\ THE SYSTEM MIGHT DO EITHER FLOORED OR SYMMETRIC DIVISION.
+\ SINCE WE HAVE ALREADY TESTED M*, FM/MOD, AND SM/REM WE CAN USE THEM IN TEST.
+IFFLOORED : T/MOD >R S>D R> FM/MOD ;
+IFFLOORED : T/ T/MOD SWAP DROP ;
+IFFLOORED : TMOD T/MOD DROP ;
+IFFLOORED : T*/MOD >R M* R> FM/MOD ;
+IFFLOORED : T*/ T*/MOD SWAP DROP ;
+IFSYM : T/MOD >R S>D R> SM/REM ;
+IFSYM : T/ T/MOD SWAP DROP ;
+IFSYM : TMOD T/MOD DROP ;
+IFSYM : T*/MOD >R M* R> SM/REM ;
+IFSYM : T*/ T*/MOD SWAP DROP ;
+
+{ 0 1 /MOD -> 0 1 T/MOD }
+{ 1 1 /MOD -> 1 1 T/MOD }
+{ 2 1 /MOD -> 2 1 T/MOD }
+{ -1 1 /MOD -> -1 1 T/MOD }
+{ -2 1 /MOD -> -2 1 T/MOD }
+{ 0 -1 /MOD -> 0 -1 T/MOD }
+{ 1 -1 /MOD -> 1 -1 T/MOD }
+{ 2 -1 /MOD -> 2 -1 T/MOD }
+{ -1 -1 /MOD -> -1 -1 T/MOD }
+{ -2 -1 /MOD -> -2 -1 T/MOD }
+{ 2 2 /MOD -> 2 2 T/MOD }
+{ -1 -1 /MOD -> -1 -1 T/MOD }
+{ -2 -2 /MOD -> -2 -2 T/MOD }
+{ 7 3 /MOD -> 7 3 T/MOD }
+{ 7 -3 /MOD -> 7 -3 T/MOD }
+{ -7 3 /MOD -> -7 3 T/MOD }
+{ -7 -3 /MOD -> -7 -3 T/MOD }
+{ MAX-INT 1 /MOD -> MAX-INT 1 T/MOD }
+{ MIN-INT 1 /MOD -> MIN-INT 1 T/MOD }
+{ MAX-INT MAX-INT /MOD -> MAX-INT MAX-INT T/MOD }
+{ MIN-INT MIN-INT /MOD -> MIN-INT MIN-INT T/MOD }
+
+{ 0 1 / -> 0 1 T/ }
+{ 1 1 / -> 1 1 T/ }
+{ 2 1 / -> 2 1 T/ }
+{ -1 1 / -> -1 1 T/ }
+{ -2 1 / -> -2 1 T/ }
+{ 0 -1 / -> 0 -1 T/ }
+{ 1 -1 / -> 1 -1 T/ }
+{ 2 -1 / -> 2 -1 T/ }
+{ -1 -1 / -> -1 -1 T/ }
+{ -2 -1 / -> -2 -1 T/ }
+{ 2 2 / -> 2 2 T/ }
+{ -1 -1 / -> -1 -1 T/ }
+{ -2 -2 / -> -2 -2 T/ }
+{ 7 3 / -> 7 3 T/ }
+{ 7 -3 / -> 7 -3 T/ }
+{ -7 3 / -> -7 3 T/ }
+{ -7 -3 / -> -7 -3 T/ }
+{ MAX-INT 1 / -> MAX-INT 1 T/ }
+{ MIN-INT 1 / -> MIN-INT 1 T/ }
+{ MAX-INT MAX-INT / -> MAX-INT MAX-INT T/ }
+{ MIN-INT MIN-INT / -> MIN-INT MIN-INT T/ }
+
+{ 0 1 MOD -> 0 1 TMOD }
+{ 1 1 MOD -> 1 1 TMOD }
+{ 2 1 MOD -> 2 1 TMOD }
+{ -1 1 MOD -> -1 1 TMOD }
+{ -2 1 MOD -> -2 1 TMOD }
+{ 0 -1 MOD -> 0 -1 TMOD }
+{ 1 -1 MOD -> 1 -1 TMOD }
+{ 2 -1 MOD -> 2 -1 TMOD }
+{ -1 -1 MOD -> -1 -1 TMOD }
+{ -2 -1 MOD -> -2 -1 TMOD }
+{ 2 2 MOD -> 2 2 TMOD }
+{ -1 -1 MOD -> -1 -1 TMOD }
+{ -2 -2 MOD -> -2 -2 TMOD }
+{ 7 3 MOD -> 7 3 TMOD }
+{ 7 -3 MOD -> 7 -3 TMOD }
+{ -7 3 MOD -> -7 3 TMOD }
+{ -7 -3 MOD -> -7 -3 TMOD }
+{ MAX-INT 1 MOD -> MAX-INT 1 TMOD }
+{ MIN-INT 1 MOD -> MIN-INT 1 TMOD }
+{ MAX-INT MAX-INT MOD -> MAX-INT MAX-INT TMOD }
+{ MIN-INT MIN-INT MOD -> MIN-INT MIN-INT TMOD }
+
+{ 0 2 1 */ -> 0 2 1 T*/ }
+{ 1 2 1 */ -> 1 2 1 T*/ }
+{ 2 2 1 */ -> 2 2 1 T*/ }
+{ -1 2 1 */ -> -1 2 1 T*/ }
+{ -2 2 1 */ -> -2 2 1 T*/ }
+{ 0 2 -1 */ -> 0 2 -1 T*/ }
+{ 1 2 -1 */ -> 1 2 -1 T*/ }
+{ 2 2 -1 */ -> 2 2 -1 T*/ }
+{ -1 2 -1 */ -> -1 2 -1 T*/ }
+{ -2 2 -1 */ -> -2 2 -1 T*/ }
+{ 2 2 2 */ -> 2 2 2 T*/ }
+{ -1 2 -1 */ -> -1 2 -1 T*/ }
+{ -2 2 -2 */ -> -2 2 -2 T*/ }
+{ 7 2 3 */ -> 7 2 3 T*/ }
+{ 7 2 -3 */ -> 7 2 -3 T*/ }
+{ -7 2 3 */ -> -7 2 3 T*/ }
+{ -7 2 -3 */ -> -7 2 -3 T*/ }
+{ MAX-INT 2 MAX-INT */ -> MAX-INT 2 MAX-INT T*/ }
+{ MIN-INT 2 MIN-INT */ -> MIN-INT 2 MIN-INT T*/ }
+
+{ 0 2 1 */MOD -> 0 2 1 T*/MOD }
+{ 1 2 1 */MOD -> 1 2 1 T*/MOD }
+{ 2 2 1 */MOD -> 2 2 1 T*/MOD }
+{ -1 2 1 */MOD -> -1 2 1 T*/MOD }
+{ -2 2 1 */MOD -> -2 2 1 T*/MOD }
+{ 0 2 -1 */MOD -> 0 2 -1 T*/MOD }
+{ 1 2 -1 */MOD -> 1 2 -1 T*/MOD }
+{ 2 2 -1 */MOD -> 2 2 -1 T*/MOD }
+{ -1 2 -1 */MOD -> -1 2 -1 T*/MOD }
+{ -2 2 -1 */MOD -> -2 2 -1 T*/MOD }
+{ 2 2 2 */MOD -> 2 2 2 T*/MOD }
+{ -1 2 -1 */MOD -> -1 2 -1 T*/MOD }
+{ -2 2 -2 */MOD -> -2 2 -2 T*/MOD }
+{ 7 2 3 */MOD -> 7 2 3 T*/MOD }
+{ 7 2 -3 */MOD -> 7 2 -3 T*/MOD }
+{ -7 2 3 */MOD -> -7 2 3 T*/MOD }
+{ -7 2 -3 */MOD -> -7 2 -3 T*/MOD }
+{ MAX-INT 2 MAX-INT */MOD -> MAX-INT 2 MAX-INT T*/MOD }
+{ MIN-INT 2 MIN-INT */MOD -> MIN-INT 2 MIN-INT T*/MOD }
+
+\ ------------------------------------------------------------------------
+TESTING HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2! ALIGN ALIGNED +! ALLOT
+
+HERE 1 ALLOT
+HERE
+CONSTANT 2NDA
+CONSTANT 1STA
+{ 1STA 2NDA U< -> <TRUE> } \ HERE MUST GROW WITH ALLOT
+{ 1STA 1+ -> 2NDA } \ ... BY ONE ADDRESS UNIT
+( MISSING TEST: NEGATIVE ALLOT )
+
+HERE 1 ,
+HERE 2 ,
+CONSTANT 2ND
+CONSTANT 1ST
+{ 1ST 2ND U< -> <TRUE> } \ HERE MUST GROW WITH ALLOT
+{ 1ST CELL+ -> 2ND } \ ... BY ONE CELL
+{ 1ST 1 CELLS + -> 2ND }
+{ 1ST @ 2ND @ -> 1 2 }
+{ 5 1ST ! -> }
+{ 1ST @ 2ND @ -> 5 2 }
+{ 6 2ND ! -> }
+{ 1ST @ 2ND @ -> 5 6 }
+{ 1ST 2@ -> 6 5 }
+{ 2 1 1ST 2! -> }
+{ 1ST 2@ -> 2 1 }
+{ 1S 1ST ! 1ST @ -> 1S } \ CAN STORE CELL-WIDE VALUE
+
+HERE 1 C,
+HERE 2 C,
+CONSTANT 2NDC
+CONSTANT 1STC
+{ 1STC 2NDC U< -> <TRUE> } \ HERE MUST GROW WITH ALLOT
+{ 1STC CHAR+ -> 2NDC } \ ... BY ONE CHAR
+{ 1STC 1 CHARS + -> 2NDC }
+{ 1STC C@ 2NDC C@ -> 1 2 }
+{ 3 1STC C! -> }
+{ 1STC C@ 2NDC C@ -> 3 2 }
+{ 4 2NDC C! -> }
+{ 1STC C@ 2NDC C@ -> 3 4 }
+
+ALIGN 1 ALLOT HERE ALIGN HERE 3 CELLS ALLOT
+CONSTANT A-ADDR CONSTANT UA-ADDR
+{ UA-ADDR ALIGNED -> A-ADDR }
+{ 1 A-ADDR C! A-ADDR C@ -> 1 }
+{ 1234 A-ADDR ! A-ADDR @ -> 1234 }
+{ 123 456 A-ADDR 2! A-ADDR 2@ -> 123 456 }
+{ 2 A-ADDR CHAR+ C! A-ADDR CHAR+ C@ -> 2 }
+{ 3 A-ADDR CELL+ C! A-ADDR CELL+ C@ -> 3 }
+{ 1234 A-ADDR CELL+ ! A-ADDR CELL+ @ -> 1234 }
+{ 123 456 A-ADDR CELL+ 2! A-ADDR CELL+ 2@ -> 123 456 }
+
+: BITS ( X -- U )
+ 0 SWAP BEGIN DUP WHILE DUP MSB AND IF >R 1+ R> THEN 2* REPEAT DROP ;
+( CHARACTERS >= 1 AU, <= SIZE OF CELL, >= 8 BITS )
+{ 1 CHARS 1 < -> <FALSE> }
+{ 1 CHARS 1 CELLS > -> <FALSE> }
+( TBD: HOW TO FIND NUMBER OF BITS? )
+
+( CELLS >= 1 AU, INTEGRAL MULTIPLE OF CHAR SIZE, >= 16 BITS )
+{ 1 CELLS 1 < -> <FALSE> }
+{ 1 CELLS 1 CHARS MOD -> 0 }
+{ 1S BITS 10 < -> <FALSE> }
+
+{ 0 1ST ! -> }
+{ 1 1ST +! -> }
+{ 1ST @ -> 1 }
+{ -1 1ST +! 1ST @ -> 0 }
+
+\ ------------------------------------------------------------------------
+TESTING CHAR [CHAR] [ ] BL S"
+
+{ BL -> 20 }
+{ CHAR X -> 58 }
+{ CHAR HELLO -> 48 }
+{ : GC1 [CHAR] X ; -> }
+{ : GC2 [CHAR] HELLO ; -> }
+{ GC1 -> 58 }
+{ GC2 -> 48 }
+{ : GC3 [ GC1 ] LITERAL ; -> }
+{ GC3 -> 58 }
+{ : GC4 S" XY" ; -> }
+{ GC4 SWAP DROP -> 2 }
+{ GC4 DROP DUP C@ SWAP CHAR+ C@ -> 58 59 }
+
+\ ------------------------------------------------------------------------
+TESTING ' ['] FIND EXECUTE IMMEDIATE COUNT LITERAL POSTPONE STATE
+
+{ : GT1 123 ; -> }
+{ ' GT1 EXECUTE -> 123 }
+{ : GT2 ['] GT1 ; IMMEDIATE -> }
+{ GT2 EXECUTE -> 123 }
+HERE 3 C, CHAR G C, CHAR T C, CHAR 1 C, CONSTANT GT1STRING
+HERE 3 C, CHAR G C, CHAR T C, CHAR 2 C, CONSTANT GT2STRING
+{ GT1STRING FIND -> ' GT1 -1 }
+{ GT2STRING FIND -> ' GT2 1 }
+( HOW TO SEARCH FOR NON-EXISTENT WORD? )
+{ : GT3 GT2 LITERAL ; -> }
+{ GT3 -> ' GT1 }
+{ GT1STRING COUNT -> GT1STRING CHAR+ 3 }
+
+{ : GT4 POSTPONE GT1 ; IMMEDIATE -> }
+{ : GT5 GT4 ; -> }
+{ GT5 -> 123 }
+{ : GT6 345 ; IMMEDIATE -> }
+{ : GT7 POSTPONE GT6 ; -> }
+{ GT7 -> 345 }
+
+{ : GT8 STATE @ ; IMMEDIATE -> }
+{ GT8 -> 0 }
+{ : GT9 GT8 LITERAL ; -> }
+{ GT9 0= -> <FALSE> }
+
+\ ------------------------------------------------------------------------
+TESTING IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE
+
+{ : GI1 IF 123 THEN ; -> }
+{ : GI2 IF 123 ELSE 234 THEN ; -> }
+{ 0 GI1 -> }
+{ 1 GI1 -> 123 }
+{ -1 GI1 -> 123 }
+{ 0 GI2 -> 234 }
+{ 1 GI2 -> 123 }
+{ -1 GI1 -> 123 }
+
+{ : GI3 BEGIN DUP 5 < WHILE DUP 1+ REPEAT ; -> }
+{ 0 GI3 -> 0 1 2 3 4 5 }
+{ 4 GI3 -> 4 5 }
+{ 5 GI3 -> 5 }
+{ 6 GI3 -> 6 }
+
+{ : GI4 BEGIN DUP 1+ DUP 5 > UNTIL ; -> }
+{ 3 GI4 -> 3 4 5 6 }
+{ 5 GI4 -> 5 6 }
+{ 6 GI4 -> 6 7 }
+
+{ : GI5 BEGIN DUP 2 > WHILE DUP 5 < WHILE DUP 1+ REPEAT 123 ELSE 345 THEN ; -> }
+{ 1 GI5 -> 1 345 }
+{ 2 GI5 -> 2 345 }
+{ 3 GI5 -> 3 4 5 123 }
+{ 4 GI5 -> 4 5 123 }
+{ 5 GI5 -> 5 123 }
+
+{ : GI6 ( N -- 0,1,..N ) DUP IF DUP >R 1- RECURSE R> THEN ; -> }
+{ 0 GI6 -> 0 }
+{ 1 GI6 -> 0 1 }
+{ 2 GI6 -> 0 1 2 }
+{ 3 GI6 -> 0 1 2 3 }
+{ 4 GI6 -> 0 1 2 3 4 }
+
+\ ------------------------------------------------------------------------
+TESTING DO LOOP +LOOP I J UNLOOP LEAVE EXIT
+
+{ : GD1 DO I LOOP ; -> }
+{ 4 1 GD1 -> 1 2 3 }
+{ 2 -1 GD1 -> -1 0 1 }
+{ MID-UINT+1 MID-UINT GD1 -> MID-UINT }
+
+{ : GD2 DO I -1 +LOOP ; -> }
+{ 1 4 GD2 -> 4 3 2 1 }
+{ -1 2 GD2 -> 2 1 0 -1 }
+{ MID-UINT MID-UINT+1 GD2 -> MID-UINT+1 MID-UINT }
+
+{ : GD3 DO 1 0 DO J LOOP LOOP ; -> }
+{ 4 1 GD3 -> 1 2 3 }
+{ 2 -1 GD3 -> -1 0 1 }
+{ MID-UINT+1 MID-UINT GD3 -> MID-UINT }
+
+{ : GD4 DO 1 0 DO J LOOP -1 +LOOP ; -> }
+{ 1 4 GD4 -> 4 3 2 1 }
+{ -1 2 GD4 -> 2 1 0 -1 }
+{ MID-UINT MID-UINT+1 GD4 -> MID-UINT+1 MID-UINT }
+
+{ : GD5 123 SWAP 0 DO I 4 > IF DROP 234 LEAVE THEN LOOP ; -> }
+{ 1 GD5 -> 123 }
+{ 5 GD5 -> 123 }
+{ 6 GD5 -> 234 }
+
+{ : GD6 ( PAT: {0 0},{0 0}{1 0}{1 1},{0 0}{1 0}{1 1}{2 0}{2 1}{2 2} )
+ 0 SWAP 0 DO
+ I 1+ 0 DO I J + 3 = IF I UNLOOP I UNLOOP EXIT THEN 1+ LOOP
+ LOOP ; -> }
+{ 1 GD6 -> 1 }
+{ 2 GD6 -> 3 }
+{ 3 GD6 -> 4 1 2 }
+
+\ ------------------------------------------------------------------------
+TESTING DEFINING WORDS: : ; CONSTANT VARIABLE CREATE DOES> >BODY
+
+{ 123 CONSTANT X123 -> }
+{ X123 -> 123 }
+{ : EQU CONSTANT ; -> }
+{ X123 EQU Y123 -> }
+{ Y123 -> 123 }
+
+{ VARIABLE V1 -> }
+{ 123 V1 ! -> }
+{ V1 @ -> 123 }
+
+{ : NOP : POSTPONE ; ; -> }
+{ NOP NOP1 NOP NOP2 -> }
+{ NOP1 -> }
+{ NOP2 -> }
+
+{ : DOES1 DOES> @ 1 + ; -> }
+{ : DOES2 DOES> @ 2 + ; -> }
+{ CREATE CR1 -> }
+{ CR1 -> HERE }
+{ ' CR1 >BODY -> HERE }
+{ 1 , -> }
+{ CR1 @ -> 1 }
+{ DOES1 -> }
+{ CR1 -> 2 }
+{ DOES2 -> }
+{ CR1 -> 3 }
+
+{ : WEIRD: CREATE DOES> 1 + DOES> 2 + ; -> }
+{ WEIRD: W1 -> }
+{ ' W1 >BODY -> HERE }
+{ W1 -> HERE 1 + }
+{ W1 -> HERE 2 + }
+
+\ ------------------------------------------------------------------------
+TESTING EVALUATE
+
+: GE1 S" 123" ; IMMEDIATE
+: GE2 S" 123 1+" ; IMMEDIATE
+: GE3 S" : GE4 345 ;" ;
+: GE5 EVALUATE ; IMMEDIATE
+
+{ GE1 EVALUATE -> 123 } ( TEST EVALUATE IN INTERP. STATE )
+{ GE2 EVALUATE -> 124 }
+{ GE3 EVALUATE -> }
+{ GE4 -> 345 }
+
+{ : GE6 GE1 GE5 ; -> } ( TEST EVALUATE IN COMPILE STATE )
+{ GE6 -> 123 }
+{ : GE7 GE2 GE5 ; -> }
+{ GE7 -> 124 }
+
+\ ------------------------------------------------------------------------
+TESTING SOURCE >IN WORD
+
+: GS1 S" SOURCE" 2DUP EVALUATE
+ >R SWAP >R = R> R> = ;
+{ GS1 -> <TRUE> <TRUE> }
+
+VARIABLE SCANS
+: RESCAN? -1 SCANS +! SCANS @ IF 0 >IN ! THEN ;
+
+{ 2 SCANS !
+345 RESCAN?
+-> 345 345 }
+
+: GS2 5 SCANS ! S" 123 RESCAN?" EVALUATE ;
+{ GS2 -> 123 123 123 123 123 }
+
+: GS3 WORD COUNT SWAP C@ ;
+{ BL GS3 HELLO -> 5 CHAR H }
+{ CHAR " GS3 GOODBYE" -> 7 CHAR G }
+{ BL GS3
+DROP -> 0 } \ BLANK LINE RETURN ZERO-LENGTH STRING
+
+: GS4 SOURCE >IN ! DROP ;
+{ GS4 123 456
+-> }
+
+\ ------------------------------------------------------------------------
+TESTING <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL
+
+: S= \ ( ADDR1 C1 ADDR2 C2 -- T/F ) COMPARE TWO STRINGS.
+ >R SWAP R@ = IF \ MAKE SURE STRINGS HAVE SAME LENGTH
+ R> ?DUP IF \ IF NON-EMPTY STRINGS
+ 0 DO
+ OVER C@ OVER C@ - IF 2DROP <FALSE> UNLOOP EXIT THEN
+ SWAP CHAR+ SWAP CHAR+
+ LOOP
+ THEN
+ 2DROP <TRUE> \ IF WE GET HERE, STRINGS MATCH
+ ELSE
+ R> DROP 2DROP <FALSE> \ LENGTHS MISMATCH
+ THEN ;
+
+: GP1 <# 41 HOLD 42 HOLD 0 0 #> S" BA" S= ;
+{ GP1 -> <TRUE> }
+
+: GP2 <# -1 SIGN 0 SIGN -1 SIGN 0 0 #> S" --" S= ;
+{ GP2 -> <TRUE> }
+
+: GP3 <# 1 0 # # #> S" 01" S= ;
+{ GP3 -> <TRUE> }
+
+: GP4 <# 1 0 #S #> S" 1" S= ;
+{ GP4 -> <TRUE> }
+
+24 CONSTANT MAX-BASE \ BASE 2 .. 36
+: COUNT-BITS
+ 0 0 INVERT BEGIN DUP WHILE >R 1+ R> 2* REPEAT DROP ;
+COUNT-BITS 2* CONSTANT #BITS-UD \ NUMBER OF BITS IN UD
+
+: GP5
+ BASE @ <TRUE>
+ MAX-BASE 1+ 2 DO \ FOR EACH POSSIBLE BASE
+ I BASE ! \ TBD: ASSUMES BASE WORKS
+ I 0 <# #S #> S" 10" S= AND
+ LOOP
+ SWAP BASE ! ;
+{ GP5 -> <TRUE> }
+
+: GP6
+ BASE @ >R 2 BASE !
+ MAX-UINT MAX-UINT <# #S #> \ MAXIMUM UD TO BINARY
+ R> BASE ! \ S: C-ADDR U
+ DUP #BITS-UD = SWAP
+ 0 DO \ S: C-ADDR FLAG
+ OVER C@ [CHAR] 1 = AND \ ALL ONES
+ >R CHAR+ R>
+ LOOP SWAP DROP ;
+{ GP6 -> <TRUE> }
+
+: GP7
+ BASE @ >R MAX-BASE BASE !
+ <TRUE>
+ A 0 DO
+ I 0 <# #S #>
+ 1 = SWAP C@ I 30 + = AND AND
+ LOOP
+ MAX-BASE A DO
+ I 0 <# #S #>
+ 1 = SWAP C@ 41 I A - + = AND AND
+ LOOP
+ R> BASE ! ;
+
+{ GP7 -> <TRUE> }
+
+\ >NUMBER TESTS
+CREATE GN-BUF 0 C,
+: GN-STRING GN-BUF 1 ;
+: GN-CONSUMED GN-BUF CHAR+ 0 ;
+: GN' [CHAR] ' WORD CHAR+ C@ GN-BUF C! GN-STRING ;
+
+{ 0 0 GN' 0' >NUMBER -> 0 0 GN-CONSUMED }
+{ 0 0 GN' 1' >NUMBER -> 1 0 GN-CONSUMED }
+{ 1 0 GN' 1' >NUMBER -> BASE @ 1+ 0 GN-CONSUMED }
+{ 0 0 GN' -' >NUMBER -> 0 0 GN-STRING } \ SHOULD FAIL TO CONVERT THESE
+{ 0 0 GN' +' >NUMBER -> 0 0 GN-STRING }
+{ 0 0 GN' .' >NUMBER -> 0 0 GN-STRING }
+
+: >NUMBER-BASED
+ BASE @ >R BASE ! >NUMBER R> BASE ! ;
+
+{ 0 0 GN' 2' 10 >NUMBER-BASED -> 2 0 GN-CONSUMED }
+{ 0 0 GN' 2' 2 >NUMBER-BASED -> 0 0 GN-STRING }
+{ 0 0 GN' F' 10 >NUMBER-BASED -> F 0 GN-CONSUMED }
+{ 0 0 GN' G' 10 >NUMBER-BASED -> 0 0 GN-STRING }
+{ 0 0 GN' G' MAX-BASE >NUMBER-BASED -> 10 0 GN-CONSUMED }
+{ 0 0 GN' Z' MAX-BASE >NUMBER-BASED -> 23 0 GN-CONSUMED }
+
+: GN1 \ ( UD BASE -- UD' LEN ) UD SHOULD EQUAL UD' AND LEN SHOULD BE ZERO.
+ BASE @ >R BASE !
+ <# #S #>
+ 0 0 2SWAP >NUMBER SWAP DROP \ RETURN LENGTH ONLY
+ R> BASE ! ;
+{ 0 0 2 GN1 -> 0 0 0 }
+{ MAX-UINT 0 2 GN1 -> MAX-UINT 0 0 }
+{ MAX-UINT DUP 2 GN1 -> MAX-UINT DUP 0 }
+{ 0 0 MAX-BASE GN1 -> 0 0 0 }
+{ MAX-UINT 0 MAX-BASE GN1 -> MAX-UINT 0 0 }
+{ MAX-UINT DUP MAX-BASE GN1 -> MAX-UINT DUP 0 }
+
+: GN2 \ ( -- 16 10 )
+ BASE @ >R HEX BASE @ DECIMAL BASE @ R> BASE ! ;
+{ GN2 -> 10 A }
+
+\ ------------------------------------------------------------------------
+TESTING FILL MOVE
+
+CREATE FBUF 00 C, 00 C, 00 C,
+CREATE SBUF 12 C, 34 C, 56 C,
+: SEEBUF FBUF C@ FBUF CHAR+ C@ FBUF CHAR+ CHAR+ C@ ;
+
+{ FBUF 0 20 FILL -> }
+{ SEEBUF -> 00 00 00 }
+
+{ FBUF 1 20 FILL -> }
+{ SEEBUF -> 20 00 00 }
+
+{ FBUF 3 20 FILL -> }
+{ SEEBUF -> 20 20 20 }
+
+{ FBUF FBUF 3 CHARS MOVE -> } \ BIZARRE SPECIAL CASE
+{ SEEBUF -> 20 20 20 }
+
+{ SBUF FBUF 0 CHARS MOVE -> }
+{ SEEBUF -> 20 20 20 }
+
+{ SBUF FBUF 1 CHARS MOVE -> }
+{ SEEBUF -> 12 20 20 }
+
+{ SBUF FBUF 3 CHARS MOVE -> }
+{ SEEBUF -> 12 34 56 }
+
+{ FBUF FBUF CHAR+ 2 CHARS MOVE -> }
+{ SEEBUF -> 12 12 34 }
+
+{ FBUF CHAR+ FBUF 2 CHARS MOVE -> }
+{ SEEBUF -> 12 34 34 }
+
+\ ------------------------------------------------------------------------
+TESTING OUTPUT: . ." CR EMIT SPACE SPACES TYPE U.
+
+: OUTPUT-TEST
+ ." YOU SHOULD SEE THE STANDARD GRAPHIC CHARACTERS:" CR
+ 41 BL DO I EMIT LOOP CR
+ 61 41 DO I EMIT LOOP CR
+ 7F 61 DO I EMIT LOOP CR
+ ." YOU SHOULD SEE 0-9 SEPARATED BY A SPACE:" CR
+ 9 1+ 0 DO I . LOOP CR
+ ." YOU SHOULD SEE 0-9 (WITH NO SPACES):" CR
+ [CHAR] 9 1+ [CHAR] 0 DO I 0 SPACES EMIT LOOP CR
+ ." YOU SHOULD SEE A-G SEPARATED BY A SPACE:" CR
+ [CHAR] G 1+ [CHAR] A DO I EMIT SPACE LOOP CR
+ ." YOU SHOULD SEE 0-5 SEPARATED BY TWO SPACES:" CR
+ 5 1+ 0 DO I [CHAR] 0 + EMIT 2 SPACES LOOP CR
+ ." YOU SHOULD SEE TWO SEPARATE LINES:" CR
+ S" LINE 1" TYPE CR S" LINE 2" TYPE CR
+ ." YOU SHOULD SEE THE NUMBER RANGES OF SIGNED AND UNSIGNED NUMBERS:" CR
+ ." SIGNED: " MIN-INT . MAX-INT . CR
+ ." UNSIGNED: " 0 U. MAX-UINT U. CR
+;
+
+{ OUTPUT-TEST -> }
+
+\ ------------------------------------------------------------------------
+TESTING INPUT: ACCEPT
+
+CREATE ABUF 80 CHARS ALLOT
+
+: ACCEPT-TEST
+ CR ." PLEASE TYPE UP TO 80 CHARACTERS:" CR
+ ABUF 80 ACCEPT
+ CR ." RECEIVED: " [CHAR] " EMIT
+ ABUF SWAP TYPE [CHAR] " EMIT CR
+;
+
+{ ACCEPT-TEST -> }
+
+\ ------------------------------------------------------------------------
+TESTING DICTIONARY SEARCH RULES
+
+{ : GDX 123 ; : GDX GDX 234 ; -> }
+
+{ GDX -> 123 234 }
+
+
+\ test suite finished. leaving engine.
+
+bye
diff --git a/roms/openbios/forth/bootstrap/interpreter.fs b/roms/openbios/forth/bootstrap/interpreter.fs
new file mode 100644
index 00000000..51870581
--- /dev/null
+++ b/roms/openbios/forth/bootstrap/interpreter.fs
@@ -0,0 +1,175 @@
+\ tag: forth interpreter
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+
+\
+\ 7.3.4.6 Display pause
+\
+
+0 value interactive?
+0 value terminate?
+
+: exit?
+ interactive? 0= if
+ false exit
+ then
+ false \ FIXME we should check whether to interrupt output
+ \ and ask the user how to proceed.
+ ;
+
+
+\
+\ 7.3.9.1 Defining words
+\
+
+: forget
+ s" This word is obsolescent." type cr
+ ['] ' execute
+ cell - dup
+ @ dup
+ last ! latest !
+ here!
+ ;
+
+\
+\ 7.3.9.2.4 Miscellaneous dictionary
+\
+
+\ interpreter. This word checks whether the interpreted word
+\ is a word in dictionary or a number. It honours compile mode
+\ and immediate/compile-only words.
+
+: interpret
+ 0 >in !
+ begin
+ parse-word dup 0> \ was there a word at all?
+ while
+ $find
+ if
+ dup flags? 0<> state @ 0= or if
+ execute
+ else
+ , \ compile mode && !immediate
+ then
+ else \ word is not known. maybe it's a number
+ 2dup $number
+ if
+ span @ >in ! \ if we encountered an error, don't continue parsing
+ type 3a emit
+ -13 throw
+ else
+ -rot 2drop 1 handle-lit
+ then
+ then
+ depth 200 >= if -3 throw then
+ depth 0< if -4 throw then
+ rdepth 200 >= if -5 throw then
+ rdepth 0< if -6 throw then
+ repeat
+ 2drop
+ ;
+
+: refill ( -- )
+ ib #ib @ expect 0 >in ! ;
+
+: print-status ( exception -- )
+ space
+ ?dup if
+ dup sys-debug \ system debug hook
+ case
+ -1 of s" Aborted." type endof
+ -2 of s" Aborted." type endof
+ -3 of s" Stack Overflow." type 0 depth! endof
+ -4 of s" Stack Underflow." type 0 depth! endof
+ -5 of s" Return Stack Overflow." type endof
+ -6 of s" Return Stack Underflow." type endof
+ -13 of s" undefined word." type endof
+ -15 of s" out of memory." type endof
+ -21 of s" undefined method." type endof
+ -22 of s" no such device." type endof
+ dup s" Exception #" type .
+ 0 state !
+ endcase
+ else
+ state @ 0= if
+ s" ok"
+ else
+ s" compiled"
+ then
+ type
+ then
+ cr
+ ;
+
+defer status
+['] noop ['] status (to)
+
+: print-prompt
+ status
+ depth . 3e emit space
+ ;
+
+defer outer-interpreter
+:noname
+ cr
+ begin
+ print-prompt
+ source 0 fill \ clean input buffer
+ refill
+
+ ['] interpret catch print-status
+ terminate?
+ until
+; ['] outer-interpreter (to)
+
+\
+\ 7.3.8.5 Other control flow commands
+\
+
+: save-source ( -- )
+ r> \ fetch our caller
+ ib >r #ib @ >r \ save current input buffer
+ source-id >r \ and all variables
+ span @ >r \ associated with it.
+ >in @ >r
+ >r \ move back our caller
+ ;
+
+: restore-source ( -- )
+ r>
+ r> >in !
+ r> span !
+ r> ['] source-id (to)
+ r> #ib !
+ r> ['] ib (to)
+ >r
+ ;
+
+: (evaluate) ( str len -- ??? )
+ save-source
+ -1 ['] source-id (to)
+ dup
+ #ib ! span !
+ ['] ib (to)
+ interpret
+ restore-source
+ ;
+
+: evaluate ( str len -- ?? )
+ 2dup + -rot
+ over + over do
+ i c@ 0a = if
+ i over -
+ (evaluate)
+ i 1+
+ then
+ loop
+ swap over - (evaluate)
+ ;
+
+: eval evaluate ;
diff --git a/roms/openbios/forth/bootstrap/memory.fs b/roms/openbios/forth/bootstrap/memory.fs
new file mode 100644
index 00000000..6fa4a2cc
--- /dev/null
+++ b/roms/openbios/forth/bootstrap/memory.fs
@@ -0,0 +1,216 @@
+\ tag: forth memory allocation
+\
+\ Copyright (C) 2002-2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ 7.3.3.2 memory allocation
+
+\ these need to be initialized by the forth kernel by now.
+variable start-mem 0 start-mem ! \ start of memory
+variable end-mem 0 end-mem ! \ end of memory
+variable free-list 0 free-list ! \ free list head
+
+\ initialize necessary variables and write a valid
+\ free-list entry containing all of the memory.
+\ start-mem: pointer to start of memory.
+\ end-mem: pointer to end of memory.
+\ free-list: head of linked free list
+
+: init-mem ( start-addr size )
+ over dup
+ start-mem ! \ write start-mem
+ free-list ! \ write first freelist entry
+ 2dup /n - swap ! \ write 'len' entry
+ over cell+ 0 swap ! \ write 'next' entry
+ + end-mem ! \ write end-mem
+ ;
+
+\ --------------------------------------------------------------------
+
+\ return pointer to smallest free block that contains
+\ at least nb bytes and the block previous the the
+\ actual block. On failure the pointer to the smallest
+\ free block is 0.
+
+: smallest-free-block ( nb -- prev ptr | 0 0 )
+ 0 free-list @
+ fffffff 0 0 >r >r >r
+ begin
+ dup
+ while
+ ( nb prev pp R: best_nb best_pp )
+ dup @ 3 pick r@ within if
+ ( nb prev pp )
+ r> r> r> 3drop \ drop old smallest
+ 2dup >r >r dup @ >r \ new smallest
+ then
+ nip dup \ prev = pp
+ cell + @ \ pp = pp->next
+ repeat
+ 3drop r> drop r> r>
+;
+
+
+\ --------------------------------------------------------------------
+
+\ allocate size bytes of memory
+\ return pointer to memory (or throws an exception on failure).
+
+: alloc-mem ( size -- addr )
+
+ \ make it legal (and fast) to allocate 0 bytes
+ dup 0= if exit then
+
+ aligned \ keep memory aligned.
+ dup smallest-free-block \ look up smallest free block.
+
+ dup 0= if
+ \ 2drop
+ -15 throw \ out of memory
+ then
+
+ ( al-size prev addr )
+
+ \ If the smallest fitting block found is bigger than
+ \ the size of the requested block plus 2*cellsize we
+ \ can split the block in 2 parts. otherwise return a
+ \ slightly bigger block than requested.
+
+ dup @ ( d->len ) 3 pick cell+ cell+ > if
+
+ \ splitting the block in 2 pieces.
+ \ new block = old block + len field + size of requested mem
+ dup 3 pick cell+ + ( al-size prev addr nd )
+
+ \ new block len = old block len - req. mem size - 1 cell
+ over @ ( al-size prev addr nd addr->len )
+ 4 pick ( ... al-size )
+ cell+ - ( al-size prev addr nd nd nd->len )
+ over ! ( al-size prev addr nd )
+
+ over cell+ @ ( al-size prev addr nd addr->next )
+ \ write addr->next to nd->next
+ over cell+ ! ( al-size prev addr nd )
+ over 4 pick swap !
+ else
+ \ don't split the block, it's too small.
+ dup cell+ @
+ then
+
+ ( al-size prev addr nd )
+
+ \ If the free block we got is the first one rewrite free-list
+ \ pointer instead of the previous entry's next field.
+ rot dup 0= if drop free-list else cell+ then
+ ( al-size addr nd prev->next|fl )
+ !
+ nip cell+ \ remove al-size and skip len field of returned pointer
+
+ ;
+
+
+\ --------------------------------------------------------------------
+
+\ free block given by addr. The length of the
+\ given block is stored at addr - cellsize.
+\
+\ merge with blocks to the left and right
+\ immediately, if they are free.
+
+: free-mem ( addr len -- )
+
+ \ we define that it is legal to free 0-byte areas
+ 0= if drop exit then
+ ( addr )
+
+ \ check if the address to free is somewhere within
+ \ our available memory. This fails badly on discontigmem
+ \ architectures. If we need more RAM than fits on one
+ \ contiguous memory area we are too bloated anyways. ;)
+
+ dup start-mem @ end-mem @ within 0= if
+ \ ." free-mem: no such memory: 0x" u. cr
+ exit
+ then
+
+ /n - \ get real block address
+ 0 free-list @ ( addr prev l )
+
+ begin \ now scan the free list
+ dup 0<> if \ only check len, if block ptr != 0
+ dup dup @ cell+ + 3 pick <
+ else
+ false
+ then
+ while
+ nip dup \ prev=l
+ cell+ @ \ l=l->next
+ repeat
+
+ ( addr prev l )
+
+ dup 0<> if \ do we have free memory to merge with?
+
+ dup dup @ cell+ + 3 pick = if \ hole hit. adding bytes.
+ \ freeaddr = end of current block -> merge
+ ( addr prev l )
+ rot @ cell+ ( prev l f->len+cellsize )
+ over @ + \ add l->len
+ over ! ( prev l )
+ swap over cell+ @ \ f = l; l = l->next;
+
+ \ The free list is sorted by addresses. When merging at the
+ \ start of our block we might also want to merge at the end
+ \ of it. Therefore we fall through to the next border check
+ \ instead of returning.
+ true \ fallthrough value
+ else
+ false \ no fallthrough
+ then
+ >r \ store fallthrough on ret stack
+
+ ( addr prev l )
+
+ dup 3 pick dup @ cell+ + = if \ hole hit. real merging.
+ \ current block starts where block to free ends.
+ \ end of free block addr = current block -> merge and exit
+ ( addr prev l )
+ 2 pick dup @ ( f f->len )
+ 2 pick @ cell+ + ( f newlen )
+ swap ! ( addr prev l )
+ 3dup drop
+ 0= if
+ free-list
+ else
+ 2 pick cell+
+ then ( value prev->next|free-list )
+ ! ( addr prev l )
+ cell+ @ rot ( prev l->next addr )
+ cell+ ! drop
+ r> drop exit \ clean up return stack
+ then
+
+ r> if 3drop exit then \ fallthrough? -> exit
+ then
+
+ \ loose block - hang it before current.
+
+ ( addr prev l )
+
+ \ hang block to free in front of the current entry.
+ dup 3 pick cell+ ! \ f->next = l;
+ free-list @ = if \ is block to free new list head?
+ over free-list !
+ then
+
+ ( addr prev )
+ dup 0<> if \ if (prev) prev->next=f
+ cell+ !
+ else
+ 2drop \ no fixup needed. clean up.
+ then
+
+ ;
diff --git a/roms/openbios/forth/bootstrap/start.fs b/roms/openbios/forth/bootstrap/start.fs
new file mode 100644
index 00000000..9aabfa2c
--- /dev/null
+++ b/roms/openbios/forth/bootstrap/start.fs
@@ -0,0 +1,69 @@
+\ tag: forth bootstrap starter.
+\
+\ Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+include bootstrap.fs \ all base words
+include interpreter.fs \ interpreter
+include builtin.fs \ builtin terminal.
+
+: include ( >filename<eol> -- )
+ linefeed parse $include
+;
+
+: encode-file ( >filename< > -- dictptr size )
+ parse-word $encode-file
+;
+
+: bye
+ s" Farewell!" cr type cr cr
+ 0 rdepth!
+ ;
+
+\ quit starts the outer interpreter of the forth system.
+\ zech describes quit as being the outer interpreter, but
+\ we split it apart to keep the interpreter elsewhere.
+
+: quit ( -- )
+ 2 rdepth!
+ outer-interpreter
+;
+
+\ initialize is the first forth word run by the kernel.
+\ this word is automatically executed by the C core on start
+\ and it's never left unless something goes really wrong or
+\ the user decides to leave the engine.
+
+variable init-chain
+
+\ :noname <definition> ; initializer
+: initializer ( xt -- )
+ here swap , 0 , \ xt, next
+ init-chain
+ begin dup @ while @ na1+ repeat
+ !
+;
+
+: initialize-forth ( startmem endmem -- )
+ over - init-mem
+ init-pockets
+ init-tmp-comp
+ init-builtin-terminal
+
+ init-chain @ \ execute initializers
+ begin dup while
+ dup @ execute
+ na1+ @
+ repeat
+ drop
+;
+
+\ compiler entrypoint
+: initialize ( startmem endmem -- )
+ initialize-forth
+ s" OpenBIOS kernel started." type cr
+ quit
+;
diff --git a/roms/openbios/forth/build.xml b/roms/openbios/forth/build.xml
new file mode 100644
index 00000000..0d699c93
--- /dev/null
+++ b/roms/openbios/forth/build.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+
+<build>
+ <!-- don't change this order -->
+ <include href="bootstrap/build.xml"/>
+ <include href="lib/build.xml"/>
+ <include href="device/build.xml"/>
+ <include href="debugging/build.xml"/>
+ <include href="admin/build.xml"/>
+ <include href="util/build.xml"/>
+ <include href="packages/build.xml"/>
+ <include href="system/build.xml"/>
+</build>
diff --git a/roms/openbios/forth/debugging/build.xml b/roms/openbios/forth/debugging/build.xml
new file mode 100644
index 00000000..3b9a0ca4
--- /dev/null
+++ b/roms/openbios/forth/debugging/build.xml
@@ -0,0 +1,18 @@
+<build>
+
+ <!--
+ build description for forth debugging command group
+
+ Copyright (C) 2004-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="openbios" target="forth">
+ <object source="client.fs"/>
+ <object source="fcode.fs"/>
+ <object source="firmware.fs"/>
+ <object source="see.fs"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/forth/debugging/client.fs b/roms/openbios/forth/debugging/client.fs
new file mode 100644
index 00000000..f3744044
--- /dev/null
+++ b/roms/openbios/forth/debugging/client.fs
@@ -0,0 +1,299 @@
+\ 7.6 Client Program Debugging command group
+
+
+\ 7.6.1 Registers display
+
+: ctrace ( -- )
+ ;
+
+: .registers ( -- )
+ ;
+
+: .fregisters ( -- )
+ ;
+
+\ to ( param [old-name< >] -- )
+
+
+\ 7.6.2 Program download and execute
+
+struct ( saved-program-state )
+ /n field >sps.entry
+ /n field >sps.file-size
+ /n field >sps.file-type
+constant saved-program-state.size
+create saved-program-state saved-program-state.size allot
+
+variable state-valid
+0 state-valid !
+
+variable file-size
+
+: !load-size file-size ! ;
+
+: load-size file-size @ ;
+
+
+\ File types identified by (init-program)
+
+0 constant elf-boot
+1 constant elf
+2 constant bootinfo
+3 constant xcoff
+4 constant pe
+5 constant aout
+10 constant fcode
+11 constant forth
+12 constant bootcode
+
+
+: init-program ( -- )
+ \ Call down to the lower level for relocation etc.
+ s" (init-program)" $find if
+ execute
+ else
+ s" Unable to locate (init-program)!" type cr
+ then
+ ;
+
+: (find-bootdevice) ( param-str param-len -- bootpath-str bootpath-len)
+ \ Parse the <param> string which is a space-separated list of one or
+ \ more potential boot devices, and return the first one that can be
+ \ successfully opened.
+
+ \ Space-separated bootpath string
+ bl left-split \ bootpathstr bootpathstr-len bootdevstr bootdevstr-len
+ dup 0= if
+
+ \ None specified. As per IEEE-1275 specification, search through each value
+ \ in boot-device and use the first that returns a valid ihandle on open.
+
+ 2drop \ drop the empty device string as we're going to use our own
+
+ s" boot-device" $find drop execute
+ bl left-split
+ begin
+ dup
+ while
+ 2dup s" Trying " type type s" ..." type cr
+ 2dup open-dev ?dup if
+ close-dev
+ 2swap drop 0 \ Fake end of string so we exit loop
+ else
+ 2drop
+ bl left-split
+ then
+ repeat
+ 2drop
+ then
+
+ \ bootargs
+ 2swap dup 0= if
+ \ None specified, use default from nvram
+ 2drop s" boot-file" $find drop execute
+ then
+
+ \ Set the bootargs property
+ encode-string
+ " /chosen" (find-dev) if
+ " bootargs" rot (property)
+ then
+;
+
+\ Locate the boot-device opened by this ihandle (currently taken as being
+\ the first non-interposed package in the instance chain)
+
+: ihandle>boot-device-handle ( ihandle -- 0 | device-ihandle -1 )
+ >r 0
+ begin r> dup >in.my-parent @ dup >r while
+ ( result ihandle R: ihandle.parent )
+ dup >in.interposed @ 0= if
+ \ Find the first non-interposed package
+ over 0= if
+ swap drop
+ else
+ drop
+ then
+ else
+ drop
+ then
+ repeat
+ r> drop drop
+
+ dup 0<> if
+ -1
+ then
+;
+
+: $load ( devstr len )
+ open-dev ( ihandle )
+ dup 0= if
+ drop
+ exit
+ then
+ dup >r
+ " load-base" evaluate swap ( load-base ihandle )
+ dup ihandle>phandle " load" rot find-method ( xt 0|1 )
+ if swap call-package !load-size else cr ." Cannot find load for this package" 2drop then
+
+ \ If the boot device path doesn't contain an explicit partition id, e.g. cd:,\\:tbxi
+ \ then the interposed partition package may have auto-probed a suitable partition. If
+ \ this is the case then it will have set the " selected-partition-args" property in
+ \ the partition package to contain the new device arguments.
+ \
+ \ In order to ensure that bootpath contains the partition argument, we use the contents
+ \ of this property if it exists to override the boot device arguments when generating
+ \ the full bootpath using get-instance-path.
+
+ my-self
+ r@ to my-self
+ " selected-partition-args" get-inherited-property 0= if
+ decode-string 2swap 2drop
+ ( myself-save partargs-str partargs-len )
+ r@ ihandle>boot-device-handle if
+ ( myself-save partargs-str partargs-len block-ihandle )
+ \ Override the arguments before get-instance-path
+ dup >in.arguments 2@ >r >r dup >r ( R: block-ihandle arg-len arg-str )
+ >in.arguments 2! ( myself-save )
+ r@ " get-instance-path" $find if
+ execute ( myself-save bootpathstr bootpathlen )
+ then
+ \ Now write the original arguments back
+ r> r> r> rot >in.arguments 2! ( myself-save bootpathstr bootpathlen R: )
+ rot ( bootpathstr bootpathlen myself-save )
+ then
+ else
+ my-self " get-instance-path" $find if
+ execute ( myself-save bootpathstr pathlen )
+ rot ( bootpathstr bootpathlen myself-save )
+ then
+ then
+ to my-self
+
+ \ Set bootpath property in /chosen
+ encode-string " /chosen" (find-dev) if
+ " bootpath" rot (property)
+ then
+
+ r> close-dev
+ init-program
+ ;
+
+: load ( "{params}<cr>" -- )
+ linefeed parse
+ (find-bootdevice)
+ $load
+;
+
+: dir ( "{paths}<cr>" -- )
+ linefeed parse
+ ascii , split-after
+ 2dup open-dev dup 0= if
+ drop
+ cr ." Unable to locate device " type
+ 2drop
+ exit
+ then
+ -rot 2drop -rot 2 pick
+ " dir" rot ['] $call-method catch
+ if
+ 3drop
+ cr ." Cannot find dir for this package"
+ then
+ close-dev
+;
+
+: go ( -- )
+ state-valid @ not if
+ s" No valid state has been set by load or init-program" type cr
+ exit
+ then
+
+ \ Call the architecture-specific code to launch the client image
+ s" (go)" $find if
+ execute
+ else
+ ." go is not yet implemented"
+ 2drop
+ then
+ ;
+
+
+\ 7.6.3 Abort and resume
+
+\ already defined !?
+\ : go ( -- )
+\ ;
+
+
+\ 7.6.4 Disassembler
+
+: dis ( addr -- )
+ ;
+
+: +dis ( -- )
+ ;
+
+\ 7.6.5 Breakpoints
+: .bp ( -- )
+ ;
+
+: +bp ( addr -- )
+ ;
+
+: -bp ( addr -- )
+ ;
+
+: --bp ( -- )
+ ;
+
+: bpoff ( -- )
+ ;
+
+: step ( -- )
+ ;
+
+: steps ( n -- )
+ ;
+
+: hop ( -- )
+ ;
+
+: hops ( n -- )
+ ;
+
+\ already defined
+\ : go ( -- )
+\ ;
+
+: gos ( n -- )
+ ;
+
+: till ( addr -- )
+ ;
+
+: return ( -- )
+ ;
+
+: .breakpoint ( -- )
+ ;
+
+: .step ( -- )
+ ;
+
+: .instruction ( -- )
+ ;
+
+
+\ 7.6.6 Symbolic debugging
+: .adr ( addr -- )
+ ;
+
+: sym ( "name< >" -- n )
+ ;
+
+: sym>value ( addr len -- addr len false | n true )
+ ;
+
+: value>sym ( n1 -- n1 false | n2 addr len true )
+ ;
diff --git a/roms/openbios/forth/debugging/fcode.fs b/roms/openbios/forth/debugging/fcode.fs
new file mode 100644
index 00000000..76099558
--- /dev/null
+++ b/roms/openbios/forth/debugging/fcode.fs
@@ -0,0 +1,14 @@
+\ 7.7 FCode Debugging command group
+
+\ The user interface versions of these FCode functions allow
+\ the user to debug FCode programs by providing named commands
+\ corresponding to FCode functions.
+
+: headerless ( -- )
+ ;
+
+: headers ( -- )
+ ;
+
+: apply ( ... "method-name< >device-specifier< >" -- ??? )
+ ;
diff --git a/roms/openbios/forth/debugging/firmware.fs b/roms/openbios/forth/debugging/firmware.fs
new file mode 100644
index 00000000..5e16a6c5
--- /dev/null
+++ b/roms/openbios/forth/debugging/firmware.fs
@@ -0,0 +1,90 @@
+\ 7.5 Firmware Debugging command group
+
+
+\ 7.5.1 Automatic stack display
+
+: (.s
+ depth 0 ?do
+ depth i - 1- pick .
+ loop
+ depth 0<> if ascii < emit space then
+ ;
+
+: showstack ( -- )
+ ['] (.s to status
+ ;
+
+: noshowstack ( -- )
+ ['] noop to status
+ ;
+
+\ 7.5.2 Serial download
+
+: dl ( -- )
+ ;
+
+
+\ 7.5.3 Dictionary
+
+\ 7.5.3.1 Dictionary search
+: .calls ( xt -- )
+ ;
+
+: $sift ( text-addr text-len -- )
+ ;
+
+: sifting ( "text< >" -- )
+ ;
+
+\ : words ( -- )
+\ \ Implemented in forth bootstrap.
+\ ;
+
+
+\ 7.5.3.2 Decompiler
+
+\ implemented in see.fs
+
+\ : see ( "old-name< >" -- )
+\ ;
+
+\ : (see) ( xt -- )
+\ ;
+
+
+\ 7.5.3.3 Patch
+
+: patch ( "new-name< >old-name< >word-to-patch< >" -- )
+ ;
+
+: (patch) ( new-n1 num1? old-n2 num2? xt -- )
+ ;
+
+
+\ 7.5.3.4 Forth source-level debugger
+
+: debug ( "old-name< >" -- )
+ parse-word \ Look up word CFA in dictionary
+ $find
+ 0 = if
+ ." could not locate word for debugging"
+ 2drop
+ else
+ (debug
+ then
+ ;
+
+: stepping ( -- )
+ ;
+
+: tracing ( -- )
+ ;
+
+: debug-off ( -- )
+ (debug-off)
+ ;
+
+: resume ( -- )
+ \ Set interpreter termination flag
+ 1 to terminate?
+ ;
diff --git a/roms/openbios/forth/debugging/see.fs b/roms/openbios/forth/debugging/see.fs
new file mode 100644
index 00000000..6977d29e
--- /dev/null
+++ b/roms/openbios/forth/debugging/see.fs
@@ -0,0 +1,114 @@
+\ tag: Forth Decompiler
+\
+\ this code implements IEEE 1275-1994 ch. 7.5.3.2
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+1 value (see-indent)
+
+: (see-cr)
+ cr (see-indent) spaces
+ ;
+
+: indent+
+ (see-indent) 2+ to (see-indent)
+ ;
+
+: indent-
+ (see-indent) 2- to (see-indent)
+ ;
+
+: (see-colon)
+ dup ." : " cell - lfa2name type (see-cr)
+ begin
+ cell+ dup @ dup ['] (semis) <>
+ while
+ space
+ dup
+ case
+
+ ['] do?branch of
+ ." if" (see-cr) indent+
+ drop cell+
+ endof
+
+ ['] dobranch of
+ ." then" indent- (see-cr)
+ drop cell+
+ endof
+
+ ['] (begin) of
+ ." begin" indent+ (see-cr)
+ drop
+ endof
+
+ ['] (again) of
+ ." again" (see-cr)
+ drop
+ endof
+
+ ['] (until) of
+ ." until" (see-cr)
+ drop
+ endof
+
+ ['] (while) of
+ indent- (see-cr)
+ ." while"
+ indent+ (see-cr)
+ drop 2 cells +
+ endof
+
+ ['] (repeat) of
+ indent- (see-cr)
+ ." repeat"
+ (see-cr)
+ drop 2 cells +
+ endof
+
+ ['] (lit) of
+ ." ( lit ) h# "
+ drop 1 cells +
+ dup @ u.
+ endof
+
+ ['] (") of
+ 22 emit space drop dup cell+ @
+ 2dup swap 2 cells + swap type
+ 22 emit
+ + aligned cell+
+ endof
+
+ cell - lfa2name type
+ endcase
+ repeat
+ cr ." ;"
+ 2drop
+ ;
+
+: (see) ( xt -- )
+ cr
+ dup @ case
+ 1 of
+ (see-colon)
+ endof
+ 3 of
+ ." constant " dup cell - lfa2name type ." = " execute .
+ endof
+ 4 of
+ ." variable " dup cell - lfa2name type ." = " execute @ .
+ endof
+ 5 of
+ ." defer " dup cell - lfa2name type cr
+ ." is " cell+ @ cell - lfa2name type cr
+ endof
+ ." primword " swap cell - lfa2name type
+ endcase
+ cr
+ ;
+
+: see ' (see) ;
diff --git a/roms/openbios/forth/device/README.device b/roms/openbios/forth/device/README.device
new file mode 100644
index 00000000..0d4d6e58
--- /dev/null
+++ b/roms/openbios/forth/device/README.device
@@ -0,0 +1,22 @@
+The code you find here implements the IEEE 1275-1994 Open Firmware
+device interface.
+
+Chapter File Comment
+<none> structures.fs generic structures used by 5.3
+5.3.2 <none> defined in user interface
+5.3.3 fcode.fs complete, partly untested
+5.3.4 package.fs incomplete
+5.3.5 property.fs incomplete
+5.3.6 display.fs incomplete
+5.3.7 other.fs incomplete
+
+H2 and
+5.3.1.1.1 preof.fs pre-IEEE-1275-1994 words
+ split.fs
+ pathres.fs path resolution
+
+ table.fs fcode evaluator
+ feval.fs (byte-load)
+
+
+2003/11/12 Stefan Reinauer <stepan@openbios.org>
diff --git a/roms/openbios/forth/device/build.xml b/roms/openbios/forth/device/build.xml
new file mode 100644
index 00000000..11544964
--- /dev/null
+++ b/roms/openbios/forth/device/build.xml
@@ -0,0 +1,31 @@
+<build>
+
+ <!--
+ build description for open firmware device interface
+
+ Copyright (C) 2004-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="openbios" target="forth">
+ <object source="structures.fs"/>
+ <object source="fcode.fs"/>
+ <object source="property.fs"/>
+ <object source="device.fs"/>
+ <object source="package.fs"/>
+ <object source="other.fs"/>
+ <object source="pathres.fs"/>
+ <object source="preof.fs"/>
+ <object source="font.fs"/>
+ <object source="logo.fs"/>
+ <object source="display.fs"/>
+ <object source="terminal.fs"/>
+ <object source="extra.fs"/>
+ <object source="feval.fs"/>
+ <object source="table.fs"/>
+ <object source="tree.fs"/>
+ <object source="builtin.fs"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/forth/device/builtin.fs b/roms/openbios/forth/device/builtin.fs
new file mode 100644
index 00000000..aaefba87
--- /dev/null
+++ b/roms/openbios/forth/device/builtin.fs
@@ -0,0 +1,30 @@
+\ tag: builtin devices
+\
+\ this code implements IEEE 1275-1994
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ nodes it's children:
+
+" /" find-device
+
+new-device
+ " builtin" device-name
+ : open true ;
+ : close ;
+
+new-device
+ " console" device-name
+ : open true ;
+ : close ;
+ : write dup >r bounds ?do i c@ (emit) loop r> ;
+ : read dup >r bounds ?do (key) i c! loop r> ;
+finish-device
+
+\ clean up afterwards
+finish-device
+0 active-package!
diff --git a/roms/openbios/forth/device/device.fs b/roms/openbios/forth/device/device.fs
new file mode 100644
index 00000000..562c9196
--- /dev/null
+++ b/roms/openbios/forth/device/device.fs
@@ -0,0 +1,202 @@
+\ tag: Package creation and deletion
+\
+\ this code implements IEEE 1275-1994
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+variable device-tree
+
+\ make defined words globally visible
+\
+: external ( -- )
+ active-package ?dup if
+ >dn.methods @ set-current
+ then
+;
+
+\ make the private wordlist active (not an OF word)
+\
+: private ( -- )
+ active-package ?dup if
+ >r
+ forth-wordlist r@ >dn.methods @ r@ >dn.priv-methods @ 3 set-order
+ r> >dn.priv-methods @ set-current
+ then
+;
+
+\ set activate package and make the world visible package wordlist
+\ the current one.
+\
+: active-package! ( phandle -- )
+ dup to active-package
+ \ locally defined words are not available
+ ?dup if
+ forth-wordlist over >dn.methods @ 2 set-order
+ >dn.methods @ set-current
+ else
+ forth-wordlist dup 1 set-order set-current
+ then
+;
+
+
+\ new-device ( -- )
+\
+\ Start new package, as child of active package.
+\ Create a new device node as a child of the active package and make the
+\ new node the active package. Create a new instance and make it the current
+\ instance; the instance that invoked new-device becomes the parent instance
+\ of the new instance.
+\ Subsequently, newly defined Forth words become the methods of the new node
+\ and newly defined data items (such as types variable, value, buffer:, and
+\ defer) are allocated and stored within the new instance.
+
+: new-device ( -- )
+ align-tree dev-node.size alloc-tree >r
+ active-package
+ dup r@ >dn.parent !
+
+ \ ( parent ) hook up at the end of the peer list
+ ?dup if
+ >dn.child
+ begin dup @ while @ >dn.peer repeat
+ r@ swap !
+ else
+ \ we are the root node!
+ r@ to device-tree
+ then
+
+ \ ( -- ) fill in device node stuff
+ inst-node.size r@ >dn.isize !
+
+ \ create two wordlists
+ wordlist r@ >dn.methods !
+ wordlist r@ >dn.priv-methods !
+
+ \ initialize template data
+ r@ >dn.itemplate
+ r@ over >in.device-node !
+ my-self over >in.my-parent !
+
+ \ make it the active package and current instance
+ to my-self
+ r@ active-package!
+
+ \ swtich to public wordlist
+ external
+ r> drop
+;
+
+\ helpers for finish-device (OF does not actually define words
+\ for device node deletion)
+
+: (delete-device) \ ( phandle )
+ >r
+ r@ >dn.parent @
+ ?dup if
+ >dn.child \ ( &first-child )
+ begin dup @ r@ <> while @ >dn.peer repeat
+ r@ >dn.peer @ swap !
+ else
+ \ root node
+ 0 to device-tree
+ then
+
+ \ XXX: free any memory related to this node.
+ \ we could have a list with free device-node headers...
+ r> drop
+;
+
+: delete-device \ ( phandle )
+ >r
+ \ first, get rid of any children
+ begin r@ >dn.child @ dup while
+ (delete-device)
+ repeat
+ drop
+
+ \ then free this node
+ r> (delete-device)
+;
+
+\ finish-device ( -- )
+\
+\ Finish this package, set active package to parent.
+\ Complete a device node that was created by new-device, as follows: If the
+\ device node has no "name" property, remove the device node from the device
+\ tree. Otherwise, save the current values of the current instance's
+\ initialized data items within the active package for later use in
+\ initializing the data items of instances created from that node. In any
+\ case, destroy the current instance, make its parent instance the current
+\ instance, and select the parent node of the device node just completed,
+\ making the parent node the active package again.
+
+: finish-device \ ( -- )
+ my-self
+ dup >in.device-node @ >r
+ >in.my-parent @ to my-self
+
+ ( -- )
+ r@ >dn.parent @ active-package!
+ s" name" r@ get-package-property if
+ \ delete the node (and any children)
+ r@ delete-device
+ else
+ 2drop
+ \ node OK
+ then
+ r> drop
+;
+
+
+\ helper function which creates and initializes an instance.
+\ open is not called. The current instance is not changed.
+\
+: create-instance ( phandle -- ihandle|0 )
+ dup >dn.isize @ ['] alloc-mem catch if 2drop 0 exit then
+ >r
+ \ we need to save the size in order to be able to release it properly
+ dup >dn.isize @ r@ >in.alloced-size !
+
+ \ clear memory (we only need to clear the head; all other data is copied)
+ r@ inst-node.size 0 fill
+
+ ( phandle R: ihandle )
+
+ \ instantiate data
+ dup >dn.methods @ r@ instance-init
+ dup >dn.priv-methods @ r@ instance-init
+
+ \ instantiate
+ dup >dn.itemplate r@ inst-node.size move
+ r@ r@ >in.instance-data !
+ my-self r@ >in.my-parent !
+ drop
+
+ r>
+;
+
+\ helper function which tears down and frees an instance
+: destroy-instance ( ihandle )
+ ?dup if
+ \ free arguments
+ dup >in.arguments 2@ free-mem
+ \ and the instance block
+ dup >in.alloced-size @
+ free-mem
+ then
+;
+
+\ Redefine to word so that statements of the form "0 to active-package"
+\ are supported for bootloaders that require it
+: to
+ ['] ' execute
+ dup ['] active-package = if
+ drop active-package!
+ else
+ (to-xt)
+ then
+; immediate
diff --git a/roms/openbios/forth/device/display.fs b/roms/openbios/forth/device/display.fs
new file mode 100644
index 00000000..fff44e00
--- /dev/null
+++ b/roms/openbios/forth/device/display.fs
@@ -0,0 +1,421 @@
+\ tag: Display device management
+\
+\ this code implements IEEE 1275-1994 ch. 5.3.6
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+hex
+
+\
+\ 5.3.6.1 Terminal emulator routines
+\
+
+\ The following values are used and set by the terminal emulator
+\ defined and described in 3.8.4.2
+0 value line# ( -- line# )
+0 value column# ( -- column# )
+0 value inverse? ( -- white-on-black? )
+0 value inverse-screen? ( -- black? )
+0 value #lines ( -- rows )
+0 value #columns ( -- columns )
+
+\ The following values are used internally by both the 1-bit and the
+\ 8-bit frame-buffer support routines.
+
+0 value frame-buffer-adr ( -- addr )
+0 value screen-height ( -- height )
+0 value screen-width ( -- width )
+0 value window-top ( -- border-height )
+0 value window-left ( -- border-width )
+0 value char-height ( -- height )
+0 value char-width ( -- width )
+0 value fontbytes ( -- bytes )
+
+\ these values are used internally and do not represent any
+\ official open firmware words
+0 value char-min
+0 value char-num
+0 value font
+
+0 value foreground-color
+0 value background-color
+create color-palette 100 cells allot
+
+2 value font-spacing
+0 value depth-bits
+0 value line-bytes
+0 value display-ih
+
+\ internal values
+0 value openbios-video-height
+0 value openbios-video-width
+
+\ The following wordset is called the "defer word interface" of the
+\ terminal-emulator support package. It gets overloaded by fb1-install
+\ or fb8-install (initiated by the framebuffer fcode driver)
+
+defer draw-character ( char -- )
+defer reset-screen ( -- )
+defer toggle-cursor ( -- )
+defer erase-screen ( -- )
+defer blink-screen ( -- )
+defer invert-screen ( -- )
+defer insert-characters ( n -- )
+defer delete-characters ( n -- )
+defer insert-lines ( n -- )
+defer delete-lines ( n -- )
+defer draw-logo ( line# addr width height -- )
+
+defer fb-emit ( x -- )
+
+: depth-bytes ( -- bytes )
+ depth-bits 1+ 8 /
+;
+
+\
+\ 5.3.6.2 Frame-buffer support routines
+\
+
+: default-font ( -- addr width height advance min-char #glyphs )
+ (romfont) (romfont-width) (romfont-height) (romfont-height) 0 100
+ ;
+
+: set-font ( addr width height advance min-char #glyphs -- )
+ to char-num
+ to char-min
+ to fontbytes
+ font-spacing + to char-height
+ to char-width
+ to font
+ ;
+
+: >font ( char -- addr )
+ char-min -
+ char-num min
+ fontbytes *
+ font +
+ ;
+
+\
+\ 5.3.6.3 Display device support
+\
+
+\
+\ 5.3.6.3.1 Frame-buffer package interface
+\
+
+: is-install ( xt -- )
+ external
+ \ Create open and other methods for this display device.
+ \ Methods to be created: open, write, draw-logo, restore
+ s" open" header
+ 1 , \ colon definition
+ ,
+ ['] (lit) ,
+ -1 ,
+ ['] (semis) ,
+ reveal
+ s" : write dup >r bounds do i c@ fb-emit loop r> ; " evaluate
+ s" : draw-logo draw-logo ; " evaluate
+ s" : restore reset-screen ; " evaluate
+ ;
+
+: is-remove ( xt -- )
+ external
+ \ Create close method for this display device.
+ s" close" header
+ 1 , \ colon definition
+ ,
+ ['] (semis) ,
+ reveal
+ ;
+
+: is-selftest ( xt -- )
+ external
+ \ Create selftest method for this display device.
+ s" selftest" header
+ 1 , \ colon definition
+ ,
+ ['] (semis) ,
+ reveal
+ ;
+
+
+\ 5.3.6.3.2 Generic one-bit frame-buffer support (optional)
+
+: fb1-nonimplemented
+ ." Monochrome framebuffer support is not implemented." cr
+ end0
+ ;
+
+: fb1-draw-character fb1-nonimplemented ; \ historical
+: fb1-reset-screen fb1-nonimplemented ;
+: fb1-toggle-cursor fb1-nonimplemented ;
+: fb1-erase-screen fb1-nonimplemented ;
+: fb1-blink-screen fb1-nonimplemented ;
+: fb1-invert-screen fb1-nonimplemented ;
+: fb1-insert-characters fb1-nonimplemented ;
+: fb1-delete-characters fb1-nonimplemented ;
+: fb1-insert-lines fb1-nonimplemented ;
+: fb1-delete-lines fb1-nonimplemented ;
+: fb1-slide-up fb1-nonimplemented ;
+: fb1-draw-logo fb1-nonimplemented ;
+: fb1-install fb1-nonimplemented ;
+
+
+\ 5.3.6.3.3 Generic eight-bit frame-buffer support
+
+\ bind to low-level C function later
+defer fb8-blitmask
+defer fb8-fillrect
+defer fb8-invertrect
+
+: fb8-line2addr ( line -- addr )
+ window-top +
+ screen-width * depth-bytes *
+ frame-buffer-adr +
+ window-left depth-bytes * +
+;
+
+: fb8-curpos2addr ( col line -- addr )
+ char-height * fb8-line2addr
+ swap char-width * depth-bytes * +
+;
+
+: fb8-copy-lines ( count from to -- )
+ fb8-line2addr swap
+ fb8-line2addr swap
+ #columns char-width * depth-bytes *
+ 3 pick * move drop
+;
+
+: fb8-clear-lines ( count line -- )
+ background-color 0
+ 2 pick window-top +
+ #columns char-width *
+ 5 pick
+ fb8-fillrect
+ 2drop
+;
+
+: fb8-draw-character ( char -- )
+ \ erase the current character
+ background-color
+ column# char-width * window-left +
+ line# char-height * window-top +
+ char-width char-height fb8-fillrect
+ \ draw the character:
+ >font
+ line# char-height * window-top + screen-width * depth-bytes *
+ column# char-width * depth-bytes *
+ window-left depth-bytes * + + frame-buffer-adr +
+ swap char-width char-height font-spacing -
+ \ normal or inverse?
+ foreground-color background-color
+ inverse? if
+ swap
+ then
+ fb8-blitmask
+ ;
+
+: fb8-reset-screen ( -- )
+ false to inverse?
+ false to inverse-screen?
+ 0 to foreground-color
+ d# 15 to background-color
+
+ \ override with OpenBIOS defaults
+ fe to background-color
+ 0 to foreground-color
+ ;
+
+: fb8-toggle-cursor ( -- )
+ column# char-width * window-left +
+ line# char-height * window-top +
+ char-width char-height font-spacing -
+ foreground-color background-color
+ fb8-invertrect
+ ;
+
+: fb8-erase-screen ( -- )
+ inverse-screen? if
+ foreground-color
+ else
+ background-color
+ then
+ 0 0 screen-width screen-height
+ fb8-fillrect
+ ;
+
+: fb8-invert-screen ( -- )
+ 0 0 screen-width screen-height
+ background-color foreground-color
+ fb8-invertrect
+ ;
+
+: fb8-blink-screen ( -- )
+ fb8-invert-screen 2000 ms
+ fb8-invert-screen
+ ;
+
+: fb8-insert-characters ( n -- )
+ \ numcopy = ( #columns - column# - n )
+ #columns over - column# -
+ char-width * depth-bytes * ( n numbytescopy )
+
+ over column# + line# fb8-curpos2addr
+ column# line# fb8-curpos2addr ( n numbytescopy destaddr srcaddr )
+ char-height 0 do
+ 3dup swap rot move
+ line-bytes + swap line-bytes + swap
+ loop 3drop
+
+ background-color
+ column# char-width * window-left + line# char-height * window-top +
+ 3 pick char-width * char-height
+ fb8-fillrect
+ drop
+ ;
+
+: fb8-delete-characters ( n -- )
+ \ numcopy = ( #columns - column# - n )
+ #columns over - column# -
+ char-width * depth-bytes * ( n numbytescopy )
+
+ over column# + line# fb8-curpos2addr
+ column# line# fb8-curpos2addr swap ( n numbytescopy destaddr srcaddr )
+ char-height 0 do
+ 3dup swap rot move
+ line-bytes + swap line-bytes + swap
+ loop 3drop
+
+ background-color
+ over #columns swap - char-width * window-left + line# char-height * window-top +
+ 3 pick char-width * char-height
+ fb8-fillrect
+ drop
+ ;
+
+: fb8-insert-lines ( n -- )
+ \ numcopy = ( #lines - n )
+ #lines over - char-height *
+ over line# char-height *
+ swap char-height * over +
+ fb8-copy-lines
+
+ char-height * line# char-height *
+ fb8-clear-lines
+ ;
+
+: fb8-delete-lines ( n -- )
+ \ numcopy = ( #lines - ( line# + n )) * char-height
+ #lines over line# + - char-height *
+ over line# + char-height *
+ line# char-height *
+ fb8-copy-lines
+
+ #lines over - char-height *
+ dup #lines char-height * swap - swap
+ fb8-clear-lines
+ drop
+;
+
+
+: fb8-draw-logo ( line# addr width height -- )
+ 2swap swap
+ char-height * window-top +
+ screen-width * window-left +
+ frame-buffer-adr +
+ swap 2swap
+ \ in-fb-start-adr logo-adr logo-width logo-height
+
+ fb8-blitmask ( fbaddr mask-addr width height -- )
+;
+
+
+: fb8-install ( width height #columns #lines -- )
+
+ \ set state variables
+ to #lines
+ to #columns
+ to screen-height
+ to screen-width
+
+ screen-width #columns char-width * - 2/ to window-left
+ screen-height #lines char-height * - 2/ to window-top
+
+ 0 to column#
+ 0 to line#
+ 0 to inverse?
+ 0 to inverse-screen?
+
+ my-self to display-ih
+
+ \ set /chosen display property
+ my-self active-package 0 to my-self
+ " /chosen" (find-dev) 0<> if
+ active-package!
+ display-ih encode-int " display" property
+ then
+ active-package! to my-self
+
+ \ set defer functions to 8bit versions
+
+ ['] fb8-draw-character to draw-character
+ ['] fb8-toggle-cursor to toggle-cursor
+ ['] fb8-erase-screen to erase-screen
+ ['] fb8-blink-screen to blink-screen
+ ['] fb8-invert-screen to invert-screen
+ ['] fb8-insert-characters to insert-characters
+ ['] fb8-delete-characters to delete-characters
+ ['] fb8-insert-lines to insert-lines
+ ['] fb8-delete-lines to delete-lines
+ ['] fb8-draw-logo to draw-logo
+ ['] fb8-reset-screen to reset-screen
+
+ \ recommended practice
+ s" iso6429-1983-colors" get-my-property if
+ 0 ff
+ else
+ 2drop d# 15 0
+ then
+ to foreground-color to background-color
+
+ \ setup palette
+ 10101 ['] color-palette cell+ ff 0 do
+ dup 2 pick i * swap ! cell+
+ loop 2drop
+
+ \ special background color
+ ffffcc ['] color-palette cell+ fe cells + !
+
+ \ load palette onto the hardware
+ ['] color-palette cell+ ff 0 do
+ dup @ ff0000 and d# 16 rshift
+ 1 pick @ ff00 and d# 8 rshift
+ 2 pick @ ff and
+ i
+ s" color!" $find if
+ execute
+ else
+ 2drop
+ then
+ cell+
+ loop drop
+
+ \ ... but let's override with some better defaults
+ fe to background-color
+ 0 to foreground-color
+
+ fb8-erase-screen
+
+ \ If we have a startup splash then display it
+ [IFDEF] CONFIG_MOL
+ mol-startup-splash 2000 ms
+ fb8-erase-screen
+ [THEN]
+;
diff --git a/roms/openbios/forth/device/extra.fs b/roms/openbios/forth/device/extra.fs
new file mode 100644
index 00000000..9ca6b78e
--- /dev/null
+++ b/roms/openbios/forth/device/extra.fs
@@ -0,0 +1,103 @@
+\ tag: Useful device related functions
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+
+: parent ( phandle -- parent.phandle|0 )
+ >dn.parent @
+;
+
+\ -------------------------------------------------------------------
+\ property helpers
+\ -------------------------------------------------------------------
+
+: int-property ( value name-str name-len -- )
+ rot encode-int 2swap property
+;
+
+\ -------------------------------------------------------------------------
+\ property utils
+\ -------------------------------------------------------------------------
+
+\ like property (except it takes a phandle as an argument)
+: encode-property ( buf len propname propname-len phandle -- )
+ dup 0= abort" null phandle"
+
+ my-self >r 0 to my-self
+ active-package >r active-package!
+
+ property
+
+ r> active-package!
+ r> to my-self
+;
+
+\ -------------------------------------------------------------------
+\ device tree iteration
+\ -------------------------------------------------------------------
+
+: iterate-tree ( phandle -- phandle|0 )
+ ?dup 0= if device-tree @ exit then
+
+ \ children first
+ dup child if
+ child exit
+ then
+
+ \ then peers
+ dup peer if
+ peer exit
+ then
+
+ \ then peer of a parent
+ begin >dn.parent @ dup while
+ dup peer if peer exit then
+ repeat
+;
+
+: iterate-tree-begin ( -- first_node )
+ device-tree @
+;
+
+
+\ -------------------------------------------------------------------
+\ device tree iteration
+\ -------------------------------------------------------------------
+
+: iterate-device-type ( lastph|0 type-str type-len -- 0|nextph )
+ rot
+ begin iterate-tree ?dup while
+ >r
+ 2dup " device_type" r@ get-package-property if 0 0 then
+ dup 0> if 1- then
+ strcmp 0= if 2drop r> exit then
+ r>
+ repeat
+ 2drop 0
+;
+
+\ -------------------------------------------------------------------
+\ device tree "cut and paste"
+\ -------------------------------------------------------------------
+
+\ add a subtree to the current device node
+: link-nodes ( phandle -- )
+ \ reparent phandle and peers
+ dup begin ?dup while
+ dup >dn.parent active-package !
+ >dn.peer @
+ repeat
+
+ \ add to list of children
+ active-package >dn.child
+ begin dup @ while @ >dn.peer repeat dup . !
+;
+
+: link-node ( phandle -- )
+ 0 over >dn.peer !
+ link-nodes
+;
diff --git a/roms/openbios/forth/device/fcode.fs b/roms/openbios/forth/device/fcode.fs
new file mode 100644
index 00000000..9083ed0e
--- /dev/null
+++ b/roms/openbios/forth/device/fcode.fs
@@ -0,0 +1,573 @@
+\ tag: FCode implementation functions
+\
+\ this code implements IEEE 1275-1994 ch. 5.3.3
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+hex
+
+0 value fcode-sys-table \ table with built-in fcodes (0-0x7ff)
+
+true value ?fcode-offset16 \ fcode offsets are 16 instead of 8 bit?
+1 value fcode-spread \ fcode spread (1, 2 or 4)
+0 value fcode-table \ pointer to fcode table
+false value ?fcode-verbose \ do verbose fcode execution?
+
+defer _fcode-debug? \ If true, save names for FCodes with headers
+true value fcode-headers? \ If true, possibly save names for FCodes.
+
+0 value fcode-stream-start \ start address of fcode stream
+0 value fcode-stream \ current fcode stream address
+
+variable fcode-end \ state variable, if true, fcode program terminates.
+defer fcode-c@ \ get byte
+
+: fcode-push-state ( -- <state information> )
+ ?fcode-offset16
+ fcode-spread
+ fcode-table
+ fcode-headers?
+ fcode-stream-start
+ fcode-stream
+ fcode-end @
+ ['] fcode-c@ behavior
+;
+
+: fcode-pop-state ( <state information> -- )
+ to fcode-c@
+ fcode-end !
+ to fcode-stream
+ to fcode-stream-start
+ to fcode-headers?
+ to fcode-table
+ to fcode-spread
+ to ?fcode-offset16
+;
+
+\
+\ fcode access helper functions
+\
+
+\ fcode-ptr
+\ convert FCode number to pointer to xt in FCode table.
+
+: fcode-ptr ( u16 -- *xt )
+ cells
+ fcode-table ?dup if + exit then
+
+ \ we are not parsing fcode at the moment
+ dup 800 cells u>= abort" User FCODE# referenced."
+ fcode-sys-table +
+;
+
+\ fcode>xt
+\ get xt according to an FCode#
+
+: fcode>xt ( u16 -- xt )
+ fcode-ptr @
+ ;
+
+\ fcode-num8
+\ get 8bit from FCode stream, taking spread into regard.
+
+: fcode-num8 ( -- c ) ( F: c -- )
+ fcode-stream
+ dup fcode-spread + to fcode-stream
+ fcode-c@
+ ;
+
+\ fcode-num8-signed ( -- c ) ( F: c -- )
+\ get 8bit signed from FCode stream
+
+: fcode-num8-signed
+ fcode-num8
+ dup 80 and 0> if
+ ff invert or
+ then
+ ;
+
+\ fcode-num16
+\ get 16bit from FCode stream
+
+: fcode-num16 ( -- num16 )
+ fcode-num8 fcode-num8 swap bwjoin
+ ;
+
+\ fcode-num16-signed ( -- c ) ( F: c -- )
+\ get 16bit signed from FCode stream
+
+: fcode-num16-signed
+ fcode-num16
+ dup 8000 and 0> if
+ ffff invert or
+ then
+ ;
+
+\ fcode-num32
+\ get 32bit from FCode stream
+
+: fcode-num32 ( -- num32 )
+ fcode-num8 fcode-num8
+ fcode-num8 fcode-num8
+ swap 2swap swap bljoin
+ ;
+
+\ fcode#
+\ Get an FCode# from FCode stream
+
+: fcode# ( -- fcode# )
+ fcode-num8
+ dup 1 f between if
+ fcode-num8 swap bwjoin
+ then
+ ;
+
+\ fcode-offset
+\ get offset from FCode stream.
+
+: fcode-offset ( -- offset )
+ ?fcode-offset16 if
+ fcode-num16-signed
+ else
+ fcode-num8-signed
+ then
+
+ \ Display offset in verbose mode
+ ?fcode-verbose if
+ dup ." (offset) " . cr
+ then
+ ;
+
+\ fcode-string
+\ get a string from FCode stream, store in pocket.
+
+: fcode-string ( -- addr len )
+ pocket dup
+ fcode-num8
+ dup rot c!
+ 2dup bounds ?do
+ fcode-num8 i c!
+ loop
+
+ \ Display string in verbose mode
+ ?fcode-verbose if
+ 2dup ." (const) " type cr
+ then
+ ;
+
+\ fcode-header
+\ retrieve FCode header from FCode stream
+
+: fcode-header
+ fcode-num8
+ fcode-num16
+ fcode-num32
+ ?fcode-verbose if
+ ." Found FCode header:" cr rot
+ ." Format : " u. cr swap
+ ." Checksum : " u. cr
+ ." Length : " u. cr
+ else
+ 3drop
+ then
+ \ TODO checksum
+ ;
+
+\ writes currently created word as fcode# read from stream
+\
+
+: fcode! ( F:FCode# -- )
+ here fcode#
+
+ \ Display fcode# in verbose mode
+ ?fcode-verbose if
+ dup ." (fcode#) " . cr
+ then
+ fcode-ptr !
+ ;
+
+
+\
+\ 5.3.3.1 Defining new FCode functions.
+\
+
+\ instance ( -- )
+\ Mark next defining word as instance specific.
+\ (defined in bootstrap.fs)
+
+\ instance-init ( wid buffer -- )
+\ Copy template from specified wordlist to instance
+\
+
+: instance-init
+ swap
+ begin @ dup 0<> while
+ dup /n + @ instance-cfa? if \ buffer dict
+ 2dup 2 /n* + @ + \ buffer dict dest
+ over 3 /n* + @ \ buffer dict dest size
+ 2 pick 4 /n* + \ buffer dict dest size src
+ -rot
+ move
+ then
+ repeat
+ 2drop
+ ;
+
+
+\ new-token ( F:/FCode#/ -- )
+\ Create a new unnamed FCode function
+
+: new-token
+ 0 0 header
+ fcode!
+ ;
+
+
+\ named-token (F:FCode-string FCode#/ -- )
+\ Create a new possibly named FCode function.
+
+: named-token
+ fcode-string
+ _fcode-debug? not if
+ 2drop 0 0
+ then
+ header
+ fcode!
+ ;
+
+
+\ external-token (F:/FCode-string FCode#/ -- )
+\ Create a new named FCode function
+
+: external-token
+ fcode-string header
+ fcode!
+ ;
+
+
+\ b(;) ( -- )
+\ End an FCode colon definition.
+
+: b(;)
+ ['] ; execute
+ ; immediate
+
+
+\ b(:) ( -- ) ( E: ... -- ??? )
+\ Defines type of new FCode function as colon definition.
+
+: b(:)
+ 1 , ]
+ ;
+
+
+\ b(buffer:) ( size -- ) ( E: -- a-addr )
+\ Defines type of new FCode function as buffer:.
+
+: b(buffer:)
+ 4 , allot
+ reveal
+ ;
+
+\ b(constant) ( nl -- ) ( E: -- nl )
+\ Defines type of new FCode function as constant.
+
+: b(constant)
+ 3 , ,
+ reveal
+ ;
+
+
+\ b(create) ( -- ) ( E: -- a-addr )
+\ Defines type of new FCode function as create word.
+
+: b(create)
+ 6 ,
+ ['] noop ,
+ reveal
+ ;
+
+
+\ b(defer) ( -- ) ( E: ... -- ??? )
+\ Defines type of new FCode function as defer word.
+
+: b(defer)
+ 5 ,
+ ['] (undefined-defer) ,
+ ['] (semis) ,
+ reveal
+ ;
+
+
+\ b(field) ( offset size -- offset+size ) ( E: addr -- addr+offset )
+\ Defines type of new FCode function as field.
+
+: b(field)
+ 6 ,
+ ['] noop ,
+ reveal
+ over ,
+ +
+ does>
+ @ +
+ ;
+
+
+\ b(value) ( x -- ) (E: -- x )
+\ Defines type of new FCode function as value.
+
+: b(value)
+ 3 , , reveal
+ ;
+
+
+\ b(variable) ( -- ) ( E: -- a-addr )
+\ Defines type of new FCode function as variable.
+
+: b(variable)
+ 4 , 0 ,
+ reveal
+ ;
+
+
+\ (is-user-word) ( name-str name-len xt -- ) ( E: ... -- ??? )
+\ Create a new named user interface command.
+
+: (is-user-word)
+ ;
+
+
+\ get-token ( fcode# -- xt immediate? )
+\ Convert FCode number to function execution token.
+
+: get-token
+ fcode>xt dup immediate?
+ ;
+
+
+\ set-token ( xt immediate? fcode# -- )
+\ Assign FCode number to existing function.
+
+: set-token
+ nip \ TODO we use the xt's immediate state for now.
+ fcode-ptr !
+ ;
+
+
+
+
+\
+\ 5.3.3.2 Literals
+\
+
+
+\ b(lit) ( -- n1 )
+\ Numeric literal FCode. Followed by FCode-num32.
+
+64bit? [IF]
+: b(lit)
+ fcode-num32 32>64
+ state @ if
+ ['] (lit) , ,
+ then
+ ; immediate
+[ELSE]
+: b(lit)
+ fcode-num32
+ state @ if
+ ['] (lit) , ,
+ then
+ ; immediate
+[THEN]
+
+
+\ b(') ( -- xt )
+\ Function literal FCode. Followed by FCode#
+
+: b(')
+ fcode# fcode>xt
+ state @ if
+ ['] (lit) , ,
+ then
+ ; immediate
+
+
+\ b(") ( -- str len )
+\ String literal FCode. Followed by FCode-string.
+
+: b(")
+ fcode-string
+ state @ if
+ \ only run handle-text in compile-mode,
+ \ otherwise we would waste a pocket.
+ handle-text
+ then
+ ; immediate
+
+
+\
+\ 5.3.3.3 Controlling values and defers
+\
+
+\ behavior ( defer-xt -- contents-xt )
+\ defined in bootstrap.fs
+
+\ b(to) ( new-value -- )
+\ FCode for setting values and defers. Followed by FCode#.
+
+: b(to)
+ fcode# fcode>xt
+ 1 handle-lit
+ ['] (to)
+ state @ if
+ ,
+ else
+ execute
+ then
+ ; immediate
+
+
+
+\
+\ 5.3.3.4 Control flow
+\
+
+
+\ offset16 ( -- )
+\ Makes subsequent FCode-offsets use 16-bit (not 8-bit) form.
+
+: offset16
+ true to ?fcode-offset16
+ ;
+
+
+\ bbranch ( -- )
+\ Unconditional branch FCode. Followed by FCode-offset.
+
+: bbranch
+ fcode-offset 0< if \ if we jump backwards, we can forsee where it goes
+ ['] dobranch ,
+ resolve-dest
+ execute-tmp-comp
+ else
+ setup-tmp-comp ['] dobranch ,
+ here 0
+ 0 ,
+ 2swap
+ then
+ ; immediate
+
+
+\ b?branch ( continue? -- )
+\ Conditional branch FCode. Followed by FCode-offset.
+
+: b?branch
+ fcode-offset 0< if \ if we jump backwards, we can forsee where it goes
+ ['] do?branch ,
+ resolve-dest
+ execute-tmp-comp
+ else
+ setup-tmp-comp ['] do?branch ,
+ here 0
+ 0 ,
+ then
+ ; immediate
+
+
+\ b(<mark) ( -- )
+\ Target of backward branches.
+
+: b(<mark)
+ setup-tmp-comp
+ here 1
+ ; immediate
+
+
+\ b(>resolve) ( -- )
+\ Target of forward branches.
+
+: b(>resolve)
+ resolve-orig
+ execute-tmp-comp
+ ; immediate
+
+
+\ b(loop) ( -- )
+\ End FCode do..loop. Followed by FCode-offset.
+
+: b(loop)
+ fcode-offset drop
+ postpone loop
+ ; immediate
+
+
+\ b(+loop) ( delta -- )
+\ End FCode do..+loop. Followed by FCode-offset.
+
+: b(+loop)
+ fcode-offset drop
+ postpone +loop
+ ; immediate
+
+
+\ b(do) ( limit start -- )
+\ Begin FCode do..loop. Followed by FCode-offset.
+
+: b(do)
+ fcode-offset drop
+ postpone do
+ ; immediate
+
+
+\ b(?do) ( limit start -- )
+\ Begin FCode ?do..loop. Followed by FCode-offset.
+
+: b(?do)
+ fcode-offset drop
+ postpone ?do
+ ; immediate
+
+
+\ b(leave) ( -- )
+\ Exit from a do..loop.
+
+: b(leave)
+ postpone leave
+ ; immediate
+
+
+\ b(case) ( sel -- sel )
+\ Begin a case (multiple selection) statement.
+
+: b(case)
+ postpone case
+ ; immediate
+
+
+\ b(endcase) ( sel | <nothing> -- )
+\ End a case (multiple selection) statement.
+
+: b(endcase)
+ postpone endcase
+ ; immediate
+
+
+\ b(of) ( sel of-val -- sel | <nothing> )
+\ FCode for of in case statement. Followed by FCode-offset.
+
+: b(of)
+ fcode-offset drop
+ postpone of
+ ; immediate
+
+\ b(endof) ( -- )
+\ FCode for endof in case statement. Followed by FCode-offset.
+
+: b(endof)
+ fcode-offset drop
+ postpone endof
+ ; immediate
diff --git a/roms/openbios/forth/device/feval.fs b/roms/openbios/forth/device/feval.fs
new file mode 100644
index 00000000..9e2773db
--- /dev/null
+++ b/roms/openbios/forth/device/feval.fs
@@ -0,0 +1,100 @@
+\ tag: FCode evaluator
+\
+\ this code implements an fcode evaluator
+\ as described in IEEE 1275-1994
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+defer init-fcode-table
+
+: alloc-fcode-table
+ 4096 cells alloc-mem to fcode-table
+ ?fcode-verbose if
+ ." fcode-table at 0x" fcode-table . cr
+ then
+ init-fcode-table
+ ;
+
+: free-fcode-table
+ fcode-table 4096 cells free-mem
+ 0 to fcode-table
+ ;
+
+: (debug-feval) ( fcode# -- fcode# )
+ \ Address
+ fcode-stream 1 - . ." : "
+
+ \ Indicate if word is compiled
+ state @ 0<> if
+ ." (compile) "
+ then
+ dup fcode>xt cell - lfa2name type
+ dup ." [ 0x" . ." ]" cr
+ ;
+
+: (feval) ( -- ?? )
+ begin
+ fcode#
+ ?fcode-verbose if
+ (debug-feval)
+ then
+ fcode>xt
+ dup flags? 0<> state @ 0= or if
+ execute
+ else
+ ,
+ then
+ fcode-end @ until
+
+ \ If we've executed incorrect FCode we may have reached the end of the FCode
+ \ program but still be in compile mode. Make sure that if this has happened
+ \ then we switch back to immediate mode to prevent internal OpenBIOS errors.
+ tmp-comp-depth @ -1 <> if
+ -1 tmp-comp-depth !
+ tmp-comp-buf @ @ here!
+ 0 state !
+ then
+;
+
+: byte-load ( addr xt -- )
+ ?fcode-verbose if
+ cr ." byte-load: evaluating fcode at 0x" over . cr
+ then
+
+ \ save state
+ >r >r fcode-push-state r> r>
+
+ \ set fcode-c@ defer
+ dup 1 = if drop ['] c@ then \ FIXME: uses c@ rather than rb@ for now...
+ to fcode-c@
+ dup to fcode-stream-start
+ to fcode-stream
+ 1 to fcode-spread
+ false to ?fcode-offset16
+ alloc-fcode-table
+ false fcode-end !
+
+ \ protect against stack overflow/underflow
+ 0 0 0 0 0 0 depth >r
+
+ ['] (feval) catch if
+ cr ." byte-load: exception caught!" cr
+ then
+
+ s" fcode-debug?" evaluate if
+ depth r@ <> if
+ cr ." byte-load: warning stack overflow, diff " depth r@ - . cr
+ then
+ then
+
+ r> depth! 3drop 3drop
+
+ free-fcode-table
+
+ \ restore state
+ fcode-pop-state
+;
diff --git a/roms/openbios/forth/device/font.fs b/roms/openbios/forth/device/font.fs
new file mode 100644
index 00000000..7b742fac
--- /dev/null
+++ b/roms/openbios/forth/device/font.fs
@@ -0,0 +1,17 @@
+\ tag: 8x16 bitmap font
+\
+\ Terminus font
+\
+\ The Terminus Font is developed by and is a property
+\ of Dimitar Toshkov Zhekov <jimmy@is-vn.bg>
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+0 value (romfont)
+0 value (romfont-width)
+0 value (romfont-height)
+
+\ encode-file romfont.bin
+\ drop value (romfont-8x16)
diff --git a/roms/openbios/forth/device/logo.fs b/roms/openbios/forth/device/logo.fs
new file mode 100644
index 00000000..4db31ef5
--- /dev/null
+++ b/roms/openbios/forth/device/logo.fs
@@ -0,0 +1,98 @@
+\ tag: monochrome logo
+\
+\ simple monochrome logo
+\ as described in IEEE 1275-1994
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+
+\ FIXME : This is currently just a test file, it contains
+\ a Pi symbol of size 64x64, not really nicely streched.
+
+\ To use an XBM (X Bitmap), the bits in the bitmap array
+\ have to be reversed, i.e. like this:
+\
+\ int main(void)
+\ {
+\ int i,j; unsigned char bit, bitnew;
+\ for (i=0; i<512; i++) {
+\ bit=openbios_bits[i]; bitnew=0;
+\ for (j=0; j<8; j++)
+\ if (bit & (1<<j)) bitnew |= (1<<(7-j));
+\ printf("%02x c, ", bitnew); if(i%8 == 7) printf("\n");
+\ }
+\ return 0;
+\ }
+
+here
+
+00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c,
+00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c,
+07 c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c,
+07 c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c,
+07 c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c,
+07 c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c,
+7f c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c,
+7f c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c,
+7f c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c,
+7f c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c,
+7f c, df c, ff c, ff c, 7f c, ff c, ff c, 90 c,
+78 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+78 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+78 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+70 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 01 c, 80 c,
+00 c, 03 c, fe c, 00 c, 07 c, f8 c, 01 c, e0 c,
+00 c, 03 c, fe c, 00 c, 07 c, f8 c, 01 c, e0 c,
+00 c, 03 c, fe c, 00 c, 07 c, fc c, 03 c, e0 c,
+00 c, 07 c, fe c, 00 c, 07 c, fc c, 07 c, e0 c,
+00 c, 3f c, fe c, 00 c, 07 c, ff c, ff c, e0 c,
+00 c, 3f c, fe c, 00 c, 07 c, ff c, ff c, e0 c,
+00 c, 3f c, fe c, 00 c, 07 c, ff c, ff c, e0 c,
+00 c, 3f c, fc c, 00 c, 07 c, ff c, ff c, c0 c,
+00 c, 3f c, f8 c, 00 c, 07 c, ff c, ff c, 80 c,
+00 c, 7f c, e0 c, 00 c, 0f c, ff c, fe c, 00 c,
+00 c, 3f c, e0 c, 00 c, 07 c, ff c, fe c, 00 c,
+00 c, 3f c, c0 c, 00 c, 07 c, ff c, fc c, 00 c,
+00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c,
+00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c,
+00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c,
+00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c,
+00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c,
+
+value (romlogo-64x64)
diff --git a/roms/openbios/forth/device/missing b/roms/openbios/forth/device/missing
new file mode 100644
index 00000000..8ea954ed
--- /dev/null
+++ b/roms/openbios/forth/device/missing
@@ -0,0 +1,38 @@
+5.3.3.1
+
+ * (is-user-word)
+
+5.3.4 Package access
+
+5.3.6 Display
+ * default-font
+ * set-font
+ * >font
+ * is-install
+ * is-remove
+ * is-selftest
+
+5.3.7 Other
+ * cpeek
+ * wpeek
+ * lpeek
+ * cpoke
+ * wpoke
+ * lpoke
+ * rb@
+ * rw@
+ * rl@
+ * rb!
+ * rw!
+ * rl!
+ * get-msecs
+ * ms
+ * alarm
+ * user-abort
+ * mac-address
+ * display-status
+ * memory-test-suite
+ * mask
+ * diagnostic-mode?
+ * suspend-fcode
+ * set-args
diff --git a/roms/openbios/forth/device/other.fs b/roms/openbios/forth/device/other.fs
new file mode 100644
index 00000000..b3900730
--- /dev/null
+++ b/roms/openbios/forth/device/other.fs
@@ -0,0 +1,233 @@
+\ tag: Other FCode functions
+\
+\ this code implements IEEE 1275-1994 ch. 5.3.7
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ The current diagnostic setting
+defer _diag-switch?
+
+
+\
+\ 5.3.7 Other FCode functions
+\
+
+hex
+
+\ 5.3.7.1 Peek/poke
+
+defer (peek)
+:noname
+ execute true
+; to (peek)
+
+: cpeek ( addr -- false | byte true )
+ ['] c@ (peek)
+ ;
+
+: wpeek ( waddr -- false | w true )
+ ['] w@ (peek)
+ ;
+
+: lpeek ( qaddr -- false | quad true )
+ ['] l@ (peek)
+ ;
+
+defer (poke)
+:noname
+ execute true
+; to (poke)
+
+: cpoke ( byte addr -- okay? )
+ ['] c! (poke)
+ ;
+
+: wpoke ( w waddr -- okay? )
+ ['] w! (poke)
+ ;
+
+: lpoke ( quad qaddr -- okay? )
+ ['] l! (poke)
+ ;
+
+
+\ 5.3.7.2 Device-register access
+
+: rb@ ( addr -- byte )
+ ;
+
+: rw@ ( waddr -- w )
+ ;
+
+: rl@ ( qaddr -- quad )
+ ;
+
+: rb! ( byte addr -- )
+ ;
+
+: rw! ( w waddr -- )
+ ;
+
+: rl! ( quad qaddr -- )
+ ;
+
+: rx@ ( oaddr - o )
+ state @ if
+ h# 22e get-token if , else execute then
+ else
+ h# 22e get-token drop execute
+ then
+ ; immediate
+
+: rx! ( o oaddr -- )
+ state @ if
+ h# 22f get-token if , else execute then
+ else
+ h# 22f get-token drop execute
+ then
+ ; immediate
+
+\ 5.3.7.3 Time
+
+\ Pointer to OBP tick value updated by timer interrupt
+variable obp-ticks
+
+\ Dummy implementation for platforms without a timer interrupt
+0 value dummy-msecs
+
+: get-msecs ( -- n )
+ \ If obp-ticks pointer is set, use it. Otherwise fall back to
+ \ dummy implementation
+ obp-ticks @ 0<> if
+ obp-ticks @
+ else
+ dummy-msecs dup 1+ to dummy-msecs
+ then
+ ;
+
+: ms ( n -- )
+ get-msecs +
+ begin dup get-msecs < until
+ drop
+ ;
+
+: alarm ( xt n -- )
+ 2drop
+ ;
+
+: user-abort ( ... -- ) ( R: ... -- )
+ ;
+
+
+\ 5.3.7.4 System information
+0003.0000 value fcode-revision ( -- n )
+
+: mac-address ( -- mac-str mac-len )
+ ;
+
+
+\ 5.3.7.5 FCode self-test
+: display-status ( n -- )
+ ;
+
+: memory-test-suite ( addr len -- fail? )
+ ;
+
+: mask ( -- a-addr )
+ ;
+
+: diagnostic-mode? ( -- diag? )
+ \ Return the NVRAM diag-switch? setting
+ _diag-switch?
+ ;
+
+\ 5.3.7.6 Start and end.
+
+\ Begin program with spread 0 followed by FCode-header.
+: start0 ( -- )
+ 0 fcode-spread !
+ offset16
+ fcode-header
+ ;
+
+\ Begin program with spread 1 followed by FCode-header.
+: start1 ( -- )
+ 1 to fcode-spread
+ offset16
+ fcode-header
+ ;
+
+\ Begin program with spread 2 followed by FCode-header.
+: start2 ( -- )
+ 2 to fcode-spread
+ offset16
+ fcode-header
+ ;
+
+\ Begin program with spread 4 followed by FCode-header.
+: start4 ( -- )
+ 4 to fcode-spread
+ offset16
+ fcode-header
+ ;
+
+\ Begin program with spread 1 followed by FCode-header.
+: version1 ( -- )
+ 1 to fcode-spread
+ fcode-header
+ ;
+
+\ Cease evaluating this FCode program.
+: end0 ( -- )
+ true fcode-end !
+ ; immediate
+
+\ Cease evaluating this FCode program.
+: end1 ( -- )
+ end0
+ ;
+
+\ Standard FCode number for undefined FCode functions.
+: ferror ( -- )
+ ." undefined fcode# encountered." cr
+ true fcode-end !
+ ;
+
+\ Pause FCode evaluation if desired; can resume later.
+: suspend-fcode ( -- )
+ \ NOT YET IMPLEMENTED.
+ ;
+
+
+\ Evaluate FCode beginning at location addr.
+
+\ : byte-load ( addr xt -- )
+\ \ this word is implemented in feval.fs
+\ ;
+
+\ Set address and arguments of new device node.
+: set-args ( arg-str arg-len unit-str unit-len -- )
+ ?my-self drop
+
+ depth 1- >r
+ " decode-unit" ['] $call-parent catch if
+ 2drop 2drop
+ then
+
+ my-self ihandle>phandle >dn.probe-addr \ offset
+ begin depth r@ > while
+ dup na1+ >r ! r>
+ repeat
+ r> 2drop
+
+ my-self >in.arguments 2@ free-mem
+ strdup my-self >in.arguments 2!
+;
+
+: dma-alloc
+ s" dma-alloc" $call-parent
+ ;
diff --git a/roms/openbios/forth/device/package.fs b/roms/openbios/forth/device/package.fs
new file mode 100644
index 00000000..d5b52c3e
--- /dev/null
+++ b/roms/openbios/forth/device/package.fs
@@ -0,0 +1,287 @@
+\ tag: Package access.
+\
+\ this code implements IEEE 1275-1994 ch. 5.3.4
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ variable last-package 0 last-package !
+\ 0 value active-package
+: current-device active-package ;
+
+\
+\ 5.3.4.1 Open/Close packages (part 1)
+\
+
+\ 0 value my-self ( -- ihandle )
+: ?my-self
+ my-self dup 0= abort" no current instance."
+ ;
+
+: my-parent ( -- ihandle )
+ ?my-self >in.my-parent @
+;
+
+: ihandle>non-interposed-phandle ( ihandle -- phandle )
+ begin dup >in.interposed @ while
+ >in.my-parent @
+ repeat
+ >in.device-node @
+;
+
+: ihandle>phandle ( ihandle -- phandle )
+ >in.device-node @
+;
+
+
+\ next-property
+\ defined in property.c
+
+: peer ( phandle -- phandle.sibling )
+ ?dup if
+ >dn.peer @
+ else
+ device-tree @
+ then
+;
+
+: child ( phandle.parent -- phandle.child )
+ \ Assume phandle == 0 indicates root node (not documented but similar
+ \ behaviour to "peer"). Used by some versions of Solaris (e.g. 9).
+ ?dup if else device-tree @ then
+
+ >dn.child @
+;
+
+
+\
+\ 5.3.4.2 Call methods from other packages
+\
+
+: find-method ( method-str method-len phandle -- false | xt true )
+ \ should we search the private wordlist too? I don't think so...
+ >dn.methods @ find-wordlist if
+ true
+ else
+ 2drop false
+ then
+;
+
+: call-package ( ... xt ihandle -- ??? )
+ my-self >r
+ to my-self
+ execute
+ r> to my-self
+;
+
+
+: $call-method ( ... method-str method-len ihandle -- ??? )
+ dup >r >in.device-node @ find-method if
+ r> call-package
+ else
+ -21 throw
+ then
+;
+
+: $call-parent ( ... method-str method-len -- ??? )
+ my-parent $call-method
+;
+
+
+\
+\ 5.3.4.1 Open/Close packages (part 2)
+\
+
+\ find-dev ( dev-str dev-len -- false | phandle true )
+\ find-rel-dev ( dev-str dev-len phandle -- false | phandle true )
+\
+\ These function works just like find-device but without
+\ any side effects (or exceptions).
+\
+defer find-dev
+
+: find-rel-dev ( dev-str dev-len phandle -- false | phandle true )
+ active-package >r active-package!
+ find-dev
+ r> active-package!
+;
+
+: find-package ( name-str name-len -- false | phandle true )
+\ Locate the support package named by name string.
+\ If the package can be located, return its phandle and true; otherwise,
+\ return false.
+\ Interpret the name in name string relative to the "packages" device node.
+\ If there are multiple packages with the same name (within the "packages"
+\ node), return the phandle for the most recently created one.
+
+ \ This does the full path resolution stuff (including
+ \ alias expansion. If we don't want that, then we should just
+ \ iterade the children of /packages.
+ " /packages" find-dev 0= if 2drop false exit then
+ find-rel-dev 0= if false exit then
+
+ true
+;
+
+: open-package ( arg-str arg-len phandle -- ihandle | 0 )
+\ Open the package indicated by phandle.
+\ Create an instance of the package identified by phandle, save in that
+\ instance the instance-argument specified by arg-string and invoke the
+\ package's open method.
+\ Return the instance handle ihandle of the new instance, or 0 if the package
+\ could not be opened. This could occur either because that package has no
+\ open method, or because its open method returned false, indicating an error.
+\ The parent instance of the new instance is the instance that invoked
+\ open-package. The current instance is not changed.
+
+ create-instance dup 0= if
+ 3drop 0 exit
+ then
+ >r
+
+ \ clone arg-str
+ strdup r@ >in.arguments 2!
+
+ \ open the package
+ " open" r@ ['] $call-method catch if 3drop false then
+ if
+ r>
+ else
+ r> destroy-instance false
+ then
+;
+
+
+: $open-package ( arg-str arg-len name-str name-len -- ihandle | 0 )
+ \ Open the support package named by name string.
+ find-package if
+ open-package
+ else
+ 2drop false
+ then
+;
+
+
+: close-package ( ihandle -- )
+\ Close the instance identified by ihandle by calling the package's close
+\ method and then destroying the instance.
+ dup " close" rot ['] $call-method catch if 3drop then
+ destroy-instance
+;
+
+\
+\ 5.3.4.3 Get local arguments
+\
+
+: my-address ( -- phys.lo ... )
+ ?my-self >in.device-node @
+ >dn.probe-addr
+ my-#acells tuck /l* + swap 1- 0
+ ?do
+ /l - dup l@ swap
+ loop
+ drop
+ ;
+
+: my-space ( -- phys.hi )
+ ?my-self >in.device-node @
+ >dn.probe-addr @
+ ;
+
+: my-unit ( -- phys.lo ... phys.hi )
+ ?my-self >in.my-unit
+ my-#acells tuck /l* + swap 0 ?do
+ /l - dup l@ swap
+ loop
+ drop
+ ;
+
+: my-args ( -- arg-str arg-len )
+ ?my-self >in.arguments 2@
+ ;
+
+\ char is not included. If char is not found, then R-len is zero
+: left-parse-string ( str len char -- R-str R-len L-str L-len )
+ left-split
+;
+
+\ parse ints "hi,...,lo" separated by comma
+: parse-ints ( str len num -- val.lo .. val.hi )
+ -rot 2 pick -rot
+ begin
+ rot 1- -rot 2 pick 0>=
+ while
+ ( num n str len )
+ 2dup ascii , strchr ?dup if
+ ( num n str len p )
+ 1+ -rot
+ 2 pick 2 pick - ( num n p str len len1+1 )
+ dup -rot - ( num n p str len1+1 len2 )
+ -rot 1- ( num n p len2 str len1 )
+ else
+ 0 0 2swap
+ then
+ $number if 0 then >r
+ repeat
+ 3drop
+
+ ( num )
+ begin 1- dup 0>= while r> swap repeat
+ drop
+;
+
+: parse-2int ( str len -- val.lo val.hi )
+ 2 parse-ints
+;
+
+
+\
+\ 5.3.4.4 Mapping tools
+\
+
+: map-low ( phys.lo ... size -- virt )
+ my-space swap s" map-in" $call-parent
+ ;
+
+: free-virtual ( virt size -- )
+ over s" address" get-my-property 0= if
+ decode-int -rot 2drop = if
+ s" address" delete-property
+ then
+ else
+ drop
+ then
+ s" map-out" $call-parent
+ ;
+
+
+\ Deprecated functions (required for compatibility with older loaders)
+
+variable package-stack-pos 0 package-stack-pos !
+create package-stack 8 cells allot
+
+: push-package ( phandle -- )
+ \ Throw an error if we attempt to push a full stack
+ package-stack-pos @ 8 >= if
+ ." cannot push-package onto full stack" cr
+ -99 throw
+ then
+ active-package
+ package-stack-pos @ /n * package-stack + !
+ package-stack-pos @ 1 + package-stack-pos !
+ active-package!
+ ;
+
+: pop-package ( -- )
+ \ Throw an error if we attempt to pop an empty stack
+ package-stack-pos @ 0 = if
+ ." cannot pop-package from empty stack" cr
+ -99 throw
+ then
+ package-stack-pos @ 1 - package-stack-pos !
+ package-stack-pos @ /n * package-stack + @
+ active-package!
+ ;
diff --git a/roms/openbios/forth/device/pathres.fs b/roms/openbios/forth/device/pathres.fs
new file mode 100644
index 00000000..a185b95a
--- /dev/null
+++ b/roms/openbios/forth/device/pathres.fs
@@ -0,0 +1,522 @@
+\ tag: Path resolution
+\
+\ this code implements IEEE 1275-1994 path resolution
+\
+\ Copyright (C) 2003 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+0 value interpose-ph
+0 0 create interpose-args , ,
+
+: expand-alias ( alias-addr alias-len -- exp-addr exp-len expanded? )
+ 2dup
+ " /aliases" find-dev 0= if 2drop false exit then
+ get-package-property if
+ false
+ else
+ 2swap 2drop
+ \ drop trailing 0 from string
+ dup if 1- then
+ true
+ then
+;
+
+\
+\ 4.3.1 Resolve aliases
+\
+
+\ the returned string is allocated with alloc-mem
+: pathres-resolve-aliases ( path-addr path-len -- path-addr path-len )
+ over c@ 2f <> if
+ 200 here + >r \ abuse dictionary for temporary storage
+
+ \ If the pathname does not begin with "/", and its first node name
+ \ component is an alias, replace the alias with its expansion.
+ ascii / split-before \ (PATH_NAME, "/") -> (TAIL HEAD)
+ ascii : split-before \ (HEAD, ":") -> (ALIAS_ARGS AL_NAME)
+ expand-alias ( TAIL ALIAS_ARGS EXP_ALIAS_NAME expanded? )
+ if
+ 2 pick 0<> if \ If ALIAS_ARGS is not empty
+ ascii / split-after \ (ALIAS_NAME, "/") -> (AL_TAIL AL_HEAD/)
+ 2swap ( TAIL AL_HEAD/ AL_TAIL )
+ ascii : split-before \ (AL_TAIL, ":") -> (DEAD_ARGS AL_TAIL)
+ 2swap 2drop ( TAIL AL_ARGS AL_HEAD ALIAS_TAIL )
+ 2swap ( TAIL AL_ARGS AL_TAIL AL_HEAD )
+ r> tmpstrcat tmpstrcat >r
+ else
+ 2swap 2drop \ drop ALIAS_ARGS
+ then
+ r> tmpstrcat drop
+ else
+ \ put thing back together again
+ r> tmpstrcat tmpstrcat drop
+ then
+ then
+
+ strdup
+ ( path-addr path-len )
+;
+
+\
+\ search struct
+\
+
+struct ( search information )
+ 2 cells field >si.path
+ 2 cells field >si.arguments
+ 2 cells field >si.unit_addr
+ 2 cells field >si.node_name
+ 2 cells field >si.free_me
+ 4 cells field >si.unit_phys
+ /n field >si.unit_phys_len
+ /n field >si.save-ihandle
+ /n field >si.save-phandle
+ /n field >si.top-ihandle
+ /n field >si.top-opened \ set after successful open
+ /n field >si.child \ node to match
+constant sinfo.size
+
+
+\
+\ 4.3.6 node name match criteria
+\
+
+: match-nodename ( childname len sinfo -- match? )
+ >r
+ 2dup r@ >si.node_name 2@
+ ( [childname] [childname] [nodename] )
+ strcmp 0= if r> 3drop true exit then
+
+ \ does NODE_NAME contain a comma?
+ r@ >si.node_name 2@ ascii , strchr
+ if r> 3drop false exit then
+
+ ( [childname] )
+ ascii , left-split 2drop r@ >si.node_name 2@
+ r> drop
+ strcmp if false else true then
+;
+
+
+\
+\ 4.3.4 exact match child node
+\
+
+\ If NODE_NAME is not empty, make sure it matches the name property
+: common-match ( sinfo -- )
+ >r
+ \ a) NODE_NAME nonempty
+ r@ >si.node_name 2@ nip if
+ " name" r@ >si.child @ get-package-property if -1 throw then
+ \ name is supposed to be null-terminated
+ dup 0> if 1- then
+ \ exit if NODE_NAME does not match
+ r@ match-nodename 0= if -2 throw then
+ then
+ r> drop
+;
+
+: (exact-match) ( sinfo -- )
+ >r
+ \ a) If NODE_NAME is not empty, make sure it matches the name property
+ r@ common-match
+
+ \ b) UNIT_PHYS nonempty?
+ r@ >si.unit_phys_len @ /l* ?dup if
+ \ check if unit_phys matches
+ " reg" r@ >si.child @ get-package-property if -3 throw then
+ ( unitbytes propaddr proplen )
+ rot r@ >si.unit_phys -rot
+ ( propaddr unit_phys proplen unitbytes )
+ swap over < if -4 throw then
+ comp if -5 throw then
+ else
+ \ c) both NODE_NAME and UNIT_PHYS empty?
+ r@ >si.node_name 2@ nip 0= if -6 throw then
+ then
+
+ r> drop
+;
+
+: exact-match ( sinfo -- match? )
+ ['] (exact-match) catch if drop false exit then
+ true
+;
+
+\
+\ 4.3.5 wildcard match child node
+\
+
+: (wildcard-match) ( sinfo -- match? )
+ >r
+ \ a) If NODE_NAME is not empty, make sure it matches the name property
+ r@ common-match
+
+ \ b) Fail if "reg" property exist
+ " reg" r@ >si.child @ get-package-property 0= if -7 throw then
+
+ \ c) Fail if both NODE_NAME and UNIT_ADDR are both empty
+ r@ >si.unit_phys_len @
+ r@ >si.node_name 2@ nip
+ or 0= if -1 throw then
+
+ \ SUCCESS
+ r> drop
+;
+
+: wildcard-match ( sinfo -- match? )
+ ['] (wildcard-match) catch if drop false exit then
+ true
+;
+
+
+\
+\ 4.3.3 match child node
+\
+
+\ used if package lacks a decode-unit method
+: def-decode-unit ( str len -- unitaddr ... )
+ parse-hex
+;
+
+: get-decode-unit-xt ( phandle -- xt )
+ " decode-unit" rot find-method
+ 0= if ['] def-decode-unit then
+;
+
+: find-child ( sinfo -- phandle )
+ >r
+ \ decode unit address string
+ r@ >si.unit_addr 2@ dup if
+ ( str len )
+ active-package get-decode-unit-xt
+ depth 3 - >r execute depth r@ - r> swap
+ ( ... a_lo ... a_hi olddepth n )
+ 4 min 0 max
+ dup r@ >si.unit_phys_len !
+ ( ... a_lo ... a_hi olddepth n )
+ r@ >si.unit_phys >r
+ begin 1- dup 0>= while
+ rot r> dup la1+ >r l!-be
+ repeat
+ r> 2drop
+ depth!
+ else
+ 2drop
+ \ clear unit_phys
+ 0 r@ >si.unit_phys_len !
+ \ r@ >si.unit_phys 4 cells 0 fill
+ then
+
+ ( R: sinfo )
+ ['] exact-match
+ begin dup while
+ active-package >dn.child @
+ begin ?dup while
+ dup r@ >si.child !
+ ( xt phandle R: sinfo )
+ r@ 2 pick execute if 2drop r> >si.child @ exit then
+ >dn.peer @
+ repeat
+ ['] exact-match = if ['] wildcard-match else 0 then
+ repeat
+
+ -99 throw
+;
+
+
+\
+\ 4.3.2 Create new linked instance procedure
+\
+
+: link-one ( sinfo -- )
+ >r
+ active-package create-instance
+ dup 0= if -99 throw then
+
+ \ change instance parent
+ r@ >si.top-ihandle @ over >in.my-parent !
+ dup r@ >si.top-ihandle !
+ to my-self
+
+ \ b) set my-args field
+ r@ >si.arguments 2@ strdup my-self >in.arguments 2!
+
+ \ e) set my-unit field
+ r@ >si.unit_addr 2@ nip if
+ \ copy UNIT_PHYS to the my-unit field
+ r@ >si.unit_phys my-self >in.my-unit 4 cells move
+ else
+ \ set unit-addr from reg property
+ " reg" active-package get-package-property 0= if
+ \ ( ihandle prop proplen )
+ \ copy address to my-unit
+ 4 cells min my-self >in.my-unit swap move
+ else
+ \ clear my-unit
+ my-self >in.my-unit 4 cells 0 fill
+ then
+ then
+
+ \ top instance has not been opened (yet)
+ false r> >si.top-opened !
+;
+
+: invoke-open ( sinfo -- )
+ " open" my-self ['] $call-method
+ catch if 3drop false then
+ 0= if -99 throw then
+
+ true swap >si.top-opened !
+;
+
+\
+\ 4.3.7 Handle interposers procedure (supplement)
+\
+
+: handle-interposers ( sinfo -- )
+ >r
+ begin
+ interpose-ph ?dup
+ while
+ 0 to interpose-ph
+ active-package swap active-package!
+
+ \ clear unit address and set arguments
+ 0 0 r@ >si.unit_addr 2!
+ interpose-args 2@ r@ >si.arguments 2!
+ r@ link-one
+ true my-self >in.interposed !
+ interpose-args 2@ free-mem
+ r@ invoke-open
+
+ active-package!
+ repeat
+
+ r> drop
+;
+
+\
+\ 4.3.1 Path resolution procedure
+\
+
+\ close-dev ( ihandle -- )
+\
+: close-dev
+ begin
+ dup
+ while
+ dup >in.my-parent @
+ swap close-package
+ repeat
+ drop
+;
+
+: path-res-cleanup ( sinfo close? )
+
+ \ tear down all instances if close? is set
+ if
+ dup >si.top-opened @ if
+ dup >si.top-ihandle @
+ ?dup if close-dev then
+ else
+ dup >si.top-ihandle @ dup
+ ( sinfo ihandle ihandle )
+ dup if >in.my-parent @ swap then
+ ( sinfo parent ihandle )
+ ?dup if destroy-instance then
+ ?dup if close-dev then
+ then
+ then
+
+ \ restore active-package and my-self
+ dup >si.save-ihandle @ to my-self
+ dup >si.save-phandle @ active-package!
+
+ \ free any allocated memory
+ dup >si.free_me 2@ free-mem
+ sinfo.size free-mem
+;
+
+: (path-resolution) ( context sinfo -- )
+ >r r@ >si.path 2@
+ ( context pathstr pathlen )
+
+ \ this allocates a copy of the string
+ pathres-resolve-aliases
+ 2dup r@ >si.free_me 2!
+
+ \ If the pathname, after possible alias expansion, begins with "/",
+ \ begin the search at the root node. Otherwise, begin at the active
+ \ package.
+
+ dup if \ make sure string is not empty
+ over c@ 2f = if
+ swap char+ swap /c - \ Remove the "/" from PATH_NAME.
+ \ Set the active package to the root node.
+ device-tree @ active-package!
+ then
+ then
+
+ r@ >si.path 2!
+ 0 0 r@ >si.unit_addr 2!
+ 0 0 r@ >si.arguments 2!
+ 0 r@ >si.top-ihandle !
+
+ \ If there is no active package, exit this procedure, returning false.
+ ( context )
+ active-package 0= if -99 throw then
+
+ \ Begin the creation of an instance chain.
+ \ NOTE--If, at this step, the active package is not the root node and
+ \ we are in open-dev or execute-device-method contexts, the instance
+ \ chain that results from the path resolution process may be incomplete.
+
+ active-package swap
+ ( virt-active-node context )
+ begin
+ r@ >si.path 2@ nip \ nonzero path?
+ while
+ \ ( active-node context )
+ \ is this open-dev or execute-device-method context?
+ dup if
+ r@ link-one
+ over active-package <> my-self >in.interposed !
+ r@ invoke-open
+ r@ handle-interposers
+ then
+ over active-package!
+
+ r@ >si.path 2@ ( PATH )
+
+ ascii / left-split ( PATH COMPONENT )
+ ascii : left-split ( PATH ARGS NODE_ADDR )
+ ascii @ left-split ( PATH ARGS UNIT_ADDR NODE_NAME )
+
+ r@ >si.node_name 2!
+ r@ >si.unit_addr 2!
+ r@ >si.arguments 2!
+ r@ >si.path 2!
+
+ ( virt-active-node context )
+
+ \ 4.3.1 i) pathname has a leading %?
+ r@ >si.node_name 2@ 2dup 2dup ascii % strchr nip = if
+ 1- swap 1+ swap r@ >si.node_name 2!
+ " /packages" find-dev drop active-package!
+ r@ find-child
+ else
+ 2drop
+ nip r@ find-child swap over
+ ( new-node context new-node )
+ then
+
+ \ (optional: open any nodes between parent and child )
+
+ active-package!
+ repeat
+
+ ( virt-active-node type )
+ dup if r@ link-one then
+ 1 = if
+ dup active-package <> my-self >in.interposed !
+ r@ invoke-open
+ r@ handle-interposers
+ then
+ active-package!
+
+ r> drop
+;
+
+: path-resolution ( context path-addr path-len -- sinfo true | false )
+ \ allocate and clear the search block
+ sinfo.size alloc-mem >r
+ r@ sinfo.size 0 fill
+
+ \ store path
+ r@ >si.path 2!
+
+ \ save ihandle and phandle
+ my-self r@ >si.save-ihandle !
+ active-package r@ >si.save-phandle !
+
+ \ save context (if we take an exception)
+ dup
+
+ r@ ['] (path-resolution)
+ catch ?dup if
+ ( context xxx xxx error )
+ r> true path-res-cleanup
+
+ \ rethrow everything except our "cleanup throw"
+ dup -99 <> if throw then
+ 3drop
+
+ \ ( context ) throw an exception if this is find-device context
+ if false else -22 throw then
+ exit
+ then
+
+ \ ( context )
+ drop r> true
+ ( sinfo true )
+;
+
+
+: open-dev ( dev-str dev-len -- ihandle | 0 )
+ 1 -rot path-resolution 0= if false exit then
+
+ ( sinfo )
+ my-self swap
+ false path-res-cleanup
+
+ ( ihandle )
+;
+
+: execute-device-method
+( ... dev-str dev-len met-str met-len -- ... false | ?? true )
+ 2swap
+ 2 -rot path-resolution 0= if 2drop false exit then
+ ( method-str method-len sinfo )
+ >r
+ my-self ['] $call-method catch
+ if 3drop false else true then
+ r> true path-res-cleanup
+;
+
+: find-device ( dev-str dev-len -- )
+ 2dup " .." strcmp 0= if
+ 2drop
+ active-package dup if >dn.parent @ then
+ \ ".." in root note?
+ dup 0= if -22 throw then
+ active-package!
+ exit
+ then
+ 0 -rot path-resolution 0= if false exit then
+ ( sinfo )
+ active-package swap
+ true path-res-cleanup
+ active-package!
+;
+
+\ find-device, but without side effects
+: (find-dev) ( dev-str dev-len -- phandle true | false )
+ active-package -rot
+ ['] find-device catch if 3drop false exit then
+ active-package swap active-package! true
+;
+
+\ Tuck on a node at the end of the chain being created.
+\ This implementation follows the interpose recommended practice
+\ (v0.2 draft).
+
+: interpose ( arg-str arg-len phandle -- )
+ to interpose-ph
+ strdup interpose-args 2!
+;
+
+['] (find-dev) to find-dev
diff --git a/roms/openbios/forth/device/preof.fs b/roms/openbios/forth/device/preof.fs
new file mode 100644
index 00000000..131beacd
--- /dev/null
+++ b/roms/openbios/forth/device/preof.fs
@@ -0,0 +1,49 @@
+\ tag: historical and pre open firmware fcode functions
+\
+\ this code implements IEEE 1275-1994 ch. H.2.2 and 5.3.1.1.1
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ H.2.2 Non-implemented FCodes
+\ Pre-Open Firmware systems assigned the following FCode numbers,
+\ but the functions were not supported. These FCode numbers stay
+\ reserved to avoid confusion.
+
+: non-implemented
+ ." Non-implemented historical or pre-Open Firmware FCode occured." cr
+ end0
+ ;
+
+: adr-mask non-implemented ;
+: b(code) non-implemented ;
+: 4-byte-id non-implemented ;
+: convert non-implemented ;
+: frame-buffer-busy? non-implemented ;
+: poll-packet non-implemented ;
+: return-buffer non-implemented ;
+: set-token-table non-implemented ;
+: set-table non-implemented ;
+: xmit-packet non-implemented ;
+
+\ historical fcode words defined by 5.3.1.1.1
+
+30000 constant fcode-version \ this opcode is considered obsolete
+30000 constant firmware-version \ this opcode is considered obsolete
+
+\ historical - Returns the type of processor.
+\ 0x5 indicates SPARC, other values are not used.
+\ ?? this could be set by the kernel during bootstrap.
+deadbeef constant processor-type ( -- processor-type )
+
+: memmap non-implemented ;
+: >physical non-implemented ;
+: my-params non-implemented ;
+: intr non-implemented ;
+: driver non-implemented ;
+: group-code non-implemented ;
+: probe non-implemented ;
+: probe-virtual non-implemented ;
diff --git a/roms/openbios/forth/device/property.fs b/roms/openbios/forth/device/property.fs
new file mode 100644
index 00000000..1d54e3ec
--- /dev/null
+++ b/roms/openbios/forth/device/property.fs
@@ -0,0 +1,335 @@
+\ tag: Property management
+\
+\ this code implements IEEE 1275-1994 ch. 5.3.5
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ small helpers.. these should go elsewhere.
+: bigendian?
+ 10 here ! here c@ 10 <>
+ ;
+
+: l!-be ( val addr )
+ 3 bounds swap do
+ dup ff and i c!
+ 8 rshift
+ -1 +loop
+ drop
+ ;
+
+: l@-be ( addr )
+ 0 swap 4 bounds do
+ i c@ swap 8 << or
+ loop
+ ;
+
+\ allocate n bytes for device tree information
+\ until I know where to put this, I put it in the
+\ dictionary.
+
+: alloc-tree ( n -- addr )
+ dup >r \ save len
+ here swap allot
+ dup r> 0 fill \ clear memory
+ ;
+
+: align-tree ( -- )
+ null-align
+ ;
+
+: no-active true abort" no active package." ;
+
+\
+\ 5.3.5 Property management
+\
+
+\ Helper function
+: find-property ( name len phandle -- &&prop|0 )
+ >dn.properties
+ begin
+ dup @
+ while
+ dup @ >prop.name @ ( name len prop propname )
+ 2over comp0 ( name len prop equal? )
+ 0= if nip nip exit then
+ >prop.next @
+ repeat
+ ( name len false )
+ 3drop false
+ ;
+
+\ From package (5.3.4.1)
+: next-property
+( previous-str previous-len phandle -- false | name-str name-len true )
+ >r
+ 2dup 0= swap 0= or if
+ 2drop r> >dn.properties @
+ else
+ r> find-property dup if @ then
+ dup if >prop.next @ then
+ then
+
+ ?dup if
+ >prop.name @ dup cstrlen true
+ ( phandle name-str name-len true )
+ else
+ false
+ then
+;
+
+
+\
+\ 5.3.5.4 Property value access
+\
+
+\ Return value for name string property in package phandle.
+: get-package-property
+ ( name-str name-len phandle -- true | prop-addr prop-len false )
+ find-property ?dup if
+ @ dup >prop.addr @
+ swap >prop.len @
+ false
+ else
+ true
+ then
+ ;
+
+\ Return value for given property in the current instance or its parents.
+: get-inherited-property
+ ( name-str name-len -- true | prop-addr prop-len false )
+ my-self
+ begin
+ ?dup
+ while
+ dup >in.device-node @ ( str len ihandle phandle )
+ 2over rot find-property ?dup if
+ @
+ ( str len ihandle prop )
+ nip nip nip ( prop )
+ dup >prop.addr @ swap >prop.len @
+ false
+ exit
+ then
+ ( str len ihandle )
+ >in.my-parent @
+ repeat
+ 2drop
+ true
+ ;
+
+\ Return value for given property in this package.
+: get-my-property ( name-str name-len -- true | prop-addr prop-len false )
+ my-self >in.device-node @ ( -- phandle )
+ get-package-property
+ ;
+
+
+\
+\ 5.3.5.2 Property array decoding
+\
+
+: decode-int ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 n )
+ dup 0> if
+ dup 4 min >r ( addr1 len1 R:minlen )
+ over r@ + swap ( addr1 addr2 len1 R:minlen )
+ r> - ( addr1 addr2 len2 )
+ rot l@-be
+ else
+ 0
+ then
+ ;
+
+\ HELPER: get #address-cell value (from parent)
+\ Legal values are 1..4 (we may optionally support longer addresses)
+: my-#acells ( -- #address-cells )
+ my-self ?dup if >in.device-node @ else active-package then
+ ?dup if >dn.parent @ then
+ ?dup if
+ " #address-cells" rot get-package-property if 2 exit then
+ \ we don't have to support more than 4 (and 0 is illegal)
+ decode-int nip nip 4 min 1 max
+ else
+ 2
+ then
+;
+
+\ HELPER: get #size-cells value (from parent)
+: my-#scells ( -- #size-cells )
+ my-self ?dup if >in.device-node @ else active-package then
+ ?dup if >dn.parent @ then
+ ?dup if
+ " #size-cells" rot get-package-property if 1 exit then
+ decode-int nip nip
+ else
+ 1
+ then
+;
+
+: decode-string ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 str len )
+ dup 0> if
+ 2dup bounds \ check property for 0 bytes
+ 0 -rot \ initial string len is 0
+ do
+ i c@ 0= if
+ leave
+ then
+ 1+
+ loop ( prop-addr1 prop-len1 len )
+ 1+ rot >r ( prop-len1 len R: prop-addr1 )
+ over min 2dup - ( prop-len1 nlen prop-len2 R: prop-addr1 )
+ r@ 2 pick + ( prop-len1 nlen prop-len2 prop-addr2 )
+ >r >r >r ( R: prop-addr1 prop-addr2 prop-len2 nlen )
+ drop
+ r> r> r> ( nlen prop-len2 prop-addr2 )
+ -rot swap 1- ( prop-addr2 prop-len2 nlen )
+ r> swap ( prop-addr2 prop-len2 str len )
+ else
+ 0 0
+ then
+ ;
+
+: decode-bytes ( addr1 len1 #bytes -- addr len2 addr1 #bytes )
+ tuck - ( addr1 #bytes len2 )
+ r> 2dup + ( addr1 #bytes addr2 ) ( R: len2 )
+ r> 2swap
+ ;
+
+: decode-phys
+ ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 phys.lo ... phys.hi )
+ my-#acells 0 ?do
+ decode-int r> r> rot >r >r >r
+ loop
+ my-#acells 0 ?do
+ r> r> r> -rot >r >r
+ loop
+ ;
+
+
+\
+\ 5.3.5.1 Property array encoding
+\
+
+: encode-int ( n -- prop-addr prop-len )
+ /l alloc-tree tuck l!-be /l
+ ;
+
+: encode-string ( str len -- prop-addr prop-len )
+ \ we trust len here. should probably check string?
+ tuck char+ alloc-tree ( len str prop-addr )
+ tuck 3 pick move ( len prop-addr )
+ swap 1+
+ ;
+
+: encode-bytes ( data-addr data-len -- prop-addr prop-len )
+ tuck alloc-tree ( len str prop-addr )
+ tuck 3 pick move
+ swap
+ ;
+
+: encode+ ( prop-addr1 prop-len1 prop-addr2 prop-len2 -- prop-addr3 prop-len3 )
+ nip +
+ ;
+
+: encode-phys ( phys.lo ... phys.hi -- prop-addr prop-len )
+ encode-int my-#acells 1- 0 ?do
+ rot encode-int encode+
+ loop
+ ;
+
+defer sbus-intr>cpu ( sbus-intr# -- cpu-intr# )
+: (sbus-intr>cpu) ." No SBUS present on this machine." cr ;
+['] (sbus-intr>cpu) to sbus-intr>cpu
+
+
+\
+\ 5.3.5.3 Property declaration
+\
+
+: (property) ( prop-addr prop-len name-str name-len dnode -- )
+ >r 2dup r@
+ align-tree
+ find-property ?dup if
+ \ If a property with that property name already exists in the
+ \ package in which the property would be created, replace its
+ \ value with the new value.
+ @ r> drop \ don't need the device node anymore.
+ -rot 2drop tuck \ drop property name
+ >prop.len ! \ overwrite old values
+ >prop.addr !
+ exit
+ then
+
+ ( prop-addr prop-len name-str name-len R: dn )
+ prop-node.size alloc-tree
+ dup >prop.next off
+
+ dup r> >dn.properties
+ begin dup @ while @ >prop.next repeat !
+ >r
+
+ ( prop-addr prop-len name-str name-len R: prop )
+
+ \ create copy of property name
+ dup char+ alloc-tree
+ dup >r swap move r>
+ ( prop-addr prop-len new-name R: prop )
+ r@ >prop.name !
+ r@ >prop.len !
+ r> >prop.addr !
+ align-tree
+ ;
+
+: property ( prop-addr prop-len name-str name-len -- )
+ my-self ?dup if
+ >in.device-node @
+ else
+ active-package
+ then
+ dup if
+ (property)
+ else
+ no-active
+ then
+ ;
+
+: (delete-property) ( name len dnode -- )
+ find-property ?dup if
+ dup @ >prop.next @ swap !
+ \ maybe we should try to reclaim the space?
+ then
+;
+
+: delete-property ( name-str name-len -- )
+ active-package ?dup if
+ (delete-property)
+ else
+ 2drop
+ then
+ ;
+
+\ Create the "name" property; value is indicated string.
+: device-name ( str len -- )
+ encode-string " name" property
+ ;
+
+\ Create "device_type" property, value is indicated string.
+: device-type ( str len -- )
+ encode-string " device_type" property
+ ;
+
+\ Create the "reg" property with the given values.
+: reg ( phys.lo ... phys.hi size -- )
+ >r ( phys.lo ... phys.hi ) encode-phys ( addr len )
+ r> ( addr1 len1 size ) encode-int ( addr1 len1 addr2 len2 )
+ encode+ ( addr len )
+ " reg" property
+ ;
+
+\ Create the "model" property; value is indicated string.
+: model ( str len -- )
+ encode-string " model" property
+ ;
diff --git a/roms/openbios/forth/device/romfont.bin b/roms/openbios/forth/device/romfont.bin
new file mode 100644
index 00000000..0b60b6fb
--- /dev/null
+++ b/roms/openbios/forth/device/romfont.bin
Binary files differ
diff --git a/roms/openbios/forth/device/structures.fs b/roms/openbios/forth/device/structures.fs
new file mode 100644
index 00000000..14dd881e
--- /dev/null
+++ b/roms/openbios/forth/device/structures.fs
@@ -0,0 +1,54 @@
+\ tag: device interface structures
+\
+\ this code implements data structures used by the
+\ IEEE 1275-1994 Open Firmware Device Interface.
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ this file contains the struct definitions for the following
+\ device tree structures:
+\ device-node
+\ active-package
+\ property
+\ instance
+
+
+struct ( instance )
+ /n field >in.instance-data \ must go first
+ /n field >in.alloced-size \ alloced size
+ /n field >in.device-node
+ /n field >in.my-parent
+ /n field >in.interposed
+ 4 cells field >in.my-unit
+ 2 cells field >in.arguments
+ \ instance-data should be null during packet initialization
+ \ this diverts access to instance variables to the dictionary
+constant inst-node.size
+
+struct ( device node )
+ /n field >dn.isize \ instance size (must go first)
+ /n field >dn.parent
+ /n field >dn.child
+ /n field >dn.peer
+ /n field >dn.properties
+ /n field >dn.methods
+ /n field >dn.priv-methods
+ /n field >dn.#acells
+ /n field >dn.probe-addr
+ inst-node.size field >dn.itemplate
+constant dev-node.size
+
+struct ( property )
+ /n field >prop.next
+ /n field >prop.name
+ /n field >prop.addr
+ /n field >prop.len
+constant prop-node.size
+
+struct ( active package )
+ /n field >ap.device-str
+constant active-package.size
diff --git a/roms/openbios/forth/device/table.fs b/roms/openbios/forth/device/table.fs
new file mode 100644
index 00000000..5c58f2d9
--- /dev/null
+++ b/roms/openbios/forth/device/table.fs
@@ -0,0 +1,462 @@
+\ tag: FCode table setup
+\
+\ this code implements an fcode evaluator
+\ as described in IEEE 1275-1994
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+hex
+
+: undefined-fcode ." undefined fcode word." cr ;
+: reserved-fcode ." reserved fcode word." cr ;
+
+: ['], ( <word> -- )
+ ' ,
+;
+
+: n['], ( n <word> -- )
+ ' swap 0 do
+ dup ,
+ loop
+ drop
+;
+
+\ the table used
+create fcode-master-table
+ ['], end0
+ f n['], reserved-fcode
+ ['], b(lit)
+ ['], b(')
+ ['], b(")
+ ['], bbranch
+ ['], b?branch
+ ['], b(loop)
+ ['], b(+loop)
+ ['], b(do)
+ ['], b(?do)
+ ['], i
+ ['], j
+ ['], b(leave)
+ ['], b(of)
+ ['], execute
+ ['], +
+ ['], -
+ ['], *
+ ['], /
+ ['], mod
+ ['], and
+ ['], or
+ ['], xor
+ ['], invert
+ ['], lshift
+ ['], rshift
+ ['], >>a
+ ['], /mod
+ ['], u/mod
+ ['], negate
+ ['], abs
+ ['], min
+ ['], max
+ ['], >r
+ ['], r>
+ ['], r@
+ ['], exit
+ ['], 0=
+ ['], 0<>
+ ['], 0<
+ ['], 0<=
+ ['], 0>
+ ['], 0>=
+ ['], <
+ ['], >
+ ['], =
+ ['], <>
+ ['], u>
+ ['], u<=
+ ['], u<
+ ['], u>=
+ ['], >=
+ ['], <=
+ ['], between
+ ['], within
+ ['], drop
+ ['], dup
+ ['], over
+ ['], swap
+ ['], rot
+ ['], -rot
+ ['], tuck
+ ['], nip
+ ['], pick
+ ['], roll
+ ['], ?dup
+ ['], depth
+ ['], 2drop
+ ['], 2dup
+ ['], 2over
+ ['], 2swap
+ ['], 2rot
+ ['], 2/
+ ['], u2/
+ ['], 2*
+ ['], /c
+ ['], /w
+ ['], /l
+ ['], /n
+ ['], ca+
+ ['], wa+
+ ['], la+
+ ['], na+
+ ['], char+
+ ['], wa1+
+ ['], la1+
+ ['], cell+
+ ['], chars
+ ['], /w*
+ ['], /l*
+ ['], cells
+ ['], on
+ ['], off
+ ['], +!
+ ['], @
+ ['], l@
+ ['], w@
+ ['], <w@
+ ['], c@
+ ['], !
+ ['], l!
+ ['], w!
+ ['], c!
+ ['], 2@
+ ['], 2!
+ ['], move
+ ['], fill
+ ['], comp
+ ['], noop
+ ['], lwsplit
+ ['], wljoin
+ ['], lbsplit
+ ['], bljoin
+ ['], wbflip
+ ['], upc
+ ['], lcc
+ ['], pack
+ ['], count
+ ['], body>
+ ['], >body
+ ['], fcode-revision
+ ['], span
+ ['], unloop
+ ['], expect
+ ['], alloc-mem
+ ['], free-mem
+ ['], key?
+ ['], key
+ ['], emit
+ ['], type
+ ['], (cr
+ ['], cr
+ ['], #out
+ ['], #line
+ ['], hold
+ ['], <#
+ ['], u#>
+ ['], sign
+ ['], u#
+ ['], u#s
+ ['], u.
+ ['], u.r
+ ['], .
+ ['], .r
+ ['], .s
+ ['], base
+ ['], convert \ reserved (compatibility)
+ ['], $number
+ ['], digit
+ ['], -1
+ ['], 0
+ ['], 1
+ ['], 2
+ ['], 3
+ ['], bl
+ ['], bs
+ ['], bell
+ ['], bounds
+ ['], here
+ ['], aligned
+ ['], wbsplit
+ ['], bwjoin
+ ['], b(<mark)
+ ['], b(>resolve)
+ ['], set-token-table
+ ['], set-table
+ ['], new-token
+ ['], named-token
+ ['], b(:)
+ ['], b(value)
+ ['], b(variable)
+ ['], b(constant)
+ ['], b(create)
+ ['], b(defer)
+ ['], b(buffer:)
+ ['], b(field)
+ ['], b(code)
+ ['], instance
+ ['], reserved-fcode
+ ['], b(;)
+ ['], b(to)
+ ['], b(case)
+ ['], b(endcase)
+ ['], b(endof)
+ ['], #
+ ['], #s
+ ['], #>
+ ['], external-token
+ ['], $find
+ ['], offset16
+ ['], evaluate
+ ['], reserved-fcode
+ ['], reserved-fcode
+ ['], c,
+ ['], w,
+ ['], l,
+ ['], ,
+ ['], um*
+ ['], um/mod
+ ['], reserved-fcode
+ ['], reserved-fcode
+ ['], d+
+ ['], d-
+ ['], get-token
+ ['], set-token
+ ['], state
+ ['], compile,
+ ['], behavior
+ 11 n['], reserved-fcode
+ ['], start0
+ ['], start1
+ ['], start2
+ ['], start4
+ 8 n['], reserved-fcode
+ ['], ferror
+ ['], version1
+ ['], 4-byte-id
+ ['], end1
+ ['], reserved-fcode
+ ['], dma-alloc
+ ['], my-address
+ ['], my-space
+ ['], memmap
+ ['], free-virtual
+ ['], >physical
+ 8 n['], reserved-fcode
+ ['], my-params
+ ['], property
+ ['], encode-int
+ ['], encode+
+ ['], encode-phys
+ ['], encode-string
+ ['], encode-bytes
+ ['], reg
+ ['], intr
+ ['], driver
+ ['], model
+ ['], device-type
+ ['], parse-2int
+ ['], is-install
+ ['], is-remove
+ ['], is-selftest
+ ['], new-device
+ ['], diagnostic-mode?
+ ['], display-status
+ ['], memory-test-suite
+ ['], group-code
+ ['], mask
+ ['], get-msecs
+ ['], ms
+ ['], finish-device
+ ['], decode-phys \ 128
+ ['], push-package
+ ['], pop-package
+ ['], interpose \ extension (recommended practice)
+ 4 n['], reserved-fcode
+ ['], map-low
+ ['], sbus-intr>cpu
+ 1e n['], reserved-fcode
+ ['], #lines
+ ['], #columns
+ ['], line#
+ ['], column#
+ ['], inverse?
+ ['], inverse-screen?
+ ['], frame-buffer-busy?
+ ['], draw-character
+ ['], reset-screen
+ ['], toggle-cursor
+ ['], erase-screen
+ ['], blink-screen
+ ['], invert-screen
+ ['], insert-characters
+ ['], delete-characters
+ ['], insert-lines
+ ['], delete-lines
+ ['], draw-logo
+ ['], frame-buffer-adr
+ ['], screen-height
+ ['], screen-width
+ ['], window-top
+ ['], window-left
+ 3 n['], reserved-fcode
+ ['], default-font
+ ['], set-font
+ ['], char-height
+ ['], char-width
+ ['], >font
+ ['], fontbytes
+ 10 n['], reserved-fcode \ fb1 words
+ ['], fb8-draw-character
+ ['], fb8-reset-screen
+ ['], fb8-toggle-cursor
+ ['], fb8-erase-screen
+ ['], fb8-blink-screen
+ ['], fb8-invert-screen
+ ['], fb8-insert-characters
+ ['], fb8-delete-characters
+ ['], fb8-insert-lines
+ ['], fb8-delete-lines
+ ['], fb8-draw-logo
+ ['], fb8-install
+ 4 n['], reserved-fcode \ reserved
+ 7 n['], reserved-fcode \ VME-bus support
+ 9 n['], reserved-fcode \ reserved
+ ['], return-buffer
+ ['], xmit-packet
+ ['], poll-packet
+ ['], reserved-fcode
+ ['], mac-address
+ 5c n['], reserved-fcode \ 1a5-200 reserved
+ ['], device-name
+ ['], my-args
+ ['], my-self
+ ['], find-package
+ ['], open-package
+ ['], close-package
+ ['], find-method
+ ['], call-package
+ ['], $call-parent
+ ['], my-parent
+ ['], ihandle>phandle
+ ['], reserved-fcode
+ ['], my-unit
+ ['], $call-method
+ ['], $open-package
+ ['], processor-type
+ ['], firmware-version
+ ['], fcode-version
+ ['], alarm
+ ['], (is-user-word)
+ ['], suspend-fcode
+ ['], abort
+ ['], catch
+ ['], throw
+ ['], user-abort
+ ['], get-my-property
+ ['], decode-int
+ ['], decode-string
+ ['], get-inherited-property
+ ['], delete-property
+ ['], get-package-property
+ ['], cpeek
+ ['], wpeek
+ ['], lpeek
+ ['], cpoke
+ ['], wpoke
+ ['], lpoke
+ ['], lwflip
+ ['], lbflip
+ ['], lbflips
+ ['], adr-mask
+ 4 n['], reserved-fcode \ 22a-22d
+64bit? [IF]
+ ['], (rx@)
+ ['], (rx!)
+[ELSE]
+ 2 n['], reserved-fcode \ 22e-22f
+[THEN]
+ ['], rb@
+ ['], rb!
+ ['], rw@
+ ['], rw!
+ ['], rl@
+ ['], rl!
+ ['], wbflips
+ ['], lwflips
+ ['], probe
+ ['], probe-virtual
+ ['], reserved-fcode
+ ['], child
+ ['], peer
+ ['], next-property
+ ['], byte-load
+ ['], set-args
+ ['], left-parse-string \ 240
+64bit? [IF]
+ ['], bxjoin
+ ['], <l@
+ ['], lxjoin
+ ['], wxjoin
+ ['], x,
+ ['], x@
+ ['], x!
+ ['], /x
+ ['], /x*
+\ ['], /xa+
+\ ['], /xa1+
+ ['], xbflip
+ ['], xbflips
+ ['], xbsplit
+ ['], xlflip
+ ['], xlflips
+ ['], xlsplit
+ ['], xwflip
+ ['], xwflips
+ ['], xwsplit
+[ELSE]
+ 7 n['], reserved-fcode \ 241-247 (Part of IEEE1275 64-bit draft standard)
+ ['], /x
+ c n['], reserved-fcode \ 249-254 (Part of IEEE1275 64-bit draft standard)
+[THEN]
+
+
+here fcode-master-table - constant fcode-master-table-size
+
+
+: nreserved ( fcode-table-ptr first last xt -- )
+ -rot 1+ swap do
+ 2dup swap i cells + !
+ loop
+ 2drop
+;
+
+:noname
+ 800 cells alloc-mem to fcode-sys-table
+
+ fcode-sys-table
+ dup 0 5ff ['] reserved-fcode nreserved \ built-in fcodes
+ dup 600 7ff ['] undefined-fcode nreserved \ vendor fcodes
+
+ \ copy built-in fcodes
+ fcode-master-table swap fcode-master-table-size move
+; initializer
+
+: (init-fcode-table) ( -- )
+ fcode-sys-table fcode-table 800 cells move
+ \ clear local fcodes
+ fcode-table 800 fff ['] undefined-fcode nreserved
+;
+
+['] (init-fcode-table) to init-fcode-table
diff --git a/roms/openbios/forth/device/terminal.fs b/roms/openbios/forth/device/terminal.fs
new file mode 100644
index 00000000..24b2d10c
--- /dev/null
+++ b/roms/openbios/forth/device/terminal.fs
@@ -0,0 +1,302 @@
+\ tag: terminal emulation
+\
+\ this code implements IEEE 1275-1994 ANNEX B
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+0 value (escseq)
+10 buffer: (sequence)
+
+: (match-number) ( x y [1|2] [1|2] -- x [z] )
+ 2dup = if \ 1 1 | 2 2
+ drop exit
+ then
+ 2dup > if
+ 2drop drop 1 exit
+ then
+ 2drop 0
+ ;
+
+: (esc-number) ( maxchar -- ?? ?? num )
+ >r depth >r ( R: depth maxchar )
+ 0 (sequence) 2+ (escseq) 2- ( 0 seq+2 seqlen-2 )
+ \ if numerical, scan until non-numerical
+ 0 ?do
+ ( 0 seq+2 )
+ dup i + c@ a
+ digit if
+ ( 0 ptr n )
+ rot a * + ( ptr val )
+ swap
+ else
+ ( 0 ptr asc )
+ ascii ; = if
+ 0 swap
+ else
+ drop leave
+ then
+ then
+
+ loop
+ depth r> - r>
+ 0 to (escseq)
+ (match-number)
+ ;
+
+: (match-seq)
+ (escseq) 1- (sequence) + c@ \ get last character in sequence
+ \ dup draw-character
+ case
+ ascii A of \ CUU - cursor up
+ 1 (esc-number)
+ 0> if
+ 1 max
+ else
+ 1
+ then
+ negate line# +
+ 0 max to line#
+ endof
+ ascii B of \ CUD - cursor down
+ 1 (esc-number)
+ 0> if
+ 1 max
+ line# +
+ #lines 1- min to line#
+ then
+ endof
+ ascii C of \ CUF - cursor forward
+ 1 (esc-number)
+ 0> if
+ 1 max
+ column# +
+ #columns 1- min to column#
+ then
+ endof
+ ascii D of \ CUB - cursor backward
+ 1 (esc-number)
+ 0> if
+ 1 max
+ negate column# +
+ 0 max to column#
+ then
+ endof
+ ascii E of \ Cursor next line (CNL)
+ \ FIXME - check agains ANSI3.64
+ 1 (esc-number)
+ 0> if
+ 1 max
+ line# +
+ #lines 1- min to line#
+ then
+ 0 to column#
+ endof
+ ascii f of
+ 2 (esc-number)
+ case
+ 2 of
+ 1- #columns 1- min to column#
+ 1- #lines 1- min to line#
+ endof
+ 1 of
+ 0 to column#
+ 1- #lines 1- min to line#
+ endof
+ 0 of
+ 0 to column#
+ 0 to line#
+ drop
+ endof
+ endcase
+ endof
+ ascii H of
+ 2 (esc-number)
+ case
+ 2 of
+ 1- #columns 1- min to column#
+ 1- #lines 1- min to line#
+ endof
+ 1 of
+ 0 to column#
+ 1- #lines 1- min to line#
+ endof
+ 0 of
+ 0 to column#
+ 0 to line#
+ drop
+ endof
+ endcase
+ endof
+ ascii J of
+ 0 to (escseq)
+ #columns column# - delete-characters
+ #lines line# - delete-lines
+ endof
+ ascii K of
+ 0 to (escseq)
+ #columns column# - delete-characters
+ endof
+ ascii L of
+ 1 (esc-number)
+ 0> if
+ 1 max
+ insert-lines
+ then
+ endof
+ ascii M of
+ 1 (esc-number)
+ 1 = if
+ 1 max
+ delete-lines
+ then
+ endof
+ ascii @ of
+ 1 (esc-number)
+ 1 = if
+ 1 max
+ insert-characters
+ then
+ endof
+ ascii P of
+ 1 (esc-number)
+ 1 = if
+ 1 max
+ delete-characters
+ then
+ endof
+ ascii m of
+ 1 (esc-number)
+ 1 = if
+ 7 = if
+ true to inverse?
+ else
+ false to inverse?
+ then
+ then
+ endof
+ ascii p of \ normal text colors
+ 0 to (escseq)
+ inverse-screen? if
+ false to inverse-screen?
+ inverse? 0= to inverse?
+ invert-screen
+ then
+ endof
+ ascii q of \ inverse text colors
+ 0 to (escseq)
+ inverse-screen? not if
+ true to inverse-screen?
+ inverse? 0= to inverse?
+ invert-screen
+ then
+ endof
+ ascii s of
+ \ Resets the display device associated with the terminal emulator.
+ 0 to (escseq)
+ reset-screen
+ endof
+ endcase
+ ;
+
+: (term-emit) ( char -- )
+ toggle-cursor
+
+ (escseq) 0> if
+ (escseq) 10 = if
+ 0 to (escseq)
+ ." overflow in esc" cr
+ drop
+ then
+ (escseq) 1 = if
+ dup ascii [ = if \ not a [
+ (sequence) 1+ c!
+ 2 to (escseq)
+ else
+ 0 to (escseq) \ break out of ESC sequence
+ ." out of ESC" cr
+ drop \ don't print breakout character
+ then
+ toggle-cursor exit
+ else
+ (sequence) (escseq) + c!
+ (escseq) 1+ to (escseq)
+ (match-seq)
+ toggle-cursor exit
+ then
+ then
+
+ case
+ 0 of \ NULL
+ toggle-cursor exit
+ endof
+ 7 of \ BEL
+ blink-screen
+ s" /screen" s" ring-bell"
+ execute-device-method
+ endof
+ 8 of \ BS
+ column# 0<> if
+ column# 1- to column#
+ toggle-cursor exit
+ then
+ endof
+ 9 of \ TAB
+ column# dup #columns = if
+ drop
+ else
+ 8 + -8 and ff and to column#
+ then
+ toggle-cursor exit
+ endof
+ a of \ LF
+ line# 1+ to line#
+ 0 to column#
+ line# #lines >= if
+ 0 to line#
+ 1 delete-lines
+ #lines 1- to line#
+ toggle-cursor exit
+ then
+ endof
+ b of \ VT
+ line# 0<> if
+ line# 1- to line#
+ then
+ toggle-cursor exit
+ endof
+ c of \ FF
+ 0 to column# 0 to line#
+ erase-screen
+ endof
+ d of \ CR
+ 0 to column#
+ toggle-cursor exit
+ endof
+ 1b of \ ESC
+ 1b (sequence) c!
+ 1 to (escseq)
+ endof
+
+ \ draw character and advance position
+ column# #columns >= if
+ 0 to column#
+ line# 1+ to line#
+ line# #lines >= if
+ 0 to line#
+ 1 delete-lines
+ #lines 1- to line#
+ then
+ then
+
+ dup draw-character
+ column# 1+ to column#
+
+ endcase
+ toggle-cursor
+ ;
+
+['] (term-emit) to fb-emit
diff --git a/roms/openbios/forth/device/tree.fs b/roms/openbios/forth/device/tree.fs
new file mode 100644
index 00000000..04f85b5c
--- /dev/null
+++ b/roms/openbios/forth/device/tree.fs
@@ -0,0 +1,59 @@
+\ tag: Device Tree
+\
+\ this code implements IEEE 1275-1994 ch. 3.5
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+
+\ root node
+new-device
+ " OpenBiosTeam,OpenBIOS" device-name
+ 1 encode-int " #address-cells" property
+ : open true ;
+ : close ;
+ : decode-unit parse-hex ;
+ : encode-unit ( addr -- str len )
+ pocket tohexstr
+ ;
+
+new-device
+ " aliases" device-name
+ : open true ;
+ : close ;
+finish-device
+
+new-device
+ " openprom" device-name
+ " BootROM" device-type
+ " OpenFirmware 3" model
+ 0 0 " relative-addressing" property
+ 0 0 " supports-bootinfo" property
+ 1 encode-int " boot-syntax" property
+
+ : selftest
+ ." OpenBIOS selftest... succeded" cr
+ true
+ ;
+ : open true ;
+ : close ;
+
+finish-device
+
+new-device
+ " options" device-name
+finish-device
+
+new-device
+ " chosen" device-name
+ 0 encode-int " stdin" property
+ 0 encode-int " stdout" property
+ \ " hda1:/boot/vmunix" encode-string " bootpath" property
+ \ " -as" encode-string " bootargs" property
+finish-device
+
+\ END
+finish-device
diff --git a/roms/openbios/forth/lib/64bit.fs b/roms/openbios/forth/lib/64bit.fs
new file mode 100644
index 00000000..239ddd02
--- /dev/null
+++ b/roms/openbios/forth/lib/64bit.fs
@@ -0,0 +1,128 @@
+\
+\ Copyright (C) 2009 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ Implementation of IEEE Draft Std P1275.6/D5
+\ Standard for Boot (Initialization Configuration) Firmware
+\ 64 Bit Extensions
+
+
+cell /x = constant 64bit?
+
+64bit? [IF]
+
+: 32>64 ( 32bitsigned -- 64bitsigned )
+ dup 80000000 and if \ is it negative?
+ ffffffff00000000 or \ then set all high bits
+ then
+;
+
+: 64>32 ( 64bitsigned -- 32bitsigned )
+ h# ffffffff and
+;
+
+: lxjoin ( quad.lo quad.hi -- o )
+ d# 32 lshift or
+;
+
+: wxjoin ( w.lo w.2 w.3 w.hi -- o )
+ wljoin >r wljoin r> lxjoin
+;
+
+: bxjoin ( b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi -- o )
+ bljoin >r bljoin r> lxjoin
+;
+
+: <l@ ( qaddr -- n )
+ l@ 32>64
+;
+
+: unaligned-x@ ( addr - o )
+ dup la1+ unaligned-l@ 64>32 swap unaligned-l@ 64>32 lxjoin
+;
+
+: unaligned-x! ( o oaddr -- )
+ >r dup d# 32 rshift r@ unaligned-l!
+ h# ffffffff and r> la1+ unaligned-l!
+;
+
+: x@ ( oaddr -- o )
+ unaligned-x@ \ for now
+;
+
+: x! ( o oaddr -- )
+ unaligned-x! \ for now
+;
+
+: (rx@) ( oaddr - o )
+ x@
+;
+
+: (rx!) ( o oaddr -- )
+ x!
+;
+
+: x, ( o -- )
+ here /x allot x!
+;
+
+: /x* ( nu1 -- nu2 )
+ /x *
+;
+
+: xa+ ( addr1 index -- addr2 )
+ /x* +
+;
+
+: xa1+ ( addr1 -- addr2 )
+ /x +
+;
+
+: xlsplit ( o -- quad.lo quad.hi )
+ dup h# ffffffff and swap d# 32 rshift
+;
+
+: xwsplit ( o -- w.lo w.2 w.3 w.hi )
+ xlsplit >r lwsplit r> lwsplit
+;
+
+: xbsplit ( o -- b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi )
+ xlsplit >r lbsplit r> lbsplit
+;
+
+: xlflip ( oct1 -- oct2 )
+ xlsplit swap lxjoin
+;
+
+: xlflips ( oaddr len -- )
+ bounds ?do
+ i unaligned-x@ xlflip i unaligned-x!
+ /x +loop
+;
+
+: xwflip ( oct1 -- oct2 )
+ xlsplit lwflip swap lwflip lxjoin
+;
+
+: xwflips ( oaddr len -- )
+ bounds ?do
+ i unaligned-x@ xwflip i unaligned-x! /x
+ +loop
+;
+
+: xbflip ( oct1 -- oct2 )
+ xlsplit lbflip swap lbflip lxjoin
+;
+
+: xbflips ( oaddr len -- )
+ bounds ?do
+ i unaligned-x@ xbflip i unaligned-x!
+ /x +loop
+;
+
+\ : b(lit) b(lit) 32>64 ;
+
+[THEN]
diff --git a/roms/openbios/forth/lib/build.xml b/roms/openbios/forth/lib/build.xml
new file mode 100644
index 00000000..34eee407
--- /dev/null
+++ b/roms/openbios/forth/lib/build.xml
@@ -0,0 +1,22 @@
+<build>
+ <!--
+ build description for openbios forth library functions
+
+ Copyright (C) 2003-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="openbios" target="forth">
+ <object source="vocabulary.fs"/>
+ <object source="string.fs"/>
+ <object source="preprocessor.fs"/>
+ <object source="preinclude.fs" /> <!-- FIXME dependencies -->
+ <object source="creation.fs"/>
+ <object source="split.fs"/>
+ <object source="lists.fs"/>
+ <object source="64bit.fs"/>
+ <object source="locals.fs"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/forth/lib/creation.fs b/roms/openbios/forth/lib/creation.fs
new file mode 100644
index 00000000..c3d0db84
--- /dev/null
+++ b/roms/openbios/forth/lib/creation.fs
@@ -0,0 +1,52 @@
+\ tag: misc useful functions
+\
+\ C bindings
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ return xt of the word just defined
+: last-xt ( -- xt )
+ latest @ na1+
+;
+
+\ -------------------------------------------------------------------------
+\ word creation
+\ -------------------------------------------------------------------------
+
+: $is-ibuf ( size name name-len -- xt )
+ instance $buffer: drop
+ last-xt
+;
+
+: is-ibuf ( size -- xt )
+ 0 0 $is-ibuf
+;
+
+: is-ivariable ( size name len -- xt )
+ 4 -rot instance $buffer: drop
+ last-xt
+;
+
+: is-xt-func ( xt|0 wordstr len )
+ header 1 ,
+ ?dup if , then
+ ['] (semis) , reveal
+;
+
+: is-2xt-func ( xt1 xt2 wordstr len )
+ header 1 ,
+ swap , ,
+ ['] (semis) , reveal
+;
+
+: is-func-begin ( wordstr len )
+ header 1 ,
+;
+
+: is-func-end ( wordstr len )
+ ['] (semis) , reveal
+;
diff --git a/roms/openbios/forth/lib/lists.fs b/roms/openbios/forth/lib/lists.fs
new file mode 100644
index 00000000..91f7867b
--- /dev/null
+++ b/roms/openbios/forth/lib/lists.fs
@@ -0,0 +1,26 @@
+\ tag: misc useful functions
+\
+\ Misc useful functions
+\
+\ Copyright (C) 2003 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ -------------------------------------------------------------------------
+\ statically allocated lists
+\ -------------------------------------------------------------------------
+\ list-head should be a variable
+
+: list-add ( listhead -- )
+ here 0 , swap \ next, [data...]
+ ( here listhead )
+ begin dup @ while @ repeat !
+;
+
+: list-get ( listptr -- nextlistptr dictptr true | false )
+ @ dup if
+ dup na1+ true
+ then
+;
diff --git a/roms/openbios/forth/lib/locals.fs b/roms/openbios/forth/lib/locals.fs
new file mode 100644
index 00000000..e697383b
--- /dev/null
+++ b/roms/openbios/forth/lib/locals.fs
@@ -0,0 +1,197 @@
+\ tag: local variables
+\
+\ Copyright (C) 2012 Mark Cave-Ayland
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+[IFDEF] CONFIG_LOCALS
+
+\ Init local variable stack
+variable locals-var-stack
+here 200 cells allot locals-var-stack !
+
+\ Set initial stack pointer
+\
+\ Stack looks like this:
+\ ... (sp n-2) local1 ... localm-1 localm (sp n-1) <-- sp
+
+locals-var-stack @ value locals-var-sp
+locals-var-sp locals-var-stack @ !
+
+0 value locals-var-count
+0 value locals-flags
+
+here 200 cells allot locals-dict-buf !
+
+8 constant #locals
+
+: (local1) locals-var-sp @ /n + ;
+: (local2) locals-var-sp @ 2 cells + ;
+: (local3) locals-var-sp @ 3 cells + ;
+: (local4) locals-var-sp @ 4 cells + ;
+: (local5) locals-var-sp @ 5 cells + ;
+: (local6) locals-var-sp @ 6 cells + ;
+: (local7) locals-var-sp @ 7 cells + ;
+: (local8) locals-var-sp @ 8 cells + ;
+
+: local1@ (local1) @ ;
+: local2@ (local2) @ ;
+: local3@ (local3) @ ;
+: local4@ (local4) @ ;
+: local5@ (local5) @ ;
+: local6@ (local6) @ ;
+: local7@ (local7) @ ;
+: local8@ (local8) @ ;
+
+: local1! (local1) ! ;
+: local2! (local2) ! ;
+: local3! (local3) ! ;
+: local4! (local4) ! ;
+: local5! (local5) ! ;
+: local6! (local6) ! ;
+: local7! (local7) ! ;
+: local8! (local8) ! ;
+
+create locals-read-table
+['] local1@ ,
+['] local2@ ,
+['] local3@ ,
+['] local4@ ,
+['] local5@ ,
+['] local6@ ,
+['] local7@ ,
+['] local8@ ,
+
+create locals-write-table
+['] local1! ,
+['] local2! ,
+['] local3! ,
+['] local4! ,
+['] local5! ,
+['] local6! ,
+['] local7! ,
+['] local8! ,
+
+
+: locals-push ( n -- )
+ locals-var-sp /n + to locals-var-sp
+ locals-var-sp !
+;
+
+: locals-0-push ( -- )
+ 0 locals-push
+;
+
+: (apply-local-flags) ( lfa -- )
+ 1 - dup c@ locals-flags or swap c!
+;
+
+: locals-no-pop? ( lfa -- ? )
+ 1 - c@ 8 and 0<>
+;
+
+: locals-drop \ Destroy current stack frame
+ locals-var-sp @ to locals-var-sp
+;
+
+['] locals-drop to locals-end
+
+: (local-init) ( str len -- )
+ header 1 , \ DOCOL
+ ['] (lit) , ['] noop , \ read-xt
+ ['] (lit) , ['] noop , \ write-xt
+ ['] 2drop , \ do nothing
+ ['] (lit) ,
+ here 5 cells - ,
+ ['] @ , ['] , , \ store read-xt
+ ['] (semis) ,
+ reveal
+ immediate
+ last @ (apply-local-flags)
+;
+
+: (local-noop) ( str len -- )
+ 2drop
+;
+
+\ Word called when consuming a local variable
+defer (local)
+
+: } ( C: current latest here -- )
+ here! latest ! current ! \ Switch back to normal dict
+ locals-dict-buf @ to locals-dict \ Make locals-dict visible to $find
+ 0 to locals-var-count
+ ['] locals-var-sp , \ save previous sp on rstack
+ ['] >r ,
+ locals-dict @ \ ( last -- )
+ begin
+ ?dup 0<>
+ while
+ >r
+ locals-var-count /n *
+ locals-read-table + @ r@ 3 cells + ! \ set read-xt
+ locals-var-count /n *
+ locals-write-table + @ r@ 5 cells + ! \ set write-xt
+ locals-var-count 1+ to locals-var-count
+ r@ locals-no-pop? if
+ ['] locals-0-push , \ initialise with 0
+ else
+ ['] locals-push , \ initialise from stack
+ then
+ r> @ \ next lfa
+ repeat
+ ['] r> ,
+ ['] locals-push , \ write previous sp
+; immediate
+
+: { ( C: -- current latest here )
+ current @ latest @ here
+ ['] (local-init) to (local)
+ 0 to locals-flags
+ 0 to locals-var-count
+ locals-dict-buf @ 200 cells 0 fill \ Zero out temporary dictionary
+ locals-dict-buf @ current ! \ Switch to locals dictionary
+ locals-dict-buf @ /n + here!
+
+ begin
+ parse-word
+ 2dup s" }" strcmp 0= if
+ 2drop
+ ['] } execute -1
+ else
+ 2dup s" ;" strcmp 0= if
+ 2drop
+ 8 to locals-flags 0 \ Don't init from stack
+ else
+ 2dup s" |" strcmp 0= if
+ 2drop
+ 8 to locals-flags 0 \ Don't init from stack
+ else
+ 2dup s" --" strcmp 0= if
+ 2drop
+ ['] (local-noop) to (local) 0
+ else
+ locals-var-count #locals < if
+ (local) 0 \ accept local
+ else
+ s" maximum locals used ignoring " type type cr 0
+ then
+ locals-var-count 1+ to locals-var-count
+ then
+ then
+ then
+ then
+ until
+; immediate
+
+: -> ( n -- )
+ parse-word $find if
+ 4 cells + @ ,
+ else
+ s" unable to find word " type type
+ then
+; immediate
+
+[THEN]
diff --git a/roms/openbios/forth/lib/preinclude.fs b/roms/openbios/forth/lib/preinclude.fs
new file mode 100644
index 00000000..6f20ea8f
--- /dev/null
+++ b/roms/openbios/forth/lib/preinclude.fs
@@ -0,0 +1,11 @@
+\
+\ config and build date includes
+\
+\ Copyright (C) 2005 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+include config.fs
+include version.fs
diff --git a/roms/openbios/forth/lib/preprocessor.fs b/roms/openbios/forth/lib/preprocessor.fs
new file mode 100644
index 00000000..89d478cf
--- /dev/null
+++ b/roms/openbios/forth/lib/preprocessor.fs
@@ -0,0 +1,76 @@
+\ tag: Forth preprocessor
+\
+\ Forth preprocessor
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+0 value prep-wid
+0 value prep-dict
+0 value prep-here
+
+: ([IF])
+ begin
+ begin parse-word dup 0= while
+ 2drop refill
+ repeat
+
+ 2dup " [IF]" strcmp 0= if 1 throw then
+ 2dup " [IFDEF]" strcmp 0= if 1 throw then
+ 2dup " [ELSE]" strcmp 0= if 2 throw then
+ 2dup " [THEN]" strcmp 0= if 3 throw then
+ " \\" strcmp 0= if linefeed parse 2drop then
+ again
+;
+
+: [IF] ( flag -- )
+ if exit then
+ 1 begin
+ ['] ([IF]) catch case
+ \ EOF (FIXME: this does not work)
+ \ -1 of ." Missing [THEN]" abort exit endof
+ \ [IF]
+ 1 of 1+ endof
+ \ [ELSE]
+ 2 of dup 1 = if 1- then endof
+ \ [THEN]
+ 3 of 1- endof
+ endcase
+ dup 0 <=
+ until drop
+; immediate
+
+: [ELSE] 0 [ ['] [IF] , ] ; immediate
+: [THEN] ; immediate
+
+:noname
+ 0 to prep-wid
+ 0 to prep-dict
+; initializer
+
+: [IFDEF] ( <word> -- )
+ prep-wid if
+ parse-word prep-wid search-wordlist dup if nip then
+ else 0 then
+ [ ['] [IF] , ]
+; immediate
+
+: [DEFINE] ( <word> -- )
+ parse-word here get-current >r >r
+ prep-dict 0= if
+ 2000 alloc-mem here!
+ here to prep-dict
+ wordlist to prep-wid
+ here to prep-here
+ then
+ prep-wid set-current prep-here here!
+ $create
+ here to prep-here
+ r> r> set-current here!
+; immediate
+
+: [0] 0 ; immediate
+: [1] 1 ; immediate
diff --git a/roms/openbios/forth/lib/split.fs b/roms/openbios/forth/lib/split.fs
new file mode 100644
index 00000000..1a7ac3a0
--- /dev/null
+++ b/roms/openbios/forth/lib/split.fs
@@ -0,0 +1,49 @@
+\ implements split-before, split-after and left-split
+\ as described in 4.3 (Path resolution)
+
+\ delimeter returned in R-string
+: split-before ( addr len delim -- addr-R len-R addr-L len-L )
+ 0 rot dup >r 0 ?do
+ ( str char cnt R: len <sys> )
+ 2 pick over + c@ 2 pick = if leave then
+ 1+
+ loop
+ nip
+ 2dup + r> 2 pick -
+ 2swap
+;
+
+\ delimeter returned in L-string
+: split-after ( addr len delim -- addr-R len-R addr-L len-L )
+ over 1- rot dup >r 0 ?do
+ ( str char cnt R: len <sys> )
+ 2 pick over + c@ 2 pick = if leave then
+ 1-
+ loop
+ nip
+ dup 0 >= if 1+ else drop r@ then
+ 2dup + r> 2 pick -
+ 2swap
+;
+
+\ delimiter not returned
+: left-split ( addr len delim -- addr-R len-R addr-L len-L )
+ 0 rot dup >r 0 ?do
+ ( str char cnt R: len <sys> )
+ 2 pick i + c@ 2 pick = if leave then
+ 1+
+ loop
+ nip
+ 2dup + 1+ r> 2 pick -
+ dup if 1- then
+ 2swap
+;
+
+\ delimiter not returned [THIS FUNCTION IS NOT NEEDED]
+: right-split ( addr len delim -- addr-R len-R addr-L len-L )
+ dup >r
+ split-after
+ dup if 2dup + 1-
+ c@ r@ = if 1- then then
+ r> drop
+;
diff --git a/roms/openbios/forth/lib/string.fs b/roms/openbios/forth/lib/string.fs
new file mode 100644
index 00000000..eb647491
--- /dev/null
+++ b/roms/openbios/forth/lib/string.fs
@@ -0,0 +1,127 @@
+\ tag: misc useful functions
+\
+\ Misc useful functions
+\
+\ Copyright (C) 2003 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ compare c-string with (str len) pair
+: comp0 ( cstr str len -- 0|-1|1 )
+ 3dup
+ comp ?dup if >r 3drop r> exit then
+ nip + c@ 0<> if 1 else 0 then
+;
+
+\ returns 0 if the strings match
+: strcmp ( str1 len1 str2 len2 -- 0|1 )
+ rot over <> if 3drop 1 exit then
+ comp if 1 else 0 then
+;
+
+: strchr ( str len char -- where|0 )
+ >r
+ begin
+ 1- dup 0>=
+ while
+ ( str len )
+ over c@ r@ = if r> 2drop exit then
+ swap 1+ swap
+ repeat
+ r> 3drop 0
+;
+
+: cstrlen ( cstr -- len )
+ dup
+ begin dup c@ while 1+ repeat
+ swap -
+;
+
+: strdup ( str len -- newstr len )
+ dup if
+ dup >r
+ dup alloc-mem dup >r swap move
+ r> r>
+ else
+ 2drop 0 0
+ then
+;
+
+: dict-strdup ( str len -- dict-addr len )
+ dup here swap allot null-align
+ swap 2dup >r >r move r> r>
+;
+
+\ -----------------------------------------------------
+\ string copy and cat variants
+\ -----------------------------------------------------
+
+: tmpstrcat ( addr2 len2 addr1 len1 tmpbuf -- buf len1+len2 tmpbuf+l1+l2 )
+ \ save return arguments
+ dup 2 pick + 4 pick + >r ( R: buf+l1+l2 )
+ over 4 pick + >r
+ dup >r
+ \ copy...
+ 2dup + >r
+ swap move r> swap move
+ r> r> r>
+;
+
+: tmpstrcpy ( addr1 len1 tmpbuf -- tmpbuf len1 tmpbuf+len1 )
+ swap 2dup >r >r move
+ r> r> 2dup +
+;
+
+
+
+\ -----------------------------------------------------
+\ number to string conversion
+\ -----------------------------------------------------
+
+: numtostr ( num buf -- buf len )
+ swap rdepth -rot
+ ( rdepth buf num )
+ begin
+ base @ u/mod swap
+ \ dup 0< if base @ + then
+ dup a < if ascii 0 else ascii a a - then + >r
+ ?dup 0=
+ until
+
+ rdepth rot - 0
+ ( buf len cnt )
+ begin
+ r> over 4 pick + c!
+ 1+ 2dup <=
+ until
+ drop
+;
+
+: tohexstr ( num buf -- buf len )
+ base @ hex -rot numtostr rot base !
+;
+
+: toudecstr ( num buf -- buf len )
+ base @ decimal -rot numtostr rot base !
+;
+
+: todecstr ( num buf -- buf len )
+ over 0< if
+ swap negate over ascii - over c! 1+
+ ( buf num buf+1 )
+ toudecstr 1+ nip
+ else
+ toudecstr
+ then
+;
+
+
+\ -----------------------------------------------------
+\ string to number conversion
+\ -----------------------------------------------------
+
+: parse-hex ( str len -- value )
+ base @ hex -rot $number if 0 then swap base !
+;
diff --git a/roms/openbios/forth/lib/vocabulary.fs b/roms/openbios/forth/lib/vocabulary.fs
new file mode 100644
index 00000000..faa75ea8
--- /dev/null
+++ b/roms/openbios/forth/lib/vocabulary.fs
@@ -0,0 +1,153 @@
+\ tag: vocabulary implementation for openbios
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\
+\ this is an implementation of DPANS94 wordlists (SEARCH EXT)
+\
+
+
+16 constant #vocs
+create vocabularies #vocs cells allot \ word lists
+['] vocabularies to context
+
+: search-wordlist ( c-addr u wid -- 0 | xt 1 | xt -1 )
+ \ Find the definition identified by the string c-addr u in the word
+ \ list identified by wid. If the definition is not found, return zero.
+ \ If the definition is found, return its execution token xt and
+ \ one (1) if the definition is immediate, minus-one (-1) otherwise.
+ find-wordlist
+ if
+ true over immediate? if
+ negate
+ then
+ else
+ 2drop false
+ then
+ ;
+
+: wordlist ( -- wid )
+ \ Creates a new empty word list, returning its word list identifier
+ \ wid. The new word list may be returned from a pool of preallocated
+ \ word lists or may be dynamically allocated in data space. A system
+ \ shall allow the creation of at least 8 new word lists in addition
+ \ to any provided as part of the system.
+ here 0 ,
+ ;
+
+: get-order ( -- wid1 .. widn n )
+ #order @ 0 ?do
+ #order @ i - 1- cells context + @
+ loop
+ #order @
+ ;
+
+: set-order ( wid1 .. widn n -- )
+ dup -1 = if
+ drop forth-last 1 \ push system default word list and number of lists
+ then
+ dup #order !
+ 0 ?do
+ i cells context + !
+ loop
+ ;
+
+: order ( -- )
+ \ display word lists in the search order in their search order sequence
+ \ from the first searched to last searched. Also display word list into
+ \ which new definitions will be placed.
+ cr
+ get-order 0 ?do
+ ." wordlist " i (.) type 2e emit space u. cr
+ loop
+ cr ." definitions: " current @ u. cr
+ ;
+
+
+: previous ( -- )
+ \ Transform the search order consisting of widn, ... wid2, wid1 (where
+ \ wid1 is searched first) into widn, ... wid2. An ambiguous condition
+ \ exists if the search order was empty before PREVIOUS was executed.
+ get-order nip 1- set-order
+ ;
+
+
+: do-vocabulary ( -- ) \ implementation factor
+ does>
+ @ >r ( ) ( R: widnew )
+ get-order swap drop ( wid1 ... widn-1 n )
+ r> swap set-order
+ ;
+
+: discard ( x1 .. xu u - ) \ implementation factor
+ 0 ?do
+ drop
+ loop
+ ;
+
+: vocabulary ( >name -- )
+ wordlist create , do-vocabulary
+ ;
+
+: also ( -- )
+ get-order over swap 1+ set-order
+ ;
+
+: only ( -- )
+ -1 set-order also
+ ;
+
+only
+
+\ create forth forth-wordlist , do-vocabulary
+create forth get-order over , discard do-vocabulary
+
+: findw ( c-addr -- c-addr 0 | w 1 | w -1 )
+ 0 ( c-addr 0 )
+ #order @ 0 ?do
+ over count ( c-addr 0 c-addr' u )
+ i cells context + @ ( c-addr 0 c-addr' u wid )
+ search-wordlist ( c-addr 0; 0 | w 1 | w -1 )
+ ?dup if ( c-addr 0; w 1 | w -1 )
+ 2swap 2drop leave ( w 1 | w -1 )
+ then ( c-addr 0 )
+ loop ( c-addr 0 | w 1 | w -1 )
+ ;
+
+: get-current ( -- wid )
+ current @
+ ;
+
+: set-current ( wid -- )
+ current !
+ ;
+
+: definitions ( -- )
+ \ Make the compilation word list the same as the first word list in
+ \ the search order. Specifies that the names of subsequent definitions
+ \ will be placed in the compilation word list.
+ \ Subsequent changes in the search order will not affect the
+ \ compilation word list.
+ context @ set-current
+ ;
+
+: forth-wordlist ( -- wid )
+ forth-last
+ ;
+
+: #words ( -- )
+ 0 last
+ begin
+ @ ?dup
+ while
+ swap 1+ swap
+ repeat
+
+ cr
+ ;
+
+true to vocabularies?
diff --git a/roms/openbios/forth/packages/Kconfig b/roms/openbios/forth/packages/Kconfig
new file mode 100644
index 00000000..16fa3065
--- /dev/null
+++ b/roms/openbios/forth/packages/Kconfig
@@ -0,0 +1,16 @@
+
+config PKG_DEBLOCKER
+ bool "Deblocker"
+ default y
+
+config PKG_DISKLABEL
+ bool "Disk Label"
+ default y
+
+config PKG_OBP_TFTP
+ bool "OBP-TFTP"
+ default y
+
+config PKG_TERMINAL_EMULATOR
+ bool "Terminal Emulator"
+ default y
diff --git a/roms/openbios/forth/packages/README b/roms/openbios/forth/packages/README
new file mode 100644
index 00000000..009f9ec3
--- /dev/null
+++ b/roms/openbios/forth/packages/README
@@ -0,0 +1,11 @@
+IEEE 1275-1994 support packages
+-------------------------------
+
+These files create the sub nodes of the /packages node. The nodes
+do normally not need an open or close method since their methods are
+called statically.
+
+Currently there are the following support packages:
+* deblocker
+* obp-tftp
+*
diff --git a/roms/openbios/forth/packages/build.xml b/roms/openbios/forth/packages/build.xml
new file mode 100644
index 00000000..16184717
--- /dev/null
+++ b/roms/openbios/forth/packages/build.xml
@@ -0,0 +1,19 @@
+<build>
+
+ <!--
+ build description for Open Firmware support packages
+
+ Copyright (C) 2004-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="openbios" target="forth">
+ <object source="packages.fs"/>
+ <object source="deblocker.fs" condition="PKG_DEBLOCKER"/>
+ <object source="disklabel.fs" condition="PKG_DISKLABEL"/>
+ <object source="terminal-emulator.fs" condition="PKG_TERM_EMUL"/>
+ <object source="obp-tftp.fs" condition="OBP_TFTP"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/forth/packages/deblocker.fs b/roms/openbios/forth/packages/deblocker.fs
new file mode 100644
index 00000000..31a37d00
--- /dev/null
+++ b/roms/openbios/forth/packages/deblocker.fs
@@ -0,0 +1,63 @@
+\ tag: deblocker support package
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+" /packages" find-device
+
+\ The deblocker package makes it easy to implement byte-oriented device
+\ methods, using the block-oriented or record-oriented methods defined by
+\ devices such as disks or tapes. It provides a layer of buffering between
+\ the high-level byte-oriented interface and the low-level block-oriented
+\ interface. deblocker uses the max-transfer, block-size, read-blocks and
+\ write-blocks methods of its parent.
+
+new-device
+ " deblocker" device-name
+ \ open ( -- flag )
+ \ Prepares the package for subsequent use, allocating the buffers used
+ \ by the deblocking process based upon the values returned by the parent
+ \ instance's max-transfer and block-size methods. Returns -1 if the
+ \ operation succeeds, 0 otherwise.
+ : open ( -- flag )
+
+ ;
+
+ \ close ( -- )
+ \ Frees all resources that were allocated by open.
+ : close ( -- )
+ ;
+
+ \ read ( adr len -- actual )
+ \ Reads at most len bytes from the device into the memory buffer
+ \ beginning at adr. Returns actual, the number of bytes actually
+ \ read, or 0 if the read operation failed. Uses the parent's read-
+ \ blocks method as necessary to satisfy the request, buffering any
+ \ unused bytes for the next request.
+
+ : read ( adr len -- actual )
+ ;
+
+ \ Writes at most len bytes from the device into the memory buffer
+ \ beginning at adr. Returns actual, the number of bytes actually
+ \ read, or 0 if the write operation failed. Uses the parent's write-
+ \ blocks method as necessary to satisfy the request, buffering any
+ \ unused bytes for the next request.
+
+ : write ( adr len -- actual )
+ ;
+
+ \ Sets the device position at which the next read or write will take
+ \ place. The position is specified by the 64-bit number x.position.
+ \ Returns 0 if the operation succeeds or -1 if it fails.
+
+ : seek ( x.position -- flag )
+ ;
+
+finish-device
+
+\ clean up afterwards
+device-end
diff --git a/roms/openbios/forth/packages/disklabel.fs b/roms/openbios/forth/packages/disklabel.fs
new file mode 100644
index 00000000..39aa13e5
--- /dev/null
+++ b/roms/openbios/forth/packages/disklabel.fs
@@ -0,0 +1,22 @@
+\ tag: disklabel support package
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+" /packages" find-device
+
+\
+\ IEEE 1275 disklabel package
+\
+
+new-device
+ " disklabel" device-name
+ \ now the methods...
+
+finish-device
+
+\ clean up afterwards
+device-end
diff --git a/roms/openbios/forth/packages/obp-tftp.fs b/roms/openbios/forth/packages/obp-tftp.fs
new file mode 100644
index 00000000..62f0e72e
--- /dev/null
+++ b/roms/openbios/forth/packages/obp-tftp.fs
@@ -0,0 +1,22 @@
+\ tag: tftp support package
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+" /packages" find-device
+
+\
+\ IEEE 1275 obp-tftp package
+\
+
+new-device
+ " obp-tftp" device-name
+ \ now the methods...
+
+finish-device
+
+\ clean up afterwards
+device-end
diff --git a/roms/openbios/forth/packages/packages.fs b/roms/openbios/forth/packages/packages.fs
new file mode 100644
index 00000000..9f79f9e5
--- /dev/null
+++ b/roms/openbios/forth/packages/packages.fs
@@ -0,0 +1,17 @@
+\ tag: /packages sub device tree
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+" /" find-device
+
+new-device
+ " packages" device-name
+ : open true ;
+ : close ;
+finish-device
+
+device-end
diff --git a/roms/openbios/forth/packages/terminal-emulator.fs b/roms/openbios/forth/packages/terminal-emulator.fs
new file mode 100644
index 00000000..0ecd348b
--- /dev/null
+++ b/roms/openbios/forth/packages/terminal-emulator.fs
@@ -0,0 +1,23 @@
+\ tag: terminal emulator support package
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+" /packages" find-device
+
+\
+\ IEEE 1275 terminal-emulator package
+\
+
+new-device
+ " terminal-emulator" device-name
+ \ now the methods...
+
+finish-device
+
+\ clean up afterwards
+
+device-end
diff --git a/roms/openbios/forth/system/build.xml b/roms/openbios/forth/system/build.xml
new file mode 100644
index 00000000..f15440a0
--- /dev/null
+++ b/roms/openbios/forth/system/build.xml
@@ -0,0 +1,16 @@
+<build>
+
+ <!--
+ build description for openbios system bindings
+
+ Copyright (C) 2004-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="openbios" target="forth">
+ <object source="main.fs"/>
+ <object source="ciface.fs"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/forth/system/ciface.fs b/roms/openbios/forth/system/ciface.fs
new file mode 100644
index 00000000..fd6c54ef
--- /dev/null
+++ b/roms/openbios/forth/system/ciface.fs
@@ -0,0 +1,363 @@
+
+0 value ciface-ph
+
+dev /openprom/
+new-device
+" client-services" device-name
+
+active-package to ciface-ph
+
+\ -------------------------------------------------------------
+\ private stuff
+\ -------------------------------------------------------------
+
+private
+
+variable callback-function
+
+: ?phandle ( phandle -- phandle )
+ dup 0= if ." NULL phandle" -1 throw then
+;
+: ?ihandle ( ihandle -- ihandle )
+ dup 0= if ." NULL ihandle" -2 throw then
+;
+
+\ copy and null terminate return string
+: ci-strcpy ( buf buflen str len -- len )
+ >r -rot dup
+ ( str buf buflen buflen R: len )
+ r@ min swap
+ ( str buf n buflen R: len )
+ over > if
+ ( str buf n )
+ 2dup + 0 swap c!
+ then
+ move r>
+;
+
+0 value memory-ih
+0 value mmu-ih
+
+:noname ( -- )
+ " /chosen" find-device
+
+ " mmu" active-package get-package-property 0= if
+ decode-int nip nip to mmu-ih
+ then
+
+ " memory" active-package get-package-property 0= if
+ decode-int nip nip to memory-ih
+ then
+ device-end
+; SYSTEM-initializer
+
+: safetype
+ ." <" dup cstrlen dup 20 < if type else 2drop ." BAD" then ." >"
+;
+
+: phandle-exists? ( phandle -- found? )
+ false swap 0
+ begin iterate-tree ?dup while
+ ( found? find-ph current-ph )
+ over over = if
+ rot drop true -rot
+ then
+ repeat
+ drop
+;
+
+\ -------------------------------------------------------------
+\ public interface
+\ -------------------------------------------------------------
+
+external
+
+\ -------------------------------------------------------------
+\ 6.3.2.1 Client interface
+\ -------------------------------------------------------------
+
+\ returns -1 if missing
+: test ( name -- 0|-1 )
+ dup cstrlen ciface-ph find-method
+ if drop 0 else -1 then
+;
+
+\ -------------------------------------------------------------
+\ 6.3.2.2 Device tree
+\ -------------------------------------------------------------
+
+: peer peer ;
+: child child ;
+: parent parent ;
+
+: getproplen ( name phandle -- len|-1 )
+ over cstrlen swap
+ ?phandle get-package-property
+ if -1 else nip then
+;
+
+: getprop ( buflen buf name phandle -- size|-1 )
+ \ detect phandle == -1
+ dup -1 = if
+ 2drop 2drop -1 exit
+ then
+
+ \ return -1 if phandle is 0 (MacOS actually does this)
+ ?dup 0= if drop 2drop -1 exit then
+
+ over cstrlen swap
+ ?phandle get-package-property if 2drop -1 exit then
+ ( buflen buf prop proplen )
+ >r swap rot r>
+ ( prop buf buflen proplen )
+ dup >r min move r>
+;
+
+\ 1 OK, 0 no more prop, -1 prev invalid
+: nextprop ( buf prev phandle -- 1|0|-1 )
+ >r
+ dup 0= if 0 else dup cstrlen then
+
+ ( buf prev prev_len )
+
+ \ verify that prev exists (overkill...)
+ dup if
+ 2dup r@ get-package-property if
+ r> 2drop drop
+ 0 swap c!
+ -1 exit
+ else
+ 2drop
+ then
+ then
+
+ ( buf prev prev_len )
+
+ r> next-property if
+ ( buf name name_len )
+ dup 1+ -rot ci-strcpy drop 1
+ else
+ ( buf )
+ 0 swap c!
+ 0
+ then
+;
+
+: setprop ( len buf name phandle -- size )
+ 3 pick >r
+ >r >r swap encode-bytes \ ( prop-addr prop-len R: phandle name )
+ r> dup cstrlen r>
+ (property)
+ r>
+;
+
+: finddevice ( dev_spec -- phandle|-1 )
+ dup cstrlen
+ \ ." FIND-DEVICE " 2dup type
+ find-dev 0= if -1 then
+ \ ." -- " dup . cr
+;
+
+: instance-to-package ( ihandle -- phandle )
+ ?ihandle ihandle>phandle
+;
+
+: package-to-path ( buflen buf phandle -- length )
+ \ XXX improve error checking
+ dup 0= if 3drop -1 exit then
+ >r swap r>
+ get-package-path
+ ( buf buflen str len )
+ ci-strcpy
+;
+
+: canon ( buflen buf dev_specifier -- len )
+ dup cstrlen find-dev if
+ ( buflen buf phandle )
+ package-to-path
+ else
+ 2drop -1
+ then
+;
+
+: instance-to-path ( buflen buf ihandle -- length )
+ \ XXX improve error checking
+ dup 0= if 3drop -1 exit then
+ >r swap r>
+ get-instance-path
+ \ ." INSTANCE: " 2dup type cr dup .
+ ( buf buflen str len )
+ ci-strcpy
+;
+
+: instance-to-interposed-path ( buflen buf ihandle -- length )
+ \ XXX improve error checking
+ dup 0= if 3drop -1 exit then
+ >r swap r>
+ get-instance-interposed-path
+ ( buf buflen str len )
+ ci-strcpy
+;
+
+: call-method ( ihandle method -- xxxx catch-result )
+ dup 0= if ." call of null method" -1 exit then
+ dup >r
+ dup cstrlen
+ \ ." call-method " 2dup type cr
+ rot ?ihandle ['] $call-method catch dup if
+ \ not necessary an error but very useful for debugging...
+ ." call-method " r@ dup cstrlen type ." : exception " dup . cr
+ then
+ r> drop
+;
+
+
+\ -------------------------------------------------------------
+\ 6.3.2.3 Device I/O
+\ -------------------------------------------------------------
+
+: open ( dev_spec -- ihandle|0 )
+ dup cstrlen open-dev
+;
+
+: close ( ihandle -- )
+ close-dev
+;
+
+: read ( len addr ihandle -- actual )
+ >r swap r>
+ dup ihandle>phandle " read" rot find-method
+ if swap call-package else 3drop -1 then
+;
+
+: write ( len addr ihandle -- actual )
+ >r swap r>
+ dup ihandle>phandle " write" rot find-method
+ if swap call-package else 3drop -1 then
+;
+
+: seek ( pos_lo pos_hi ihandle -- status )
+ dup ihandle>phandle " seek" rot find-method
+ if swap call-package else 3drop -1 then
+;
+
+
+\ -------------------------------------------------------------
+\ 6.3.2.4 Memory
+\ -------------------------------------------------------------
+
+: claim ( align size virt -- baseaddr|-1 )
+ -rot swap
+ ciface-ph " cif-claim" rot find-method
+ if execute else 3drop -1 then
+;
+
+: release ( size virt -- )
+ swap
+ ciface-ph " cif-release" rot find-method
+ if execute else 2drop -1 then
+;
+
+\ -------------------------------------------------------------
+\ 6.3.2.5 Control transfer
+\ -------------------------------------------------------------
+
+: boot ( bootspec -- )
+ ." BOOT"
+;
+
+: enter ( -- )
+ ." ENTER"
+;
+
+\ exit ( -- ) is defined later (clashes with builtin exit)
+
+: chain ( virt size entry args len -- )
+ ." CHAIN"
+;
+
+\ -------------------------------------------------------------
+\ 6.3.2.6 User interface
+\ -------------------------------------------------------------
+
+: interpret ( xxx cmdstring -- ??? catch-reult )
+ dup cstrlen
+ \ ." INTERPRETE: --- " 2dup type
+ ['] evaluate catch dup if
+ \ this is not necessary an error...
+ ." interpret: exception " dup . ." caught" cr
+
+ \ Force back to interpret state on error, otherwise the next call to
+ \ interpret gets confused if the error occurred in compile mode
+ 0 state !
+ then
+ \ ." --- " cr
+;
+
+: set-callback ( newfunc -- oldfunc )
+ callback-function @
+ swap
+ callback-function !
+;
+
+\ : set-symbol-lookup ( sym-to-value -- value-to-sym ) ;
+
+
+\ -------------------------------------------------------------
+\ 6.3.2.7 Time
+\ -------------------------------------------------------------
+
+: milliseconds ( -- ms )
+ get-msecs
+;
+
+\ -------------------------------------------------------------
+\ arch?
+\ -------------------------------------------------------------
+
+: start-cpu ( xxx xxx xxx --- )
+ ." Start CPU unimplemented" cr
+ 3drop
+;
+
+\ -------------------------------------------------------------
+\ special
+\ -------------------------------------------------------------
+
+: exit ( -- )
+ ." EXIT"
+ outer-interpreter
+;
+
+: test-method ( cstring-method phandle -- missing? )
+ swap dup cstrlen rot
+
+ \ Check for incorrect phandle
+ dup phandle-exists? false = if
+ -1 throw
+ then
+
+ find-method 0= if -1 else drop 0 then
+;
+
+finish-device
+device-end
+
+
+\ -------------------------------------------------------------
+\ entry point
+\ -------------------------------------------------------------
+
+: client-iface ( [args] name len -- [args] -1 | [rets] 0 )
+ ciface-ph find-method 0= if -1 exit then
+ catch ?dup if
+ cr ." Unexpected client interface exception: " . -2 cr exit
+ then
+ 0
+;
+
+: client-call-iface ( [args] name len -- [args] -1 | [rets] 0 )
+ ciface-ph find-method 0= if -1 exit then
+ execute
+ 0
+;
diff --git a/roms/openbios/forth/system/main.fs b/roms/openbios/forth/system/main.fs
new file mode 100644
index 00000000..122ab1fa
--- /dev/null
+++ b/roms/openbios/forth/system/main.fs
@@ -0,0 +1,60 @@
+\ tag: misc useful functions
+\
+\ Open Firmware Startup
+\
+\ Copyright (C) 2003 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+variable PREPOST-list
+variable POST-list
+variable SYSTEM-list
+variable DIAG-list
+
+: PREPOST-initializer ( xt -- )
+ PREPOST-list list-add ,
+;
+
+: POST-initializer ( xt -- )
+ POST-list list-add ,
+;
+
+: SYSTEM-initializer ( xt -- )
+ SYSTEM-list list-add ,
+;
+
+: DIAG-initializer ( xt -- )
+ DIAG-list list-add ,
+;
+
+
+\ OpenFirmware entrypoint
+: initialize-of ( startmem endmem -- )
+ initialize-forth
+
+ PREPOST-list begin list-get while @ execute repeat
+ POST-list begin list-get while @ execute repeat
+ SYSTEM-list begin list-get while @ execute repeat
+
+ \ evaluate nvramrc script
+ use-nvramrc? if
+ nvramrc evaluate
+ then
+
+ \ probe-all etc.
+ suppress-banner? 0= if
+ probe-all
+ install-console
+ banner
+ then
+
+ DIAG-list begin list-get while @ execute repeat
+
+ auto-boot? if
+ boot-command evaluate
+ then
+
+ outer-interpreter
+;
diff --git a/roms/openbios/forth/testsuite/README b/roms/openbios/forth/testsuite/README
new file mode 100644
index 00000000..7aa98dea
--- /dev/null
+++ b/roms/openbios/forth/testsuite/README
@@ -0,0 +1,8 @@
+TESTSUITES
+----------
+
+This directory contains additional testsuites for some open
+firmware components. They are not built per default.
+
+
+tag: testsuites readme
diff --git a/roms/openbios/forth/testsuite/build.xml b/roms/openbios/forth/testsuite/build.xml
new file mode 100644
index 00000000..7b7d62bc
--- /dev/null
+++ b/roms/openbios/forth/testsuite/build.xml
@@ -0,0 +1,16 @@
+<build>
+
+ <!--
+ build description for OpenBIOS test suite
+
+ Copyright (C) 2004-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="testsuite" target="forth">
+ <object source="memory-testsuite.fs"/>
+ <object source="splitfunc-testsuite.fs"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/forth/testsuite/fract.fs b/roms/openbios/forth/testsuite/fract.fs
new file mode 100644
index 00000000..39c98405
--- /dev/null
+++ b/roms/openbios/forth/testsuite/fract.fs
@@ -0,0 +1,35 @@
+\ tag: forth fractal example
+\
+\ Copyright (C) 2002, 2003 Volker Poplawski <volker@poplawski.de>
+\ Stefan Reinauer
+
+\ This example even fits in a signature ;-)
+
+\ hex 4666 dup negate do i 4000 dup 2* negate do 2a 0 dup 2dup 1e 0 do
+\ 2swap * d >>a 4 pick + -rot - j + dup dup * e >>a rot dup dup * e >>a
+\ rot swap 2dup + 10000 > if 3drop 2drop 20 0 dup 2dup leave then loop
+\ 2drop 2drop type 268 +loop cr drop 5de +loop
+
+
+: fract
+4666 dup negate
+do
+ i 4000 dup 2* negate
+ do
+ 2a 0 dup 2dup 1e 0
+ do
+ 2swap * d >>a 4 pick +
+ -rot - j +
+ dup dup * e >>a rot
+ dup dup * e >>a rot
+ swap
+ 2dup + 10000 > if
+ 3drop 2drop 20 0 dup 2dup leave
+ then
+ loop
+ 2drop 2drop
+ emit
+ 268 +loop
+ cr drop
+5de +loop
+;
diff --git a/roms/openbios/forth/testsuite/framebuffer-test.fs b/roms/openbios/forth/testsuite/framebuffer-test.fs
new file mode 100644
index 00000000..11099325
--- /dev/null
+++ b/roms/openbios/forth/testsuite/framebuffer-test.fs
@@ -0,0 +1,10 @@
+
+: test-screen
+ 10 10 pci-l@
+ f0 0 do
+ dup d# 1280 i * +
+ 500 i fill
+ loop
+ ;
+
+ test-screen
diff --git a/roms/openbios/forth/testsuite/memory-testsuite.fs b/roms/openbios/forth/testsuite/memory-testsuite.fs
new file mode 100644
index 00000000..9dace511
--- /dev/null
+++ b/roms/openbios/forth/testsuite/memory-testsuite.fs
@@ -0,0 +1,106 @@
+\ this is the memory management testsuite.
+\
+\ run it with paflof < memory-testsuite.fs 2>/dev/null
+
+s" memory.fs" included
+
+\ dumps all free-list entries
+\ useful for debugging.
+
+: dump-freelist ( -- )
+ ." Dumping freelist:" cr
+ free-list @
+
+ \ If the free list is empty we notify the user.
+ dup 0= if ." empty." drop cr exit then
+
+ begin dup 0<> while
+ dup ." entry 0x" . \ print pointer to entry
+ dup cell+ @ ." , next=0x" u. \ pointer to next entry
+ dup @ ." , size=0x" u. cr \ len of current entry
+
+ cell+ @
+ repeat
+ cr drop
+ ;
+
+\ simple testsuite. run testsuite-init to initialize
+\ with some dummy memory in the dictionary.
+\ run testsuite-test[1..3] for different tests.
+
+: testsuite-init ( -- )
+ here 40000 cell+ dup allot ( -- ptr len )
+ init-mem
+
+ ." start-mem = 0x" start-mem @ . cr
+ ." end-mem = 0x" end-mem @ . cr
+ ." free-list = 0x" free-list @ . cr
+
+ ." Memory management initialized." cr
+ dump-freelist
+ ;
+
+: testsuite-test1 ( -- )
+ ." Test No. 1: Allocating all available memory (256k)" cr
+
+ 40000 alloc-mem
+ dup 0<> if
+ ." worked, ptr=0x" dup .
+ else
+ ." did not work."
+ then
+ cr
+
+ dump-freelist
+ ." Freeing memory." cr
+ ." stack=" .s cr
+ free-mem
+ dump-freelist
+ ;
+
+: testsuite-test2 ( -- )
+ ." Test No. 2: Allocating 5 blocks" cr
+ 4000 alloc-mem
+ 4000 alloc-mem
+ 4000 alloc-mem
+ 4000 alloc-mem
+ 4000 alloc-mem
+
+ ." Allocated 5 blocks. Stack:" cr .s cr
+
+ dump-freelist
+
+ ." Freeing Block 2" cr
+ 3 pick free-mem dump-freelist
+
+ ." Freeing Block 4" cr
+ over free-mem dump-freelist
+
+ ." Freeing Block 3" cr
+ 2 pick free-mem dump-freelist
+
+ ." Cleaning up blocks 1 and 5" cr
+ free-mem \ Freeing block 5
+ dump-freelist
+ 3drop \ blocks 4, 3, 2
+ free-mem
+
+ dump-freelist
+ ;
+
+: testsuite-test3 ( -- )
+ ." Test No. 3: freeing illegal address 0xdeadbeef." cr
+ deadbeef free-mem
+ dump-freelist
+ ;
+
+: testsuite ( -- )
+ testsuite-init
+ testsuite-test1
+ testsuite-test2
+ testsuite-test3
+ ;
+
+testsuite
+
+bye
diff --git a/roms/openbios/forth/testsuite/splitfunc-testsuite.fs b/roms/openbios/forth/testsuite/splitfunc-testsuite.fs
new file mode 100644
index 00000000..00469bb5
--- /dev/null
+++ b/roms/openbios/forth/testsuite/splitfunc-testsuite.fs
@@ -0,0 +1,38 @@
+\ this is the splitfunc testsuite.
+\
+\ run it with paflof < splitfunc-testsuite.fs 2>/dev/null
+
+\ implements split-before, split-after and left-split
+\ as described in 4.3 (Path resolution)
+
+s" splitfunc.fs" included
+
+: test-split
+ s" var/log/messages" 2dup
+
+ cr ." split-before test:" cr
+ 2dup ." String: " type cr
+ 2f split-before
+ 2swap
+ ." initial: " type cr ." remainder:" type cr
+ cr
+ ." split-after test:" cr
+ 2f split-after cr
+ 2swap
+ ." initial: " type cr ." remainder:" type cr
+
+ ." foobar test" cr
+
+ s" foobar" 2dup
+
+ 2f split-after cr
+ 2swap
+ ." initial: " type cr ." remainder:" type cr
+
+ 2f split-after cr
+ 2swap
+ ." initial: " type cr ." remainder:" type cr
+ ;
+
+
+
diff --git a/roms/openbios/forth/util/apic.fs b/roms/openbios/forth/util/apic.fs
new file mode 100644
index 00000000..82a62aa7
--- /dev/null
+++ b/roms/openbios/forth/util/apic.fs
@@ -0,0 +1,62 @@
+\
+\ ioapic and local apic tester
+\
+\ Copyright (C) 2003 Stefan Reinauer
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+hex
+
+fee00000 constant lapic_base
+fec00000 constant ioapic_base
+
+: read_lapic ( regoffset -- value )
+ lapic_base + l@
+ ;
+
+: write_lapic ( value regoffset -- )
+ lapic_base + l!
+ ;
+
+: read_ioapic ( regoffset -- low_value high_value )
+ 2* 10 + dup
+ ioapic_base l! ioapic_base 4 cells + l@
+ swap 1+
+ ioapic_base l! ioapic_base 4 cells + l@
+ ;
+
+: write_ioapic ( low high regoffset -- )
+ 2* 10 + dup ( low high offs offs )
+ ioapic_base l! rot ioapic_base 4 cells + l! ( high offs )
+ 1+
+ ioapic_base l! ioapic_base 4 cells + l! ( high offs )
+ ;
+
+: test-lapic
+ s" Dumping local apic:" type cr
+ 3f0 0 do
+ i dup ( lapic_base + ) s" 0x" type . s" = 0x" type read_lapic space .
+ i 30 and 0= if cr then
+ 10 +loop
+ cr
+ ;
+
+: test-ioapic
+ s" Dumping io apic:" type cr
+ 17 0 do
+ i dup s" irq=" type . read_ioapic s" = 0x" type . s" ." type .
+ i 1 and 0<> if
+ cr
+ then
+ loop
+ cr
+ ;
+
+: dump-apics
+ test-lapic
+ test-ioapic
+ ;
+
+\ tag: apic test utility
diff --git a/roms/openbios/forth/util/build.xml b/roms/openbios/forth/util/build.xml
new file mode 100644
index 00000000..4839d2cd
--- /dev/null
+++ b/roms/openbios/forth/util/build.xml
@@ -0,0 +1,19 @@
+<build>
+
+ <!--
+ build description for OpenBIOS utility functions
+
+ Copyright (C) 2004-2005 by Stefan Reinauer
+ See the file "COPYING" for further information about
+ the copyright and warranty status of this work.
+ -->
+
+ <dictionary name="openbios" target="forth">
+ <object source="util.fs"/>
+ <object source="pci.fs"/>
+ <!-- We don't want/need these at the moment
+ <object source="apic.fs"/>
+ -->
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/forth/util/pci.fs b/roms/openbios/forth/util/pci.fs
new file mode 100644
index 00000000..57ded626
--- /dev/null
+++ b/roms/openbios/forth/util/pci.fs
@@ -0,0 +1,92 @@
+\ tag: PCI helper functions
+\
+\ Copyright (C) 2003-2004 Stefan Reinauer
+\ Copyright (C) 2003 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ simple set of words for pci access, these are not
+\ compliant to the PCI bus binding of OpenFirmware.
+
+\ only forth
+\ vocabulary pci
+\ also pci definitions
+
+hex
+
+: busdevfn ( bus dev fn -- busdevfn )
+ 7 and swap
+ 1f and 3 << or ( dev fn -- devfn )
+ swap 8 << or ( bus devfn -- busdevfn )
+ ;
+
+: config-command ( busdevfn reg -- reg addr )
+ dup -rot
+ 3 invert and
+ swap 8 << or
+ 80000000 or
+ ;
+
+: pci-c@ ( busdevfn reg -- x )
+ config-command
+ cf8 iol!
+ 3 and cfc +
+ ioc@
+ ;
+
+: pci-w@ ( busdevfn reg -- x )
+ config-command
+ cf8 iol!
+ 2 and cfc + iow@
+ ;
+
+: pci-l@ ( busdevfn reg -- x )
+ config-command
+ cf8 iol!
+ drop
+ cfc iol@
+ ;
+
+: pci-c! ( busdevfn reg val -- )
+ -rot config-command
+ cf8 iol!
+ 3 and cfc + ioc!
+ ;
+
+: pci-w! ( busdevfn reg val -- )
+ -rot config-command
+ cf8 iol!
+ 2 and cfc + iow!
+ ;
+
+: pci-l! ( busdevfn reg val -- )
+ -rot config-command
+ cf8 iol!
+ drop
+ cfc iol!
+ ;
+
+: dump-pci-device ( bus dev fn -- )
+ 2 pick (.) type 3a emit over
+ (.) type 2e emit dup (.) type 20 emit 5b emit \ 0:18.0 [
+ busdevfn >r
+ r@ 0 pci-w@ u. 2f emit r@ 2 pci-w@ u. 5d emit \ 1022/1100]
+ r>
+ \ now we iterate
+ 10 0 do
+ cr i todigit emit 30 emit 3a emit 20 emit
+ 10 0 do
+ dup i j 4 << or pci-c@
+ dup 4 >> todigit emit f and todigit emit
+ 20 emit
+ loop
+ loop
+ drop
+ cr cr
+ ;
+
+\ : test-pci
+\ 0 2 0 dump-pci-device
+\ ;
diff --git a/roms/openbios/forth/util/util.fs b/roms/openbios/forth/util/util.fs
new file mode 100644
index 00000000..6f549bf5
--- /dev/null
+++ b/roms/openbios/forth/util/util.fs
@@ -0,0 +1,95 @@
+\ tag: Utility functions
+\
+\ Utility functions
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ -------------------------------------------------------------------------
+\ package utils
+\ -------------------------------------------------------------------------
+
+( method-str method-len package-str package-len -- xt|0 )
+: $find-package-method
+ find-package 0= if 2drop false exit then
+ find-method 0= if 0 then
+;
+
+\ like $call-parent but takes an xt
+: call-parent ( ... xt -- ??? )
+ my-parent call-package
+;
+
+: [active-package],
+ ['] (lit) , active-package ,
+; immediate
+
+\ -------------------------------------------------------------------------
+\ word creation
+\ -------------------------------------------------------------------------
+
+: ?mmissing ( name len -- 1 name len | 0 )
+ 2dup active-package find-method
+ if 3drop false else true then
+;
+
+\ install trivial open and close functions
+: is-open ( -- )
+ " open" ?mmissing if ['] true -rot is-xt-func then
+ " close" ?mmissing if 0 -rot is-xt-func then
+;
+
+\ is-relay installs a relay function (a function that calls
+\ a function with the same name but belonging to a different node).
+\ The execution behaviour of xt should be ( -- ptr-to-ihandle ).
+\
+: is-relay ( xt ph name-str name-len -- )
+ rot >r 2dup r> find-method 0= if
+ \ function missing (not necessarily an error)
+ 3drop exit
+ then
+
+ -rot is-func-begin
+ ( xt method-xt )
+ ['] (lit) , , \ ['] method
+ , ['] @ , \ xt @
+ ['] call-package , \ call-package
+ is-func-end
+;
+
+\ -------------------------------------------------------------------------
+\ install deblocker bindings
+\ -------------------------------------------------------------------------
+
+: (open-deblocker) ( varaddr -- )
+ " deblocker" find-package if
+ 0 0 rot open-package
+ else 0 then
+ swap !
+;
+
+: is-deblocker ( -- )
+ " deblocker" find-package 0= if exit then >r
+ " deblocker" is-ivariable
+
+ \ create open-deblocker
+ " open-deblocker" is-func-begin
+ dup , ['] (open-deblocker) ,
+ is-func-end
+
+ \ create close-deblocker
+ " close-deblocker" is-func-begin
+ dup , ['] @ , ['] close-package ,
+ is-func-end
+
+ ( save-ph deblk-xt R: deblocker-ph )
+ r>
+ 2dup " read" is-relay
+ 2dup " seek" is-relay
+ 2dup " write" is-relay
+ 2dup " tell" is-relay
+ 2drop
+;
diff --git a/roms/openbios/fs/build.xml b/roms/openbios/fs/build.xml
new file mode 100644
index 00000000..9ecc0055
--- /dev/null
+++ b/roms/openbios/fs/build.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<build>
+
+ <library name="fs" type="static" target="target">
+ <object source="ioglue.c"/>
+ </library>
+
+ <include href="grubfs/build.xml"/>
+ <include href="hfs/build.xml"/>
+ <include href="hfsplus/build.xml"/>
+ <include href="iso9660/build.xml"/>
+ <include href="ext2/build.xml"/>
+
+</build>
diff --git a/roms/openbios/fs/ext2/build.xml b/roms/openbios/fs/ext2/build.xml
new file mode 100644
index 00000000..98e9e056
--- /dev/null
+++ b/roms/openbios/fs/ext2/build.xml
@@ -0,0 +1,14 @@
+<build>
+ <library name="fs" type="static" target="target">
+ <object source="ext2_close.c" condition="EXT2"/>
+ <object source="ext2_closedir.c" condition="EXT2"/>
+ <object source="ext2_fs.c" condition="EXT2"/>
+ <object source="ext2_lseek.c" condition="EXT2"/>
+ <object source="ext2_mount.c" condition="EXT2"/>
+ <object source="ext2_open.c" condition="EXT2"/>
+ <object source="ext2_opendir.c" condition="EXT2"/>
+ <object source="ext2_read.c" condition="EXT2"/>
+ <object source="ext2_readdir.c" condition="EXT2"/>
+ <object source="ext2_utils.c" condition="EXT2"/>
+ </library>
+</build>
diff --git a/roms/openbios/fs/ext2/ext2.h b/roms/openbios/fs/ext2/ext2.h
new file mode 100644
index 00000000..ad858928
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#ifndef __EXT2_H__
+#define __EXT2_H__
+
+#include "ext2_fs.h"
+
+typedef struct ext2_VOLUME {
+ int fd;
+ struct ext2_super_block *super;
+ unsigned int current;
+ char *buffer;
+} ext2_VOLUME;
+
+typedef struct ext2_DIR {
+ ext2_VOLUME *volume;
+ struct ext2_inode *inode;
+ off_t index;
+} ext2_DIR;
+
+typedef struct ext2_FILE {
+ ext2_VOLUME *volume;
+ struct ext2_inode *inode;
+ off_t offset;
+ char *path;
+} ext2_FILE;
+#endif /* __LIBEXT2_H__ */
diff --git a/roms/openbios/fs/ext2/ext2_close.c b/roms/openbios/fs/ext2/ext2_close.c
new file mode 100644
index 00000000..f370e181
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_close.c
@@ -0,0 +1,18 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+
+void ext2_close(ext2_FILE *file)
+{
+ if (file == NULL)
+ return;
+ free(file->inode);
+ free(file->path);
+ free(file);
+}
diff --git a/roms/openbios/fs/ext2/ext2_closedir.c b/roms/openbios/fs/ext2/ext2_closedir.c
new file mode 100644
index 00000000..e9f06319
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_closedir.c
@@ -0,0 +1,18 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+#include "ext2.h"
+
+void ext2_closedir(ext2_DIR *dir)
+{
+ if (dir == NULL)
+ return;
+ free(dir->inode);
+ free(dir);
+}
diff --git a/roms/openbios/fs/ext2/ext2_fs.c b/roms/openbios/fs/ext2/ext2_fs.c
new file mode 100644
index 00000000..66eb0b43
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_fs.c
@@ -0,0 +1,309 @@
+/*
+ * /packages/ext2-files
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ * (c) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libext2.h"
+#include "ext2_utils.h"
+#include "fs/fs.h"
+#include "libc/vsprintf.h"
+#include "libc/diskio.h"
+
+extern void ext2_init( void );
+
+typedef struct {
+ enum { FILE, DIR } type;
+ union {
+ ext2_FILE *file;
+ ext2_DIR *dir;
+ };
+} ext2_COMMON;
+
+typedef struct {
+ ext2_VOLUME *volume;
+ ext2_COMMON *common;
+} ext2_info_t;
+
+DECLARE_NODE( ext2, 0, sizeof(ext2_info_t), "+/packages/ext2-files" );
+
+
+static const int days_month[12] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static const int days_month_leap[12] =
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static inline int is_leap(int year)
+{
+ return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
+}
+
+static void
+print_date(time_t sec)
+{
+ unsigned int second, minute, hour, month, day, year;
+ int current;
+ const int *days;
+
+ second = sec % 60;
+ sec /= 60;
+
+ minute = sec % 60;
+ sec /= 60;
+
+ hour = sec % 24;
+ sec /= 24;
+
+ year = sec * 100 / 36525;
+ sec -= year * 36525 / 100;
+ year += 1970;
+
+ days = is_leap(year) ? days_month_leap : days_month;
+
+ current = 0;
+ month = 0;
+ while (month < 12) {
+ if (sec <= current + days[month]) {
+ break;
+ }
+ current += days[month];
+ month++;
+ }
+ month++;
+
+ day = sec - current + 1;
+
+ forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
+ year, month, day, hour, minute, second);
+}
+
+
+/************************************************************************/
+/* Standard package methods */
+/************************************************************************/
+
+/* ( -- success? ) */
+static void
+ext2_files_open( ext2_info_t *mi )
+{
+ int fd;
+ char *path = my_args_copy();
+
+ fd = open_ih( my_parent() );
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ mi->volume = ext2_mount(fd);
+ if (!mi->volume) {
+ RET( 0 );
+ }
+
+ mi->common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON));
+ if (mi->common == NULL)
+ RET( 0 );
+
+ mi->common->dir = ext2_opendir(mi->volume, path);
+ if (mi->common->dir == NULL) {
+ mi->common->file = ext2_open(mi->volume, path);
+ if (mi->common->file == NULL) {
+ free(mi->common);
+ RET( 0 );
+ }
+ mi->common->type = FILE;
+ RET( -1 );
+ }
+ mi->common->type = DIR;
+ RET( -1 );
+}
+
+/* ( -- ) */
+static void
+ext2_files_close( ext2_info_t *mi )
+{
+ ext2_COMMON *common = mi->common;
+
+ if (common->type == FILE)
+ ext2_close(common->file);
+ else if (common->type == DIR)
+ ext2_closedir(common->dir);
+ free(common);
+
+ ext2_umount(mi->volume);
+}
+
+/* ( buf len -- actlen ) */
+static void
+ext2_files_read( ext2_info_t *mi )
+{
+ int count = POP();
+ char *buf = (char *)cell2pointer(POP());
+
+ ext2_COMMON *common = mi->common;
+ if (common->type != FILE)
+ RET( -1 );
+
+ RET ( ext2_read( common->file, buf, count ) );
+}
+
+/* ( pos.d -- status ) */
+static void
+ext2_files_seek( ext2_info_t *mi )
+{
+ long long pos = DPOP();
+ int offs = (int)pos;
+ int whence = SEEK_SET;
+ int ret;
+ ext2_COMMON *common = mi->common;
+
+ if (common->type != FILE)
+ RET( -1 );
+
+ ret = ext2_lseek(common->file, offs, whence);
+ if (ret)
+ RET( -1 );
+ else
+ RET( 0 );
+}
+
+/* ( addr -- size ) */
+static void
+ext2_files_load( ext2_info_t *mi )
+{
+ char *buf = (char *)cell2pointer(POP());
+ int count;
+
+ ext2_COMMON *common = mi->common;
+ if (common->type != FILE)
+ RET( -1 );
+
+ /* Seek to the end in order to get the file size */
+ ext2_lseek(common->file, 0, SEEK_END);
+ count = common->file->offset;
+ ext2_lseek(common->file, 0, SEEK_SET);
+
+ RET ( ext2_read( common->file, buf, count ) );
+}
+
+/* ( -- cstr ) */
+static void
+ext2_files_get_path( ext2_info_t *mi )
+{
+ ext2_COMMON *common = mi->common;
+
+ if (common->type != FILE)
+ RET( 0 );
+
+ RET( pointer2cell(strdup(common->file->path)) );
+}
+
+/* ( -- cstr ) */
+static void
+ext2_files_get_fstype( ext2_info_t *mi )
+{
+ PUSH( pointer2cell(strdup("ext2")) );
+}
+
+/* static method, ( pathstr len ihandle -- ) */
+static void
+ext2_files_dir( ext2_info_t *dummy )
+{
+ ext2_COMMON *common;
+ ext2_VOLUME *volume;
+ struct ext2_dir_entry_2 *entry;
+ struct ext2_inode inode;
+ int fd;
+
+ ihandle_t ih = POP();
+ char *path = pop_fstr_copy();
+
+ fd = open_ih( ih );
+ if ( fd == -1 ) {
+ free( path );
+ return;
+ }
+
+ volume = ext2_mount(fd);
+ if (!volume) {
+ return;
+ }
+
+ common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON));
+ common->dir = ext2_opendir(volume, path);
+
+ forth_printf("\n");
+ while ( (entry = ext2_readdir(common->dir)) ) {
+ ext2_get_inode(common->dir->volume, entry->inode, &inode);
+ forth_printf("% 10d ", inode.i_size);
+ print_date(inode.i_mtime);
+ if (S_ISDIR(inode.i_mode))
+ forth_printf("%s\\\n", entry->name);
+ else
+ forth_printf("%s\n", entry->name);
+ }
+
+ ext2_closedir( common->dir );
+ ext2_umount( volume );
+
+ close_io( fd );
+
+ free( common );
+ free( path );
+}
+
+/* static method, ( pos.d ih -- flag? ) */
+static void
+ext2_files_probe( ext2_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ long long offs = DPOP();
+ int fd, ret = 0;
+
+ fd = open_ih(ih);
+ if (fd >= 0) {
+ if (ext2_probe(fd, offs)) {
+ ret = -1;
+ }
+ close_io(fd);
+ } else {
+ ret = -1;
+ }
+
+ RET (ret);
+}
+
+
+static void
+ext2_initializer( ext2_info_t *dummy )
+{
+ fword("register-fs-package");
+}
+
+NODE_METHODS( ext2 ) = {
+ { "probe", ext2_files_probe },
+ { "open", ext2_files_open },
+ { "close", ext2_files_close },
+ { "read", ext2_files_read },
+ { "seek", ext2_files_seek },
+ { "load", ext2_files_load },
+ { "dir", ext2_files_dir },
+
+ /* special */
+ { "get-path", ext2_files_get_path },
+ { "get-fstype", ext2_files_get_fstype },
+
+ { NULL, ext2_initializer },
+};
+
+void
+ext2_init( void )
+{
+ REGISTER_NODE( ext2 );
+}
diff --git a/roms/openbios/fs/ext2/ext2_fs.h b/roms/openbios/fs/ext2/ext2_fs.h
new file mode 100644
index 00000000..4a7adff7
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_fs.h
@@ -0,0 +1,534 @@
+/*
+ * This file has been copied from
+ * linux/include/linux/ext2_fs.h
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/include/linux/minix_fs.h
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#ifndef _EXT2_FS_H
+#define _EXT2_FS_H
+
+/* from /usr/include/linux/magic.h */
+
+#define EXT2_SUPER_MAGIC 0xEF53
+
+/*
+ * The second extended filesystem constants/structures
+ */
+
+/*
+ * Define EXT2FS_DEBUG to produce debug messages
+ */
+#undef EXT2FS_DEBUG
+
+/*
+ * Define EXT2_RESERVATION to reserve data blocks for expanding files
+ */
+#define EXT2_DEFAULT_RESERVE_BLOCKS 8
+/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
+#define EXT2_MAX_RESERVE_BLOCKS 1027
+#define EXT2_RESERVE_WINDOW_NOT_ALLOCATED 0
+/*
+ * The second extended file system version
+ */
+#define EXT2FS_DATE "95/08/09"
+#define EXT2FS_VERSION "0.5b"
+
+/*
+ * Debug code
+ */
+#ifdef EXT2FS_DEBUG
+# define ext2_debug(f, a...) { \
+ printk ("EXT2-fs DEBUG (%s, %d): %s:", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ printk (f, ## a); \
+ }
+#else
+# define ext2_debug(f, a...) /**/
+#endif
+
+/*
+ * Special inode numbers
+ */
+#define EXT2_BAD_INO 1 /* Bad blocks inode */
+#define EXT2_ROOT_INO 2 /* Root inode */
+#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
+#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
+
+/* First non-reserved inode for old ext2 filesystems */
+#define EXT2_GOOD_OLD_FIRST_INO 11
+
+/* Assume that user mode programs are passing in an ext2fs superblock, not
+ * a kernel struct super_block. This will allow us to call the feature-test
+ * macros from user land. */
+#define EXT2_SB(sb) (sb)
+
+/*
+ * Maximal count of links to a file
+ */
+#define EXT2_LINK_MAX 32000
+
+/*
+ * Macro-instructions used to manage several block sizes
+ */
+#define EXT2_MIN_BLOCK_SIZE 1024
+#define EXT2_MAX_BLOCK_SIZE 4096
+#define EXT2_MIN_BLOCK_LOG_SIZE 10
+# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
+#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (uint32_t))
+# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
+#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+ EXT2_GOOD_OLD_INODE_SIZE : \
+ (s)->s_inode_size)
+#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
+ EXT2_GOOD_OLD_FIRST_INO : \
+ (s)->s_first_ino)
+
+/*
+ * Macro-instructions used to manage fragments
+ */
+#define EXT2_MIN_FRAG_SIZE 1024
+#define EXT2_MAX_FRAG_SIZE 4096
+#define EXT2_MIN_FRAG_LOG_SIZE 10
+# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
+# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
+
+/*
+ * Structure of a blocks group descriptor
+ */
+struct ext2_group_desc
+{
+ uint32_t bg_block_bitmap; /* Blocks bitmap block */
+ uint32_t bg_inode_bitmap; /* Inodes bitmap block */
+ uint32_t bg_inode_table; /* Inodes table block */
+ uint16_t bg_free_blocks_count; /* Free blocks count */
+ uint16_t bg_free_inodes_count; /* Free inodes count */
+ uint16_t bg_used_dirs_count; /* Directories count */
+ uint16_t bg_pad;
+ uint32_t bg_reserved[3];
+};
+
+/*
+ * Macro-instructions used to manage group descriptors
+ */
+# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
+# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
+
+/*
+ * Constants relative to the data blocks
+ */
+#define EXT2_NDIR_BLOCKS 12
+#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
+#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
+#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
+#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
+
+/*
+ * Inode flags (GETFLAGS/SETFLAGS)
+ */
+#define EXT2_SECRM_FL FS_SECRM_FL /* Secure deletion */
+#define EXT2_UNRM_FL FS_UNRM_FL /* Undelete */
+#define EXT2_COMPR_FL FS_COMPR_FL /* Compress file */
+#define EXT2_SYNC_FL FS_SYNC_FL /* Synchronous updates */
+#define EXT2_IMMUTABLE_FL FS_IMMUTABLE_FL /* Immutable file */
+#define EXT2_APPEND_FL FS_APPEND_FL /* writes to file may only append */
+#define EXT2_NODUMP_FL FS_NODUMP_FL /* do not dump file */
+#define EXT2_NOATIME_FL FS_NOATIME_FL /* do not update atime */
+/* Reserved for compression usage... */
+#define EXT2_DIRTY_FL FS_DIRTY_FL
+#define EXT2_COMPRBLK_FL FS_COMPRBLK_FL /* One or more compressed clusters */
+#define EXT2_NOCOMP_FL FS_NOCOMP_FL /* Don't compress */
+#define EXT2_ECOMPR_FL FS_ECOMPR_FL /* Compression error */
+/* End compression flags --- maybe not all used */
+#define EXT2_BTREE_FL FS_BTREE_FL /* btree format dir */
+#define EXT2_INDEX_FL FS_INDEX_FL /* hash-indexed directory */
+#define EXT2_IMAGIC_FL FS_IMAGIC_FL /* AFS directory */
+#define EXT2_JOURNAL_DATA_FL FS_JOURNAL_DATA_FL /* Reserved for ext3 */
+#define EXT2_NOTAIL_FL FS_NOTAIL_FL /* file tail should not be merged */
+#define EXT2_DIRSYNC_FL FS_DIRSYNC_FL /* dirsync behaviour (directories only) */
+#define EXT2_TOPDIR_FL FS_TOPDIR_FL /* Top of directory hierarchies*/
+#define EXT2_RESERVED_FL FS_RESERVED_FL /* reserved for ext2 lib */
+
+#define EXT2_FL_USER_VISIBLE FS_FL_USER_VISIBLE /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE FS_FL_USER_MODIFIABLE /* User modifiable flags */
+
+/*
+ * ioctl commands
+ */
+#define EXT2_IOC_GETFLAGS FS_IOC_GETFLAGS
+#define EXT2_IOC_SETFLAGS FS_IOC_SETFLAGS
+#define EXT2_IOC_GETVERSION FS_IOC_GETVERSION
+#define EXT2_IOC_SETVERSION FS_IOC_SETVERSION
+#define EXT2_IOC_GETRSVSZ _IOR('f', 5, long)
+#define EXT2_IOC_SETRSVSZ _IOW('f', 6, long)
+
+/*
+ * ioctl commands in 32 bit emulation
+ */
+#define EXT2_IOC32_GETFLAGS FS_IOC32_GETFLAGS
+#define EXT2_IOC32_SETFLAGS FS_IOC32_SETFLAGS
+#define EXT2_IOC32_GETVERSION FS_IOC32_GETVERSION
+#define EXT2_IOC32_SETVERSION FS_IOC32_SETVERSION
+
+/*
+ * Structure of an inode on the disk
+ */
+struct ext2_inode {
+ uint16_t i_mode; /* File mode */
+ uint16_t i_uid; /* Low 16 bits of Owner Uid */
+ uint32_t i_size; /* Size in bytes */
+ uint32_t i_atime; /* Access time */
+ uint32_t i_ctime; /* Creation time */
+ uint32_t i_mtime; /* Modification time */
+ uint32_t i_dtime; /* Deletion Time */
+ uint16_t i_gid; /* Low 16 bits of Group Id */
+ uint16_t i_links_count; /* Links count */
+ uint32_t i_blocks; /* Blocks count */
+ uint32_t i_flags; /* File flags */
+ union {
+ struct {
+ uint32_t l_i_reserved1;
+ } linux1;
+ struct {
+ uint32_t h_i_translator;
+ } hurd1;
+ struct {
+ uint32_t m_i_reserved1;
+ } masix1;
+ } osd1; /* OS dependent 1 */
+ uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+ uint32_t i_generation; /* File version (for NFS) */
+ uint32_t i_file_acl; /* File ACL */
+ uint32_t i_dir_acl; /* Directory ACL */
+ uint32_t i_faddr; /* Fragment address */
+ union {
+ struct {
+ uint8_t l_i_frag; /* Fragment number */
+ uint8_t l_i_fsize; /* Fragment size */
+ uint16_t i_pad1;
+ uint16_t l_i_uid_high; /* these 2 fields */
+ uint16_t l_i_gid_high; /* were reserved2[0] */
+ uint32_t l_i_reserved2;
+ } linux2;
+ struct {
+ uint8_t h_i_frag; /* Fragment number */
+ uint8_t h_i_fsize; /* Fragment size */
+ uint16_t h_i_mode_high;
+ uint16_t h_i_uid_high;
+ uint16_t h_i_gid_high;
+ uint32_t h_i_author;
+ } hurd2;
+ struct {
+ uint8_t m_i_frag; /* Fragment number */
+ uint8_t m_i_fsize; /* Fragment size */
+ uint16_t m_pad1;
+ uint32_t m_i_reserved2[2];
+ } masix2;
+ } osd2; /* OS dependent 2 */
+};
+
+#define i_size_high i_dir_acl
+
+#if defined(__KERNEL__) || defined(__linux__)
+#define i_reserved1 osd1.linux1.l_i_reserved1
+#define i_frag osd2.linux2.l_i_frag
+#define i_fsize osd2.linux2.l_i_fsize
+#define i_uid_low i_uid
+#define i_gid_low i_gid
+#define i_uid_high osd2.linux2.l_i_uid_high
+#define i_gid_high osd2.linux2.l_i_gid_high
+#define i_reserved2 osd2.linux2.l_i_reserved2
+#endif
+
+#ifdef __hurd__
+#define i_translator osd1.hurd1.h_i_translator
+#define i_frag osd2.hurd2.h_i_frag;
+#define i_fsize osd2.hurd2.h_i_fsize;
+#define i_uid_high osd2.hurd2.h_i_uid_high
+#define i_gid_high osd2.hurd2.h_i_gid_high
+#define i_author osd2.hurd2.h_i_author
+#endif
+
+#ifdef __masix__
+#define i_reserved1 osd1.masix1.m_i_reserved1
+#define i_frag osd2.masix2.m_i_frag
+#define i_fsize osd2.masix2.m_i_fsize
+#define i_reserved2 osd2.masix2.m_i_reserved2
+#endif
+
+/*
+ * File system states
+ */
+#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
+#define EXT2_ERROR_FS 0x0002 /* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK 0x000001 /* Do mount-time checks */
+#define EXT2_MOUNT_OLDALLOC 0x000002 /* Don't use the new Orlov allocator */
+#define EXT2_MOUNT_GRPID 0x000004 /* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG 0x000008 /* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT 0x000010 /* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO 0x000020 /* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC 0x000040 /* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF 0x000080 /* Mimics the Minix statfs */
+#define EXT2_MOUNT_NOBH 0x000100 /* No buffer_heads */
+#define EXT2_MOUNT_NO_UID32 0x000200 /* Disable 32-bit UIDs */
+#define EXT2_MOUNT_XATTR_USER 0x004000 /* Extended user attributes */
+#define EXT2_MOUNT_POSIX_ACL 0x008000 /* POSIX Access Control Lists */
+#define EXT2_MOUNT_XIP 0x010000 /* Execute in place */
+#define EXT2_MOUNT_USRQUOTA 0x020000 /* user quota */
+#define EXT2_MOUNT_GRPQUOTA 0x040000 /* group quota */
+#define EXT2_MOUNT_RESERVATION 0x080000 /* Preallocation */
+
+
+#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \
+ EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
+
+/*
+ * Behaviour when detecting errors
+ */
+#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
+#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
+#define EXT2_ERRORS_PANIC 3 /* Panic */
+#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
+
+/*
+ * Structure of the super block
+ */
+struct ext2_super_block {
+ uint32_t s_inodes_count; /* Inodes count */
+ uint32_t s_blocks_count; /* Blocks count */
+ uint32_t s_r_blocks_count; /* Reserved blocks count */
+ uint32_t s_free_blocks_count; /* Free blocks count */
+ uint32_t s_free_inodes_count; /* Free inodes count */
+ uint32_t s_first_data_block; /* First Data Block */
+ uint32_t s_log_block_size; /* Block size */
+ uint32_t s_log_frag_size; /* Fragment size */
+ uint32_t s_blocks_per_group; /* # Blocks per group */
+ uint32_t s_frags_per_group; /* # Fragments per group */
+ uint32_t s_inodes_per_group; /* # Inodes per group */
+ uint32_t s_mtime; /* Mount time */
+ uint32_t s_wtime; /* Write time */
+ uint16_t s_mnt_count; /* Mount count */
+ uint16_t s_max_mnt_count; /* Maximal mount count */
+ uint16_t s_magic; /* Magic signature */
+ uint16_t s_state; /* File system state */
+ uint16_t s_errors; /* Behaviour when detecting errors */
+ uint16_t s_minor_rev_level; /* minor revision level */
+ uint32_t s_lastcheck; /* time of last check */
+ uint32_t s_checkinterval; /* max. time between checks */
+ uint32_t s_creator_os; /* OS */
+ uint32_t s_rev_level; /* Revision level */
+ uint16_t s_def_resuid; /* Default uid for reserved blocks */
+ uint16_t s_def_resgid; /* Default gid for reserved blocks */
+ /*
+ * These fields are for EXT2_DYNAMIC_REV superblocks only.
+ *
+ * Note: the difference between the compatible feature set and
+ * the incompatible feature set is that if there is a bit set
+ * in the incompatible feature set that the kernel doesn't
+ * know about, it should refuse to mount the filesystem.
+ *
+ * e2fsck's requirements are more strict; if it doesn't know
+ * about a feature in either the compatible or incompatible
+ * feature set, it must abort and not try to meddle with
+ * things it doesn't understand...
+ */
+ uint32_t s_first_ino; /* First non-reserved inode */
+ uint16_t s_inode_size; /* size of inode structure */
+ uint16_t s_block_group_nr; /* block group # of this superblock */
+ uint32_t s_feature_compat; /* compatible feature set */
+ uint32_t s_feature_incompat; /* incompatible feature set */
+ uint32_t s_feature_ro_compat; /* readonly-compatible feature set */
+ uint8_t s_uuid[16]; /* 128-bit uuid for volume */
+ char s_volume_name[16]; /* volume name */
+ char s_last_mounted[64]; /* directory where last mounted */
+ uint32_t s_algorithm_usage_bitmap; /* For compression */
+ /*
+ * Performance hints. Directory preallocation should only
+ * happen if the EXT2_COMPAT_PREALLOC flag is on.
+ */
+ uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
+ uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
+ uint16_t s_padding1;
+ /*
+ * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
+ */
+ uint8_t s_journal_uuid[16]; /* uuid of journal superblock */
+ uint32_t s_journal_inum; /* inode number of journal file */
+ uint32_t s_journal_dev; /* device number of journal file */
+ uint32_t s_last_orphan; /* start of list of inodes to delete */
+ uint32_t s_hash_seed[4]; /* HTREE hash seed */
+ uint8_t s_def_hash_version; /* Default hash version to use */
+ uint8_t s_reserved_char_pad;
+ uint16_t s_reserved_word_pad;
+ uint32_t s_default_mount_opts;
+ uint32_t s_first_meta_bg; /* First metablock block group */
+ uint32_t s_reserved[190]; /* Padding to the end of the block */
+};
+
+/*
+ * Codes for operating systems
+ */
+#define EXT2_OS_LINUX 0
+#define EXT2_OS_HURD 1
+#define EXT2_OS_MASIX 2
+#define EXT2_OS_FREEBSD 3
+#define EXT2_OS_LITES 4
+
+/*
+ * Revision levels
+ */
+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
+#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+
+#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
+#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
+
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+
+/*
+ * Feature set definitions
+ */
+
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
+ ( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
+#define EXT2_SET_COMPAT_FEATURE(sb,mask) \
+ EXT2_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
+#define EXT2_SET_RO_COMPAT_FEATURE(sb,mask) \
+ EXT2_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
+#define EXT2_SET_INCOMPAT_FEATURE(sb,mask) \
+ EXT2_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
+#define EXT2_CLEAR_COMPAT_FEATURE(sb,mask) \
+ EXT2_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
+#define EXT2_CLEAR_RO_COMPAT_FEATURE(sb,mask) \
+ EXT2_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
+#define EXT2_CLEAR_INCOMPAT_FEATURE(sb,mask) \
+ EXT2_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
+
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
+#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
+#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
+#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010
+#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
+#define EXT2_FEATURE_COMPAT_ANY 0xffffffff
+
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
+#define EXT2_FEATURE_RO_COMPAT_ANY 0xffffffff
+
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
+#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
+#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
+
+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
+#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
+ EXT2_FEATURE_INCOMPAT_META_BG)
+#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP
+#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP
+
+/*
+ * Default values for user and/or group using reserved blocks
+ */
+#define EXT2_DEF_RESUID 0
+#define EXT2_DEF_RESGID 0
+
+/*
+ * Default mount options
+ */
+#define EXT2_DEFM_DEBUG 0x0001
+#define EXT2_DEFM_BSDGROUPS 0x0002
+#define EXT2_DEFM_XATTR_USER 0x0004
+#define EXT2_DEFM_ACL 0x0008
+#define EXT2_DEFM_UID16 0x0010
+ /* Not used by ext2, but reserved for use by ext3 */
+#define EXT3_DEFM_JMODE 0x0060
+#define EXT3_DEFM_JMODE_DATA 0x0020
+#define EXT3_DEFM_JMODE_ORDERED 0x0040
+#define EXT3_DEFM_JMODE_WBACK 0x0060
+
+/*
+ * Structure of a directory entry
+ */
+#define EXT2_NAME_LEN 255
+
+struct ext2_dir_entry {
+ uint32_t inode; /* Inode number */
+ uint16_t rec_len; /* Directory entry length */
+ uint16_t name_len; /* Name length */
+ char name[EXT2_NAME_LEN]; /* File name */
+};
+
+/*
+ * The new version of the directory entry. Since EXT2 structures are
+ * stored in intel byte order, and the name_len field could never be
+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
+ * file_type field.
+ */
+struct ext2_dir_entry_2 {
+ uint32_t inode; /* Inode number */
+ uint16_t rec_len; /* Directory entry length */
+ uint8_t name_len; /* Name length */
+ uint8_t file_type;
+ char name[EXT2_NAME_LEN]; /* File name */
+};
+
+/*
+ * Ext2 directory file types. Only the low 3 bits are used. The
+ * other bits are reserved for now.
+ */
+enum {
+ EXT2_FT_UNKNOWN,
+ EXT2_FT_REG_FILE,
+ EXT2_FT_DIR,
+ EXT2_FT_CHRDEV,
+ EXT2_FT_BLKDEV,
+ EXT2_FT_FIFO,
+ EXT2_FT_SOCK,
+ EXT2_FT_SYMLINK,
+ EXT2_FT_MAX
+};
+
+/*
+ * EXT2_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define EXT2_DIR_PAD 4
+#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
+#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
+ ~EXT2_DIR_ROUND)
+#define EXT2_MAX_REC_LEN ((1<<16)-1)
+
+#endif /* _EXT2_FS_H */
diff --git a/roms/openbios/fs/ext2/ext2_lseek.c b/roms/openbios/fs/ext2/ext2_lseek.c
new file mode 100644
index 00000000..e837d89b
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_lseek.c
@@ -0,0 +1,38 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+#include "ext2.h"
+
+int ext2_lseek(ext2_FILE *file, long offset, int whence)
+{
+ long new_offset;
+
+ switch(whence)
+ {
+ case SEEK_SET:
+ new_offset = offset;
+ break;
+ case SEEK_CUR:
+ new_offset = file->offset + offset;
+ break;
+ case SEEK_END:
+ new_offset = file->inode->i_size + offset;
+ break;
+ default:
+ return -1;
+ }
+
+ if ( (new_offset < 0) ||
+ (new_offset > file->inode->i_size) )
+ return -1;
+
+ file->offset = new_offset;
+
+ return new_offset;
+}
diff --git a/roms/openbios/fs/ext2/ext2_mount.c b/roms/openbios/fs/ext2/ext2_mount.c
new file mode 100644
index 00000000..06b63dec
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_mount.c
@@ -0,0 +1,62 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+#include "ext2.h"
+#include "ext2_utils.h"
+
+#define SB_OFFSET (2)
+
+ext2_VOLUME* ext2_mount(int fd)
+{
+ ext2_VOLUME *volume;
+ struct ext2_super_block *super;
+ char *buffer;
+
+ super = (struct ext2_super_block*)malloc(sizeof(struct ext2_super_block));
+ if (super == NULL)
+ return NULL;
+
+ ext2_get_super(fd, super);
+ if (super->s_magic != EXT2_SUPER_MAGIC) {
+ free(super);
+ return NULL;
+ }
+
+ buffer = (char*)malloc(EXT2_BLOCK_SIZE(super));
+ if (buffer == NULL) {
+ free(super);
+ return NULL;
+ }
+
+ volume = (ext2_VOLUME*)malloc(sizeof(ext2_VOLUME));
+ if (volume == NULL) {
+ free(super);
+ free(buffer);
+ return NULL;
+ }
+
+ volume->buffer = buffer;
+ volume->fd = fd;
+ volume->super = super;
+
+ volume->current = -1;
+ ext2_read_block(volume, 0);
+
+ return volume;
+}
+
+int ext2_umount(ext2_VOLUME* volume)
+{
+ if (volume == NULL)
+ return -1;
+ free(volume->super);
+ free(volume->buffer);
+ free(volume);
+ return 0;
+}
diff --git a/roms/openbios/fs/ext2/ext2_open.c b/roms/openbios/fs/ext2/ext2_open.c
new file mode 100644
index 00000000..03a89bbd
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_open.c
@@ -0,0 +1,65 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+#include "ext2.h"
+#include "ext2_utils.h"
+
+ext2_FILE* ext2_open(ext2_VOLUME *volume, const char* pathname)
+{
+ ext2_FILE *file;
+ struct ext2_inode *inode;
+ int ino;
+ int ret;
+
+ ino = ext2_seek_name(volume, pathname);
+ if (ino == 0)
+ return NULL;
+
+ inode = (struct ext2_inode*)malloc(sizeof(struct ext2_inode));
+ if (inode == NULL)
+ return NULL;
+
+ ret = ext2_get_inode(volume, ino, inode);
+ if (ret == -1) {
+ free(inode);
+ return NULL;
+ }
+ if (S_ISLNK(inode->i_mode)) {
+ static char buffer[1024];
+ int i, last = 0;
+ strcpy(buffer, pathname);
+ for (i = 0; buffer[i]; i++)
+ if (buffer[i] == '\\')
+ last = i;
+ buffer[last] = '\\';
+ strcpy(buffer + last + 1, (char*)inode->i_block);
+ ino = ext2_seek_name((ext2_VOLUME*)volume, buffer);
+ if (ino == 0) {
+ free(inode);
+ return NULL;
+ }
+ ret = ext2_get_inode((ext2_VOLUME*)volume, ino, inode);
+ if (ret == -1) {
+ free(inode);
+ return NULL;
+ }
+ }
+
+ file = (ext2_FILE*)malloc(sizeof(ext2_FILE));
+ if (file == NULL) {
+ free(inode);
+ return NULL;
+ }
+ file->volume = volume;
+ file->inode = inode;
+ file->offset = 0;
+ file->path = strdup(pathname);
+
+ return file;
+}
diff --git a/roms/openbios/fs/ext2/ext2_opendir.c b/roms/openbios/fs/ext2/ext2_opendir.c
new file mode 100644
index 00000000..3363e0b3
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_opendir.c
@@ -0,0 +1,49 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+#include "ext2.h"
+#include "ext2_utils.h"
+
+ext2_DIR* ext2_opendir(ext2_VOLUME *volume, const char *name)
+{
+ ext2_DIR* dir;
+ int ino;
+ struct ext2_inode *inode;
+ int ret;
+
+ ino = ext2_seek_name(volume, name);
+ if (ino == 0)
+ return NULL;
+
+ inode = (struct ext2_inode*)malloc(sizeof(struct ext2_inode));
+ if (inode == NULL)
+ return NULL;
+
+ ret = ext2_get_inode(volume, ino, inode);
+ if (ret == -1) {
+ free(inode);
+ return NULL;
+ }
+
+ if (!S_ISDIR(inode->i_mode)) {
+ free(inode);
+ return NULL;
+ }
+
+ dir = (ext2_DIR*)malloc(sizeof(ext2_DIR));
+ if (dir == NULL) {
+ free(inode);
+ return NULL;
+ }
+ dir->volume = (ext2_VOLUME*)volume;
+ dir->inode = inode;
+ dir->index = 0;
+
+ return dir;
+}
diff --git a/roms/openbios/fs/ext2/ext2_read.c b/roms/openbios/fs/ext2/ext2_read.c
new file mode 100644
index 00000000..975b3675
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_read.c
@@ -0,0 +1,23 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+#include "ext2.h"
+#include "ext2_utils.h"
+
+size_t ext2_read(ext2_FILE *file, void *buf, size_t count)
+{
+ int ret;
+
+ ret = ext2_read_data(file->volume, file->inode, file->offset,
+ buf, count);
+ if (ret == -1)
+ return -1;
+ file->offset += ret;
+ return ret;
+}
diff --git a/roms/openbios/fs/ext2/ext2_readdir.c b/roms/openbios/fs/ext2/ext2_readdir.c
new file mode 100644
index 00000000..09ba95c9
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_readdir.c
@@ -0,0 +1,25 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+#include "ext2_utils.h"
+
+static struct ext2_dir_entry_2 entry;
+
+struct ext2_dir_entry_2 *ext2_readdir(ext2_DIR *dir)
+{
+ int ret;
+
+ ret = ext2_dir_entry(dir->volume, dir->inode, dir->index, &entry);
+ if (ret == -1)
+ return NULL;
+ dir->index = ret;
+
+ entry.name[entry.name_len] = 0;
+ return &entry;
+}
diff --git a/roms/openbios/fs/ext2/ext2_utils.c b/roms/openbios/fs/ext2/ext2_utils.c
new file mode 100644
index 00000000..64563c82
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_utils.c
@@ -0,0 +1,332 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libext2.h"
+#include "ext2_utils.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+#include "libc/byteorder.h"
+
+int ext2_probe(int fd, long long offset)
+{
+ struct ext2_super_block *super;
+
+ super = (struct ext2_super_block*)malloc(sizeof(struct ext2_super_block));
+ seek_io(fd, 2 * 512 + offset);
+ read_io(fd, super, sizeof (*super));
+
+ if (__le16_to_cpu(super->s_magic) != EXT2_SUPER_MAGIC) {
+ free(super);
+ return 0;
+ }
+
+ free(super);
+ return -1;
+}
+
+void ext2_get_super(int fd, struct ext2_super_block *super)
+{
+ seek_io(fd, 2 * 512);
+ read_io(fd, super, sizeof (*super));
+
+ super->s_inodes_count = __le32_to_cpu(super->s_inodes_count);
+ super->s_blocks_count = __le32_to_cpu(super->s_blocks_count);
+ super->s_r_blocks_count = __le32_to_cpu(super->s_r_blocks_count);
+ super->s_free_blocks_count = __le32_to_cpu(super->s_free_blocks_count);
+ super->s_free_inodes_count = __le32_to_cpu(super->s_free_inodes_count);
+ super->s_first_data_block = __le32_to_cpu(super->s_first_data_block);
+ super->s_log_block_size = __le32_to_cpu(super->s_log_block_size);
+ super->s_log_frag_size = __le32_to_cpu(super->s_log_frag_size);
+ super->s_blocks_per_group = __le32_to_cpu(super->s_blocks_per_group);
+ super->s_frags_per_group = __le32_to_cpu(super->s_frags_per_group);
+ super->s_inodes_per_group = __le32_to_cpu(super->s_inodes_per_group);
+ super->s_mtime = __le32_to_cpu(super->s_mtime);
+ super->s_wtime = __le32_to_cpu(super->s_wtime);
+ super->s_mnt_count = __le16_to_cpu(super->s_mnt_count);
+ super->s_max_mnt_count = __le16_to_cpu(super->s_max_mnt_count);
+ super->s_magic = __le16_to_cpu(super->s_magic);
+ super->s_state = __le16_to_cpu(super->s_state);
+ super->s_errors = __le16_to_cpu(super->s_errors);
+ super->s_minor_rev_level = __le16_to_cpu(super->s_minor_rev_level);
+ super->s_lastcheck = __le32_to_cpu(super->s_lastcheck);
+ super->s_checkinterval = __le32_to_cpu(super->s_checkinterval);
+ super->s_creator_os = __le32_to_cpu(super->s_creator_os);
+ super->s_rev_level = __le32_to_cpu(super->s_rev_level);
+ super->s_def_resuid = __le16_to_cpu(super->s_def_resuid);
+ super->s_def_resgid = __le16_to_cpu(super->s_def_resgid);
+ super->s_first_ino = __le32_to_cpu(super->s_first_ino);
+ super->s_inode_size = __le16_to_cpu(super->s_inode_size);
+ super->s_block_group_nr = __le16_to_cpu(super->s_block_group_nr);
+ super->s_feature_compat = __le32_to_cpu(super->s_feature_compat);
+ super->s_feature_incompat = __le32_to_cpu(super->s_feature_incompat);
+ super->s_feature_ro_compat = __le32_to_cpu(super->s_feature_ro_compat);
+ super->s_algorithm_usage_bitmap =
+ __le32_to_cpu(super->s_algorithm_usage_bitmap);
+ super->s_journal_inum = __le32_to_cpu(super->s_journal_inum);
+ super->s_journal_dev = __le32_to_cpu(super->s_journal_dev);
+ super->s_last_orphan = __le32_to_cpu(super->s_last_orphan);
+ super->s_hash_seed[0] = __le32_to_cpu(super->s_hash_seed[0]);
+ super->s_hash_seed[1] = __le32_to_cpu(super->s_hash_seed[1]);
+ super->s_hash_seed[2] = __le32_to_cpu(super->s_hash_seed[2]);
+ super->s_hash_seed[3] = __le32_to_cpu(super->s_hash_seed[3]);
+ super->s_default_mount_opts =
+ __le32_to_cpu(super->s_default_mount_opts);
+ super->s_first_meta_bg = __le32_to_cpu(super->s_first_meta_bg);
+}
+
+void ext2_read_block(ext2_VOLUME* volume, unsigned int fsblock)
+{
+ long long offset;
+
+ if (fsblock == volume->current)
+ return;
+
+ volume->current = fsblock;
+ offset = fsblock * EXT2_BLOCK_SIZE(volume->super);
+
+ seek_io(volume->fd, offset);
+ read_io(volume->fd, volume->buffer, EXT2_BLOCK_SIZE(volume->super));
+}
+
+void ext2_get_group_desc(ext2_VOLUME* volume,
+ int group_id, struct ext2_group_desc *gdp)
+{
+ unsigned int block, offset;
+ struct ext2_group_desc *le_gdp;
+
+ block = 1 + volume->super->s_first_data_block;
+ block += group_id / EXT2_DESC_PER_BLOCK(volume->super);
+ ext2_read_block(volume, block);
+
+ offset = group_id % EXT2_DESC_PER_BLOCK(volume->super);
+ offset *= sizeof(*gdp);
+
+ le_gdp = (struct ext2_group_desc *)(volume->buffer + offset);
+
+ gdp->bg_block_bitmap = __le32_to_cpu(le_gdp->bg_block_bitmap);
+ gdp->bg_inode_bitmap = __le32_to_cpu(le_gdp->bg_inode_bitmap);
+ gdp->bg_inode_table = __le32_to_cpu(le_gdp->bg_inode_table);
+ gdp->bg_free_blocks_count = __le16_to_cpu(le_gdp->bg_free_blocks_count);
+ gdp->bg_free_inodes_count = __le16_to_cpu(le_gdp->bg_free_inodes_count);
+ gdp->bg_used_dirs_count = __le16_to_cpu(le_gdp->bg_used_dirs_count);
+}
+
+int ext2_get_inode(ext2_VOLUME* volume,
+ unsigned int ino, struct ext2_inode *inode)
+{
+ struct ext2_group_desc desc;
+ unsigned int block;
+ unsigned int group_id;
+ unsigned int offset;
+ struct ext2_inode *le_inode;
+ int i;
+
+ ino--;
+
+ group_id = ino / EXT2_INODES_PER_GROUP(volume->super);
+ ext2_get_group_desc(volume, group_id, &desc);
+
+ ino %= EXT2_INODES_PER_GROUP(volume->super);
+
+ block = desc.bg_inode_table;
+ block += ino / (EXT2_BLOCK_SIZE(volume->super) /
+ EXT2_INODE_SIZE(volume->super));
+ ext2_read_block(volume, block);
+
+ offset = ino % (EXT2_BLOCK_SIZE(volume->super) /
+ EXT2_INODE_SIZE(volume->super));
+ offset *= EXT2_INODE_SIZE(volume->super);
+
+ le_inode = (struct ext2_inode *)(volume->buffer + offset);
+
+ inode->i_mode = __le16_to_cpu(le_inode->i_mode);
+ inode->i_uid = __le16_to_cpu(le_inode->i_uid);
+ inode->i_size = __le32_to_cpu(le_inode->i_size);
+ inode->i_atime = __le32_to_cpu(le_inode->i_atime);
+ inode->i_ctime = __le32_to_cpu(le_inode->i_ctime);
+ inode->i_mtime = __le32_to_cpu(le_inode->i_mtime);
+ inode->i_dtime = __le32_to_cpu(le_inode->i_dtime);
+ inode->i_gid = __le16_to_cpu(le_inode->i_gid);
+ inode->i_links_count = __le16_to_cpu(le_inode->i_links_count);
+ inode->i_blocks = __le32_to_cpu(le_inode->i_blocks);
+ inode->i_flags = __le32_to_cpu(le_inode->i_flags);
+ if (S_ISLNK(inode->i_mode)) {
+ memcpy(inode->i_block, le_inode->i_block, EXT2_N_BLOCKS * 4);
+ } else {
+ for (i = 0; i < EXT2_N_BLOCKS; i++)
+ inode->i_block[i] = __le32_to_cpu(le_inode->i_block[i]);
+ }
+ inode->i_generation = __le32_to_cpu(le_inode->i_generation);
+ inode->i_file_acl = __le32_to_cpu(le_inode->i_file_acl);
+ inode->i_dir_acl = __le32_to_cpu(le_inode->i_dir_acl);
+ inode->i_faddr = __le32_to_cpu(le_inode->i_faddr);
+ inode->osd2.linux2.l_i_frag = le_inode->osd2.linux2.l_i_frag;
+ inode->osd2.linux2.l_i_fsize = le_inode->osd2.linux2.l_i_fsize;
+ inode->osd2.linux2.l_i_uid_high =
+ __le16_to_cpu(le_inode->osd2.linux2.l_i_uid_high);
+ inode->osd2.linux2.l_i_gid_high =
+ __le16_to_cpu(le_inode->osd2.linux2.l_i_gid_high);
+ return 0;
+}
+
+unsigned int ext2_get_block_addr(ext2_VOLUME* volume, struct ext2_inode *inode,
+ unsigned int logical)
+{
+ unsigned int physical;
+ unsigned int addr_per_block;
+
+ /* direct */
+
+ if (logical < EXT2_NDIR_BLOCKS) {
+ physical = inode->i_block[logical];
+ return physical;
+ }
+
+ /* indirect */
+
+ logical -= EXT2_NDIR_BLOCKS;
+
+ addr_per_block = EXT2_ADDR_PER_BLOCK (volume->super);
+ if (logical < addr_per_block) {
+ ext2_read_block(volume, inode->i_block[EXT2_IND_BLOCK]);
+ physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical]);
+ return physical;
+ }
+
+ /* double indirect */
+
+ logical -= addr_per_block;
+
+ if (logical < addr_per_block * addr_per_block) {
+ ext2_read_block(volume, inode->i_block[EXT2_DIND_BLOCK]);
+ physical = __le32_to_cpu(((unsigned int *)volume->buffer)
+ [logical / addr_per_block]);
+ ext2_read_block(volume, physical);
+ physical = __le32_to_cpu(((unsigned int *)volume->buffer)
+ [logical % addr_per_block]);
+ return physical;
+ }
+
+ /* triple indirect */
+
+ logical -= addr_per_block * addr_per_block;
+ ext2_read_block(volume, inode->i_block[EXT2_DIND_BLOCK]);
+ physical = __le32_to_cpu(((unsigned int *)volume->buffer)
+ [logical / (addr_per_block * addr_per_block)]);
+ ext2_read_block(volume, physical);
+ logical = logical % (addr_per_block * addr_per_block);
+ physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical / addr_per_block]);
+ ext2_read_block(volume, physical);
+ physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical % addr_per_block]);
+ return physical;
+}
+
+int ext2_read_data(ext2_VOLUME* volume, struct ext2_inode *inode,
+ off_t offset, char *buffer, size_t length)
+{
+ unsigned int logical, physical;
+ int blocksize = EXT2_BLOCK_SIZE(volume->super);
+ int shift;
+ size_t read;
+
+ if (offset >= inode->i_size)
+ return -1;
+
+ if (offset + length >= inode->i_size)
+ length = inode->i_size - offset;
+
+ read = 0;
+ logical = offset / blocksize;
+ shift = offset % blocksize;
+
+ if (shift) {
+ physical = ext2_get_block_addr(volume, inode, logical);
+ ext2_read_block(volume, physical);
+
+ if (length < blocksize - shift) {
+ memcpy(buffer, volume->buffer + shift, length);
+ return length;
+ }
+ read += blocksize - shift;
+ memcpy(buffer, volume->buffer + shift, read);
+
+ buffer += read;
+ length -= read;
+ logical++;
+ }
+
+ while (length) {
+ physical = ext2_get_block_addr(volume, inode, logical);
+ ext2_read_block(volume, physical);
+
+ if (length < blocksize) {
+ memcpy(buffer, volume->buffer, length);
+ read += length;
+ return read;
+ }
+ memcpy(buffer, volume->buffer, blocksize);
+
+ buffer += blocksize;
+ length -= blocksize;
+ read += blocksize;
+ logical++;
+ }
+
+ return read;
+}
+
+off_t ext2_dir_entry(ext2_VOLUME *volume, struct ext2_inode *inode,
+ off_t index, struct ext2_dir_entry_2 *entry)
+{
+ int ret;
+
+ ret = ext2_read_data(volume, inode, index,
+ (char*)entry, sizeof(*entry));
+ if (ret == -1)
+ return -1;
+
+ entry->inode = __le32_to_cpu(entry->inode);
+ entry->rec_len = __le16_to_cpu(entry->rec_len);
+ return index + entry->rec_len;
+}
+
+unsigned int ext2_seek_name(ext2_VOLUME *volume, const char *name)
+{
+ struct ext2_inode inode;
+ int ret;
+ unsigned int ino;
+ off_t index;
+ struct ext2_dir_entry_2 entry;
+
+ ino = EXT2_ROOT_INO;
+ while(1) {
+ while (*name == '\\')
+ name++;
+ if (!*name)
+ break;
+ ret = ext2_get_inode(volume, ino, &inode);
+ if (ret == -1)
+ return 0;
+ index = 0;
+ while (1) {
+ index = ext2_dir_entry(volume, &inode, index, &entry);
+ if (index == -1)
+ return 0;
+ ret = strncmp(name, entry.name, entry.name_len);
+ if (ret == 0 &&
+ (name[entry.name_len] == 0 ||
+ name[entry.name_len] == '\\')) {
+ ino = entry.inode;
+ break;
+ }
+ }
+ name += entry.name_len;
+ }
+
+ return ino;
+}
diff --git a/roms/openbios/fs/ext2/ext2_utils.h b/roms/openbios/fs/ext2/ext2_utils.h
new file mode 100644
index 00000000..43544d87
--- /dev/null
+++ b/roms/openbios/fs/ext2/ext2_utils.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#ifndef __EXT2_UTILS_H__
+#define __EXT2_UTILS_H__
+
+#include "ext2_fs.h"
+#include "ext2.h"
+
+/* from linux/stat.h */
+
+#define S_IFMT 00170000
+#define S_IFSOCK 0140000
+#define S_IFLNK 0120000
+#define S_IFREG 0100000
+#define S_IFBLK 0060000
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+
+/* utilities */
+
+extern int ext2_probe(int fd, long long offset);
+extern void ext2_get_super(int fd, struct ext2_super_block *super);
+extern void ext2_read_block(ext2_VOLUME* volume, unsigned int fsblock);
+extern void ext2_get_group_desc(ext2_VOLUME* volume,
+ int group_id, struct ext2_group_desc *gdp);
+extern int ext2_get_inode(ext2_VOLUME* volume,
+ unsigned int ino, struct ext2_inode *inode);
+extern unsigned int ext2_get_block_addr(ext2_VOLUME* volume,
+ struct ext2_inode *inode,
+ unsigned int logical);
+extern int ext2_read_data(ext2_VOLUME* volume, struct ext2_inode *inode,
+ off_t offset, char *buffer, size_t length);
+extern off_t ext2_dir_entry(ext2_VOLUME *volume, struct ext2_inode *inode,
+ off_t offset, struct ext2_dir_entry_2 *entry);
+extern unsigned int ext2_seek_name(ext2_VOLUME *volume, const char *name);
+#endif /* __EXT2_UTILS_H__ */
diff --git a/roms/openbios/fs/ext2/libext2.h b/roms/openbios/fs/ext2/libext2.h
new file mode 100644
index 00000000..12d22a44
--- /dev/null
+++ b/roms/openbios/fs/ext2/libext2.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#ifndef __LIBEXT2_H__
+#define __LIBEXT2_H__
+
+#include "config.h"
+#include "ext2.h"
+
+extern ext2_VOLUME* ext2_mount(int fd);
+extern int ext2_umount(ext2_VOLUME *volume);
+extern ext2_DIR* ext2_opendir(ext2_VOLUME *, const char *name);
+extern struct ext2_dir_entry_2* ext2_readdir(ext2_DIR* dir);
+extern void ext2_closedir(ext2_DIR *dir);
+extern ext2_FILE* ext2_open(ext2_VOLUME *, const char* pathname);
+extern size_t ext2_read(ext2_FILE *file, void *buf, size_t count);
+extern void ext2_close(ext2_FILE *file);
+extern int ext2_lseek(ext2_FILE *file, long offset, int whence);
+
+#endif /* __LIBEXT2_H__ */
diff --git a/roms/openbios/fs/grubfs/Kconfig b/roms/openbios/fs/grubfs/Kconfig
new file mode 100644
index 00000000..55fec8b7
--- /dev/null
+++ b/roms/openbios/fs/grubfs/Kconfig
@@ -0,0 +1,83 @@
+config FSYS_EXT2FS
+ depends on GRUBFS
+ bool "EXT2 support"
+ default n
+ help
+ Include EXT2 filesystem support
+
+config FSYS_FAT
+ depends on GRUBFS
+ bool "(V)FAT support"
+ default n
+ help
+ Include VFAT/FAT (MSDOS / Windows95) filesystem support
+
+config FSYS_JFS
+ depends on GRUBFS
+ bool "JFS support"
+ default n
+ help
+ Include JFS support
+
+config FSYS_MINIX
+ depends on GRUBFS
+ bool "Minix filesystem support"
+ default n
+ help
+ Include Minix filesystem support
+
+config FSYS_REISERFS
+ depends on GRUBFS
+ bool "Reiser filesystem support"
+ default n
+ help
+ Include Reiser filesystem support
+
+config FSYS_XFS
+ depends on GRUBFS
+ bool "XFS support"
+ default n
+ help
+ Include XFS support
+
+config FSYS_UFS
+ depends on GRUBFS
+ bool "UFS/UFS2 support"
+ default n
+ help
+ Include UFS/UFS2 support
+
+config FSYS_ISO9660
+ depends on GRUBFS
+ bool "ISO 9660 support"
+ default n
+ help
+ Include ISO9660 (cdrom) filesystem support
+
+config FSYS_FFS
+ depends on GRUBFS
+ bool "FreeBSD FFS support"
+ default n
+ help
+ Include FreeBSD FFS filesystem support
+
+config FSYS_VSTAFS
+ depends on GRUBFS
+ bool "VSTA filesystem support"
+ default n
+ help
+ Include VSTA filesystem support
+
+config FSYS_NTFS
+ depends on GRUBFS
+ bool "NT filesystem support"
+ default n
+ help
+ Include NTFS filesystem support
+
+config FSYS_AFFS
+ depends on GRUBFS
+ bool "Amiga fast filesystem support"
+ default n
+ help
+ Include Amiga FFS filesystem support
diff --git a/roms/openbios/fs/grubfs/build.xml b/roms/openbios/fs/grubfs/build.xml
new file mode 100644
index 00000000..e5fb64a5
--- /dev/null
+++ b/roms/openbios/fs/grubfs/build.xml
@@ -0,0 +1,17 @@
+<build>
+ <library name="fs" type="static" target="target">
+ <object source="grubfs_fs.c"/>
+ <object source="fsys_ext2fs.c" condition="FSYS_EXT2FS" flags="-DFSYS_EXT2FS -fno-strict-aliasing"/>
+ <object source="fsys_fat.c" condition="FSYS_FAT" flags="-DFSYS_FAT -fno-strict-aliasing"/>
+ <object source="fsys_jfs.c" condition="FSYS_JFS" flags="-DFSYS_JFS -fno-strict-aliasing"/>
+ <object source="fsys_minix.c" condition="FSYS_MINIX" flags="-DFSYS_MINIX -fno-strict-aliasing"/>
+ <object source="fsys_reiserfs.c" condition="FSYS_REISERFS" flags="-DFSYS_REISERFS -fno-strict-aliasing"/>
+ <object source="fsys_xfs.c" condition="FSYS_XFS" flags="-DFSYS_XFS -fno-strict-aliasing"/>
+ <object source="fsys_ufs.c" condition="FSYS_UFS" flags="-DFSYS_UFS -fno-strict-aliasing"/>
+ <object source="fsys_ffs.c" condition="FSYS_FFS" flags="-DFSYS_FFS -fno-strict-aliasing"/>
+ <object source="fsys_vstafs.c" condition="FSYS_VSTAFS" flags="-DFSYS_VSTAFS -fno-strict-aliasing"/>
+ <object source="fsys_iso9660.c" condition="FSYS_ISO9660" flags="-DFSYS_ISO9660 -fno-strict-aliasing"/>
+ <object source="fsys_ntfs.c" condition="FSYS_NTFS" flags="-DFSYS_NTFS -fno-strict-aliasing"/>
+ <object source="fsys_affs.c" condition="FSYS_AFFS" flags="-DFSYS_AFFS -fno-strict-aliasing"/>
+ </library>
+</build>
diff --git a/roms/openbios/fs/grubfs/debug.h b/roms/openbios/fs/grubfs/debug.h
new file mode 100644
index 00000000..7494d316
--- /dev/null
+++ b/roms/openbios/fs/grubfs/debug.h
@@ -0,0 +1 @@
+/* for grub compatibility */
diff --git a/roms/openbios/fs/grubfs/defs.h b/roms/openbios/fs/grubfs/defs.h
new file mode 100644
index 00000000..3a3128ce
--- /dev/null
+++ b/roms/openbios/fs/grubfs/defs.h
@@ -0,0 +1,86 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Common definitions for Berkeley Fast File System.
+ */
+
+/*
+ * Compatibility definitions for disk IO.
+ */
+
+/*
+ * Disk devices do all IO in 512-byte blocks.
+ */
+#define DEV_BSIZE 512
+
+/*
+ * Conversion between bytes and disk blocks.
+ */
+#define btodb(byte_offset) ((byte_offset) >> 9)
+#define dbtob(block_number) ((block_number) << 9)
+
+typedef struct _quad_
+ {
+ unsigned int val[2]; /* 2 int values make... */
+ }
+quad; /* an 8-byte item */
+
+typedef unsigned int mach_time_t; /* an unsigned int */
+typedef unsigned int mach_daddr_t; /* an unsigned int */
+typedef unsigned int mach_off_t; /* another unsigned int */
+
+typedef unsigned short mach_uid_t;
+typedef unsigned short mach_gid_t;
+typedef unsigned int mach_ino_t;
+
+#define NBBY 8
+
+/*
+ * The file system is made out of blocks of at most MAXBSIZE units,
+ * with smaller units (fragments) only in the last direct block.
+ * MAXBSIZE primarily determines the size of buffers in the buffer
+ * pool. It may be made larger without any effect on existing
+ * file systems; however, making it smaller may make some file
+ * systems unmountable.
+ *
+ * Note that the disk devices are assumed to have DEV_BSIZE "sectors"
+ * and that fragments must be some multiple of this size.
+ */
+#define MAXBSIZE 8192
+#define MAXFRAG 8
+
+/*
+ * MAXPATHLEN defines the longest permissible path length
+ * after expanding symbolic links.
+ *
+ * MAXSYMLINKS defines the maximum number of symbolic links
+ * that may be expanded in a path name. It should be set
+ * high enough to allow all legitimate uses, but halt infinite
+ * loops reasonably quickly.
+ */
+
+#define MAXPATHLEN 1024
+#define MAXSYMLINKS 8
diff --git a/roms/openbios/fs/grubfs/dir.h b/roms/openbios/fs/grubfs/dir.h
new file mode 100644
index 00000000..a775cab8
--- /dev/null
+++ b/roms/openbios/fs/grubfs/dir.h
@@ -0,0 +1,141 @@
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)dir.h 7.6 (Berkeley) 5/9/89
+ */
+
+#ifndef _BOOT_UFS_DIR_H_
+#define _BOOT_UFS_DIR_H_
+
+/*
+ * A directory consists of some number of blocks of DIRBLKSIZ
+ * bytes, where DIRBLKSIZ is chosen such that it can be transferred
+ * to disk in a single atomic operation (e.g. 512 bytes on most machines).
+ *
+ * Each DIRBLKSIZ byte block contains some number of directory entry
+ * structures, which are of variable length. Each directory entry has
+ * a struct direct at the front of it, containing its inode number,
+ * the length of the entry, and the length of the name contained in
+ * the entry. These are followed by the name padded to a 4 byte boundary
+ * with null bytes. All names are guaranteed null terminated.
+ * The maximum length of a name in a directory is MAXNAMLEN.
+ *
+ * The macro DIRSIZ(dp) gives the amount of space required to represent
+ * a directory entry. Free space in a directory is represented by
+ * entries which have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes
+ * in a directory block are claimed by the directory entries. This
+ * usually results in the last entry in a directory having a large
+ * dp->d_reclen. When entries are deleted from a directory, the
+ * space is returned to the previous entry in the same directory
+ * block by increasing its dp->d_reclen. If the first entry of
+ * a directory block is free, then its dp->d_ino is set to 0.
+ * Entries other than the first in a directory do not normally have
+ * dp->d_ino set to 0.
+ */
+#define DIRBLKSIZ DEV_BSIZE
+#define MAXNAMLEN 255
+
+struct direct
+ {
+ unsigned int d_ino; /* inode number of entry */
+ unsigned short d_reclen; /* length of this record */
+ unsigned short d_namlen; /* length of string in d_name */
+ char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */
+ };
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry. This requires the amount of space in struct direct
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+#define DIRSIZ(dp) \
+ ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+#ifdef KERNEL
+/*
+ * Template for manipulating directories.
+ * Should use struct direct's, but the name field
+ * is MAXNAMLEN - 1, and this just won't do.
+ */
+struct dirtemplate
+ {
+ unsigned int dot_ino;
+ short dot_reclen;
+ short dot_namlen;
+ char dot_name[4]; /* must be multiple of 4 */
+ unsigned int dotdot_ino;
+ short dotdot_reclen;
+ short dotdot_namlen;
+ char dotdot_name[4]; /* ditto */
+ };
+#endif
+
+/*
+ * The following information should be obtained from <dirent.h>
+ * and is provided solely (and temporarily) for backward compatibility.
+ */
+#ifndef KERNEL
+#define d_fileno d_ino /* compatibility with POSIX */
+#ifndef DEV_BSIZE
+#define DEV_BSIZE 512
+#endif
+/*
+ * Definitions for library routines operating on directories.
+ */
+typedef struct _dirdesc
+ {
+ int dd_fd;
+ int dd_loc;
+ int dd_size;
+ char dd_buf[DIRBLKSIZ];
+ }
+DIR;
+
+#define dirfd(dirp) ((dirp)->dd_fd)
+
+#ifndef NULL
+#define NULL 0
+#endif
+#endif /* not KERNEL */
+#endif /* _BOOT_UFS_DIR_H_ */
diff --git a/roms/openbios/fs/grubfs/disk_inode.h b/roms/openbios/fs/grubfs/disk_inode.h
new file mode 100644
index 00000000..68a61c7a
--- /dev/null
+++ b/roms/openbios/fs/grubfs/disk_inode.h
@@ -0,0 +1,110 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Copyright (c) 1982, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)inode.h 7.5 (Berkeley) 7/3/89
+ */
+
+#ifndef _BOOT_UFS_DISK_INODE_H_
+#define _BOOT_UFS_DISK_INODE_H_
+
+/*
+ * The I node is the focus of all file activity in the BSD Fast File System.
+ * There is a unique inode allocated for each active file,
+ * each current directory, each mounted-on file, text file, and the root.
+ * An inode is 'named' by its dev/inumber pair. (iget/iget.c)
+ * Data in icommon is read in from permanent inode on volume.
+ */
+
+#define FFS_NDADDR 12 /* direct addresses in inode */
+#define FFS_NIADDR 3 /* indirect addresses in inode */
+
+#define FFS_MAX_FASTLINK_SIZE ((FFS_NDADDR + FFS_NIADDR) \
+ * sizeof (mach_daddr_t))
+
+struct icommon
+ {
+ unsigned short ic_mode; /* 0: mode and type of file */
+ short ic_nlink; /* 2: number of links to file */
+ mach_uid_t ic_uid; /* 4: owner's user id */
+ mach_gid_t ic_gid; /* 6: owner's group id */
+ quad ic_size; /* 8: number of bytes in file */
+ mach_time_t ic_atime; /* 16: time last accessed */
+ int ic_atspare;
+ mach_time_t ic_mtime; /* 24: time last modified */
+ int ic_mtspare;
+ mach_time_t ic_ctime; /* 32: last time inode changed */
+ int ic_ctspare;
+ union
+ {
+ struct
+ {
+ mach_daddr_t Mb_db[FFS_NDADDR]; /* 40: disk block addresses */
+ mach_daddr_t Mb_ib[FFS_NIADDR]; /* 88: indirect blocks */
+ }
+ ic_Mb;
+ char ic_Msymlink[FFS_MAX_FASTLINK_SIZE];
+ /* 40: symbolic link name */
+ }
+ ic_Mun;
+#define ic_db ic_Mun.ic_Mb.Mb_db
+#define ic_ib ic_Mun.ic_Mb.Mb_ib
+#define ic_symlink ic_Mun.ic_Msymlink
+ int ic_flags; /* 100: status, currently unused */
+ int ic_blocks; /* 104: blocks actually held */
+ int ic_gen; /* 108: generation number */
+ int ic_spare[4]; /* 112: reserved, currently unused */
+ };
+
+/*
+ * Same structure, but on disk.
+ */
+struct dinode
+ {
+ union
+ {
+ struct icommon di_com;
+ char di_char[128];
+ }
+ di_un;
+ };
+#define di_ic di_un.di_com
+
+#endif /* _BOOT_UFS_DISK_INODE_H_ */
diff --git a/roms/openbios/fs/grubfs/disk_inode_ffs.h b/roms/openbios/fs/grubfs/disk_inode_ffs.h
new file mode 100644
index 00000000..3a2cfc6d
--- /dev/null
+++ b/roms/openbios/fs/grubfs/disk_inode_ffs.h
@@ -0,0 +1,101 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Copyright (c) 1982, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)inode.h 7.5 (Berkeley) 7/3/89
+ */
+
+#ifndef _BOOT_UFS_DISK_INODE_FFS_H_
+#define _BOOT_UFS_DISK_INODE_FFS_H_
+
+#define NDADDR FFS_NDADDR
+#define NIADDR FFS_NIADDR
+
+#define MAX_FASTLINK_SIZE FFS_MAX_FASTLINK_SIZE
+
+#define IC_FASTLINK 0x0001 /* Symbolic link in inode */
+
+#define i_mode ic_mode
+#define i_nlink ic_nlink
+#define i_uid ic_uid
+#define i_gid ic_gid
+#if defined(BYTE_MSF) && BYTE_MSF
+#define i_size ic_size.val[1]
+#else /* BYTE_LSF */
+#define i_size ic_size.val[0]
+#endif
+#define i_db ic_db
+#define i_ib ic_ib
+#define i_atime ic_atime
+#define i_mtime ic_mtime
+#define i_ctime ic_ctime
+#define i_blocks ic_blocks
+#define i_rdev ic_db[0]
+#define i_symlink ic_symlink
+#define i_flags ic_flags
+#define i_gen ic_gen
+
+/* modes */
+#define IFMT 0xf000 /* type of file */
+#define IFCHR 0x2000 /* character special */
+#define IFDIR 0x4000 /* directory */
+#define IFBLK 0x6000 /* block special */
+#define IFREG 0x8000 /* regular */
+#define IFLNK 0xa000 /* symbolic link */
+#define IFSOCK 0xc000 /* socket */
+
+
+#define ISUID 0x0800 /* set user id on execution */
+#define ISGID 0x0400 /* set group id on execution */
+#define ISVTX 0x0200 /* save swapped text even after use */
+#define IREAD 0x0100 /* read, write, execute permissions */
+#define IWRITE 0x0080
+#define IEXEC 0x0040
+
+#ifdef EEK
+#define f_fs u.ffs.ffs_fs
+#define i_ic u.ffs.ffs_ic
+#define f_nindir u.ffs.ffs_nindir
+#define f_blk u.ffs.ffs_blk
+#define f_blksize u.ffs.ffs_blksize
+#define f_blkno u.ffs.ffs_blkno
+#endif /* EEK */
+
+#endif /* _BOOT_UFS_DISK_INODE_FFS_H_ */
diff --git a/roms/openbios/fs/grubfs/fat.h b/roms/openbios/fs/grubfs/fat.h
new file mode 100644
index 00000000..43d38aef
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fat.h
@@ -0,0 +1,99 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+
+/*
+ * Defines for the FAT BIOS Parameter Block (embedded in the first block
+ * of the partition.
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+/* Note that some shorts are not aligned, and must therefore
+ * be declared as array of two bytes.
+ */
+struct fat_bpb {
+ __s8 ignored[3]; /* Boot strap short or near jump */
+ __s8 system_id[8]; /* Name - can be used to special case
+ partition manager volumes */
+ __u16 bytes_per_sect; /* bytes per logical sector */
+ __u8 sects_per_clust;/* sectors/cluster */
+ __u16 reserved_sects; /* reserved sectors */
+ __u8 num_fats; /* number of FATs */
+ __u16 dir_entries; /* root directory entries */
+ __u16 short_sectors; /* number of sectors */
+ __u8 media; /* media code (unused) */
+ __u16 fat_length; /* sectors/FAT */
+ __u16 secs_track; /* sectors per track */
+ __u16 heads; /* number of heads */
+ __u32 hidden; /* hidden sectors (unused) */
+ __u32 long_sectors; /* number of sectors (if short_sectors == 0) */
+
+ /* The following fields are only used by FAT32 */
+ __u32 fat32_length; /* sectors/FAT */
+ __u16 flags; /* bit 8: fat mirroring, low 4: active fat */
+ __u16 version; /* major, minor filesystem version */
+ __u32 root_cluster; /* first cluster in root directory */
+ __u16 info_sector; /* filesystem info sector */
+ __u16 backup_boot; /* backup boot sector */
+ __u16 reserved2[6]; /* Unused */
+} __attribute__ ((packed));
+
+/*
+ * Defines how to differentiate a 12-bit and 16-bit FAT.
+ */
+
+#define FAT_MAX_12BIT_CLUST 4087 /* 4085 + 2 */
+
+/*
+ * Defines for the file "attribute" byte
+ */
+
+#define FAT_ATTRIB_OK_MASK 0x37
+#define FAT_ATTRIB_NOT_OK_MASK 0xC8
+#define FAT_ATTRIB_DIR 0x10
+#define FAT_ATTRIB_LONGNAME 0x0F
+
+/*
+ * Defines for FAT directory entries
+ */
+
+#define FAT_DIRENTRY_LENGTH 32
+
+#define FAT_DIRENTRY_ATTRIB(entry) \
+ (*((unsigned char *) (entry+11)))
+#define FAT_DIRENTRY_VALID(entry) \
+ ( ((*((unsigned char *) entry)) != 0) \
+ && ((*((unsigned char *) entry)) != 0xE5) \
+ && !(FAT_DIRENTRY_ATTRIB(entry) & FAT_ATTRIB_NOT_OK_MASK) )
+#define FAT_DIRENTRY_FIRST_CLUSTER(entry) \
+ ((*((unsigned short *) (entry+26)))+(*((unsigned short *) (entry+20)) << 16))
+#define FAT_DIRENTRY_FILELENGTH(entry) \
+ (*((unsigned long *) (entry+28)))
+
+#define FAT_LONGDIR_ID(entry) \
+ (*((unsigned char *) (entry)))
+#define FAT_LONGDIR_ALIASCHECKSUM(entry) \
+ (*((unsigned char *) (entry+13)))
diff --git a/roms/openbios/fs/grubfs/filesys.h b/roms/openbios/fs/grubfs/filesys.h
new file mode 100644
index 00000000..6b6f9760
--- /dev/null
+++ b/roms/openbios/fs/grubfs/filesys.h
@@ -0,0 +1,303 @@
+/* GRUB compatibility header
+ *
+ * taken from filo and grub.
+ */
+
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2003 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/* This disables some portion of code */
+#define STAGE1_5 1
+
+#if defined CONFIG_X86
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+static __inline__ unsigned int
+ffz (unsigned int word)
+{
+ __asm__ ("bsfl %1,%0"
+ : "=r" (word)
+ : "r" (~word));
+ return word;
+}
+
+static __inline__ unsigned int
+log2 (unsigned int word)
+{
+ __asm__ ("bsfl %1,%0"
+ : "=r" (word)
+ : "r" (word));
+ return word;
+}
+
+#elif defined (CONFIG_PPC)
+static __inline__ unsigned long
+ __ilog2(unsigned long x)
+{
+ unsigned long lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+ return 31 - lz;
+}
+
+static __inline__ unsigned long
+ffz(unsigned long x)
+{
+ if ((x = ~x) == 0)
+ return 32;
+
+ return __ilog2(x & -x);
+}
+
+#define log2(n) ffz(~(n))
+
+#else
+
+static __inline__ unsigned int log2(unsigned int word)
+{
+ /* assume 8 bits per byte. */
+ unsigned int i = 1 << (sizeof(word)*8 - 1);
+ unsigned int pow = sizeof(word) * 8 - 1;
+
+ if (! word) {
+ /* invalid parameter */
+ return -1;
+ }
+ for(; i > word; i >>= 1, pow--) ;
+
+ return pow;
+}
+
+#define ffz(n) log2(~(n))
+
+#endif
+
+static inline int
+substring (const char *s1, const char *s2)
+{
+ while (*s1 == *s2)
+ {
+ /* The strings match exactly. */
+ if (! *(s1++))
+ return 0;
+ s2 ++;
+ }
+
+ /* S1 is a substring of S2. */
+ if (*s1 == 0)
+ return -1;
+
+ /* S1 isn't a substring. */
+ return 1;
+}
+
+#define grub_memmove memmove
+#define grub_strcmp strcmp
+
+#define MAXINT 0x7fffffff
+
+/* This is only used by fsys_* to determine if it's hard disk. If it is,
+ * they try to guess filesystem type by partition type. I guess it is
+ * not necessory, so hardcoded to 0 (first floppy) --ts1 */
+#define current_drive 0
+#define current_slice 0
+#define current_partition 0
+
+/* we fake this for now, assuming that the filesystem is not corrupt */
+#define part_length -1
+extern int filepos;
+extern int filemax;
+extern int fsmax;
+
+/* Error codes (descriptions are in common.c) */
+typedef enum
+{
+ ERR_NONE = 0,
+ ERR_BAD_FILENAME,
+ ERR_BAD_FILETYPE,
+ ERR_BAD_GZIP_DATA,
+ ERR_BAD_GZIP_HEADER,
+ ERR_BAD_PART_TABLE,
+ ERR_BAD_VERSION,
+ ERR_BELOW_1MB,
+ ERR_BOOT_COMMAND,
+ ERR_BOOT_FAILURE,
+ ERR_BOOT_FEATURES,
+ ERR_DEV_FORMAT,
+ ERR_DEV_VALUES,
+ ERR_EXEC_FORMAT,
+ ERR_FILELENGTH,
+ ERR_FILE_NOT_FOUND,
+ ERR_FSYS_CORRUPT,
+ ERR_FSYS_MOUNT,
+ ERR_GEOM,
+ ERR_NEED_LX_KERNEL,
+ ERR_NEED_MB_KERNEL,
+ ERR_NO_DISK,
+ ERR_NO_PART,
+ ERR_NUMBER_PARSING,
+ ERR_OUTSIDE_PART,
+ ERR_READ,
+ ERR_SYMLINK_LOOP,
+ ERR_UNRECOGNIZED,
+ ERR_WONT_FIT,
+ ERR_WRITE,
+ ERR_BAD_ARGUMENT,
+ ERR_UNALIGNED,
+ ERR_PRIVILEGED,
+ ERR_DEV_NEED_INIT,
+ ERR_NO_DISK_SPACE,
+ ERR_NUMBER_OVERFLOW,
+
+ MAX_ERR_NUM
+} grub_error_t;
+
+extern grub_error_t errnum;
+
+#define grub_open file_open
+#define grub_read file_read
+#define grub_seek file_seek
+#define grub_close file_close
+
+/* instrumentation variables */
+/* (Not used in FILO) */
+extern void (*disk_read_hook) (int, int, int);
+extern void (*disk_read_func) (int, int, int);
+
+#define FSYS_BUFLEN 0x8000
+extern char FSYS_BUF[FSYS_BUFLEN];
+
+#define print_possibilities 0
+
+#define SECTOR_SIZE 512
+#define SECTOR_BITS 9
+
+#ifdef CONFIG_FSYS_FAT
+int fat_mount (void);
+int fat_read (char *buf, int len);
+int fat_dir (char *dirname);
+#endif
+
+#ifdef CONFIG_FSYS_EXT2FS
+int ext2fs_mount (void);
+int ext2fs_read (char *buf, int len);
+int ext2fs_dir (char *dirname);
+#endif
+
+#ifdef CONFIG_FSYS_MINIX
+int minix_mount (void);
+int minix_read (char *buf, int len);
+int minix_dir (char *dirname);
+#endif
+
+#ifdef CONFIG_FSYS_REISERFS
+int reiserfs_mount (void);
+int reiserfs_read (char *buf, int len);
+int reiserfs_dir (char *dirname);
+int reiserfs_embed (int *start_sector, int needed_sectors);
+#endif
+
+#ifdef CONFIG_FSYS_JFS
+int jfs_mount (void);
+int jfs_read (char *buf, int len);
+int jfs_dir (char *dirname);
+int jfs_embed (int *start_sector, int needed_sectors);
+#endif
+
+#ifdef CONFIG_FSYS_XFS
+int xfs_mount (void);
+int xfs_read (char *buf, int len);
+int xfs_dir (char *dirname);
+#endif
+
+#ifdef CONFIG_FSYS_UFS
+int ufs_mount (void);
+int ufs_read (char *buf, int len);
+int ufs_dir (char *dirname);
+int ufs_embed (int *start_sector, int needed_sectors);
+#endif
+
+#ifdef CONFIG_FSYS_ISO9660
+int iso9660_mount (void);
+int iso9660_read (char *buf, int len);
+int iso9660_dir (char *dirname);
+#endif
+
+/* This is not a flag actually, but used as if it were a flag. */
+#define PC_SLICE_TYPE_HIDDEN_FLAG 0x10
+
+#define PC_SLICE_TYPE_NONE 0
+#define PC_SLICE_TYPE_FAT12 1
+#define PC_SLICE_TYPE_FAT16_LT32M 4
+#define PC_SLICE_TYPE_EXTENDED 5
+#define PC_SLICE_TYPE_FAT16_GT32M 6
+#define PC_SLICE_TYPE_FAT32 0xb
+#define PC_SLICE_TYPE_FAT32_LBA 0xc
+#define PC_SLICE_TYPE_FAT16_LBA 0xe
+#define PC_SLICE_TYPE_WIN95_EXTENDED 0xf
+#define PC_SLICE_TYPE_EZD 0x55
+#define PC_SLICE_TYPE_MINIX 0x80
+#define PC_SLICE_TYPE_LINUX_MINIX 0x81
+#define PC_SLICE_TYPE_EXT2FS 0x83
+#define PC_SLICE_TYPE_LINUX_EXTENDED 0x85
+#define PC_SLICE_TYPE_VSTAFS 0x9e
+#define PC_SLICE_TYPE_DELL_UTIL 0xde
+#define PC_SLICE_TYPE_LINUX_RAID 0xfd
+
+/* For convinience. */
+/* Check if TYPE is a FAT partition type. Clear the hidden flag before
+ the check, to allow the user to mount a hidden partition in GRUB. */
+#define IS_PC_SLICE_TYPE_FAT(type) \
+ ({ int _type = (type) & ~PC_SLICE_TYPE_HIDDEN_FLAG; \
+ _type == PC_SLICE_TYPE_FAT12 \
+ || _type == PC_SLICE_TYPE_FAT16_LT32M \
+ || _type == PC_SLICE_TYPE_FAT16_GT32M \
+ || _type == PC_SLICE_TYPE_FAT16_LBA \
+ || _type == PC_SLICE_TYPE_FAT32 \
+ || _type == PC_SLICE_TYPE_FAT32_LBA \
+ || _type == PC_SLICE_TYPE_DELL_UTIL; })
+
+#define IS_PC_SLICE_TYPE_MINIX(type) \
+ (((type) == PC_SLICE_TYPE_MINIX) \
+ || ((type) == PC_SLICE_TYPE_LINUX_MINIX))
+
+#define IS_PC_SLICE_TYPE_BSD_WITH_FS(type,fs) 0
+
+/* possible values for the *BSD-style partition type */
+#define FS_UNUSED 0 /* unused */
+#define FS_SWAP 1 /* swap */
+#define FS_V6 2 /* Sixth Edition */
+#define FS_V7 3 /* Seventh Edition */
+#define FS_SYSV 4 /* System V */
+#define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
+#define FS_V8 6 /* Eighth Edition, 4K blocks */
+#define FS_BSDFFS 7 /* 4.2BSD fast file system */
+#define FS_MSDOS 8 /* MSDOS file system */
+#define FS_BSDLFS 9 /* 4.4BSD log-structured file system */
+#define FS_OTHER 10 /* in use, but unknown/unsupported */
+#define FS_HPFS 11 /* OS/2 high-performance file system */
+#define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */
+#define FS_BOOT 13 /* partition contains bootstrap */
+#define FS_ADOS 14 /* AmigaDOS fast file system */
+#define FS_HFS 15 /* Macintosh HFS */
+#define FS_FILECORE 16 /* Acorn Filecore Filing System */
+#define FS_EXT2FS 17 /* Linux Extended 2 file system */
diff --git a/roms/openbios/fs/grubfs/fs.h b/roms/openbios/fs/grubfs/fs.h
new file mode 100644
index 00000000..260e9264
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fs.h
@@ -0,0 +1,457 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)fs.h 7.7 (Berkeley) 5/9/89
+ */
+
+/*
+ * Each disk drive contains some number of file systems.
+ * A file system consists of a number of cylinder groups.
+ * Each cylinder group has inodes and data.
+ *
+ * A file system is described by its super-block, which in turn
+ * describes the cylinder groups. The super-block is critical
+ * data and is replicated in each cylinder group to protect against
+ * catastrophic loss. This is done at `newfs' time and the critical
+ * super-block data does not change, so the copies need not be
+ * referenced further unless disaster strikes.
+ *
+ * For file system fs, the offsets of the various blocks of interest
+ * are given in the super block as:
+ * [fs->fs_sblkno] Super-block
+ * [fs->fs_cblkno] Cylinder group block
+ * [fs->fs_iblkno] Inode blocks
+ * [fs->fs_dblkno] Data blocks
+ * The beginning of cylinder group cg in fs, is given by
+ * the ``cgbase(fs, cg)'' macro.
+ *
+ * The first boot and super blocks are given in absolute disk addresses.
+ * The byte-offset forms are preferred, as they don't imply a sector size.
+ */
+#define BBSIZE 8192
+#define SBSIZE 8192
+#define BBOFF ((mach_off_t)(0))
+#define SBOFF ((mach_off_t)(BBOFF + BBSIZE))
+#define BBLOCK ((mach_daddr_t)(0))
+#define SBLOCK ((mach_daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
+
+/*
+ * Addresses stored in inodes are capable of addressing fragments
+ * of `blocks'. File system blocks of at most size MAXBSIZE can
+ * be optionally broken into 2, 4, or 8 pieces, each of which is
+ * addressible; these pieces may be DEV_BSIZE, or some multiple of
+ * a DEV_BSIZE unit.
+ *
+ * Large files consist of exclusively large data blocks. To avoid
+ * undue wasted disk space, the last data block of a small file may be
+ * allocated as only as many fragments of a large block as are
+ * necessary. The file system format retains only a single pointer
+ * to such a fragment, which is a piece of a single large block that
+ * has been divided. The size of such a fragment is determinable from
+ * information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
+ *
+ * The file system records space availability at the fragment level;
+ * to determine block availability, aligned fragments are examined.
+ *
+ * The root inode is the root of the file system.
+ * Inode 0 can't be used for normal purposes and
+ * historically bad blocks were linked to inode 1,
+ * thus the root inode is 2. (inode 1 is no longer used for
+ * this purpose, however numerous dump tapes make this
+ * assumption, so we are stuck with it)
+ */
+#define ROOTINO ((mach_ino_t)2) /* i number of all roots */
+
+/*
+ * MINBSIZE is the smallest allowable block size.
+ * In order to insure that it is possible to create files of size
+ * 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
+ * MINBSIZE must be big enough to hold a cylinder group block,
+ * thus changes to (struct cg) must keep its size within MINBSIZE.
+ * Note that super blocks are always of size SBSIZE,
+ * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
+ */
+#define MINBSIZE 4096
+
+/*
+ * The path name on which the file system is mounted is maintained
+ * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
+ * the super block for this name.
+ * The limit on the amount of summary information per file system
+ * is defined by MAXCSBUFS. It is currently parameterized for a
+ * maximum of two million cylinders.
+ */
+#define MAXMNTLEN 512
+#define MAXCSBUFS 32
+
+/*
+ * Per cylinder group information; summarized in blocks allocated
+ * from first cylinder group data blocks. These blocks have to be
+ * read in from fs_csaddr (size fs_cssize) in addition to the
+ * super block.
+ *
+ * N.B. sizeof(struct csum) must be a power of two in order for
+ * the ``fs_cs'' macro to work (see below).
+ */
+struct csum
+ {
+ int cs_ndir; /* number of directories */
+ int cs_nbfree; /* number of free blocks */
+ int cs_nifree; /* number of free inodes */
+ int cs_nffree; /* number of free frags */
+ };
+
+/*
+ * Super block for a file system.
+ */
+#define FS_MAGIC 0x011954
+struct fs
+ {
+ int xxx1; /* struct fs *fs_link; */
+ int xxx2; /* struct fs *fs_rlink; */
+ mach_daddr_t fs_sblkno; /* addr of super-block in filesys */
+ mach_daddr_t fs_cblkno; /* offset of cyl-block in filesys */
+ mach_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */
+ mach_daddr_t fs_dblkno; /* offset of first data after cg */
+ int fs_cgoffset; /* cylinder group offset in cylinder */
+ int fs_cgmask; /* used to calc mod fs_ntrak */
+ mach_time_t fs_time; /* last time written */
+ int fs_size; /* number of blocks in fs */
+ int fs_dsize; /* number of data blocks in fs */
+ int fs_ncg; /* number of cylinder groups */
+ int fs_bsize; /* size of basic blocks in fs */
+ int fs_fsize; /* size of frag blocks in fs */
+ int fs_frag; /* number of frags in a block in fs */
+/* these are configuration parameters */
+ int fs_minfree; /* minimum percentage of free blocks */
+ int fs_rotdelay; /* num of ms for optimal next block */
+ int fs_rps; /* disk revolutions per second */
+/* these fields can be computed from the others */
+ int fs_bmask; /* ``blkoff'' calc of blk offsets */
+ int fs_fmask; /* ``fragoff'' calc of frag offsets */
+ int fs_bshift; /* ``lblkno'' calc of logical blkno */
+ int fs_fshift; /* ``numfrags'' calc number of frags */
+/* these are configuration parameters */
+ int fs_maxcontig; /* max number of contiguous blks */
+ int fs_maxbpg; /* max number of blks per cyl group */
+/* these fields can be computed from the others */
+ int fs_fragshift; /* block to frag shift */
+ int fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+ int fs_sbsize; /* actual size of super block */
+ int fs_csmask; /* csum block offset */
+ int fs_csshift; /* csum block number */
+ int fs_nindir; /* value of NINDIR */
+ int fs_inopb; /* value of INOPB */
+ int fs_nspf; /* value of NSPF */
+/* yet another configuration parameter */
+ int fs_optim; /* optimization preference, see below */
+/* these fields are derived from the hardware */
+ int fs_npsect; /* # sectors/track including spares */
+ int fs_interleave; /* hardware sector interleave */
+ int fs_trackskew; /* sector 0 skew, per track */
+ int fs_headswitch; /* head switch time, usec */
+ int fs_trkseek; /* track-to-track seek, usec */
+/* sizes determined by number of cylinder groups and their sizes */
+ mach_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
+ int fs_cssize; /* size of cyl grp summary area */
+ int fs_cgsize; /* cylinder group size */
+/* these fields are derived from the hardware */
+ int fs_ntrak; /* tracks per cylinder */
+ int fs_nsect; /* sectors per track */
+ int fs_spc; /* sectors per cylinder */
+/* this comes from the disk driver partitioning */
+ int fs_ncyl; /* cylinders in file system */
+/* these fields can be computed from the others */
+ int fs_cpg; /* cylinders per group */
+ int fs_ipg; /* inodes per group */
+ int fs_fpg; /* blocks per group * fs_frag */
+/* this data must be re-computed after crashes */
+ struct csum fs_cstotal; /* cylinder summary information */
+/* these fields are cleared at mount time */
+ char fs_fmod; /* super block modified flag */
+ char fs_clean; /* file system is clean flag */
+ char fs_ronly; /* mounted read-only flag */
+ char fs_flags; /* currently unused flag */
+ char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
+/* these fields retain the current block allocation info */
+ int fs_cgrotor; /* last cg searched */
+#if 1
+ int was_fs_csp[MAXCSBUFS];
+#else
+ struct csum *fs_csp[MAXCSBUFS]; /* list of fs_cs info buffers */
+#endif
+ int fs_cpc; /* cyl per cycle in postbl */
+ short fs_opostbl[16][8]; /* old rotation block list head */
+ long fs_sparecon[50]; /* reserved for future constants */
+ long fs_contigsumsize; /* size of cluster summary array */
+ long fs_maxsymlinklen; /* max length of an internal symlink */
+ long fs_inodefmt; /* format of on-disk inodes */
+ quad fs_maxfilesize; /* maximum representable file size */
+ quad fs_qbmask; /* ~fs_bmask - for use with quad size */
+ quad fs_qfmask; /* ~fs_fmask - for use with quad size */
+ long fs_state; /* validate fs_clean field */
+ int fs_postblformat; /* format of positional layout tables */
+ int fs_nrpos; /* number of rotaional positions */
+ int fs_postbloff; /* (short) rotation block list head */
+ int fs_rotbloff; /* (char) blocks for each rotation */
+ int fs_magic; /* magic number */
+ unsigned char fs_space[1]; /* list of blocks for each rotation */
+/* actually longer */
+ };
+/*
+ * Preference for optimization.
+ */
+#define FS_OPTTIME 0 /* minimize allocation time */
+#define FS_OPTSPACE 1 /* minimize disk fragmentation */
+
+/*
+ * Rotational layout table format types
+ */
+#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
+#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */
+/*
+ * Macros for access to superblock array structures
+ */
+#define fs_postbl(fs, cylno) \
+ (((fs)->fs_postblformat == FS_42POSTBLFMT) \
+ ? ((fs)->fs_opostbl[cylno]) \
+ : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos))
+#define fs_rotbl(fs) \
+ (((fs)->fs_postblformat == FS_42POSTBLFMT) \
+ ? ((fs)->fs_space) \
+ : ((unsigned char *)((char *)(fs) + (fs)->fs_rotbloff)))
+
+/*
+ * Convert cylinder group to base address of its global summary info.
+ *
+ * N.B. This macro assumes that sizeof(struct csum) is a power of two.
+ */
+#define fs_cs(fs, indx) \
+ fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask]
+
+/*
+ * Cylinder group block for a file system.
+ */
+#define CG_MAGIC 0x090255
+struct cg
+ {
+ int xxx1; /* struct cg *cg_link; */
+ int cg_magic; /* magic number */
+ mach_time_t cg_time; /* time last written */
+ int cg_cgx; /* we are the cgx'th cylinder group */
+ short cg_ncyl; /* number of cyl's this cg */
+ short cg_niblk; /* number of inode blocks this cg */
+ int cg_ndblk; /* number of data blocks this cg */
+ struct csum cg_cs; /* cylinder summary information */
+ int cg_rotor; /* position of last used block */
+ int cg_frotor; /* position of last used frag */
+ int cg_irotor; /* position of last used inode */
+ int cg_frsum[MAXFRAG]; /* counts of available frags */
+ int cg_btotoff; /* (long) block totals per cylinder */
+ int cg_boff; /* (short) free block positions */
+ int cg_iusedoff; /* (char) used inode map */
+ int cg_freeoff; /* (char) free block map */
+ int cg_nextfreeoff; /* (char) next available space */
+ int cg_sparecon[16]; /* reserved for future use */
+ unsigned char cg_space[1]; /* space for cylinder group maps */
+/* actually longer */
+ };
+/*
+ * Macros for access to cylinder group array structures
+ */
+#define cg_blktot(cgp) \
+ (((cgp)->cg_magic != CG_MAGIC) \
+ ? (((struct ocg *)(cgp))->cg_btot) \
+ : ((int *)((char *)(cgp) + (cgp)->cg_btotoff)))
+#define cg_blks(fs, cgp, cylno) \
+ (((cgp)->cg_magic != CG_MAGIC) \
+ ? (((struct ocg *)(cgp))->cg_b[cylno]) \
+ : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos))
+#define cg_inosused(cgp) \
+ (((cgp)->cg_magic != CG_MAGIC) \
+ ? (((struct ocg *)(cgp))->cg_iused) \
+ : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff)))
+#define cg_blksfree(cgp) \
+ (((cgp)->cg_magic != CG_MAGIC) \
+ ? (((struct ocg *)(cgp))->cg_free) \
+ : ((unsigned char *)((char *)(cgp) + (cgp)->cg_freeoff)))
+#define cg_chkmagic(cgp) \
+ ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC)
+
+/*
+ * The following structure is defined
+ * for compatibility with old file systems.
+ */
+struct ocg
+ {
+ int xxx1; /* struct ocg *cg_link; */
+ int xxx2; /* struct ocg *cg_rlink; */
+ mach_time_t cg_time; /* time last written */
+ int cg_cgx; /* we are the cgx'th cylinder group */
+ short cg_ncyl; /* number of cyl's this cg */
+ short cg_niblk; /* number of inode blocks this cg */
+ int cg_ndblk; /* number of data blocks this cg */
+ struct csum cg_cs; /* cylinder summary information */
+ int cg_rotor; /* position of last used block */
+ int cg_frotor; /* position of last used frag */
+ int cg_irotor; /* position of last used inode */
+ int cg_frsum[8]; /* counts of available frags */
+ int cg_btot[32]; /* block totals per cylinder */
+ short cg_b[32][8]; /* positions of free blocks */
+ char cg_iused[256]; /* used inode map */
+ int cg_magic; /* magic number */
+ unsigned char cg_free[1]; /* free block map */
+/* actually longer */
+ };
+
+/*
+ * Turn file system block numbers into disk block addresses.
+ * This maps file system blocks to device size blocks.
+ */
+#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb)
+#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb)
+
+/*
+ * Cylinder group macros to locate things in cylinder groups.
+ * They calc file system addresses of cylinder group data structures.
+ */
+#define cgbase(fs, c) ((mach_daddr_t)((fs)->fs_fpg * (c)))
+#define cgstart(fs, c) \
+ (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask)))
+#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
+#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */
+#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
+#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
+
+/*
+ * Macros for handling inode numbers:
+ * inode number to file system block offset.
+ * inode number to cylinder group number.
+ * inode number to file system block address.
+ */
+#define itoo(fs, x) ((x) % INOPB(fs))
+#define itog(fs, x) ((x) / (fs)->fs_ipg)
+#define itod(fs, x) \
+ ((mach_daddr_t)(cgimin(fs, itog(fs, x)) + \
+ (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
+
+/*
+ * Give cylinder group number for a file system block.
+ * Give cylinder group block number for a file system block.
+ */
+#define dtog(fs, d) ((d) / (fs)->fs_fpg)
+#define dtogd(fs, d) ((d) % (fs)->fs_fpg)
+
+/*
+ * Extract the bits for a block from a map.
+ * Compute the cylinder and rotational position of a cyl block addr.
+ */
+#define blkmap(fs, map, loc) \
+ (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
+#define cbtocylno(fs, bno) \
+ ((bno) * NSPF(fs) / (fs)->fs_spc)
+#define cbtorpos(fs, bno) \
+ (((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \
+ (bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \
+ (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect)
+
+/*
+ * The following macros optimize certain frequently calculated
+ * quantities by using shifts and masks in place of divisions
+ * modulos and multiplications.
+ */
+#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
+ ((loc) & ~(fs)->fs_bmask)
+#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \
+ ((loc) & ~(fs)->fs_fmask)
+#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
+ ((loc) >> (fs)->fs_bshift)
+#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
+ ((loc) >> (fs)->fs_fshift)
+#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \
+ (((size) + (fs)->fs_bsize - 1) & (fs)->fs_bmask)
+#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
+ (((size) + (fs)->fs_fsize - 1) & (fs)->fs_fmask)
+#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \
+ ((frags) >> (fs)->fs_fragshift)
+#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \
+ ((blks) << (fs)->fs_fragshift)
+#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \
+ ((fsb) & ((fs)->fs_frag - 1))
+#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \
+ ((fsb) &~ ((fs)->fs_frag - 1))
+
+/*
+ * Determine the number of available frags given a
+ * percentage to hold in reserve
+ */
+#define freespace(fs, percentreserved) \
+ (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
+ (fs)->fs_cstotal.cs_nffree - ((fs)->fs_dsize * (percentreserved) / 100))
+
+/*
+ * Determining the size of a file block in the file system.
+ */
+#define blksize(fs, ip, lbn) \
+ (((lbn) >= NDADDR || (ip)->i_size >= ((lbn) + 1) << (fs)->fs_bshift) \
+ ? (fs)->fs_bsize \
+ : (fragroundup(fs, blkoff(fs, (ip)->i_size))))
+#define dblksize(fs, dip, lbn) \
+ (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \
+ ? (fs)->fs_bsize \
+ : (fragroundup(fs, blkoff(fs, (dip)->di_size))))
+
+/*
+ * Number of disk sectors per block; assumes DEV_BSIZE byte sector size.
+ */
+#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift)
+#define NSPF(fs) ((fs)->fs_nspf)
+
+/*
+ * INOPB is the number of inodes in a secondary storage block.
+ */
+#define INOPB(fs) ((fs)->fs_inopb)
+#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift)
+
+/*
+ * NINDIR is the number of indirects in a file system block.
+ */
+#define NINDIR(fs) ((fs)->fs_nindir)
diff --git a/roms/openbios/fs/grubfs/fsys_affs.c b/roms/openbios/fs/grubfs/fsys_affs.c
new file mode 100644
index 00000000..c4a76322
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_affs.c
@@ -0,0 +1,712 @@
+#ifdef FSYS_AFFS
+#include "shared.h"
+#include "filesys.h"
+
+/******************************** RDB definitions */
+#define RDB_LOCATION_LIMIT 16
+#define IDNAME_RIGIDDISK 0x5244534B /* 'RDSK' */
+
+struct RigidDiskBlock
+{
+ unsigned long rdb_ID;
+ unsigned long rdb_SummedLongs;
+ long rdb_ChkSum;
+ unsigned long rdb_HostID;
+ unsigned long rdb_BlockBytes;
+ unsigned long rdb_Flags;
+ unsigned long rdb_BadBlockList;
+ unsigned long rdb_PartitionList;
+ unsigned long rdb_FileSysHeaderList;
+ unsigned long rdb_DriveInit;
+ unsigned long rdb_Reserved1[6];
+ unsigned long rdb_Cylinders;
+ unsigned long rdb_Sectors;
+ unsigned long rdb_Heads;
+ unsigned long rdb_Interleave;
+ unsigned long rdb_Park;
+ unsigned long rdb_Reserved2[3];
+ unsigned long rdb_WritePreComp;
+ unsigned long rdb_ReducedWrite;
+ unsigned long rdb_StepRate;
+ unsigned long rdb_Reserved3[5];
+ unsigned long rdb_RDBBlocksLo;
+ unsigned long rdb_RDBBlocksHi;
+ unsigned long rdb_LoCylinder;
+ unsigned long rdb_HiCylinder;
+ unsigned long rdb_CylBlocks;
+ unsigned long rdb_AutoParkSeconds;
+ unsigned long rdb_HighRDSKBlock;
+ unsigned long rdb_Reserved4;
+ char rdb_DiskVendor[8];
+ char rdb_DiskProduct[16];
+ char rdb_DiskRevision[4];
+ char rdb_ControllerVendor[8];
+ char rdb_ControllerProduct[16];
+ char rdb_ControllerRevision[4];
+ char rdb_DriveInitName[40];
+};
+
+struct PartitionBlock
+{
+ unsigned long pb_ID;
+ unsigned long pb_SummedLongs;
+ long pb_ChkSum;
+ unsigned long pb_HostID;
+ unsigned long pb_Next;
+ unsigned long pb_Flags;
+ unsigned long pb_Reserved1[2];
+ unsigned long pb_DevFlags;
+ char pb_DriveName[32];
+ unsigned long pb_Reserved2[15];
+ unsigned long pb_Environment[20];
+ unsigned long pb_EReserved[12];
+};
+
+#define DE_TABLESIZE 0
+#define DE_SIZEBLOCK 1
+#define DE_BLOCKSIZE 2
+#define DE_NUMHEADS 3
+#define DE_SECSPERBLOCK 4
+#define DE_BLKSPERTRACK 5
+#define DE_RESERVEDBLKS 6
+#define DE_PREFAC 7
+#define DE_INTERLEAVE 8
+#define DE_LOWCYL 9
+#define DE_HIGHCYL 10
+#define DE_UPPERCYL DE_HIGHCYL
+#define DE_NUMBUFFERS 11
+#define DE_BUFMEMTYPE 12
+#define DE_MEMBUFTYPE DE_BUFMEMTYPE
+#define DE_MAXTRANSFER 13
+#define DE_MASK 14
+#define DE_BOOTPRI 15
+#define DE_DOSTYPE 16
+#define DE_BAUD 17
+#define DE_CONTROL 18
+#define DE_BOOTBLOCKS 19
+
+
+/******************************** AFFS definitions */
+#define T_SHORT 2
+#define T_LIST 16
+
+#define ST_FILE -3
+#define ST_ROOT 1
+#define ST_USERDIR 2
+
+struct BootBlock{
+ int id;
+ int chksum;
+ int rootblock;
+ int data[127];
+};
+
+struct RootBlock{
+ int p_type; //0
+ int n1[2]; //1-2
+ int hashtable_size; //3
+ int n2; //4
+ int checksum; //5
+ int hashtable[72]; //6-77
+ int bitmap_valid_flag; //78
+ int bitmap_ptrs[25]; //79-103
+ int bitmap_extension; //104
+ int root_days; //105
+ int root_mins; //106
+ int root_ticks; //107;
+ char diskname[32]; //108-115
+ int n3[2]; //116-117
+ int volume_days; //118
+ int volume_mins; //119
+ int volume_ticks; //120
+ int creation_days; //121
+ int creation_mins; //122
+ int creation_ticks; //123
+ int n4[3]; //124-126
+ int s_type; //127
+};
+
+struct DirHeader {
+ int p_type; //0
+ int own_key; //1
+ int n1[3]; //2-4
+ int checksum; //5
+ int hashtable[72]; //6-77
+ int n2; //78
+ int owner; //79
+ int protection; //80
+ int n3; //81
+ char comment[92]; //82-104
+ int days; //105
+ int mins; //106
+ int ticks; //107
+ char name[32]; //108-115
+ int n4[2]; //116-117
+ int linkchain; //118
+ int n5[5]; //119-123
+ int hashchain; //124
+ int parent; //125
+ int n6; //126
+ int s_type; //127
+};
+
+struct FileHeader {
+ int p_type; //0
+ int own_key; //1
+ int n1[3]; //2-4
+ int checksum; //5
+ int filekey_table[72]; //6-77
+ int n2; //78
+ int owner; //79
+ int protection; //80
+ int bytesize; //81
+ char comment[92]; //82-104
+ int days; //105
+ int mins; //106
+ int ticks; //107
+ char name[32]; //108-115
+ int n3[2]; //116-117
+ int linkchain; //118
+ int n4[5]; //119-123
+ int hashchain; //124
+ int parent; //125
+ int extension; //126
+ int s_type; //127
+};
+
+struct FileKeyExtension{
+ int p_type; //0
+ int own_key; //1
+ int table_size; //2
+ int n1[2]; //3-4
+ int checksum; //5
+ int filekey_table[72]; //6-77
+ int info[46]; //78-123
+ int n2; //124
+ int parent; //125
+ int extension; //126
+ int s_type; //127
+};
+
+struct Position {
+ unsigned int block;
+ short filekey;
+ unsigned short byte;
+ unsigned int offset;
+};
+
+struct ReadData {
+ unsigned int header_block;
+ struct Position current;
+ unsigned int filesize;
+};
+
+//#warning "Big vs. little endian for configure needed"
+#define AROS_BE2LONG(l) \
+ ( \
+ ((((unsigned long)(l)) >> 24) & 0x000000FFUL) | \
+ ((((unsigned long)(l)) >> 8) & 0x0000FF00UL) | \
+ ((((unsigned long)(l)) << 8) & 0x00FF0000UL) | \
+ ((((unsigned long)(l)) << 24) & 0xFF000000UL) \
+ )
+
+struct CacheBlock {
+ int blocknum;
+ unsigned short flags;
+ unsigned short access_count;
+ unsigned int blockbuffer[128];
+};
+#define LockBuffer(x) (((struct CacheBlock *)(x))->flags |= 0x0001)
+#define UnLockBuffer(x) (((struct CacheBlock *)(x))->flags &= ~0x0001)
+
+#define MAX_CACHE_BLOCKS 10
+
+struct FSysBuffer {
+ struct ReadData file;
+ struct CacheBlock blocks[MAX_CACHE_BLOCKS];
+};
+
+#define bootBlock(x) ((struct BootBlock *)(x)->blockbuffer)
+#define rootBlock(x) ((struct RootBlock *)(x)->blockbuffer)
+#define dirHeader(x) ((struct DirHeader *)(x)->blockbuffer)
+#define fileHeader(x) ((struct FileHeader *)(x)->blockbuffer)
+#define extensionBlock(x) ((struct FileKeyExtension *)(x)->blockbuffer)
+
+#define rdsk(x) ((struct RigidDiskBlock *)(x)->blockbuffer)
+#define part(x) ((struct PartitionBlock *)(x)->blockbuffer)
+
+static struct FSysBuffer *fsysb;
+static int blockoffset; /* offset if there is an embedded RDB partition */
+static int rootb; /* block number of root block */
+static int rdbb; /* block number of rdb block */
+
+static void initCache(void)
+{
+int i;
+
+ for (i=0;i<MAX_CACHE_BLOCKS;i++)
+ {
+ fsysb->blocks[i].blocknum = -1;
+ fsysb->blocks[i].flags = 0;
+ fsysb->blocks[i].access_count = 0;
+ }
+}
+
+static struct CacheBlock *getBlock(unsigned int block)
+{
+struct CacheBlock *freeblock;
+int i;
+
+ /* get first unlocked block */
+ i = 0;
+ do
+ {
+ freeblock = &fsysb->blocks[i++];
+ } while (freeblock->flags & 0x0001);
+ /* search through list if block is already loaded in */
+ for (i=0;i<MAX_CACHE_BLOCKS;i++)
+ {
+ if (fsysb->blocks[i].blocknum == block)
+ {
+ fsysb->blocks[i].access_count++;
+ return &fsysb->blocks[i];
+ }
+ if (!(fsysb->blocks[i].flags & 0x0001))
+ if (freeblock->access_count>fsysb->blocks[i].access_count)
+ freeblock = &fsysb->blocks[i];
+ }
+ freeblock->blocknum = block;
+ devread(block+blockoffset, 0, 512, (char *)freeblock->blockbuffer);
+ return freeblock;
+}
+
+static unsigned int calcChkSum(unsigned short SizeBlock, unsigned int *buffer)
+{
+unsigned int sum=0,count=0;
+
+ for (count=0;count<SizeBlock;count++)
+ sum += AROS_BE2LONG(buffer[count]);
+ return sum;
+}
+
+int affs_mount(void) {
+struct CacheBlock *cblock;
+int i;
+
+ if (
+ (current_drive & 0x80) &&
+ (current_partition != 0xFFFFFF) &&
+ (current_slice != 0x30)
+ )
+ return 0;
+ fsysb = (struct FSysBuffer *)FSYS_BUF;
+ blockoffset = 0;
+ initCache();
+ /* check for rdb partitiontable */
+ for (i=0;i<RDB_LOCATION_LIMIT;i++)
+ {
+ cblock = getBlock(i);
+ if (
+ (
+ ((AROS_BE2LONG(bootBlock(cblock)->id) & 0xFFFFFF00)==0x444F5300) &&
+ ((AROS_BE2LONG(bootBlock(cblock)->id) & 0xFF)>0)
+ ) ||
+ (AROS_BE2LONG(cblock->blockbuffer[0]) == IDNAME_RIGIDDISK)
+ )
+ break;
+ }
+ if (i == RDB_LOCATION_LIMIT)
+ return 0;
+ if (AROS_BE2LONG(cblock->blockbuffer[0]) == IDNAME_RIGIDDISK)
+ {
+ /* we have an RDB partition table within a MBR-Partition */
+ rdbb = i;
+ }
+ else if (i<2)
+ {
+ /* partition type is 0x30 = AROS and AFFS formatted */
+ rdbb = RDB_LOCATION_LIMIT;
+ rootb = (part_length-1+2)/2;
+ cblock = getBlock(rootb);
+ if (
+ (AROS_BE2LONG(rootBlock(cblock)->p_type) != T_SHORT) ||
+ (AROS_BE2LONG(rootBlock(cblock)->s_type) != ST_ROOT) ||
+ calcChkSum(128, cblock->blockbuffer)
+ )
+ return 0;
+ }
+ else
+ return 0;
+ return 1;
+}
+
+static int seek(unsigned long offset)
+{
+struct CacheBlock *cblock;
+unsigned long block;
+unsigned long togo;
+
+ block = fsysb->file.header_block;
+
+ togo = offset / 512;
+ fsysb->file.current.filekey = 71-(togo % 72);
+ togo /= 72;
+ fsysb->file.current.byte = offset % 512;
+ fsysb->file.current.offset = offset;
+ while ((togo) && (block))
+ {
+ disk_read_func = disk_read_hook;
+ cblock = getBlock(block);
+ disk_read_func = NULL;
+ block = AROS_BE2LONG(extensionBlock(cblock)->extension);
+ togo--;
+ }
+ if (togo)
+ return 1;
+ fsysb->file.current.block = block;
+ return 0;
+}
+
+int affs_read(char *buf, int len) {
+struct CacheBlock *cblock;
+unsigned short size;
+unsigned int readbytes = 0;
+
+ if (fsysb->file.current.offset != filepos)
+ {
+ if (seek(filepos))
+ return ERR_FILELENGTH;
+ }
+ if (fsysb->file.current.block == 0)
+ return 0;
+ if (len>(fsysb->file.filesize-fsysb->file.current.offset))
+ len=fsysb->file.filesize-fsysb->file.current.offset;
+ disk_read_func = disk_read_hook;
+ cblock = getBlock(fsysb->file.current.block);
+ disk_read_func = NULL;
+ while (len)
+ {
+ disk_read_func = disk_read_hook;
+ if (fsysb->file.current.filekey<0)
+ {
+ fsysb->file.current.filekey = 71;
+ fsysb->file.current.block = AROS_BE2LONG(extensionBlock(cblock)->extension);
+ if (fsysb->file.current.block)
+ {
+ cblock = getBlock(fsysb->file.current.block);
+ }
+ //#warning "else shouldn't occour"
+ }
+ size = 512;
+ size -= fsysb->file.current.byte;
+ if (size>len)
+ {
+ size = len;
+ devread
+ (
+ AROS_BE2LONG
+ (
+ extensionBlock(cblock)->filekey_table
+ [fsysb->file.current.filekey]
+ )+blockoffset,
+ fsysb->file.current.byte, size, (char *)((long)buf+readbytes)
+ );
+ fsysb->file.current.byte += size;
+ }
+ else
+ {
+ devread
+ (
+ AROS_BE2LONG
+ (
+ extensionBlock(cblock)->filekey_table
+ [fsysb->file.current.filekey]
+ )+blockoffset,
+ fsysb->file.current.byte, size, (char *)((long)buf+readbytes)
+ );
+ fsysb->file.current.byte = 0;
+ fsysb->file.current.filekey--;
+ }
+ disk_read_func = NULL;
+ len -= size;
+ readbytes += size;
+ }
+ fsysb->file.current.offset += readbytes;
+ filepos = fsysb->file.current.offset;
+ return readbytes;
+}
+
+static unsigned char capitalch(unsigned char ch, unsigned char flags)
+{
+
+ if ((flags==0) || (flags==1))
+ return (unsigned char)((ch>='a') && (ch<='z') ? ch-('a'-'A') : ch);
+ else // DOS\(>=2)
+ return (unsigned char)(((ch>=224) && (ch<=254) && (ch!=247)) ||
+ ((ch>='a') && (ch<='z')) ? ch-('a'-'A') : ch);
+}
+
+// str2 is a BCPL string
+static int noCaseStrCmp(char *str1, char *str2, unsigned char flags)
+{
+unsigned char length;
+
+ length=str2++[0];
+ do {
+ if ((*str1==0) && (length==0))
+ return 0;
+ length--;
+// if ((*str1==0) && (*str2==0)) return 1;
+ } while (capitalch(*str1++,flags)==capitalch(*str2++,flags));
+ str1--;
+ return (*str1) ? 1 : -1;
+}
+
+static unsigned int getHashKey(char *name,unsigned int tablesize, unsigned char flags)
+{
+unsigned int length;
+
+ length=0;
+ while (name[length] != 0)
+ length++;
+ while (*name!=0)
+ length=(length * 13 +capitalch(*name++,flags)) & 0x7FF;
+ return length%tablesize;
+}
+
+static grub_error_t getHeaderBlock(char *name, struct CacheBlock **dirh)
+{
+int key;
+
+ key = getHashKey(name, 72, 1);
+ if (!dirHeader(*dirh)->hashtable[key])
+ return ERR_FILE_NOT_FOUND;
+ *dirh = getBlock(AROS_BE2LONG(dirHeader(*dirh)->hashtable[key]));
+ if (calcChkSum(128, (*dirh)->blockbuffer))
+ {
+#ifdef DEBUG_AFFS
+printf("ghb: %d\n", (*dirh)->blocknum);
+#endif
+ return ERR_FSYS_CORRUPT;
+ }
+ if (AROS_BE2LONG(dirHeader(*dirh)->p_type) != T_SHORT)
+ return ERR_BAD_FILETYPE;
+ while (noCaseStrCmp(name,dirHeader(*dirh)->name,1) != 0)
+ {
+ if (!dirHeader(*dirh)->hashchain)
+ return ERR_FILE_NOT_FOUND;
+ *dirh = getBlock(AROS_BE2LONG(dirHeader(*dirh)->hashchain));
+ if (calcChkSum(128, (*dirh)->blockbuffer))
+ {
+#ifdef DEBUG_AFFS
+printf("ghb2: %d\n", (*dirh)->blocknum);
+#endif
+ return ERR_FSYS_CORRUPT;
+ }
+ if (AROS_BE2LONG(dirHeader(*dirh)->p_type) != T_SHORT)
+ return ERR_BAD_FILETYPE;
+ }
+ return 0;
+}
+
+static char *copyPart(char *src, char *dst)
+{
+ while ((*src != '/') && (*src))
+ *dst++ = *src++;
+ if (*src == '/')
+ src++;
+ *dst-- = 0;
+ /* cut off spaces at the end */
+ while (*dst == ' ')
+ *dst-- = 0;
+ return src;
+}
+
+static grub_error_t findBlock(char *name, struct CacheBlock **dirh)
+{
+char dname[32];
+int block;
+
+ name++; /* skip "/" */
+ /* partition table part */
+ if (rdbb < RDB_LOCATION_LIMIT)
+ {
+ int bpc;
+
+ blockoffset = 0;
+ *dirh = getBlock(rdbb);
+ if (*name==0)
+ return 0;
+ name = copyPart(name, dname);
+ bpc = AROS_BE2LONG(rdsk(*dirh)->rdb_Sectors)*AROS_BE2LONG(rdsk(*dirh)->rdb_Heads);
+ block = AROS_BE2LONG(rdsk(*dirh)->rdb_PartitionList);
+ while (block != -1)
+ {
+ *dirh = getBlock(block);
+ if (noCaseStrCmp(dname, part(*dirh)->pb_DriveName, 1) == 0)
+ break;
+ block = AROS_BE2LONG(part(*dirh)->pb_Next);
+ }
+ if (block == -1)
+ return ERR_FILE_NOT_FOUND;
+ if (
+ ((AROS_BE2LONG(part(*dirh)->pb_Environment[DE_DOSTYPE]) & 0xFFFFFF00)!=0x444F5300) ||
+ ((AROS_BE2LONG(part(*dirh)->pb_Environment[DE_DOSTYPE]) & 0xFF)==0)
+ )
+ return ERR_BAD_FILETYPE;
+ blockoffset = AROS_BE2LONG(part(*dirh)->pb_Environment[DE_LOWCYL]);
+ rootb = AROS_BE2LONG(part(*dirh)->pb_Environment[DE_HIGHCYL]);
+ rootb = rootb-blockoffset+1; /* highcyl-lowcyl+1 */
+ rootb *= bpc;
+ rootb = rootb-1+AROS_BE2LONG(part(*dirh)->pb_Environment[DE_RESERVEDBLKS]);
+ rootb /= 2;
+ blockoffset *= bpc;
+ }
+
+ /* filesystem part */
+ *dirh = getBlock(rootb);
+ while (*name)
+ {
+ if (
+ (AROS_BE2LONG(dirHeader(*dirh)->s_type) != ST_ROOT) &&
+ (AROS_BE2LONG(dirHeader(*dirh)->s_type) != ST_USERDIR)
+ )
+ return ERR_BAD_FILETYPE;
+ name = copyPart(name, dname);
+ errnum = getHeaderBlock(dname, dirh);
+ if (errnum)
+ return errnum;
+ }
+ return 0;
+}
+
+#ifndef STAGE1_5
+static void checkPossibility(char *filename, char *bstr)
+{
+ char cstr[32];
+
+ if (noCaseStrCmp(filename, bstr, 1)<=0)
+ {
+ if (print_possibilities>0)
+ print_possibilities = -print_possibilities;
+ memcpy(cstr, bstr+1, bstr[0]);
+ cstr[bstr[0]]=0;
+ print_a_completion(cstr);
+ }
+}
+#else
+#define checkPossibility(a, b) do { } while(0)
+#endif
+
+int affs_dir(char *dirname)
+{
+ struct CacheBlock *buffer1;
+ struct CacheBlock *buffer2;
+ char *current = dirname;
+ char filename[128];
+ char *fname = filename;
+ int i,block;
+
+ if (print_possibilities)
+ {
+ while (*current)
+ current++;
+ while (*current != '/')
+ current--;
+ current++;
+ while (*current)
+ {
+ *fname++ = *current;
+ *current++ = 0;
+ }
+ *fname=0;
+ errnum = findBlock(dirname, &buffer1);
+ if (errnum)
+ return 0;
+ if (AROS_BE2LONG(dirHeader(buffer1)->p_type) == IDNAME_RIGIDDISK)
+ {
+ block = AROS_BE2LONG(rdsk(buffer1)->rdb_PartitionList);
+ while (block != -1)
+ {
+ buffer1 = getBlock(block);
+ checkPossibility(filename, part(buffer1)->pb_DriveName);
+ block = AROS_BE2LONG(part(buffer1)->pb_Next);
+ }
+#ifndef STAGE1_5
+ if (*filename == 0)
+ if (print_possibilities>0)
+ print_possibilities = -print_possibilities;
+#endif
+ }
+ else if (AROS_BE2LONG(dirHeader(buffer1)->p_type) == T_SHORT)
+ {
+ LockBuffer(buffer1);
+ for (i=0;i<72;i++)
+ {
+ block = dirHeader(buffer1)->hashtable[i];
+ while (block)
+ {
+ buffer2 = getBlock(AROS_BE2LONG(block));
+ if (calcChkSum(128, buffer2->blockbuffer))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+ if (AROS_BE2LONG(dirHeader(buffer2)->p_type) != T_SHORT)
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ checkPossibility(filename, dirHeader(buffer2)->name);
+ block = dirHeader(buffer2)->hashchain;
+ }
+ }
+ UnLockBuffer(buffer1);
+#ifndef STAGE1_5
+ if (*filename == 0)
+ if (print_possibilities>0)
+ print_possibilities = -print_possibilities;
+#endif
+ }
+ else
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ while (*current != '/')
+ current--;
+ current++;
+ fname = filename;
+ while (*fname)
+ *current++ = *fname++;
+ //#warning "TODO: add some more chars until possibilities differ"
+ if (print_possibilities>0)
+ errnum = ERR_FILE_NOT_FOUND;
+ return (print_possibilities<0);
+ }
+ else
+ {
+ while (*current && !isspace(*current))
+ *fname++ = *current++;
+ *fname = 0;
+
+ errnum = findBlock(filename, &buffer2);
+ if (errnum)
+ return 0;
+ if (AROS_BE2LONG(fileHeader(buffer2)->s_type)!=ST_FILE)
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ fsysb->file.header_block = AROS_BE2LONG(fileHeader(buffer2)->own_key);
+ fsysb->file.current.block = AROS_BE2LONG(fileHeader(buffer2)->own_key);
+ fsysb->file.current.filekey = 71;
+ fsysb->file.current.byte = 0;
+ fsysb->file.current.offset = 0;
+ fsysb->file.filesize = AROS_BE2LONG(fileHeader(buffer2)->bytesize);
+ filepos = 0;
+ filemax = fsysb->file.filesize;
+ return 1;
+ }
+}
+#endif
diff --git a/roms/openbios/fs/grubfs/fsys_ext2fs.c b/roms/openbios/fs/grubfs/fsys_ext2fs.c
new file mode 100644
index 00000000..05425bbd
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_ext2fs.c
@@ -0,0 +1,794 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifdef FSYS_EXT2FS
+
+#include "config.h"
+#include "shared.h"
+#include "filesys.h"
+#include "libc/byteorder.h"
+
+#ifdef CONFIG_DEBUG_EXT2FS
+#define E2DEBUG
+#endif
+
+static int mapblock1, mapblock2;
+
+/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
+#define DEV_BSIZE 512
+
+/* include/linux/fs.h */
+#define BLOCK_SIZE 1024 /* initial block size for superblock read */
+/* made up, defaults to 1 but can be passed via mount_opts */
+#define WHICH_SUPER 1
+/* kind of from fs/ext2/super.c */
+#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */
+
+/* include/asm-i386/types.h */
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+/*
+ * Constants relative to the data blocks, from ext2_fs.h
+ */
+#define EXT2_NDIR_BLOCKS 12
+#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
+#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
+#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
+#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
+
+/* include/linux/ext2_fs.h */
+struct ext2_super_block
+ {
+ __u32 s_inodes_count; /* Inodes count */
+ __u32 s_blocks_count; /* Blocks count */
+ __u32 s_r_blocks_count; /* Reserved blocks count */
+ __u32 s_free_blocks_count; /* Free blocks count */
+ __u32 s_free_inodes_count; /* Free inodes count */
+ __u32 s_first_data_block; /* First Data Block */
+ __u32 s_log_block_size; /* Block size */
+ __s32 s_log_frag_size; /* Fragment size */
+ __u32 s_blocks_per_group; /* # Blocks per group */
+ __u32 s_frags_per_group; /* # Fragments per group */
+ __u32 s_inodes_per_group; /* # Inodes per group */
+ __u32 s_mtime; /* Mount time */
+ __u32 s_wtime; /* Write time */
+ __u16 s_mnt_count; /* Mount count */
+ __s16 s_max_mnt_count; /* Maximal mount count */
+ __u16 s_magic; /* Magic signature */
+ __u16 s_state; /* File system state */
+ __u16 s_errors; /* Behaviour when detecting errors */
+ __u16 s_pad;
+ __u32 s_lastcheck; /* time of last check */
+ __u32 s_checkinterval; /* max. time between checks */
+ __u32 s_creator_os; /* OS */
+ __u32 s_rev_level; /* Revision level */
+ __u16 s_def_resuid; /* Default uid for reserved blocks */
+ __u16 s_def_resgid; /* Default gid for reserved blocks */
+ __u32 s_reserved[235]; /* Padding to the end of the block */
+ };
+
+struct ext2_group_desc
+ {
+ __u32 bg_block_bitmap; /* Blocks bitmap block */
+ __u32 bg_inode_bitmap; /* Inodes bitmap block */
+ __u32 bg_inode_table; /* Inodes table block */
+ __u16 bg_free_blocks_count; /* Free blocks count */
+ __u16 bg_free_inodes_count; /* Free inodes count */
+ __u16 bg_used_dirs_count; /* Directories count */
+ __u16 bg_pad;
+ __u32 bg_reserved[3];
+ };
+
+struct ext2_inode
+ {
+ __u16 i_mode; /* File mode */
+ __u16 i_uid; /* Owner Uid */
+ __u32 i_size; /* 4: Size in bytes */
+ __u32 i_atime; /* Access time */
+ __u32 i_ctime; /* 12: Creation time */
+ __u32 i_mtime; /* Modification time */
+ __u32 i_dtime; /* 20: Deletion Time */
+ __u16 i_gid; /* Group Id */
+ __u16 i_links_count; /* 24: Links count */
+ __u32 i_blocks; /* Blocks count */
+ __u32 i_flags; /* 32: File flags */
+ union
+ {
+ struct
+ {
+ __u32 l_i_reserved1;
+ }
+ linux1;
+ struct
+ {
+ __u32 h_i_translator;
+ }
+ hurd1;
+ struct
+ {
+ __u32 m_i_reserved1;
+ }
+ masix1;
+ }
+ osd1; /* OS dependent 1 */
+ __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
+ __u32 i_version; /* File version (for NFS) */
+ __u32 i_file_acl; /* File ACL */
+ __u32 i_dir_acl; /* Directory ACL */
+ __u32 i_faddr; /* Fragment address */
+ union
+ {
+ struct
+ {
+ __u8 l_i_frag; /* Fragment number */
+ __u8 l_i_fsize; /* Fragment size */
+ __u16 i_pad1;
+ __u32 l_i_reserved2[2];
+ }
+ linux2;
+ struct
+ {
+ __u8 h_i_frag; /* Fragment number */
+ __u8 h_i_fsize; /* Fragment size */
+ __u16 h_i_mode_high;
+ __u16 h_i_uid_high;
+ __u16 h_i_gid_high;
+ __u32 h_i_author;
+ }
+ hurd2;
+ struct
+ {
+ __u8 m_i_frag; /* Fragment number */
+ __u8 m_i_fsize; /* Fragment size */
+ __u16 m_pad1;
+ __u32 m_i_reserved2[2];
+ }
+ masix2;
+ }
+ osd2; /* OS dependent 2 */
+ };
+
+/* linux/posix_type.h */
+typedef long linux_off_t;
+
+/* linux/ext2fs.h */
+#define EXT2_NAME_LEN 255
+struct ext2_dir_entry
+ {
+ __u32 inode; /* Inode number */
+ __u16 rec_len; /* Directory entry length */
+ __u8 name_len; /* Name length */
+ __u8 file_type;
+ char name[EXT2_NAME_LEN]; /* File name */
+ };
+
+/* ext2/super.c */
+#define EXT2_SUPER_MAGIC 0xEF53 /* include/linux/ext2_fs.h */
+#define EXT2_ROOT_INO 2 /* include/linux/ext2_fs.h */
+#define PATH_MAX 1024 /* include/linux/limits.h */
+#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
+
+/* made up, these are pointers into FSYS_BUF */
+/* read once, always stays there: */
+#define SUPERBLOCK \
+ ((struct ext2_super_block *)(FSYS_BUF))
+#define GROUP_DESC \
+ ((struct ext2_group_desc *) \
+ ((char *)SUPERBLOCK + sizeof(struct ext2_super_block)))
+#define INODE \
+ ((struct ext2_inode *)((char *)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
+#define DATABLOCK1 \
+ ((char *)((char *)INODE + sizeof(struct ext2_inode)))
+#define DATABLOCK2 \
+ ((char *)((char *)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK)))
+
+/* linux/ext2_fs.h */
+#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
+#define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
+
+/* linux/ext2_fs.h */
+#define EXT2_BLOCK_SIZE_BITS(s) (__le32_to_cpu((s)->s_log_block_size) + 10)
+/* kind of from ext2/super.c */
+#define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s))
+/* linux/ext2fs.h */
+#define EXT2_DESC_PER_BLOCK(s) \
+ (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+/* linux/stat.h */
+#define S_IFMT 00170000
+#define S_IFLNK 0120000
+#define S_IFREG 0100000
+#define S_IFDIR 0040000
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+
+#ifdef E2DEBUG
+void
+dump_super(struct ext2_super_block *s)
+{
+ printf(" superblock 0x%x:\n", s);
+ printf(" inodes=%d\n", __le32_to_cpu(s->s_inodes_count));
+ printf(" blocks=%d\n", __le32_to_cpu(s->s_blocks_count));
+ printf(" reserved=%d\n", __le32_to_cpu(s->s_r_blocks_count));
+ printf(" i_free=%d\n", __le32_to_cpu(s->s_free_inodes_count));
+ printf(" b_free=%d\n", __le32_to_cpu(s->s_free_blocks_count));
+ printf(" first=%d\n", __le32_to_cpu(s->s_first_data_block));
+ printf(" log_b_size=%d, b_size=%d\n", __le32_to_cpu(s->s_log_block_size), EXT2_BLOCK_SIZE(s));
+ printf(" log_f_size=%d\n", __le32_to_cpu(s->s_log_frag_size));
+ printf(" bpg=%d\n", __le32_to_cpu(s->s_blocks_per_group));
+ printf(" fpg=%d\n", __le32_to_cpu(s->s_frags_per_group));
+ printf(" ipg=%d\n", __le32_to_cpu(s->s_inodes_per_group));
+}
+
+void
+dump_group_desc(struct ext2_group_desc *g)
+{
+ printf(" group_desc 0x%x:\n", g);
+ printf(" b_bmap block=%d\n", __le32_to_cpu(g->bg_block_bitmap));
+ printf(" i_bmap block=%d\n", __le32_to_cpu(g->bg_inode_bitmap));
+ printf(" i_tab block=%d\n", __le32_to_cpu(g->bg_inode_table));
+ printf(" free_blks=%d\n", __le16_to_cpu(g->bg_free_blocks_count));
+ printf(" free_inodes=%d\n", __le16_to_cpu(g->bg_free_inodes_count));
+ printf(" used_dirs=%d\n", __le16_to_cpu(g->bg_used_dirs_count));
+}
+
+void
+dump_inode(struct ext2_inode *i)
+{
+ printf(" inode 0x%x:\n", i);
+ printf(" mode=%o\n", __le16_to_cpu(i->i_mode));
+ printf(" uid=%d\n", __le16_to_cpu(i->i_uid));
+ printf(" gid=%d\n", __le16_to_cpu(i->i_gid));
+ printf(" size=%d\n", __le32_to_cpu(i->i_size));
+ printf(" atime=%d\n", __le32_to_cpu(i->i_atime));
+ printf(" ctime=%d\n", __le32_to_cpu(i->i_ctime));
+ printf(" mtime=%d\n", __le32_to_cpu(i->i_mtime));
+ printf(" dtime=%d\n", __le32_to_cpu(i->i_dtime));
+ printf(" links=%d\n", __le16_to_cpu(i->i_links_count));
+ printf(" blocks=%d\n", __le32_to_cpu(i->i_blocks));
+ printf(" flags=%d\n", __le32_to_cpu(i->i_flags));
+}
+
+void
+dump_inode_data(unsigned char *inode, int len)
+{
+ static char hexdigit[] = "0123456789abcdef";
+ unsigned char *i;
+ for (i = inode;
+ i < (inode + len);
+ i++)
+ {
+ printf ("%c", hexdigit[*i >> 4]);
+ printf ("%c", hexdigit[*i % 16]);
+ if (!((i + 1 - inode) % 16))
+ {
+ printf ("\n");
+ }
+ else
+ {
+ printf (" ");
+ }
+ }
+}
+#endif
+
+/* check filesystem types and read superblock into memory buffer */
+int
+ext2fs_mount (void)
+{
+ int retval = 1;
+
+ if ((((current_drive & 0x80) || (current_slice != 0))
+ && (current_slice != PC_SLICE_TYPE_EXT2FS)
+ && (current_slice != PC_SLICE_TYPE_LINUX_RAID)
+ && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
+ && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))
+ || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE))
+ || !devread (SBLOCK, 0, sizeof (struct ext2_super_block),
+ (char *) SUPERBLOCK)
+ || __le16_to_cpu(SUPERBLOCK->s_magic) != EXT2_SUPER_MAGIC)
+ retval = 0;
+
+ return retval;
+}
+
+/* Takes a file system block number and reads it into BUFFER. */
+static int
+ext2_rdfsb (int fsblock, char * buffer)
+{
+#ifdef E2DEBUG
+ printf ("ext2_rdfsb: fsblock %d, devblock %d, size %d\n", fsblock,
+ fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
+ EXT2_BLOCK_SIZE (SUPERBLOCK));
+#endif /* E2DEBUG */
+ return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0,
+ EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
+}
+
+/* from
+ ext2/inode.c:ext2_bmap()
+*/
+/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
+ a physical block (the location in the file system) via an inode. */
+static int
+ext2fs_block_map (int logical_block)
+{
+
+#ifdef E2DEBUG
+ printf ("ext2fs_block_map(%d)\n", logical_block);
+#endif /* E2DEBUG */
+
+ /* if it is directly pointed to by the inode, return that physical addr */
+ if (logical_block < EXT2_NDIR_BLOCKS)
+ {
+#ifdef E2DEBUG
+ printf ("ext2fs_block_map: returning %d\n", __le32_to_cpu(INODE->i_block[logical_block]));
+#endif /* E2DEBUG */
+ return __le32_to_cpu(INODE->i_block[logical_block]);
+ }
+ /* else */
+ logical_block -= EXT2_NDIR_BLOCKS;
+ /* try the indirect block */
+ if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
+ {
+ if (mapblock1 != 1
+ && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_IND_BLOCK]), DATABLOCK1))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ mapblock1 = 1;
+ return __le32_to_cpu(((__u32 *) DATABLOCK1)[logical_block]);
+ }
+ /* else */
+ logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
+ /* now try the double indirect block */
+ if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
+ {
+ int bnum;
+ if (mapblock1 != 2
+ && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_DIND_BLOCK]), DATABLOCK1))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ mapblock1 = 2;
+ if ((bnum = __le32_to_cpu(((__u32 *) DATABLOCK1)
+ [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
+ != mapblock2
+ && !ext2_rdfsb (bnum, DATABLOCK2))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ mapblock2 = bnum;
+ return __le32_to_cpu(((__u32 *) DATABLOCK2)
+ [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]);
+ }
+ /* else */
+ mapblock2 = -1;
+ logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
+ if (mapblock1 != 3
+ && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_TIND_BLOCK]), DATABLOCK1))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ mapblock1 = 3;
+ if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK1)
+ [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
+ * 2)]),
+ DATABLOCK2))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK2)
+ [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
+ & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]),
+ DATABLOCK2))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ return __le32_to_cpu(((__u32 *) DATABLOCK2)
+ [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]);
+}
+
+/* preconditions: all preconds of ext2fs_block_map */
+int
+ext2fs_read (char *buf, int len)
+{
+ int logical_block;
+ int offset;
+ int map;
+ int ret = 0;
+ int size = 0;
+
+#ifdef E2DEBUG
+ printf("ext2fs_read(0x%x, %d)\n", buf, len);
+ dump_inode(INODE);
+ dump_inode_data((unsigned char *)INODE, sizeof (struct ext2_inode));
+#endif /* E2DEBUG */
+ while (len > 0)
+ {
+ /* find the (logical) block component of our location */
+ logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
+ offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
+ map = ext2fs_block_map (logical_block);
+#ifdef E2DEBUG
+ printf ("map=%d\n", map);
+#endif /* E2DEBUG */
+ if (map < 0)
+ break;
+
+ size = EXT2_BLOCK_SIZE (SUPERBLOCK);
+ size -= offset;
+ if (size > len)
+ size = len;
+
+ disk_read_func = disk_read_hook;
+
+ devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
+ offset, size, buf);
+
+ disk_read_func = NULL;
+
+ buf += size;
+ len -= size;
+ filepos += size;
+ ret += size;
+ }
+
+ if (errnum)
+ ret = 0;
+
+ return ret;
+}
+
+
+/* Based on:
+ def_blk_fops points to
+ blkdev_open, which calls (I think):
+ sys_open()
+ do_open()
+ open_namei()
+ dir_namei() which accesses current->fs->root
+ fs->root was set during original mount:
+ (something)... which calls (I think):
+ ext2_read_super()
+ iget()
+ __iget()
+ read_inode()
+ ext2_read_inode()
+ uses desc_per_block_bits, which is set in ext2_read_super()
+ also uses group descriptors loaded during ext2_read_super()
+ lookup()
+ ext2_lookup()
+ ext2_find_entry()
+ ext2_getblk()
+
+*/
+
+/* preconditions: ext2fs_mount already executed, therefore supblk in buffer
+ * known as SUPERBLOCK
+ * returns: 0 if error, nonzero iff we were able to find the file successfully
+ * postconditions: on a nonzero return, buffer known as INODE contains the
+ * inode of the file we were trying to look up
+ * side effects: messes up GROUP_DESC buffer area
+ */
+int
+ext2fs_dir (char *dirname)
+{
+ int current_ino = EXT2_ROOT_INO; /* start at the root */
+ int updir_ino = current_ino; /* the parent of the current directory */
+ int group_id; /* which group the inode is in */
+ int group_desc; /* fs pointer to that group */
+ int desc; /* index within that group */
+ int ino_blk; /* fs pointer of the inode's information */
+ int str_chk = 0; /* used to hold the results of a string compare */
+ struct ext2_group_desc *gdp;
+ struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
+
+ char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
+ int link_count = 0;
+
+ char *rest;
+ char ch; /* temp char holder */
+
+ int off; /* offset within block of directory entry (off mod blocksize) */
+ int loc; /* location within a directory */
+ int blk; /* which data blk within dir entry (off div blocksize) */
+ long map; /* fs pointer of a particular block from dir entry */
+ struct ext2_dir_entry *dp; /* pointer to directory entry */
+
+ /* loop invariants:
+ current_ino = inode to lookup
+ dirname = pointer to filename component we are cur looking up within
+ the directory known pointed to by current_ino (if any)
+ */
+
+#ifdef E2DEBUG
+ printf("****** ext2fs_dir(%s)\n", dirname);
+ dump_super(SUPERBLOCK);
+#endif /* E2DEBUG */
+
+ while (1)
+ {
+#ifdef E2DEBUG
+ printf ("ext2fs_dir: inode %d\n", current_ino);
+ printf ("ext2fs_dir: dirname=%s\n", dirname);
+#endif /* E2DEBUG */
+
+ /* look up an inode */
+ group_id = (current_ino - 1) / __le32_to_cpu(SUPERBLOCK->s_inodes_per_group);
+ group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
+ desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);
+#ifdef E2DEBUG
+ printf ("ext2fs_dir: ipg=%d, dpb=%d\n", __le32_to_cpu(SUPERBLOCK->s_inodes_per_group),
+ EXT2_DESC_PER_BLOCK (SUPERBLOCK));
+ printf ("ext2fs_dir: group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc);
+#endif /* E2DEBUG */
+ if (!ext2_rdfsb (
+ (WHICH_SUPER + group_desc + __le32_to_cpu(SUPERBLOCK->s_first_data_block)),
+ (char*) GROUP_DESC))
+ {
+ return 0;
+ }
+
+#ifdef E2DEBUG
+ dump_group_desc(GROUP_DESC);
+#endif /* E2DEBUG */
+
+ gdp = GROUP_DESC;
+ ino_blk = __le32_to_cpu(gdp[desc].bg_inode_table) +
+ (((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group))
+ >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
+#ifdef E2DEBUG
+ printf ("ext2fs_dir: itab_blk=%d, i_in_grp=%d, log2=%d\n",
+ __le32_to_cpu(gdp[desc].bg_inode_table),
+ ((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group)),
+ log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
+ printf ("ext2fs_dir: inode table fsblock=%d\n", ino_blk);
+#endif /* E2DEBUG */
+ if (!ext2_rdfsb (ino_blk, (char *)INODE))
+ {
+ return 0;
+ }
+
+ /* reset indirect blocks! */
+ mapblock2 = mapblock1 = -1;
+
+ raw_inode = INODE +
+ ((current_ino - 1)
+ & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
+#ifdef E2DEBUG
+ printf ("ext2fs_dir: ipb=%d, sizeof(inode)=%d\n",
+ (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
+ sizeof (struct ext2_inode));
+ printf ("ext2fs_dir: inode=%x, raw_inode=%x\n", INODE, raw_inode);
+ printf ("ext2fs_dir: offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
+ dump_inode(raw_inode);
+ dump_inode_data((unsigned char *)INODE, EXT2_BLOCK_SIZE(SUPERBLOCK));
+ printf ("ext2fs_dir: first word=%x\n", *((int *) raw_inode));
+#endif /* E2DEBUG */
+
+ /* copy inode to fixed location */
+ memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode));
+
+#ifdef E2DEBUG
+ dump_inode(INODE);
+ printf ("ext2fs_dir: first word=%x\n", *((int *) INODE));
+#endif /* E2DEBUG */
+
+ /* If we've got a symbolic link, then chase it. */
+ if (S_ISLNK (__le16_to_cpu(INODE->i_mode)))
+ {
+ int len;
+ if (++link_count > MAX_LINK_COUNT)
+ {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ }
+
+ /* Find out how long our remaining name is. */
+ len = 0;
+ while (dirname[len] && !isspace (dirname[len]))
+ len++;
+
+ /* Get the symlink size. */
+ filemax = __le32_to_cpu(INODE->i_size);
+ if (filemax + len > sizeof (linkbuf) - 2)
+ {
+ errnum = ERR_FILELENGTH;
+ return 0;
+ }
+
+ if (len)
+ {
+ /* Copy the remaining name to the end of the symlink data.
+ Note that DIRNAME and LINKBUF may overlap! */
+ memmove (linkbuf + filemax, dirname, len);
+ }
+ linkbuf[filemax + len] = '\0';
+
+ /* Read the symlink data. */
+ if (__le32_to_cpu(INODE->i_blocks))
+ {
+ /* Read the necessary blocks, and reset the file pointer. */
+ len = file_read (linkbuf, filemax);
+ filepos = 0;
+ if (!len)
+ return 0;
+ }
+ else
+ {
+ /* Copy the data directly from the inode. */
+ len = filemax;
+ memmove (linkbuf, (char *) INODE->i_block, len);
+ }
+
+#ifdef E2DEBUG
+ printf ("ext2fs_dir: symlink=%s\n", linkbuf);
+#endif
+
+ dirname = linkbuf;
+ if (*dirname == '/')
+ {
+ /* It's an absolute link, so look it up in root. */
+ current_ino = EXT2_ROOT_INO;
+ updir_ino = current_ino;
+ }
+ else
+ {
+ /* Relative, so look it up in our parent directory. */
+ current_ino = updir_ino;
+ }
+
+ /* Try again using the new name. */
+ continue;
+ }
+
+ /* if end of filename, INODE points to the file's inode */
+ if (!*dirname || isspace (*dirname))
+ {
+ if (!S_ISREG (__le16_to_cpu(INODE->i_mode)))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ filemax = __le32_to_cpu(INODE->i_size);
+ return 1;
+ }
+
+ /* else we have to traverse a directory */
+ updir_ino = current_ino;
+
+ /* skip over slashes */
+ while (*dirname == '/')
+ dirname++;
+
+ /* if this isn't a directory of sufficient size to hold our file, abort */
+ if (!(__le32_to_cpu(INODE->i_size)) || !S_ISDIR (__le16_to_cpu(INODE->i_mode)))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ /* skip to next slash or end of filename (space) */
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
+ rest++);
+
+ /* look through this directory and find the next filename component */
+ /* invariant: rest points to slash after the next filename component */
+ *rest = 0;
+ loc = 0;
+
+ do
+ {
+
+#ifdef E2DEBUG
+ printf ("ext2fs_dir: dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc);
+#endif /* E2DEBUG */
+
+ /* if our location/byte offset into the directory exceeds the size,
+ give up */
+ if (loc >= __le32_to_cpu(INODE->i_size))
+ {
+ if (print_possibilities < 0)
+ {
+# if 0
+ putchar ('\n');
+# endif
+ }
+ else
+ {
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ }
+ return (print_possibilities < 0);
+ }
+
+ /* else, find the (logical) block component of our location */
+ blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
+
+ /* we know which logical block of the directory entry we are looking
+ for, now we have to translate that to the physical (fs) block on
+ the disk */
+ map = ext2fs_block_map (blk);
+#ifdef E2DEBUG
+ printf ("ext2fs_dir: fs block=%d\n", map);
+#endif /* E2DEBUG */
+ mapblock2 = -1;
+ if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ *rest = ch;
+ return 0;
+ }
+ off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
+ dp = (struct ext2_dir_entry *) (DATABLOCK2 + off);
+ /* advance loc prematurely to next on-disk directory entry */
+ loc += __le16_to_cpu(dp->rec_len);
+
+ /* NOTE: ext2fs filenames are NOT null-terminated */
+
+#ifdef E2DEBUG
+ printf ("ext2fs_dir: directory entry ino=%d\n", __le32_to_cpu(dp->inode));
+ if (__le32_to_cpu(dp->inode))
+ printf ("entry=%s\n", dp->name);
+#endif /* E2DEBUG */
+
+ if (__le32_to_cpu(dp->inode))
+ {
+ int saved_c = dp->name[dp->name_len];
+
+ dp->name[dp->name_len] = 0;
+ str_chk = substring (dirname, dp->name);
+
+# ifndef STAGE1_5
+ if (print_possibilities && ch != '/'
+ && (!*dirname || str_chk <= 0))
+ {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (dp->name);
+ }
+# endif
+
+ dp->name[dp->name_len] = saved_c;
+ }
+
+ }
+ while (!__le32_to_cpu(dp->inode) || (str_chk || (print_possibilities && ch != '/')));
+
+ current_ino = __le32_to_cpu(dp->inode);
+ *(dirname = rest) = ch;
+ }
+ /* never get here */
+}
+
+#endif /* FSYS_EXT2_FS */
diff --git a/roms/openbios/fs/grubfs/fsys_fat.c b/roms/openbios/fs/grubfs/fsys_fat.c
new file mode 100644
index 00000000..a7e160d1
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_fat.c
@@ -0,0 +1,477 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifdef FSYS_FAT
+
+#include "shared.h"
+#include "filesys.h"
+#include "fat.h"
+
+struct fat_superblock
+{
+ int fat_offset;
+ int fat_length;
+ int fat_size;
+ int root_offset;
+ int root_max;
+ int data_offset;
+
+ int num_sectors;
+ int num_clust;
+ int clust_eof_marker;
+ int sects_per_clust;
+ int sectsize_bits;
+ int clustsize_bits;
+ int root_cluster;
+
+ int cached_fat;
+ int file_cluster;
+ int current_cluster_num;
+ int current_cluster;
+};
+
+/* pointer(s) into filesystem info buffer for DOS stuff */
+#define FAT_SUPER ( (struct fat_superblock *) \
+ ( FSYS_BUF + 32256) )/* 512 bytes long */
+#define FAT_BUF ( FSYS_BUF + 30208 ) /* 4 sector FAT buffer */
+#define NAME_BUF ( FSYS_BUF + 29184 ) /* Filename buffer (833 bytes) */
+
+#define FAT_CACHE_SIZE 2048
+
+int
+fat_mount (void)
+{
+ struct fat_bpb bpb;
+ __u32 magic, first_fat;
+
+ /* Check partition type for harddisk */
+ if (((current_drive & 0x80) || (current_slice != 0))
+ && ! IS_PC_SLICE_TYPE_FAT (current_slice)
+ && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_MSDOS)))
+ return 0;
+
+ /* Read bpb */
+ if (! devread (0, 0, sizeof (bpb), (char *) &bpb))
+ return 0;
+
+ /* Check if the number of sectors per cluster is zero here, to avoid
+ zero division. */
+ if (bpb.sects_per_clust == 0)
+ return 0;
+
+ FAT_SUPER->sectsize_bits = log2 (bpb.bytes_per_sect);
+ FAT_SUPER->clustsize_bits
+ = FAT_SUPER->sectsize_bits + log2 (bpb.sects_per_clust);
+
+ /* Fill in info about super block */
+ FAT_SUPER->num_sectors = bpb.short_sectors
+ ? bpb.short_sectors : bpb.long_sectors;
+
+ /* FAT offset and length */
+ FAT_SUPER->fat_offset = bpb.reserved_sects;
+ FAT_SUPER->fat_length =
+ bpb.fat_length ? bpb.fat_length : bpb.fat32_length;
+
+ /* Rootdir offset and length for FAT12/16 */
+ FAT_SUPER->root_offset =
+ FAT_SUPER->fat_offset + bpb.num_fats * FAT_SUPER->fat_length;
+ FAT_SUPER->root_max = FAT_DIRENTRY_LENGTH * bpb.dir_entries;
+
+ /* Data offset and number of clusters */
+ FAT_SUPER->data_offset =
+ FAT_SUPER->root_offset
+ + ((FAT_SUPER->root_max - 1) >> FAT_SUPER->sectsize_bits) + 1;
+ FAT_SUPER->num_clust =
+ 2 + ((FAT_SUPER->num_sectors - FAT_SUPER->data_offset)
+ / bpb.sects_per_clust);
+ FAT_SUPER->sects_per_clust = bpb.sects_per_clust;
+
+ if (!bpb.fat_length)
+ {
+ /* This is a FAT32 */
+ if (bpb.dir_entries)
+ return 0;
+
+ if (bpb.flags & 0x0080)
+ {
+ /* FAT mirroring is disabled, get active FAT */
+ int active_fat = bpb.flags & 0x000f;
+ if (active_fat >= bpb.num_fats)
+ return 0;
+ FAT_SUPER->fat_offset += active_fat * FAT_SUPER->fat_length;
+ }
+
+ FAT_SUPER->fat_size = 8;
+ FAT_SUPER->root_cluster = bpb.root_cluster;
+
+ /* Yes the following is correct. FAT32 should be called FAT28 :) */
+ FAT_SUPER->clust_eof_marker = 0xffffff8;
+ }
+ else
+ {
+ if (!FAT_SUPER->root_max)
+ return 0;
+
+ FAT_SUPER->root_cluster = -1;
+ if (FAT_SUPER->num_clust > FAT_MAX_12BIT_CLUST)
+ {
+ FAT_SUPER->fat_size = 4;
+ FAT_SUPER->clust_eof_marker = 0xfff8;
+ }
+ else
+ {
+ FAT_SUPER->fat_size = 3;
+ FAT_SUPER->clust_eof_marker = 0xff8;
+ }
+ }
+
+
+ /* Now do some sanity checks */
+
+ if (bpb.bytes_per_sect != (1 << FAT_SUPER->sectsize_bits)
+ || bpb.bytes_per_sect != SECTOR_SIZE
+ || bpb.sects_per_clust != (1 << (FAT_SUPER->clustsize_bits
+ - FAT_SUPER->sectsize_bits))
+ || FAT_SUPER->num_clust <= 2
+ || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE)
+ > FAT_SUPER->fat_length))
+ return 0;
+
+ /* kbs: Media check on first FAT entry [ported from PUPA] */
+
+ if (!devread(FAT_SUPER->fat_offset, 0,
+ sizeof(first_fat), (char *)&first_fat))
+ return 0;
+
+ if (FAT_SUPER->fat_size == 8)
+ {
+ first_fat &= 0x0fffffff;
+ magic = 0x0fffff00;
+ }
+ else if (FAT_SUPER->fat_size == 4)
+ {
+ first_fat &= 0x0000ffff;
+ magic = 0xff00;
+ }
+ else
+ {
+ first_fat &= 0x00000fff;
+ magic = 0x0f00;
+ }
+
+ if (first_fat != (magic | bpb.media))
+ return 0;
+
+ FAT_SUPER->cached_fat = - 2 * FAT_CACHE_SIZE;
+ return 1;
+}
+
+int
+fat_read (char *buf, int len)
+{
+ int logical_clust;
+ int offset;
+ int ret = 0;
+ int size;
+
+ if (FAT_SUPER->file_cluster < 0)
+ {
+ /* root directory for fat16 */
+ size = FAT_SUPER->root_max - filepos;
+ if (size > len)
+ size = len;
+ if (!devread(FAT_SUPER->root_offset, filepos, size, buf))
+ return 0;
+ filepos += size;
+ return size;
+ }
+
+ logical_clust = filepos >> FAT_SUPER->clustsize_bits;
+ offset = (filepos & ((1 << FAT_SUPER->clustsize_bits) - 1));
+ if (logical_clust < FAT_SUPER->current_cluster_num)
+ {
+ FAT_SUPER->current_cluster_num = 0;
+ FAT_SUPER->current_cluster = FAT_SUPER->file_cluster;
+ }
+
+ while (len > 0)
+ {
+ int sector;
+ while (logical_clust > FAT_SUPER->current_cluster_num)
+ {
+ /* calculate next cluster */
+ int fat_entry =
+ FAT_SUPER->current_cluster * FAT_SUPER->fat_size;
+ int next_cluster;
+ int cached_pos = (fat_entry - FAT_SUPER->cached_fat);
+
+ if (cached_pos < 0 ||
+ (cached_pos + FAT_SUPER->fat_size) > 2*FAT_CACHE_SIZE)
+ {
+ FAT_SUPER->cached_fat = (fat_entry & ~(2*SECTOR_SIZE - 1));
+ cached_pos = (fat_entry - FAT_SUPER->cached_fat);
+ sector = FAT_SUPER->fat_offset
+ + FAT_SUPER->cached_fat / (2*SECTOR_SIZE);
+ if (!devread (sector, 0, FAT_CACHE_SIZE, (char*) FAT_BUF))
+ return 0;
+ }
+ next_cluster = * (unsigned long *) (FAT_BUF + (cached_pos >> 1));
+ if (FAT_SUPER->fat_size == 3)
+ {
+ if (cached_pos & 1)
+ next_cluster >>= 4;
+ next_cluster &= 0xFFF;
+ }
+ else if (FAT_SUPER->fat_size == 4)
+ next_cluster &= 0xFFFF;
+
+ if (next_cluster >= FAT_SUPER->clust_eof_marker)
+ return ret;
+ if (next_cluster < 2 || next_cluster >= FAT_SUPER->num_clust)
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+
+ FAT_SUPER->current_cluster = next_cluster;
+ FAT_SUPER->current_cluster_num++;
+ }
+
+ sector = FAT_SUPER->data_offset +
+ ((FAT_SUPER->current_cluster - 2) << (FAT_SUPER->clustsize_bits
+ - FAT_SUPER->sectsize_bits));
+ size = (1 << FAT_SUPER->clustsize_bits) - offset;
+ if (size > len)
+ size = len;
+
+ disk_read_func = disk_read_hook;
+
+ devread(sector, offset, size, buf);
+
+ disk_read_func = NULL;
+
+ len -= size;
+ buf += size;
+ ret += size;
+ filepos += size;
+ logical_clust++;
+ offset = 0;
+ }
+ return errnum ? 0 : ret;
+}
+
+int
+fat_dir (char *dirname)
+{
+ char *rest, ch, dir_buf[FAT_DIRENTRY_LENGTH];
+ char *filename = (char *) NAME_BUF;
+ int attrib = FAT_ATTRIB_DIR;
+#ifndef STAGE1_5
+ int do_possibilities = 0;
+#endif
+
+ /* XXX I18N:
+ * the positions 2,4,6 etc are high bytes of a 16 bit unicode char
+ */
+ static unsigned char longdir_pos[] =
+ { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };
+ int slot = -2;
+ int alias_checksum = -1;
+
+ FAT_SUPER->file_cluster = FAT_SUPER->root_cluster;
+ filepos = 0;
+ FAT_SUPER->current_cluster_num = MAXINT;
+
+ /* main loop to find desired directory entry */
+ loop:
+
+ /* if we have a real file (and we're not just printing possibilities),
+ then this is where we want to exit */
+
+ if (!*dirname || isspace (*dirname))
+ {
+ if (attrib & FAT_ATTRIB_DIR)
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /* continue with the file/directory name interpretation */
+
+ while (*dirname == '/')
+ dirname++;
+
+ if (!(attrib & FAT_ATTRIB_DIR))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ /* Directories don't have a file size */
+ filemax = MAXINT;
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+
+ *rest = 0;
+
+# ifndef STAGE1_5
+ if (print_possibilities && ch != '/')
+ do_possibilities = 1;
+# endif
+
+ while (1)
+ {
+ if (fat_read (dir_buf, FAT_DIRENTRY_LENGTH) != FAT_DIRENTRY_LENGTH
+ || dir_buf[0] == 0)
+ {
+ if (!errnum)
+ {
+# ifndef STAGE1_5
+ if (print_possibilities < 0)
+ {
+#if 0
+ putchar ('\n');
+#endif
+ return 1;
+ }
+# endif /* STAGE1_5 */
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ }
+
+ return 0;
+ }
+
+ if (FAT_DIRENTRY_ATTRIB (dir_buf) == FAT_ATTRIB_LONGNAME)
+ {
+ /* This is a long filename. The filename is build from back
+ * to front and may span multiple entries. To bind these
+ * entries together they all contain the same checksum over
+ * the short alias.
+ *
+ * The id field tells if this is the first entry (the last
+ * part) of the long filename, and also at which offset this
+ * belongs.
+ *
+ * We just write the part of the long filename this entry
+ * describes and continue with the next dir entry.
+ */
+ int i, offset;
+ unsigned char id = FAT_LONGDIR_ID(dir_buf);
+
+ if ((id & 0x40))
+ {
+ id &= 0x3f;
+ slot = id;
+ filename[slot * 13] = 0;
+ alias_checksum = FAT_LONGDIR_ALIASCHECKSUM(dir_buf);
+ }
+
+ if (id != slot || slot == 0
+ || alias_checksum != FAT_LONGDIR_ALIASCHECKSUM(dir_buf))
+ {
+ alias_checksum = -1;
+ continue;
+ }
+
+ slot--;
+ offset = slot * 13;
+
+ for (i=0; i < 13; i++)
+ filename[offset+i] = dir_buf[longdir_pos[i]];
+ continue;
+ }
+
+ if (!FAT_DIRENTRY_VALID (dir_buf))
+ continue;
+
+ if (alias_checksum != -1 && slot == 0)
+ {
+ int i;
+ unsigned char sum;
+
+ slot = -2;
+ for (sum = 0, i = 0; i< 11; i++)
+ sum = ((sum >> 1) | (sum << 7)) + dir_buf[i];
+
+ if (sum == alias_checksum)
+ {
+# ifndef STAGE1_5
+ if (do_possibilities)
+ goto print_filename;
+# endif /* STAGE1_5 */
+
+ if (substring (dirname, filename) == 0)
+ break;
+ }
+ }
+
+ /* XXX convert to 8.3 filename format here */
+ {
+ int i, j, c;
+
+ for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i]))
+ && !isspace (c); i++);
+
+ filename[i++] = '.';
+
+ for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j]))
+ && !isspace (c); j++);
+
+ if (j == 0)
+ i--;
+
+ filename[i + j] = 0;
+ }
+
+# ifndef STAGE1_5
+ if (do_possibilities)
+ {
+ print_filename:
+ if (substring (dirname, filename) <= 0)
+ {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (filename);
+ }
+ continue;
+ }
+# endif /* STAGE1_5 */
+
+ if (substring (dirname, filename) == 0)
+ break;
+ }
+
+ *(dirname = rest) = ch;
+
+ attrib = FAT_DIRENTRY_ATTRIB (dir_buf);
+ filemax = FAT_DIRENTRY_FILELENGTH (dir_buf);
+ filepos = 0;
+ FAT_SUPER->file_cluster = FAT_DIRENTRY_FIRST_CLUSTER (dir_buf);
+ FAT_SUPER->current_cluster_num = MAXINT;
+
+ /* go back to main loop at top of function */
+ goto loop;
+}
+
+#endif /* FSYS_FAT */
diff --git a/roms/openbios/fs/grubfs/fsys_ffs.c b/roms/openbios/fs/grubfs/fsys_ffs.c
new file mode 100644
index 00000000..c6804b8b
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_ffs.c
@@ -0,0 +1,311 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/*
+ * Elements of this file were originally from the FreeBSD "biosboot"
+ * bootloader file "disk.c" dated 4/12/95.
+ *
+ * The license and header comments from that file are included here.
+ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:35:49 rpd
+ * $Id: fsys_ffs.c,v 1.10 2001/11/12 06:57:29 okuji Exp $
+ */
+
+#ifdef FSYS_FFS
+
+#include "shared.h"
+
+#include "filesys.h"
+
+#include "defs.h"
+#include "disk_inode.h"
+#include "disk_inode_ffs.h"
+#include "dir.h"
+#include "fs.h"
+
+/* used for filesystem map blocks */
+static int mapblock;
+static int mapblock_offset;
+static int mapblock_bsize;
+
+/* pointer to superblock */
+#define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 ))
+#define INODE ((struct icommon *) ( FSYS_BUF + 16384 ))
+#define MAPBUF ( FSYS_BUF + 24576 )
+#define MAPBUF_LEN 8192
+
+
+int
+ffs_mount (void)
+{
+ int retval = 1;
+
+ if ((((current_drive & 0x80) || (current_slice != 0))
+ && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS))
+ || part_length < (SBLOCK + (SBSIZE / DEV_BSIZE))
+ || !devread (SBLOCK, 0, SBSIZE, (char *) SUPERBLOCK)
+ || SUPERBLOCK->fs_magic != FS_MAGIC)
+ retval = 0;
+
+ mapblock = -1;
+ mapblock_offset = -1;
+
+ return retval;
+}
+
+static int
+block_map (int file_block)
+{
+ int bnum, offset, bsize;
+
+ if (file_block < NDADDR)
+ return (INODE->i_db[file_block]);
+
+ /* If the blockmap loaded does not include FILE_BLOCK,
+ load a new blockmap. */
+ if ((bnum = fsbtodb (SUPERBLOCK, INODE->i_ib[0])) != mapblock
+ || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize))
+ {
+ if (MAPBUF_LEN < SUPERBLOCK->fs_bsize)
+ {
+ offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK));
+ bsize = MAPBUF_LEN;
+
+ if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize)
+ offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int);
+ }
+ else
+ {
+ bsize = SUPERBLOCK->fs_bsize;
+ offset = 0;
+ }
+
+ if (! devread (bnum, offset * sizeof (int), bsize, (char *) MAPBUF))
+ {
+ mapblock = -1;
+ mapblock_bsize = -1;
+ mapblock_offset = -1;
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+
+ mapblock = bnum;
+ mapblock_bsize = bsize;
+ mapblock_offset = offset;
+ }
+
+ return (((int *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK))
+ - mapblock_offset]);
+}
+
+
+int
+ffs_read (char *buf, int len)
+{
+ int logno, off, size, map, ret = 0;
+
+ while (len && !errnum)
+ {
+ off = blkoff (SUPERBLOCK, filepos);
+ logno = lblkno (SUPERBLOCK, filepos);
+ size = blksize (SUPERBLOCK, INODE, logno);
+
+ if ((map = block_map (logno)) < 0)
+ break;
+
+ size -= off;
+
+ if (size > len)
+ size = len;
+
+ disk_read_func = disk_read_hook;
+
+ devread (fsbtodb (SUPERBLOCK, map), off, size, buf);
+
+ disk_read_func = NULL;
+
+ buf += size;
+ len -= size;
+ filepos += size;
+ ret += size;
+ }
+
+ if (errnum)
+ ret = 0;
+
+ return ret;
+}
+
+
+int
+ffs_dir (char *dirname)
+{
+ char *rest, ch;
+ int block, off, loc, map, ino = ROOTINO;
+ struct direct *dp;
+
+/* main loop to find destination inode */
+loop:
+
+ /* load current inode (defaults to the root inode) */
+
+ if (!devread (fsbtodb (SUPERBLOCK, itod (SUPERBLOCK, ino)),
+ ino % (SUPERBLOCK->fs_inopb) * sizeof (struct dinode),
+ sizeof (struct dinode), (char *) INODE))
+ return 0; /* XXX what return value? */
+
+ /* if we have a real file (and we're not just printing possibilities),
+ then this is where we want to exit */
+
+ if (!*dirname || isspace (*dirname))
+ {
+ if ((INODE->i_mode & IFMT) != IFREG)
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ filemax = INODE->i_size;
+
+ /* incomplete implementation requires this! */
+ fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize;
+ return 1;
+ }
+
+ /* continue with file/directory name interpretation */
+
+ while (*dirname == '/')
+ dirname++;
+
+ if (!(INODE->i_size) || ((INODE->i_mode & IFMT) != IFDIR))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+
+ *rest = 0;
+ loc = 0;
+
+ /* loop for reading a the entries in a directory */
+
+ do
+ {
+ if (loc >= INODE->i_size)
+ {
+#if 0
+ putchar ('\n');
+#endif
+
+ if (print_possibilities < 0)
+ return 1;
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ return 0;
+ }
+
+ if (!(off = blkoff (SUPERBLOCK, loc)))
+ {
+ block = lblkno (SUPERBLOCK, loc);
+
+ if ((map = block_map (block)) < 0
+ || !devread (fsbtodb (SUPERBLOCK, map), 0,
+ blksize (SUPERBLOCK, INODE, block),
+ (char *) FSYS_BUF))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ *rest = ch;
+ return 0;
+ }
+ }
+
+ dp = (struct direct *) (FSYS_BUF + off);
+ loc += dp->d_reclen;
+
+#ifndef STAGE1_5
+ if (dp->d_ino && print_possibilities && ch != '/'
+ && (!*dirname || substring (dirname, dp->d_name) <= 0))
+ {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+
+ print_a_completion (dp->d_name);
+ }
+#endif /* STAGE1_5 */
+ }
+ while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
+ || (print_possibilities && ch != '/')));
+
+ /* only get here if we have a matching directory entry */
+
+ ino = dp->d_ino;
+ *(dirname = rest) = ch;
+
+ /* go back to main loop at top of function */
+ goto loop;
+}
+
+int
+ffs_embed (int *start_sector, int needed_sectors)
+{
+ /* XXX: I don't know if this is really correct. Someone who is
+ familiar with BSD should check for this. */
+ if (needed_sectors > 14)
+ return 0;
+
+ *start_sector = 1;
+#if 1
+ /* FIXME: Disable the embedding in FFS until someone checks if
+ the code above is correct. */
+ return 0;
+#else
+ return 1;
+#endif
+}
+
+#endif /* FSYS_FFS */
diff --git a/roms/openbios/fs/grubfs/fsys_iso9660.c b/roms/openbios/fs/grubfs/fsys_iso9660.c
new file mode 100644
index 00000000..12f94b73
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_iso9660.c
@@ -0,0 +1,342 @@
+/*
+ * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
+ * including Rock Ridge Extensions support
+ *
+ * Copyright (C) 1998, 1999 Kousuke Takai <tak@kmc.kyoto-u.ac.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+/*
+ * References:
+ * linux/fs/isofs/rock.[ch]
+ * mkisofs-1.11.1/diag/isoinfo.c
+ * mkisofs-1.11.1/iso9660.h
+ * (all are written by Eric Youngdale)
+ *
+ * Modifications by:
+ * Leonid Lisovskiy <lly@pisem.net> 2003
+ */
+
+/*
+ * Modified to make it work with FILO
+ * 2003-10 by SONE Takeshi
+ */
+
+#ifdef FSYS_ISO9660
+
+#include "shared.h"
+#include "filesys.h"
+#include "iso9660.h"
+#include "debug.h"
+
+#if defined(__sparc__) || defined(__PPC__)
+#define ENDIAN b
+#else
+#define ENDIAN l
+#endif
+
+struct iso_superblock {
+ unsigned long vol_sector;
+
+ unsigned long file_start;
+};
+
+#define ISO_SUPER ((struct iso_superblock *)(FSYS_BUF))
+#define PRIMDESC ((struct iso_primary_descriptor *)(FSYS_BUF + 2048))
+#define DIRREC ((struct iso_directory_record *)(FSYS_BUF + 4096))
+#define RRCONT_BUF ((unsigned char *)(FSYS_BUF + 6144))
+#define NAME_BUF ((unsigned char *)(FSYS_BUF + 8192))
+
+static int
+iso9660_devread (int sector, int byte_offset, int byte_len, char *buf)
+{
+ /* FILO uses 512-byte "soft" sector, and ISO-9660 uses 2048-byte
+ * CD-ROM sector */
+ return devread(sector<<2, byte_offset, byte_len, buf);
+}
+
+int
+iso9660_mount (void)
+{
+ unsigned int sector;
+
+ /*
+ * Because there is no defined slice type ID for ISO-9660 filesystem,
+ * this test will pass only either (1) if entire disk is used, or
+ * (2) if current partition is BSD style sub-partition whose ID is
+ * ISO-9660.
+ */
+ /*if ((current_partition != 0xFFFFFF)
+ && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice, FS_ISO9660))
+ return 0;*/
+
+ /*
+ * Currently, only FIRST session of MultiSession disks are supported !!!
+ */
+ for (sector = 16 ; sector < 32 ; sector++)
+ {
+ if (!iso9660_devread(sector, 0, sizeof(*PRIMDESC), (char *)PRIMDESC))
+ break;
+ /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */
+ if (CHECK4(&PRIMDESC->type, ISO_VD_PRIMARY, 'C', 'D', '0')
+ && CHECK2(PRIMDESC->id + 3, '0', '1'))
+ {
+ ISO_SUPER->vol_sector = sector;
+ ISO_SUPER->file_start = 0;
+ fsmax = PRIMDESC->volume_space_size.ENDIAN;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+iso9660_dir (char *dirname)
+{
+ struct iso_directory_record *idr;
+ RR_ptr_t rr_ptr;
+ struct rock_ridge *ce_ptr;
+ unsigned int pathlen;
+ int size;
+ unsigned int extent;
+ unsigned int rr_len;
+ unsigned char file_type;
+ unsigned char rr_flag;
+
+ idr = &PRIMDESC->root_directory_record;
+ ISO_SUPER->file_start = 0;
+
+ do
+ {
+ while (*dirname == '/') /* skip leading slashes */
+ dirname++;
+ /* pathlen = strcspn(dirname, "/\n\t "); */
+ for (pathlen = 0 ;
+ dirname[pathlen]
+ && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ;
+ pathlen++)
+ ;
+
+ size = idr->size.ENDIAN;
+ extent = idr->extent.ENDIAN;
+
+ while (size > 0)
+ {
+ if (!iso9660_devread(extent, 0, ISO_SECTOR_SIZE, (char *)DIRREC))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+ extent++;
+
+ idr = (struct iso_directory_record *)DIRREC;
+ for (; idr->length.ENDIAN > 0;
+ idr = (struct iso_directory_record *)((char *)idr + idr->length.ENDIAN) )
+ {
+ const char *name = (char *)idr->name;
+ unsigned int name_len = idr->name_len.ENDIAN;
+
+ file_type = (idr->flags.ENDIAN & 2) ? ISO_DIRECTORY : ISO_REGULAR;
+ if (name_len == 1)
+ {
+ if ((name[0] == 0) || /* self */
+ (name[0] == 1)) /* parent */
+ continue;
+ }
+ if (name_len > 2 && CHECK2(name + name_len - 2, ';', '1'))
+ {
+ name_len -= 2; /* truncate trailing file version */
+ if (name_len > 1 && name[name_len - 1] == '.')
+ name_len--; /* truncate trailing dot */
+ }
+
+ /*
+ * Parse Rock-Ridge extension
+ */
+ rr_len = (idr->length.ENDIAN - idr->name_len.ENDIAN
+ - (unsigned char)sizeof(struct iso_directory_record)
+ + (unsigned char)sizeof(idr->name));
+ rr_ptr.ptr = ((char *)idr + idr->name_len.ENDIAN
+ + sizeof(struct iso_directory_record)
+ - sizeof(idr->name));
+ if (rr_len & 1)
+ rr_ptr.ptr++, rr_len--;
+ ce_ptr = NULL;
+ rr_flag = RR_FLAG_NM | RR_FLAG_PX;
+
+ while (rr_len >= 4)
+ {
+ if (rr_ptr.rr->version != 1)
+ {
+#ifndef STAGE1_5
+ if (debug)
+ printf(
+ "Non-supported version (%d) RockRidge chunk "
+ "`%c%c'\n", rr_ptr.rr->version,
+ rr_ptr.rr->signature & 0xFF,
+ rr_ptr.rr->signature >> 8);
+#endif
+ }
+ else if (CHECK2(&rr_ptr.rr->signature, 'R', 'R')
+ && rr_ptr.rr->len >= 5)
+ rr_flag &= rr_ptr.rr->u.rr.flags.ENDIAN;
+ else if (CHECK2(&rr_ptr.rr->signature, 'N', 'M'))
+ {
+ name = (char *)rr_ptr.rr->u.nm.name;
+ name_len = rr_ptr.rr->len - 5;
+ rr_flag &= ~RR_FLAG_NM;
+ }
+ else if (CHECK2(&rr_ptr.rr->signature, 'P', 'X')
+ && rr_ptr.rr->len >= 36)
+ {
+ file_type = ((rr_ptr.rr->u.px.mode.ENDIAN & POSIX_S_IFMT)
+ == POSIX_S_IFREG
+ ? ISO_REGULAR
+ : ((rr_ptr.rr->u.px.mode.ENDIAN & POSIX_S_IFMT)
+ == POSIX_S_IFDIR
+ ? ISO_DIRECTORY : ISO_OTHER));
+ rr_flag &= ~RR_FLAG_PX;
+ }
+ else if (CHECK2(&rr_ptr.rr->signature, 'C', 'E')
+ && rr_ptr.rr->len >= 28)
+ ce_ptr = rr_ptr.rr;
+ if (!rr_flag)
+ /*
+ * There is no more extension we expects...
+ */
+ break;
+ rr_len -= rr_ptr.rr->len;
+ rr_ptr.ptr += rr_ptr.rr->len;
+ if (rr_len < 4 && ce_ptr != NULL)
+ {
+ /* preserve name before loading new extent. */
+ if( RRCONT_BUF <= (unsigned char *)name
+ && (unsigned char *)name < RRCONT_BUF + ISO_SECTOR_SIZE )
+ {
+ memcpy(NAME_BUF, name, name_len);
+ name = (char *)NAME_BUF;
+ }
+ rr_ptr.ptr = (char *)(RRCONT_BUF + ce_ptr->u.ce.offset.ENDIAN);
+ rr_len = ce_ptr->u.ce.size.ENDIAN;
+ if (!iso9660_devread(ce_ptr->u.ce.extent.ENDIAN, 0,
+ ISO_SECTOR_SIZE, (char *)RRCONT_BUF))
+ {
+ errnum = 0; /* this is not fatal. */
+ break;
+ }
+ ce_ptr = NULL;
+ }
+ } /* rr_len >= 4 */
+
+ filemax = MAXINT;
+ if (name_len >= pathlen
+ && !strnicmp(name, dirname, pathlen))
+ {
+ if (dirname[pathlen] == '/' || !print_possibilities)
+ {
+ /*
+ * DIRNAME is directory component of pathname,
+ * or we are to open a file.
+ */
+ if (pathlen == name_len)
+ {
+ if (dirname[pathlen] == '/')
+ {
+ if (file_type != ISO_DIRECTORY)
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ goto next_dir_level;
+ }
+ if (file_type != ISO_REGULAR)
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ ISO_SUPER->file_start = idr->extent.ENDIAN;
+ filepos = 0;
+ filemax = idr->size.ENDIAN;
+ return 1;
+ }
+ }
+ else /* Completion */
+ {
+#ifndef STAGE1_5
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ memcpy(NAME_BUF, name, name_len);
+ NAME_BUF[name_len] = '\0';
+ print_a_completion (NAME_BUF);
+#endif
+ }
+ }
+ } /* for */
+
+ size -= ISO_SECTOR_SIZE;
+ } /* size>0 */
+
+ if (dirname[pathlen] == '/' || print_possibilities >= 0)
+ {
+ errnum = ERR_FILE_NOT_FOUND;
+ return 0;
+ }
+
+next_dir_level:
+ dirname += pathlen;
+
+ } while (*dirname == '/');
+
+ return 1;
+}
+
+int
+iso9660_read (char *buf, int len)
+{
+ int sector, blkoffset, size, ret;
+
+ if (ISO_SUPER->file_start == 0)
+ return 0;
+
+ ret = 0;
+ blkoffset = filepos & (ISO_SECTOR_SIZE - 1);
+ sector = filepos >> ISO_SECTOR_BITS;
+ while (len > 0)
+ {
+ size = ISO_SECTOR_SIZE - blkoffset;
+ if (size > len)
+ size = len;
+
+ disk_read_func = disk_read_hook;
+
+ if (!iso9660_devread(ISO_SUPER->file_start + sector, blkoffset, size, buf))
+ return 0;
+
+ disk_read_func = NULL;
+
+ len -= size;
+ buf += size;
+ ret += size;
+ filepos += size;
+ sector++;
+ blkoffset = 0;
+ }
+
+ return ret;
+}
+
+#endif /* FSYS_ISO9660 */
diff --git a/roms/openbios/fs/grubfs/fsys_jfs.c b/roms/openbios/fs/grubfs/fsys_jfs.c
new file mode 100644
index 00000000..66469e68
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_jfs.c
@@ -0,0 +1,404 @@
+/* fsys_jfs.c - an implementation for the IBM JFS file system */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001,2002 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifdef FSYS_JFS
+
+#include "shared.h"
+#include "filesys.h"
+#include "jfs.h"
+
+#define MAX_LINK_COUNT 8
+
+#define DTTYPE_INLINE 0
+#define DTTYPE_PAGE 1
+
+struct jfs_info
+{
+ int bsize;
+ int l2bsize;
+ int bdlog;
+ int xindex;
+ int xlastindex;
+ int sindex;
+ int slastindex;
+ int de_index;
+ int dttype;
+ xad_t *xad;
+ ldtentry_t *de;
+};
+
+static struct jfs_info jfs;
+
+#define xtpage ((xtpage_t *)FSYS_BUF)
+#define dtpage ((dtpage_t *)((char *)FSYS_BUF + 4096))
+#define fileset ((dinode_t *)((char *)FSYS_BUF + 8192))
+#define inode ((dinode_t *)((char *)FSYS_BUF + 8192 + sizeof(dinode_t)))
+#define dtroot ((dtroot_t *)(&inode->di_btroot))
+
+static ldtentry_t de_always[2] = {
+ {1, -1, 2, {'.', '.'}, 0},
+ {1, -1, 1, {'.'}, 0}
+};
+
+static int
+isinxt (s64 key, s64 offset, s64 len)
+{
+ return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
+}
+
+static xad_t *
+first_extent (dinode_t *di)
+{
+ xtpage_t *xtp;
+
+ jfs.xindex = 2;
+ xtp = (xtpage_t *)&di->di_btroot;
+ jfs.xad = &xtp->xad[2];
+ if (xtp->header.flag & BT_LEAF) {
+ jfs.xlastindex = xtp->header.nextindex;
+ } else {
+ do {
+ devread (addressXAD (jfs.xad) << jfs.bdlog, 0,
+ sizeof(xtpage_t), (char *)xtpage);
+ jfs.xad = &xtpage->xad[2];
+ } while (!(xtpage->header.flag & BT_LEAF));
+ jfs.xlastindex = xtpage->header.nextindex;
+ }
+
+ return jfs.xad;
+}
+
+static xad_t *
+next_extent (void)
+{
+ if (++jfs.xindex < jfs.xlastindex) {
+ } else if (xtpage->header.next) {
+ devread (xtpage->header.next << jfs.bdlog, 0,
+ sizeof(xtpage_t), (char *)xtpage);
+ jfs.xlastindex = xtpage->header.nextindex;
+ jfs.xindex = XTENTRYSTART;
+ jfs.xad = &xtpage->xad[XTENTRYSTART];
+ } else {
+ return NULL;
+ }
+ return ++jfs.xad;
+}
+
+
+static void
+di_read (u32 inum, dinode_t *di)
+{
+ s64 key;
+ u32 xd, ioffset;
+ s64 offset;
+ xad_t *xad;
+ pxd_t pxd;
+
+ key = (((inum >> L2INOSPERIAG) << L2INOSPERIAG) + 4096) >> jfs.l2bsize;
+ xd = (inum & (INOSPERIAG - 1)) >> L2INOSPEREXT;
+ ioffset = ((inum & (INOSPERIAG - 1)) & (INOSPEREXT - 1)) << L2DISIZE;
+ xad = first_extent (fileset);
+ do {
+ offset = offsetXAD (xad);
+ if (isinxt (key, offset, lengthXAD (xad))) {
+ devread ((addressXAD (xad) + key - offset) << jfs.bdlog,
+ 3072 + xd*sizeof(pxd_t), sizeof(pxd_t), (char *)&pxd);
+ devread (addressPXD (&pxd) << jfs.bdlog,
+ ioffset, DISIZE, (char *)di);
+ break;
+ }
+ } while ((xad = next_extent ()));
+}
+
+static ldtentry_t *
+next_dentry (void)
+{
+ ldtentry_t *de;
+ s8 *stbl;
+
+ if (jfs.dttype == DTTYPE_INLINE) {
+ if (jfs.sindex < jfs.slastindex) {
+ return (ldtentry_t *)&dtroot->slot[(int)dtroot->header.stbl[jfs.sindex++]];
+ }
+ } else {
+ de = (ldtentry_t *)dtpage->slot;
+ stbl = (s8 *)&de[(int)dtpage->header.stblindex];
+ if (jfs.sindex < jfs.slastindex) {
+ return &de[(int)stbl[jfs.sindex++]];
+ } else if (dtpage->header.next) {
+ devread (dtpage->header.next << jfs.bdlog, 0,
+ sizeof(dtpage_t), (char *)dtpage);
+ jfs.slastindex = dtpage->header.nextindex;
+ jfs.sindex = 1;
+ return &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]];
+ }
+ }
+
+ return (jfs.de_index < 2) ? &de_always[jfs.de_index++] : NULL;
+}
+
+static ldtentry_t *
+first_dentry (void)
+{
+ dtroot_t *dtr;
+ pxd_t *xd;
+ idtentry_t *de;
+
+ dtr = (dtroot_t *)&inode->di_btroot;
+ jfs.sindex = 0;
+ jfs.de_index = 0;
+
+ de_always[0].inumber = inode->di_parent;
+ de_always[1].inumber = inode->di_number;
+ if (dtr->header.flag & BT_LEAF) {
+ jfs.dttype = DTTYPE_INLINE;
+ jfs.slastindex = dtr->header.nextindex;
+ } else {
+ de = (idtentry_t *)dtpage->slot;
+ jfs.dttype = DTTYPE_PAGE;
+ xd = &((idtentry_t *)dtr->slot)[(int)dtr->header.stbl[0]].xd;
+ for (;;) {
+ devread (addressPXD (xd) << jfs.bdlog, 0,
+ sizeof(dtpage_t), (char *)dtpage);
+ if (dtpage->header.flag & BT_LEAF)
+ break;
+ xd = &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]].xd;
+ }
+ jfs.slastindex = dtpage->header.nextindex;
+ }
+
+ return next_dentry ();
+}
+
+
+static dtslot_t *
+next_dslot (int next)
+{
+ return (jfs.dttype == DTTYPE_INLINE)
+ ? (dtslot_t *)&dtroot->slot[next]
+ : &((dtslot_t *)dtpage->slot)[next];
+}
+
+static void
+uni2ansi (UniChar *uni, char *ansi, int len)
+{
+ for (; len; len--, uni++)
+ *ansi++ = (*uni & 0xff80) ? '?' : *(char *)uni;
+}
+
+int
+jfs_mount (void)
+{
+ struct jfs_superblock super;
+
+ if (part_length < MINJFS >> SECTOR_BITS
+ || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
+ sizeof(struct jfs_superblock), (char *)&super)
+ || (super.s_magic != JFS_MAGIC)
+ || !devread ((AITBL_OFF >> SECTOR_BITS) + FILESYSTEM_I,
+ 0, DISIZE, (char*)fileset)) {
+ return 0;
+ }
+
+ jfs.bsize = super.s_bsize;
+ jfs.l2bsize = super.s_l2bsize;
+ jfs.bdlog = jfs.l2bsize - SECTOR_BITS;
+
+ return 1;
+}
+
+int
+jfs_read (char *buf, int len)
+{
+ xad_t *xad;
+ s64 endofprev, endofcur;
+ s64 offset, xadlen;
+ int toread, startpos, endpos;
+
+ startpos = filepos;
+ endpos = filepos + len;
+ endofprev = (1ULL << 62) - 1;
+ xad = first_extent (inode);
+ do {
+ offset = offsetXAD (xad);
+ xadlen = lengthXAD (xad);
+ if (isinxt (filepos >> jfs.l2bsize, offset, xadlen)) {
+ endofcur = (offset + xadlen) << jfs.l2bsize;
+ toread = (endofcur >= endpos)
+ ? len : (endofcur - filepos);
+
+ disk_read_func = disk_read_hook;
+ devread (addressXAD (xad) << jfs.bdlog,
+ filepos - (offset << jfs.l2bsize), toread, buf);
+ disk_read_func = NULL;
+
+ buf += toread;
+ len -= toread;
+ filepos += toread;
+ } else if (offset > endofprev) {
+ toread = ((offset << jfs.l2bsize) >= endpos)
+ ? len : ((offset - endofprev) << jfs.l2bsize);
+ len -= toread;
+ filepos += toread;
+ for (; toread; toread--) {
+ *buf++ = 0;
+ }
+ continue;
+ }
+ endofprev = offset + xadlen;
+ xad = next_extent ();
+ } while (len > 0 && xad);
+
+ return filepos - startpos;
+}
+
+int
+jfs_dir (char *dirname)
+{
+ char *ptr, *rest, ch;
+ ldtentry_t *de;
+ dtslot_t *ds;
+ u32 inum, parent_inum;
+ s64 di_size;
+ u32 di_mode;
+ int namlen, cmp, n, link_count;
+ char namebuf[JFS_NAME_MAX + 1], linkbuf[JFS_PATH_MAX];
+
+ parent_inum = inum = ROOT_I;
+ link_count = 0;
+ for (;;) {
+ di_read (inum, inode);
+ di_size = inode->di_size;
+ di_mode = inode->di_mode;
+
+ if ((di_mode & IFMT) == IFLNK) {
+ if (++link_count > MAX_LINK_COUNT) {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ }
+ if (di_size < (di_mode & INLINEEA ? 256 : 128)) {
+ grub_memmove (linkbuf, inode->di_fastsymlink, di_size);
+ n = di_size;
+ } else if (di_size < JFS_PATH_MAX - 1) {
+ filepos = 0;
+ filemax = di_size;
+ n = jfs_read (linkbuf, filemax);
+ } else {
+ errnum = ERR_FILELENGTH;
+ return 0;
+ }
+
+ inum = (linkbuf[0] == '/') ? ROOT_I : parent_inum;
+ while (n < (JFS_PATH_MAX - 1) && (linkbuf[n++] = *dirname++));
+ linkbuf[n] = 0;
+ dirname = linkbuf;
+ continue;
+ }
+
+ if (!*dirname || isspace (*dirname)) {
+ if ((di_mode & IFMT) != IFREG) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ filepos = 0;
+ filemax = di_size;
+ return 1;
+ }
+
+ if ((di_mode & IFMT) != IFDIR) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ for (; *dirname == '/'; dirname++);
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+ *rest = 0;
+
+ de = first_dentry ();
+ for (;;) {
+ namlen = de->namlen;
+ if (de->next == -1) {
+ uni2ansi (de->name, namebuf, namlen);
+ namebuf[namlen] = 0;
+ } else {
+ uni2ansi (de->name, namebuf, DTLHDRDATALEN);
+ ptr = namebuf;
+ ptr += DTLHDRDATALEN;
+ namlen -= DTLHDRDATALEN;
+ ds = next_dslot (de->next);
+ while (ds->next != -1) {
+ uni2ansi (ds->name, ptr, DTSLOTDATALEN);
+ ptr += DTSLOTDATALEN;
+ namlen -= DTSLOTDATALEN;
+ ds = next_dslot (ds->next);
+ }
+ uni2ansi (ds->name, ptr, namlen);
+ ptr += namlen;
+ *ptr = 0;
+ }
+
+ cmp = (!*dirname) ? -1 : substring (dirname, namebuf);
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/'
+ && cmp <= 0) {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (namebuf);
+ } else
+#endif
+ if (cmp == 0) {
+ parent_inum = inum;
+ inum = de->inumber;
+ *(dirname = rest) = ch;
+ break;
+ }
+ de = next_dentry ();
+ if (de == NULL) {
+ if (print_possibilities < 0)
+ return 1;
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ return 0;
+ }
+ }
+ }
+}
+
+int
+jfs_embed (int *start_sector, int needed_sectors)
+{
+ struct jfs_superblock super;
+
+ if (needed_sectors > 63
+ || !devread (SUPER1_OFF >> SECTOR_BITS, 0,
+ sizeof (struct jfs_superblock),
+ (char *)&super)
+ || (super.s_magic != JFS_MAGIC)) {
+ return 0;
+ }
+
+ *start_sector = 1;
+ return 1;
+}
+
+#endif /* FSYS_JFS */
diff --git a/roms/openbios/fs/grubfs/fsys_minix.c b/roms/openbios/fs/grubfs/fsys_minix.c
new file mode 100644
index 00000000..d16b58c8
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_minix.c
@@ -0,0 +1,535 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/* Restrictions:
+ This is MINIX V1 only (yet)
+ Disk creation is like:
+ mkfs.minix -c DEVICE
+*/
+
+#ifdef FSYS_MINIX
+
+#include "shared.h"
+#include "filesys.h"
+
+/* #define DEBUG_MINIX */
+
+/* indirect blocks */
+static int mapblock1, mapblock2, namelen;
+
+/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
+#define DEV_BSIZE 512
+
+/* include/linux/fs.h */
+#define BLOCK_SIZE_BITS 10
+#define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
+
+/* made up, defaults to 1 but can be passed via mount_opts */
+#define WHICH_SUPER 1
+/* kind of from fs/ext2/super.c (is OK for minix) */
+#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */
+
+/* include/asm-i386/type.h */
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+/* include/linux/minix_fs.h */
+#define MINIX_ROOT_INO 1
+
+/* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */
+#define MINIX_LINK_MAX 250
+#define MINIX2_LINK_MAX 65530
+
+#define MINIX_I_MAP_SLOTS 8
+#define MINIX_Z_MAP_SLOTS 64
+#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
+#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
+#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */
+#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */
+#define MINIX_VALID_FS 0x0001 /* Clean fs. */
+#define MINIX_ERROR_FS 0x0002 /* fs has errors. */
+
+#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
+#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
+
+#define MINIX_V1 0x0001 /* original minix fs */
+#define MINIX_V2 0x0002 /* minix V2 fs */
+
+/* originally this is :
+#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version
+ here we have */
+#define INODE_VERSION(inode) (SUPERBLOCK->s_version)
+
+/*
+ * This is the original minix inode layout on disk.
+ * Note the 8-bit gid and atime and ctime.
+ */
+struct minix_inode {
+ __u16 i_mode;
+ __u16 i_uid;
+ __u32 i_size;
+ __u32 i_time;
+ __u8 i_gid;
+ __u8 i_nlinks;
+ __u16 i_zone[9];
+};
+
+/*
+ * The new minix inode has all the time entries, as well as
+ * long block numbers and a third indirect block (7+1+1+1
+ * instead of 7+1+1). Also, some previously 8-bit values are
+ * now 16-bit. The inode is now 64 bytes instead of 32.
+ */
+struct minix2_inode {
+ __u16 i_mode;
+ __u16 i_nlinks;
+ __u16 i_uid;
+ __u16 i_gid;
+ __u32 i_size;
+ __u32 i_atime;
+ __u32 i_mtime;
+ __u32 i_ctime;
+ __u32 i_zone[10];
+};
+
+/*
+ * minix super-block data on disk
+ */
+struct minix_super_block {
+ __u16 s_ninodes;
+ __u16 s_nzones;
+ __u16 s_imap_blocks;
+ __u16 s_zmap_blocks;
+ __u16 s_firstdatazone;
+ __u16 s_log_zone_size;
+ __u32 s_max_size;
+ __u16 s_magic;
+ __u16 s_state;
+ __u32 s_zones;
+};
+
+struct minix_dir_entry {
+ __u16 inode;
+ char name[0];
+};
+
+/* made up, these are pointers into FSYS_BUF */
+/* read once, always stays there: */
+#define SUPERBLOCK \
+ ((struct minix_super_block *)(FSYS_BUF))
+#define INODE \
+ ((struct minix_inode *)((char *) SUPERBLOCK + BLOCK_SIZE))
+#define DATABLOCK1 \
+ ((char *)((char *)INODE + sizeof(struct minix_inode)))
+#define DATABLOCK2 \
+ ((char *)((char *)DATABLOCK1 + BLOCK_SIZE))
+
+/* linux/stat.h */
+#define S_IFMT 00170000
+#define S_IFLNK 0120000
+#define S_IFREG 0100000
+#define S_IFDIR 0040000
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+
+#define PATH_MAX 1024 /* include/linux/limits.h */
+#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
+
+/* check filesystem types and read superblock into memory buffer */
+int
+minix_mount (void)
+{
+ if (((current_drive & 0x80) || current_slice != 0)
+ && ! IS_PC_SLICE_TYPE_MINIX (current_slice)
+ && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER))
+ return 0; /* The partition is not of MINIX type */
+
+ if (part_length < (SBLOCK +
+ (sizeof (struct minix_super_block) / DEV_BSIZE)))
+ return 0; /* The partition is too short */
+
+ if (!devread (SBLOCK, 0, sizeof (struct minix_super_block),
+ (char *) SUPERBLOCK))
+ return 0; /* Cannot read superblock */
+
+ switch (SUPERBLOCK->s_magic)
+ {
+ case MINIX_SUPER_MAGIC:
+ namelen = 14;
+ break;
+ case MINIX_SUPER_MAGIC2:
+ namelen = 30;
+ break;
+ default:
+ return 0; /* Unsupported type */
+ }
+
+ return 1;
+}
+
+/* Takes a file system block number and reads it into BUFFER. */
+static int
+minix_rdfsb (int fsblock, char *buffer)
+{
+ return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0,
+ BLOCK_SIZE, buffer);
+}
+
+/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
+ a physical block (the location in the file system) via an inode. */
+static int
+minix_block_map (int logical_block)
+{
+ int i;
+
+ if (logical_block < 7)
+ return INODE->i_zone[logical_block];
+
+ logical_block -= 7;
+ if (logical_block < 512)
+ {
+ i = INODE->i_zone[7];
+
+ if (!i || ((mapblock1 != 1)
+ && !minix_rdfsb (i, DATABLOCK1)))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ mapblock1 = 1;
+ return ((__u16 *) DATABLOCK1) [logical_block];
+ }
+
+ logical_block -= 512;
+ i = INODE->i_zone[8];
+ if (!i || ((mapblock1 != 2)
+ && !minix_rdfsb (i, DATABLOCK1)))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ mapblock1 = 2;
+ i = ((__u16 *) DATABLOCK1)[logical_block >> 9];
+ if (!i || ((mapblock2 != i)
+ && !minix_rdfsb (i, DATABLOCK2)))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return -1;
+ }
+ mapblock2 = i;
+ return ((__u16 *) DATABLOCK2)[logical_block & 511];
+}
+
+/* read from INODE into BUF */
+int
+minix_read (char *buf, int len)
+{
+ int logical_block;
+ int offset;
+ int map;
+ int ret = 0;
+ int size = 0;
+
+ while (len > 0)
+ {
+ /* find the (logical) block component of our location */
+ logical_block = filepos >> BLOCK_SIZE_BITS;
+ offset = filepos & (BLOCK_SIZE - 1);
+ map = minix_block_map (logical_block);
+#ifdef DEBUG_MINIX
+ printf ("map=%d\n", map);
+#endif
+ if (map < 0)
+ break;
+
+ size = BLOCK_SIZE;
+ size -= offset;
+ if (size > len)
+ size = len;
+
+ disk_read_func = disk_read_hook;
+
+ devread (map * (BLOCK_SIZE / DEV_BSIZE),
+ offset, size, buf);
+
+ disk_read_func = NULL;
+
+ buf += size;
+ len -= size;
+ filepos += size;
+ ret += size;
+ }
+
+ if (errnum)
+ ret = 0;
+
+ return ret;
+}
+
+/* preconditions: minix_mount already executed, therefore supblk in buffer
+ known as SUPERBLOCK
+ returns: 0 if error, nonzero iff we were able to find the file successfully
+ postconditions: on a nonzero return, buffer known as INODE contains the
+ inode of the file we were trying to look up
+ side effects: none yet */
+int
+minix_dir (char *dirname)
+{
+ int current_ino = MINIX_ROOT_INO; /* start at the root */
+ int updir_ino = current_ino; /* the parent of the current directory */
+ int ino_blk; /* fs pointer of the inode's info */
+
+ int str_chk = 0; /* used ot hold the results of a string
+ compare */
+
+ struct minix_inode * raw_inode; /* inode info for current_ino */
+
+ char linkbuf[PATH_MAX]; /* buffer for following sym-links */
+ int link_count = 0;
+
+ char * rest;
+ char ch;
+
+ int off; /* offset within block of directory
+ entry */
+ int loc; /* location within a directory */
+ int blk; /* which data blk within dir entry */
+ long map; /* fs pointer of a particular block from
+ dir entry */
+ struct minix_dir_entry * dp; /* pointer to directory entry */
+
+ /* loop invariants:
+ current_ino = inode to lookup
+ dirname = pointer to filename component we are cur looking up within
+ the directory known pointed to by current_ino (if any) */
+
+#ifdef DEBUG_MINIX
+ printf ("\n");
+#endif
+
+ while (1)
+ {
+#ifdef DEBUG_MINIX
+ printf ("inode %d, dirname %s\n", current_ino, dirname);
+#endif
+
+ ino_blk = (2 + SUPERBLOCK->s_imap_blocks + SUPERBLOCK->s_zmap_blocks
+ + (current_ino - 1) / MINIX_INODES_PER_BLOCK);
+ if (! minix_rdfsb (ino_blk, (char *) INODE))
+ return 0;
+
+ /* reset indirect blocks! */
+ mapblock2 = mapblock1 = -1;
+
+ raw_inode = INODE + ((current_ino - 1) % MINIX_INODES_PER_BLOCK);
+
+ /* copy inode to fixed location */
+ memmove ((void *) INODE, (void *) raw_inode,
+ sizeof (struct minix_inode));
+
+ /* If we've got a symbolic link, then chase it. */
+ if (S_ISLNK (INODE->i_mode))
+ {
+ int len;
+
+ if (++link_count > MAX_LINK_COUNT)
+ {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ }
+#ifdef DEBUG_MINIX
+ printf ("S_ISLNK (%s)\n", dirname);
+#endif
+
+ /* Find out how long our remaining name is. */
+ len = 0;
+ while (dirname[len] && !isspace (dirname[len]))
+ len++;
+
+ /* Get the symlink size. */
+ filemax = (INODE->i_size);
+ if (filemax + len > sizeof (linkbuf) - 2)
+ {
+ errnum = ERR_FILELENGTH;
+ return 0;
+ }
+
+ if (len)
+ {
+ /* Copy the remaining name to the end of the symlink data.
+ Note that DIRNAME and LINKBUF may overlap! */
+ memmove (linkbuf + filemax, dirname, len);
+ }
+ linkbuf[filemax + len] = '\0';
+
+ /* Read the necessary blocks, and reset the file pointer. */
+ len = grub_read (linkbuf, filemax);
+ filepos = 0;
+ if (!len)
+ return 0;
+
+#ifdef DEBUG_MINIX
+ printf ("symlink=%s\n", linkbuf);
+#endif
+
+ dirname = linkbuf;
+ if (*dirname == '/')
+ {
+ /* It's an absolute link, so look it up in root. */
+ current_ino = MINIX_ROOT_INO;
+ updir_ino = current_ino;
+ }
+ else
+ {
+ /* Relative, so look it up in our parent directory. */
+ current_ino = updir_ino;
+ }
+
+ /* Try again using the new name. */
+ continue;
+ }
+
+ /* If end of filename, INODE points to the file's inode */
+ if (!*dirname || isspace (*dirname))
+ {
+ if (!S_ISREG (INODE->i_mode))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ filemax = (INODE->i_size);
+ return 1;
+ }
+
+ /* else we have to traverse a directory */
+ updir_ino = current_ino;
+
+ /* skip over slashes */
+ while (*dirname == '/')
+ dirname++;
+
+ /* if this isn't a directory of sufficient size to hold our file,
+ abort */
+ if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ /* skip to next slash or end of filename (space) */
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
+ rest++);
+
+ /* look through this directory and find the next filename component */
+ /* invariant: rest points to slash after the next filename component */
+ *rest = 0;
+ loc = 0;
+
+ do
+ {
+#ifdef DEBUG_MINIX
+ printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname, rest, loc);
+#endif
+
+ /* if our location/byte offset into the directory exceeds the size,
+ give up */
+ if (loc >= INODE->i_size)
+ {
+ if (print_possibilities < 0)
+ {
+#if 0
+ putchar ('\n');
+#endif
+ }
+ else
+ {
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ }
+ return (print_possibilities < 0);
+ }
+
+ /* else, find the (logical) block component of our location */
+ blk = loc >> BLOCK_SIZE_BITS;
+
+ /* we know which logical block of the directory entry we are looking
+ for, now we have to translate that to the physical (fs) block on
+ the disk */
+ map = minix_block_map (blk);
+#ifdef DEBUG_MINIX
+ printf ("fs block=%d\n", map);
+#endif
+ mapblock2 = -1;
+ if ((map < 0) || !minix_rdfsb (map, DATABLOCK2))
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ *rest = ch;
+ return 0;
+ }
+ off = loc & (BLOCK_SIZE - 1);
+ dp = (struct minix_dir_entry *) (DATABLOCK2 + off);
+ /* advance loc prematurely to next on-disk directory entry */
+ loc += sizeof (dp->inode) + namelen;
+
+ /* NOTE: minix filenames are NULL terminated if < NAMELEN
+ else exact */
+
+#ifdef DEBUG_MINIX
+ printf ("directory entry ino=%d\n", dp->inode);
+ if (dp->inode)
+ printf ("entry=%s\n", dp->name);
+#endif
+
+ if (dp->inode)
+ {
+ int saved_c = dp->name[namelen];
+
+ dp->name[namelen] = 0;
+ str_chk = substring (dirname, dp->name);
+
+# ifndef STAGE1_5
+ if (print_possibilities && ch != '/'
+ && (!*dirname || str_chk <= 0))
+ {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (dp->name);
+ }
+# endif
+
+ dp->name[namelen] = saved_c;
+ }
+
+ }
+ while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
+
+ current_ino = dp->inode;
+ *(dirname = rest) = ch;
+ }
+ /* never get here */
+}
+
+#endif /* FSYS_MINIX */
diff --git a/roms/openbios/fs/grubfs/fsys_ntfs.c b/roms/openbios/fs/grubfs/fsys_ntfs.c
new file mode 100644
index 00000000..a244f5c6
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_ntfs.c
@@ -0,0 +1,1255 @@
+/* vim: set sw=4 :*/
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/*
+ * Samuel Leo <samuel@_.remove.me._szonline.net>
+ * Limitations:
+ * 1. Only 32 bit size support
+ * 2. don't support >1k MFT record size, >16k INDEX record size
+ * 3. don't support recursive at_attribute_list
+ * 4. don't support compressed attribute other than Datastream
+ * 5. all MFT's at_attribute_list must resident at first run list
+ * 6. don't support journaling
+ * 7. don't support EFS encryption
+ * 8. don't support mount point and junction
+ */
+#ifdef FSYS_NTFS
+
+//#define DEBUG_NTFS 1
+
+/*
+#define NO_ATTRIBUTE_LIST 1
+ totally disable at_attribute_list support,
+ if no compressed/fragment file and MFT,
+ not recommended
+#define NO_NON_RESIDENT_ATTRIBUTE_LIST 1
+ disable non-resident at_attribute_list support,
+ if no huge compressed/fragment file and MFT
+#define NO_NTFS_DECOMPRESSION 1
+ disable ntfs compressed file support
+#define NO_ALTERNATE_DATASTREAM 1
+ disable ntfs alternate datastream support
+*/
+
+#include "shared.h"
+#include "filesys.h"
+
+#ifdef STAGE1_5
+/* safe turn off non-resident attribute list if MFT fragments < 4000 */
+//#define NO_NON_RESIDENT_ATTRIBUTE_LIST 1
+#define NO_NTFS_DECOMPRESSION 1
+#endif
+
+#define MAX_MFT_RECORD_SIZE 1024
+#define MAX_INDEX_RECORD_SIZE 16384
+#define MAX_INDEX_BITMAP_SIZE 4096
+#define DECOMP_DEST_BUFFER_SIZE 16384
+#define DECOMP_SOURCE_BUFFER_SIZE (8192+2)
+#define MAX_DIR_DEPTH 64
+
+/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
+#define DEV_BSIZE 512
+
+/* include/linux/fs.h */
+#define BLOCK_SIZE 512
+
+#define WHICH_SUPER 1
+#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */
+
+/* include/asm-i386/type.h */
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+
+#define FILE_MFT 0
+#define FILE_MFTMIRR 1
+#define FILE_LOGFILE 2
+#define FILE_VOLUME 3
+#define FILE_ATTRDEF 4
+#define FILE_ROOT 5
+#define FILE_BITMAP 6
+#define FILE_BOOT 7
+#define FILE_BADCLUS 8
+#define FILE_QUOTA 9
+#define FILE_UPCASE 10
+
+#define at_standard_information 0x10
+#define at_attribute_list 0x20
+#define at_filename 0x30
+#define at_security_descriptor 0x50
+#define at_data 0x80
+#define at_index_root 0x90
+#define at_index_allocation 0xa0
+#define at_bitmap 0xb0
+#define at_symlink 0xc0
+
+#define NONAME ""
+#define ATTR_NORMAL 0
+#define ATTR_COMPRESSED 1
+#define ATTR_RESIDENT 2
+#define ATTR_ENCRYPTED 16384
+#define ATTR_SPARSE 32768
+
+typedef struct run_list {
+ char *start;
+ char *ptr;
+ int svcn;
+ int evcn;
+ int vcn;
+ int cnum0;
+ int cnum;
+ int clen;
+} RUNL;
+
+typedef struct ntfs_mft_record {
+ char mft[MAX_MFT_RECORD_SIZE];
+ char mft2[MAX_MFT_RECORD_SIZE];
+ int attr_type;
+ char *attr_name;
+ int attr_flag;
+ int attr_size;
+ char *attr;
+ int attr_len;
+ RUNL runl;
+ char *attr_list;
+ int attr_list_len;
+ int attr_list_size;
+ int attr_list_off;
+ int attr_inited;
+ char attr_list_buf[2*BLOCK_SIZE];
+ RUNL attr_list_runl;
+} MFTR;
+
+
+#define index_data ((char *)FSYS_BUF)
+#define bitmap_data ((__u8 *)(FSYS_BUF+MAX_INDEX_RECORD_SIZE))
+#define dcdbuf ((__u8 *)index_data)
+#define dcsbuf (bitmap_data)
+#define dcend (dcsbuf+DECOMP_SOURCE_BUFFER_SIZE)
+#define fnbuf ((char *)(bitmap_data+MAX_INDEX_BITMAP_SIZE))
+#define mmft ((MFTR *)dcend)
+#define cmft ((MFTR *)(dcend+sizeof(MFTR)))
+#define mft_run ((RUNL *)(dcend+2*sizeof(MFTR)))
+#define path_ino ((int *)(dcend+2*sizeof(MFTR)+sizeof(RUNL)))
+#define cluster16 (path_ino+MAX_DIR_DEPTH)
+#define index16 cluster16[16]
+#define blocksize cluster16[17]
+#define clustersize cluster16[18]
+#define mft_record_size cluster16[19]
+#define index_record_size cluster16[20]
+#define dcvcn cluster16[21]
+#define dcoff cluster16[22]
+#define dclen cluster16[23]
+#define dcrem cluster16[24]
+#define dcslen cluster16[25]
+#define dcsptr ((__u8 *)cluster16[26])
+#define is_ads_completion cluster16[27]
+
+static int read_mft_record(int mftno, char *mft, int self);
+static int read_attribute(MFTR *mftr, int offset, char *buf, int len, RUNL *from_rl);
+static int get_next_run(RUNL *runl);
+
+static inline int
+nsubstring (char *s1, char *s2)
+{
+ while (tolower(*s1) == tolower(*s2))
+ {
+ /* The strings match exactly. */
+ if (! *(s1++))
+ return 0;
+ s2 ++;
+ }
+
+ /* S1 is a substring of S2. */
+ if (*s1 == 0)
+ return -1;
+
+ /* S1 isn't a substring. */
+ return 1;
+}
+
+static int fixup_record(char *record, char *magic, int size)
+{
+ int start, count, offset;
+ __u16 fixup;
+
+ if(*(int *)record != *(int *)magic)
+ return 0;
+ start=*(__u16 *)(record+4);
+ count=*(__u16 *)(record+6);
+ count--;
+ if(size && blocksize*count != size)
+ return 0;
+ fixup = *(__u16 *)(record+start);
+ start+=2;
+ offset=blocksize-2;
+ while(count--){
+ if(*(__u16 *)(record+offset)!=fixup)
+ return 0;
+ *(__u16 *)(record+offset) = *(__u16 *)(record+start);
+ start+=2;
+ offset+=blocksize;
+ }
+ return 1;
+}
+
+static void rewind_run_list( RUNL *runl) {
+ runl->vcn = runl->svcn;
+ runl->ptr = runl->start;
+ runl->cnum0 = 0;
+ runl->cnum = 0;
+ runl->clen = 0;
+}
+
+static int get_next_run(RUNL *runl){
+ int t, n, v;
+
+#ifdef DEBUG_NTFS
+ printf("get_next_run: s=%d e=%d c=%d start=%x ptr=%x\n",
+ runl->svcn, runl->evcn, runl->vcn, runl->start, runl->ptr);
+#endif
+
+ runl->vcn += runl->clen;
+ if(runl->vcn > runl->evcn) {
+ return 0;
+ }
+
+ t = *(runl->ptr)++;
+ n = t&0xf;
+ runl->clen = 0; v = 1;
+ while(n--) {
+ runl->clen += v * *((__u8 *)runl->ptr)++;
+ v <<= 8;
+ }
+ n = (t>>4)&0xf;
+ if(n==0)
+ runl->cnum = 0;
+ else {
+ int c = 0;
+ v = 1;
+ while(n--) {
+ c += v * *((__u8 *)runl->ptr)++;
+ v <<= 8;
+ }
+ if(c & (v>>1)) c -= v;
+ runl->cnum0 += c;
+ runl->cnum = runl->cnum0;
+ }
+#ifdef DEBUG_NTFS
+ printf("got_next_run: t=%x cluster %x len %x vcn=%x ecn=%x\n",
+ t, runl->cnum, runl->clen, runl->vcn, runl->evcn);
+#endif
+ return 1;
+}
+
+#ifndef NO_ATTRIBUTE_LIST
+static void init_run_list(char *attr, int len, RUNL *runl, __u32 *initp) {
+ int allocated;
+
+ runl->svcn = *(__u32 *)(attr+0x10); /* only support 32 bit */
+ runl->evcn = *(__u32 *)(attr+0x18); /* only support 32 bit */
+ runl->start = attr + *(__u16 *)(attr+0x20);
+ allocated = *(__u32 *)(attr+0x28);
+ if(initp) *initp = *(__u32 *)(attr+0x38);
+ if(!runl->evcn) runl->evcn = (allocated - 1) / clustersize;
+#ifdef DEBUG_NTFS
+ printf("size %d allocated=%d inited=%d cegin=%x csize=%d vcn=%d-%d\n",
+ /*attr_size*/ *(__u32 *)(attr+0x30),
+ /*allocated*/ *(__u32 *)(attr+0x28),
+ /*attr_inited*/ *(__u32 *)(attr+0x38),
+ /*cengin*/ *(__u16 *)(attr+0x22),
+ /*csize*/ *(__u16 *)(attr+0x40),
+ runl->svcn, runl->evcn);
+#endif
+ rewind_run_list(runl);
+}
+#endif
+
+
+static int find_attribute(char *mft, int type, char *name, char **attr, int *size, int *len, int *flag) {
+ int t, l, r, n, i, namelen;
+ unsigned short *attr_name;
+
+ n = strlen(name);
+ r = mft_record_size - *(__u16 *)(mft+0x14);
+ mft += *(__u16 *)(mft+0x14);
+ while( (t = *(__s32 *)mft) != -1 ) {
+ l = *(__u32 *)(mft+4);
+ if(l>r) break;
+#ifdef DEBUG_NTFS
+ printf("type = %x len = %d namelen=%d resident=%d compresed=%d attrno=%d\n",
+ t, l,
+ /*namelen*/ *(mft+9),
+ //name = (__u16 *)(mft + *(__u16 *)(mft+10)),
+ /*resident */ (*(mft+8) == 0),
+ /*compressed*/ *(__u16 *)(mft+12),
+ /*attrno*/ *(__u16 *)(mft+14));
+#endif
+ namelen = *(mft+9);
+ if(t == type) {
+#ifndef STAGE1_5
+#ifndef NO_ALTERNATE_DATASTREAM
+ if(is_ads_completion && type == at_data) {
+ if(namelen && namelen >= n &&
+ (!*(mft+8)/*resident*/ || !*(__u32 *)(attr+0x10)/*svcn==0*/))
+ {
+ for(i=0, attr_name=(__u16 *)(mft + *(__u16 *)(mft+10)); i < n; i++)
+ if(tolower(name[i]) != tolower(attr_name[i]))
+ break;
+ if(i >= n) {
+ for(; i < namelen; i++)
+ name[i] = attr_name[i];
+ name[i] = '\0';
+ if(print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion(fnbuf);
+ name[n] = '\0';
+ }
+ }
+ } else
+#endif
+#endif
+ if(namelen == n) {
+
+ for(i=0, attr_name=(__u16 *)(mft + *(__u16 *)(mft+10)); i<n; i++)
+ if(tolower(name[i]) != tolower(attr_name[i]))
+ break;
+ if(i>=n) {
+ if(flag) *flag = *(__u16 *)(mft+12);
+ if(*(mft+8) == 0) {
+ if(flag) *flag |= ATTR_RESIDENT;
+#ifdef DEBUG_NTFS
+ printf("resident data at %x size %x indexed=%d\n",
+ /*data*/ *(__u16 *)(mft+0x14),
+ /*attr_size*/ *(__u16 *)(mft+0x10),
+ /*indexed*/ *(__u16 *)(mft+0x16));
+#endif
+ if(attr) *attr = mft + *(__u16 *)(mft+0x14);
+ if(size) *size = *(__u16 *)(mft+0x10);
+ if(len) *len = *(__u16 *)(mft+0x10);
+ } else {
+ if(attr) *attr = mft;
+ if(size) *size = *(__u32 *)(mft+0x30);
+ if(len) *len = l;
+ }
+ return 1;
+ }
+ }
+ }
+ mft += l;
+ r -= l;
+ }
+ return 0;
+}
+
+#ifndef NO_ATTRIBUTE_LIST
+static __u32 get_next_attribute_list(MFTR *mftr, int *size) {
+ int l, t, mftno;
+#ifdef DEBUG_NTFS
+ printf("get_next_attribute_list: type=%x\n",mftr->attr_type);
+#endif
+again:
+ while(mftr->attr_list_len>0x14) {
+ t = *(__u32 *)(mftr->attr_list + 0);
+ l = *(__u16 *)(mftr->attr_list + 4);
+#ifdef DEBUG_NTFS
+ printf("attr_list type=%x len=%x remain=%x\n", t, l, mftr->attr_list_len);
+#endif
+ if(l==0 || l>mftr->attr_list_len) return 0;
+ mftno = *(__u32 *)(mftr->attr_list + 0x10);
+ mftr->attr_list_len -= l;
+ mftr->attr_list += l;
+ if(t==mftr->attr_type)
+ {
+#ifdef DEBUG_NTFS
+ printf("attr_list mftno=%x\n", mftno);
+#endif
+ if(read_mft_record(mftno, mftr->mft2, (mftr==mmft))==0)
+ break;
+ if(find_attribute(mftr->mft2, mftr->attr_type, mftr->attr_name,
+ &mftr->attr, size, &mftr->attr_len, &mftr->attr_flag))
+ return 1;
+ }
+ }
+#ifndef NO_NON_RESIDENT_ATTRIBUTE_LIST
+ if(mftr->attr_list_off < mftr->attr_list_size) {
+ int len = mftr->attr_list_size - mftr->attr_list_off;
+ if(len > BLOCK_SIZE) len = BLOCK_SIZE;
+
+ if(mftr->attr_list_len)
+ memmove(mftr->attr_list_buf, mftr->attr_list, mftr->attr_list_len);
+ mftr->attr_list = mftr->attr_list_buf;
+
+ if(read_attribute( NULL, mftr->attr_list_off,
+ mftr->attr_list_buf + mftr->attr_list_len,
+ len, &mftr->attr_list_runl) != len)
+ {
+#ifdef DEBUG_NTFS
+ printf("CORRUPT NON-RESIDENT ATTRIBUTE_LIST\n");
+#endif
+ /* corrupt */
+ errnum = ERR_FSYS_CORRUPT;
+ mftr->attr_list_size = 0;
+ mftr->attr_len = 0;
+ mftr->attr_list = NULL;
+ return 0;
+ }
+
+ mftr->attr_list_len += len;
+ mftr->attr_list_off += len;
+ goto again;
+ }
+#endif
+ mftr->attr_list = NULL;
+ return 0;
+}
+#endif
+
+static int search_attribute( MFTR *mftr, int type, char *name)
+{
+#ifdef DEBUG_NTFS
+ printf("searching attribute %x <%s>\n", type, name);
+#endif
+
+ mftr->attr_type = type;
+ mftr->attr_name = name;
+ mftr->attr_list = NULL;
+ mftr->attr_list_len = 0;
+ mftr->attr_list_size = 0;
+ mftr->attr_list_off = 0;
+ dcrem = dclen = 0;
+
+#ifndef NO_ATTRIBUTE_LIST
+ if(find_attribute(mftr->mft, at_attribute_list, NONAME,
+ &mftr->attr_list, &mftr->attr_list_size,
+ &mftr->attr_list_len, &mftr->attr_list_off)) {
+ if(mftr->attr_list_off&ATTR_RESIDENT) {
+ /* resident at_attribute_list */
+ mftr->attr_list_size = 0;
+#ifdef DEBUG_NTFS
+ printf("resident attribute_list len=%x\n", mftr->attr_list_len);
+#endif
+ } else {
+#ifdef DEBUG_NTFS
+ printf("non-resident attribute_list len=%x size=%x\n",
+ mftr->attr_list_len, mftr->attr_list_size);
+#endif
+#ifndef NO_NON_RESIDENT_ATTRIBUTE_LIST
+ init_run_list(mftr->attr_list, mftr->attr_list_len, &mftr->attr_list_runl, NULL);
+ if(get_next_run(&mftr->attr_list_runl)==0 ||
+ mftr->attr_list_runl.cnum==0)
+ mftr->attr_list_size = 0;
+#endif
+ mftr->attr_list = NULL;
+ mftr->attr_list_len = 0;
+ }
+ }
+#endif
+
+ if(find_attribute(mftr->mft, type, name,
+ &mftr->attr, &mftr->attr_size, &mftr->attr_len,
+ &mftr->attr_flag)
+#ifndef NO_ATTRIBUTE_LIST
+ || get_next_attribute_list(mftr, &mftr->attr_size)
+#endif
+ )
+ {
+#ifndef NO_ATTRIBUTE_LIST
+ if(!(mftr->attr_flag&ATTR_RESIDENT)){
+ init_run_list(mftr->attr, mftr->attr_len, &mftr->runl, &mftr->attr_inited);
+ if(mftr->attr_inited > mftr->attr_size)
+ mftr->attr_inited = mftr->attr_size;
+ if(get_next_run(&mftr->runl)==0) {
+ mftr->attr_flag |= ATTR_RESIDENT;
+ mftr->attr_len = 0;
+ }
+ } else
+ mftr->attr_inited = mftr->attr_size;
+#endif
+
+ return 1;
+ }
+
+ mftr->attr_type = 0;
+ return 0;
+}
+
+static int get_run( RUNL *rl, int vcn, int *clp, int *lenp) {
+ if(rl->evcn < vcn)
+ return 0;
+
+ if(rl->vcn > vcn) {
+ rewind_run_list(rl);
+ get_next_run(rl);
+ }
+
+ while(rl->vcn+rl->clen <= vcn)
+ {
+ if(get_next_run(rl)==0)
+ return 0;
+ }
+
+ if(clp) *clp = rl->cnum == 0 ? 0 : rl->cnum + vcn - rl->vcn;
+ if(lenp) *lenp = rl->clen - vcn + rl->vcn;
+ return 1;
+}
+
+static int search_run(MFTR *mftr, int vcn) {
+
+ if( mftr->attr==NULL && !search_attribute(mftr, mftr->attr_type, mftr->attr_name))
+ return 0;
+
+ if(mftr->runl.svcn > vcn)
+ search_attribute(mftr, mftr->attr_type, mftr->attr_name);
+
+#ifdef NO_ATTRIBUTE_LIST
+ if(mftr->runl.evcn < vcn)
+ return 0;
+#else
+ while(mftr->runl.evcn < vcn) {
+ if(get_next_attribute_list(mftr, NULL)==0) {
+ mftr->attr = NULL;
+ return 0;
+ }
+ init_run_list(mftr->attr, mftr->attr_len, &mftr->runl, NULL);
+ if(get_next_run(&mftr->runl)==0) {
+ mftr->attr = NULL;
+ return 0;
+ }
+ }
+#endif
+
+ return 1;
+}
+
+static int read_attribute(MFTR *mftr, int offset, char *buf, int len, RUNL *from_rl) {
+ int vcn;
+ int cnum, clen;
+ int done = 0;
+ int n;
+ RUNL *rl;
+
+ if(!from_rl && (mftr->attr_flag & ATTR_RESIDENT)) {
+ /* resident attribute */
+ if(offset > mftr->attr_len)
+ return 0;
+ if(offset+len > mftr->attr_len)
+ len = mftr->attr_len - offset;
+ memmove( buf, mftr->attr + offset, len);
+ return len;
+ }
+
+ vcn = offset / clustersize;
+ offset %= clustersize;
+
+ while(len>0) {
+ if(from_rl)
+ rl = from_rl;
+ else if(search_run(mftr, vcn) == 0)
+ break;
+ else
+ rl = &mftr->runl;
+ if(get_run(rl, vcn, &cnum, &clen) == 0)
+ break;
+ if(cnum==0 && from_rl)
+ break;
+ n = clen * clustersize - offset;
+ if(n > len) n = len;
+ if(cnum==0) {
+ memset( buf, 0, n);
+ } else if(!devread(cnum*(clustersize>>9)+(offset>>9), offset&0x1ff, n, buf))
+ break;
+
+ buf += n;
+ vcn += (offset+n)/clustersize;
+ done += n;
+ offset = 0;
+ len -= n;
+ }
+ return done;
+}
+
+static int read_mft_record(int mftno, char *mft, int self){
+#ifdef DEBUG_NTFS
+ printf("Reading MFT record: mftno=%d\n", mftno);
+#endif
+ if( read_attribute( mmft, mftno * mft_record_size,
+ mft, mft_record_size, self?mft_run:NULL) != mft_record_size)
+ return 0;
+ if(!fixup_record( mft, "FILE", mft_record_size))
+ return 0;
+ return 1;
+}
+
+#ifndef NO_NTFS_DECOMPRESSION
+static int get_16_cluster(MFTR *mftr, int vcn) {
+ int n = 0, cnum, clen;
+ while(n < 16 && search_run(mftr, vcn) && get_run(&mftr->runl, vcn, &cnum, &clen) && cnum) {
+ if(clen > 16 - n)
+ clen = 16 - n;
+ vcn += clen;
+ while(clen--)
+ cluster16[n++] = cnum++;
+ }
+ cluster16[n] = 0;
+ return n;
+}
+
+static inline int compressed_block_size( unsigned char *src ) {
+ return 3 + (*(__u16 *)src & 0xfff);
+}
+
+static int decompress_block(unsigned char *dest, unsigned char *src) {
+ int head;
+ int copied=0;
+ unsigned char *last;
+ int bits;
+ int tag=0;
+
+ /* high bit indicates that compression was performed */
+ if(!(*(__u16 *)src & 0x8000)) {
+ memmove(dest,src+2,0x1000);
+ return 0x1000;
+ }
+
+ if((head = *(__u16 *)src & 0xFFF)==0)
+ /* block is not used */
+ return 0;
+
+ src += 2;
+ last = src+head;
+ bits = 0;
+
+ while(src<=last)
+ {
+ if(copied>4096)
+ {
+#ifdef DEBUG_NTFS
+ printf("decompress error 1\n");
+#endif
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+ if(!bits){
+ tag=*(__u8 *)src;
+ bits=8;
+ src++;
+ if(src>last)
+ break;
+ }
+ if(tag & 1){
+ int i,len,delta,code,lmask,dshift;
+ code = *(__u16 *)src;
+ src+=2;
+ if(!copied)
+ {
+#ifdef DEBUG_NTFS
+ printf("decompress error 2\n");
+#endif
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+ for(i=copied-1,lmask=0xFFF,dshift=12;i>=0x10;i>>=1)
+ {
+ lmask >>= 1;
+ dshift--;
+ }
+ delta = code >> dshift;
+ len = (code & lmask) + 3;
+ for(i=0; i<len; i++)
+ {
+ dest[copied]=dest[copied-delta-1];
+ copied++;
+ }
+ } else
+ dest[copied++]=*(__u8 *)src++;
+ tag>>=1;
+ bits--;
+ }
+
+ return copied;
+}
+#endif
+
+int ntfs_read(char *buf, int len){
+ int ret;
+#ifdef STAGE1_5
+/* stage2 can't be resident/compressed/encrypted files,
+ * but does sparse flag, cause stage2 never sparsed
+ */
+ if((cmft->attr_flag&~ATTR_SPARSE) != ATTR_NORMAL)
+ return 0;
+ disk_read_func = disk_read_hook;
+ ret = read_attribute(cmft, filepos, buf, len, 0);
+ disk_read_func = NULL;
+ filepos += ret;
+#else
+
+#ifndef NO_NTFS_DECOMPRESSION
+ int off;
+ int vcn;
+ int size;
+ int len0;
+#endif
+
+ if(len<=0 || filepos >= cmft->attr_size || (cmft->attr_flag&ATTR_ENCRYPTED))
+ return 0;
+
+ if(filepos+len > cmft->attr_size)
+ len = cmft->attr_size - filepos;
+ if(filepos >= cmft->attr_inited) {
+#ifdef DEBUG_NTFS
+printf("reading uninitialized data 1\n");
+#endif
+ memset(buf, 0, len);
+ return len;
+ } else if(filepos+len > cmft->attr_inited) {
+ len0 = len;
+ len = cmft->attr_inited - filepos;
+ len0 -= len;
+ } else
+ len0 = 0;
+#ifdef DEBUG_NTFS
+printf("read filepos=%x filemax=%x inited=%x len=%x len0=%x\n",filepos,filemax,cmft->attr_inited,len,len0);
+#endif
+
+ if((cmft->attr_flag&(ATTR_COMPRESSED|ATTR_RESIDENT)) != ATTR_COMPRESSED) {
+ if(cmft->attr_flag==ATTR_NORMAL)
+ disk_read_func = disk_read_hook;
+ ret = read_attribute(cmft, filepos, buf, len, 0);
+ if(cmft->attr_flag==ATTR_NORMAL)
+ disk_read_func = NULL;
+ filepos += ret;
+ if(ret==len && len0) {
+ memset(buf+len, 0, len0);
+ filepos += len0;
+ ret += len0;
+ }
+ return ret;
+ }
+
+ ret = 0;
+
+#ifndef NO_NTFS_DECOMPRESSION
+ /* NTFS don't support compression if cluster size > 4k */
+ if(clustersize > 4096) {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+
+ while(len > 0){
+#ifdef DEBUG_NTFS
+printf("Reading filepos=%x len=%x\n", filepos, len);
+#endif
+ if(filepos >= dcoff && filepos < (dcoff+dclen)) {
+#ifdef DEBUG_NTFS
+printf("decompress cache %x+%x\n", dcoff, dclen);
+#endif
+ size = dcoff + dclen - filepos;
+ if(size > len) size = len;
+ memmove( buf, dcdbuf + filepos - dcoff, size);
+ filepos += size;
+ len -= size;
+ ret += size;
+ buf += size;
+ if(len==0) {
+ if(len0) {
+#ifdef DEBUG_NTFS
+printf("reading uninitialized data 2\n");
+#endif
+ memset(buf, 0, len0);
+ filepos += len0;
+ ret += len0;
+ }
+ return ret;
+ }
+ }
+
+ vcn = filepos / clustersize / 16;
+ vcn *= 16;
+ off = filepos % (16 * clustersize);
+ if( dcvcn != vcn || filepos < dcoff)
+ dcrem = 0;
+
+#ifdef DEBUG_NTFS
+printf("vcn %x off %x dcrem %x\n", vcn, off, dcrem);
+#endif
+ if(dcrem) {
+ int head;
+
+ /* reading source */
+ if(dcslen < 2 || compressed_block_size(dcsptr) > dcslen) {
+ if(cluster16[index16]==0) {
+ errnum = ERR_FSYS_CORRUPT;
+ return ret;
+ }
+ if(dcslen)
+ memmove(dcsbuf, dcsptr, dcslen);
+ dcsptr = dcsbuf;
+ while((dcslen+clustersize) < DECOMP_SOURCE_BUFFER_SIZE) {
+ if(cluster16[index16]==0)
+ break;
+#ifdef DEBUG_NTFS
+printf("reading dcslen=%x cluster %x\n", dcslen, cluster16[index16]);
+#endif
+ if(!devread(cluster16[index16]*(clustersize>>9), 0, clustersize, dcsbuf+dcslen))
+ return ret;
+ dcslen += clustersize;
+ index16++;
+ }
+ }
+ /* flush destination */
+ dcoff += dclen;
+ dclen = 0;
+
+ while(dcrem && dclen < DECOMP_DEST_BUFFER_SIZE &&
+ dcslen >= 2 && (head=compressed_block_size(dcsptr)) <= dcslen) {
+ size = decompress_block(dcdbuf+dclen, dcsptr);
+ if(dcrem>=0x1000 && size!=0x1000) {
+ errnum = ERR_FSYS_CORRUPT;
+ return ret;
+ }
+ dcrem -= size;
+ dclen += size;
+ dcsptr += head;
+ dcslen -= head;
+ }
+ continue;
+ }
+ dclen = dcrem = 0;
+#ifdef DEBUG_NTFS
+printf("get next 16 clusters\n");
+#endif
+ switch(get_16_cluster(cmft, vcn)) {
+ case 0:
+#ifdef DEBUG_NTFS
+printf("sparse\n");
+#endif
+ /* sparse */
+ size = 16 * clustersize - off;
+ if( len < size )
+ size = len;
+#ifndef STAGE1_5
+ memset( buf, 0, size);
+#endif
+ filepos += size;
+ len -= size;
+ ret += size;
+ buf += size;
+ break;
+
+ case 16:
+#ifdef DEBUG_NTFS
+printf("uncompressed\n");
+#endif
+ /* uncompressed */
+ index16 = off / clustersize;
+ off %= clustersize;
+ while(index16 < 16) {
+ size = clustersize - off;
+ if( len < size )
+ size = len;
+ if(!devread(cluster16[index16]*(clustersize>>9)+(off>>9), off&0x1ff, size, buf))
+ return ret;
+ filepos += size;
+ len -= size;
+ ret += size;
+ if(len==0)
+ return ret;
+ off = 0;
+ buf += size;
+ index16++;
+ }
+ break;
+
+ default:
+#ifdef DEBUG_NTFS
+printf("compressed\n");
+#endif
+ index16 = 0;
+ dcvcn = vcn;
+ dcoff = vcn * clustersize;
+ dcrem = cmft->attr_inited - dcoff;
+ if(dcrem > 16 * clustersize)
+ dcrem = 16 * clustersize;
+ dcsptr = dcsbuf;
+ dcslen = 0;
+ }
+ }
+ if(len0) {
+#ifdef DEBUG_NTFS
+printf("reading uninitialized data 3\n");
+#endif
+ memset(buf, 0, len0);
+ filepos += len0;
+ ret += len0;
+ }
+#else
+ errnum = FSYS_CORRUPT;
+#endif /*NO_NTFS_DECOMPRESSION*/
+#endif /*STAGE1_5*/
+ return ret;
+}
+
+int ntfs_mount (void)
+{
+ char *sb = (char *)FSYS_BUF;
+ int mft_record;
+ int spc;
+
+ if (((current_drive & 0x80) || (current_slice != 0))
+ && (current_slice != /*PC_SLICE_TYPE_NTFS*/7)
+ && (current_slice != /*PC_SLICE_TYPE_NTFS*/0x17))
+ return 0;
+
+ if (!devread (0, 0, 512, (char *) FSYS_BUF))
+ return 0; /* Cannot read superblock */
+
+ if(sb[3]!='N' || sb[4]!='T' || sb[5]!='F' || sb[6]!='S')
+ return 0;
+ blocksize = *(__u16 *)(sb+0xb);
+ spc = *(unsigned char *)(sb+0xd);
+ clustersize = spc * blocksize;
+ mft_record_size = *(char *)(sb+0x40);
+ index_record_size = *(char *)(sb+0x44);
+ if(mft_record_size>0)
+ mft_record_size *= clustersize;
+ else
+ mft_record_size = 1 << (-mft_record_size);
+
+ index_record_size *= clustersize;
+ mft_record = *(__u32 *)(sb+0x30); /* only support 32 bit */
+ spc = clustersize / 512;
+
+ if(mft_record_size > MAX_MFT_RECORD_SIZE || index_record_size > MAX_INDEX_RECORD_SIZE) {
+ /* only support 1k MFT record, 4k INDEX record */
+ return 0;
+ }
+
+#ifdef DEBUG_NTFS
+ printf("spc=%x mft_record=%x:%x\n", spc, *(__s64 *)(sb+0x30));
+#endif
+
+ if (!devread (mft_record*spc, 0, mft_record_size, mmft->mft))
+ return 0; /* Cannot read superblock */
+
+ if(!fixup_record( mmft->mft, "FILE", mft_record_size))
+ return 0;
+
+#ifndef NO_ALTERNATE_DATASTREAM
+ is_ads_completion = 0;
+#endif
+ if(!search_attribute(mmft, at_data, NONAME)) return 0;
+
+ *mft_run = mmft->runl;
+
+ *path_ino = FILE_ROOT;
+
+ return 1;
+}
+
+int
+ntfs_dir (char *dirname)
+{
+ char *rest, ch;
+ int namelen;
+ int depth = 0;
+ int chk_sfn = 1;
+ int flag = 0;
+ int record_offset;
+ int my_index_record_size;
+ unsigned char *index_entry = 0, *entry, *index_end;
+ int i;
+
+ /* main loop to find desired directory entry */
+loop:
+
+#ifdef DEBUG_NTFS
+ printf("dirname=%s\n", dirname);
+#endif
+ if(!read_mft_record(path_ino[depth], cmft->mft, 0))
+ {
+#ifdef DEBUG_NTFS
+ printf("MFT error 1\n");
+#endif
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+
+ /* if we have a real file (and we're not just printing possibilities),
+ then this is where we want to exit */
+
+ if (!*dirname || isspace (*dirname) || *dirname==':')
+ {
+#ifndef STAGE1_5
+#ifndef NO_ALTERNATE_DATASTREAM
+ if (*dirname==':' && print_possibilities) {
+ char *tmp;
+
+ /* preparing ADS name completion */
+ for(tmp = dirname; *tmp != '/'; tmp--);
+ for(tmp++, rest=fnbuf; *tmp && !isspace(*tmp); *rest++ = *tmp++)
+ if(*tmp==':') dirname = rest;
+ *rest++ = '\0';
+
+ is_ads_completion = 1;
+ search_attribute(cmft, at_data, dirname+1);
+ is_ads_completion = 0;
+
+ if(errnum==0) {
+ if(print_possibilities < 0)
+ return 1;
+ errnum = ERR_FILE_NOT_FOUND;
+ }
+ return 0;
+ }
+#endif
+#endif
+
+ if (*dirname==':') dirname++;
+ for (rest = dirname; (ch = *rest) && !isspace (ch); rest++);
+ *rest = 0;
+
+#ifdef DEBUG_NTFS
+ printf("got file: search at_data\n");
+#endif
+
+ if (!search_attribute(cmft, at_data, dirname)) {
+ errnum = *(dirname-1)==':'?ERR_FILE_NOT_FOUND:ERR_BAD_FILETYPE;
+ *rest = ch;
+ return 0;
+ }
+ *rest = ch;
+
+ filemax = cmft->attr_size;
+#ifdef DEBUG_NTFS
+ printf("filemax=%x\n", filemax);
+#endif
+ return 1;
+ }
+
+ if(depth >= (MAX_DIR_DEPTH-1)) {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+
+ /* continue with the file/directory name interpretation */
+
+ while (*dirname == '/')
+ dirname++;
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/' && ch != ':'; rest++);
+
+ *rest = 0;
+
+ if (!search_attribute(cmft, at_index_root, "$I30"))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ read_attribute(cmft, 0, fnbuf, 16, 0);
+ my_index_record_size = *(__u32 *)(fnbuf+8);
+
+ if(my_index_record_size > MAX_INDEX_RECORD_SIZE) {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+
+#ifdef DEBUG_NTFS
+ printf("index_record_size=%x\n", my_index_record_size);
+#endif
+
+ if(cmft->attr_size > MAX_INDEX_RECORD_SIZE) {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+ read_attribute(cmft, 0, index_data, cmft->attr_size, 0);
+ index_end = index_data + cmft->attr_size;
+ index_entry = index_data + 0x20;
+ record_offset = -1;
+
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/' && ch != ':' && !*dirname)
+ {
+ print_possibilities = -print_possibilities;
+ /* fake '.' for empty directory */
+ print_a_completion (".");
+ }
+#endif
+
+ if (search_attribute(cmft, at_bitmap, "$I30")) {
+ if(cmft->attr_size > MAX_INDEX_BITMAP_SIZE) {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+
+ read_attribute(cmft, 0, bitmap_data, cmft->attr_size, 0);
+
+ if (search_attribute(cmft, at_index_allocation, "$I30")==0) {
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+
+ for(record_offset = 0; record_offset*my_index_record_size<cmft->attr_size; record_offset++){
+ int bit = 1 << (record_offset&3);
+ int byte = record_offset>>3;
+#ifdef DEBUG_NTFS
+ printf("record_offset=%x\n", record_offset);
+#endif
+ if((bitmap_data[byte]&bit))
+ break;
+ }
+
+ if(record_offset*my_index_record_size>=cmft->attr_size) record_offset = -1;
+ }
+
+ do
+ {
+ entry = index_entry; index_entry += *(__u16 *)(entry+8);
+ if(entry+0x50>=index_entry||entry>=index_end||
+ index_entry>=index_end||(entry[0x12]&2)){
+ if(record_offset < 0 ||
+ !read_attribute(cmft, record_offset*my_index_record_size, index_data, my_index_record_size, 0)){
+ if (!errnum)
+ {
+ if (print_possibilities < 0)
+ {
+#if 0
+ putchar ('\n');
+#endif
+ return 1;
+ }
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ }
+
+ return 0;
+ }
+ if(!fixup_record( index_data, "INDX", my_index_record_size))
+ {
+#ifdef DEBUG_NTFS
+ printf("index error\n");
+#endif
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+ entry = index_data + 0x18 + *(__u16 *)(index_data+0x18);
+ index_entry = entry + *(__u16 *)(entry+8);
+ index_end = index_data + my_index_record_size - 0x52;
+ for(record_offset++; record_offset*my_index_record_size<cmft->attr_size; record_offset++){
+ int bit = 1 << (record_offset&3);
+ int byte = record_offset>>3;
+ if((bitmap_data[byte]&bit)) break;
+ }
+ if(record_offset*my_index_record_size>=cmft->attr_size) record_offset = -1;
+#ifdef DEBUG_NTFS
+ printf("record_offset=%x\n", record_offset);
+#endif
+ }
+ flag = entry[0x51];
+ path_ino[depth+1] = *(__u32 *)entry;
+ if(path_ino[depth+1] < 16)
+ continue;
+ namelen = entry[0x50];
+ //if(index_data[0x48]&2) printf("hidden file\n");
+#ifndef STAGE1_5
+ /* skip short file name */
+ if( flag == 2 && print_possibilities && ch != '/' && ch != ':' )
+ continue;
+#endif
+
+ for( i = 0, entry+=0x52; i < namelen; i++, entry+=2 )
+ {
+ int c = *(__u16 *)entry;
+ if(c==' '||c>=0x100)
+ fnbuf[i] = '_';
+ else
+ fnbuf[i] = c;
+ }
+ fnbuf[namelen] = 0;
+#ifdef DEBUG_NTFS
+ printf("FLAG: %d NAME: %s inum=%d\n", flag,fnbuf,path_ino[depth+1]);
+#endif
+
+ //uncntrl(fnbuf);
+
+ chk_sfn = nsubstring(dirname,fnbuf);
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/' && ch != ':'
+ && (!*dirname || chk_sfn <= 0))
+ {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (fnbuf);
+ }
+#endif /* STAGE1_5 */
+ }
+ while (chk_sfn != 0 ||
+ (print_possibilities && ch != '/' && ch != ':'));
+
+ *(dirname = rest) = ch;
+
+ depth++;
+
+ /* go back to main loop at top of function */
+ goto loop;
+}
+
+#ifdef DEBUG_NTFS
+int dump_block(char *msg, char *buf, int size){
+ int l = (size+15)/16;
+ int off;
+ int i, j;
+ int c;
+ printf("----- %s -----\n", msg);
+ for( i = 0, off = 0; i < l; i++, off+=16)
+ {
+ if(off<16)
+ printf("000%x:", off);
+ else if(off<256)
+ printf("00%x:", off);
+ else
+ printf("0%x:", off);
+ for(j=0;j<16;j++)
+ {
+ c = buf[off+j]&0xff;
+ if( c >= 16 )
+ printf("%c%x",j==8?'-':' ',c);
+ else
+ printf("%c0%x",j==8?'-':' ',c);
+ }
+ printf(" ");
+ for(j=0;j<16;j++) {
+ char c = buf[off+j];
+ printf("%c",c<' '||c>='\x7f'?'.':c);
+ }
+ printf("\n");
+ }
+}
+#endif
+#endif /* FSYS_NTFS */
diff --git a/roms/openbios/fs/grubfs/fsys_reiserfs.c b/roms/openbios/fs/grubfs/fsys_reiserfs.c
new file mode 100644
index 00000000..b94a3352
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_reiserfs.c
@@ -0,0 +1,1220 @@
+/* fsys_reiserfs.c - an implementation for the ReiserFS filesystem */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifdef FSYS_REISERFS
+#include "shared.h"
+#include "filesys.h"
+
+#undef REISERDEBUG
+
+/* Some parts of this code (mainly the structures and defines) are
+ * from the original reiser fs code, as found in the linux kernel.
+ */
+
+/* include/asm-i386/types.h */
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+typedef unsigned long long __u64;
+
+/* linux/posix_type.h */
+typedef long linux_off_t;
+
+#include "libc/byteorder.h"
+
+/* include/linux/reiser_fs.h */
+/* This is the new super block of a journaling reiserfs system */
+struct reiserfs_super_block
+{
+ __u32 s_block_count; /* blocks count */
+ __u32 s_free_blocks; /* free blocks count */
+ __u32 s_root_block; /* root block number */
+ __u32 s_journal_block; /* journal block number */
+ __u32 s_journal_dev; /* journal device number */
+ __u32 s_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */
+ __u32 s_journal_trans_max; /* max number of blocks in a transaction. */
+ __u32 s_journal_magic; /* random value made on fs creation */
+ __u32 s_journal_max_batch; /* max number of blocks to batch into a trans */
+ __u32 s_journal_max_commit_age; /* in seconds, how old can an async commit be */
+ __u32 s_journal_max_trans_age; /* in seconds, how old can a transaction be */
+ __u16 s_blocksize; /* block size */
+ __u16 s_oid_maxsize; /* max size of object id array */
+ __u16 s_oid_cursize; /* current size of object id array */
+ __u16 s_state; /* valid or error */
+ char s_magic[16]; /* reiserfs magic string indicates that file system is reiserfs */
+ __u16 s_tree_height; /* height of disk tree */
+ __u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */
+ __u16 s_version;
+ char s_unused[128]; /* zero filled by mkreiserfs */
+};
+
+#define REISERFS_MAX_SUPPORTED_VERSION 2
+#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
+#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
+
+#define MAX_HEIGHT 7
+
+/* must be correct to keep the desc and commit structs at 4k */
+#define JOURNAL_TRANS_HALF 1018
+
+/* first block written in a commit. */
+struct reiserfs_journal_desc {
+ __u32 j_trans_id; /* id of commit */
+ __u32 j_len; /* length of commit. len +1 is the commit block */
+ __u32 j_mount_id; /* mount id of this trans*/
+ __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */
+ char j_magic[12];
+};
+
+/* last block written in a commit */
+struct reiserfs_journal_commit {
+ __u32 j_trans_id; /* must match j_trans_id from the desc block */
+ __u32 j_len; /* ditto */
+ __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */
+ char j_digest[16]; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
+};
+
+/* this header block gets written whenever a transaction is considered
+ fully flushed, and is more recent than the last fully flushed
+ transaction.
+ fully flushed means all the log blocks and all the real blocks are
+ on disk, and this transaction does not need to be replayed.
+*/
+struct reiserfs_journal_header {
+ /* id of last fully flushed transaction */
+ __u32 j_last_flush_trans_id;
+ /* offset in the log of where to start replay after a crash */
+ __u32 j_first_unflushed_offset;
+ /* mount id to detect very old transactions */
+ __u32 j_mount_id;
+};
+
+/* magic string to find desc blocks in the journal */
+#define JOURNAL_DESC_MAGIC "ReIsErLB"
+
+
+/*
+ * directories use this key as well as old files
+ */
+struct offset_v1
+{
+ /*
+ * for regular files this is the offset to the first byte of the
+ * body, contained in the object-item, as measured from the start of
+ * the entire body of the object.
+ *
+ * for directory entries, k_offset consists of hash derived from
+ * hashing the name and using few bits (23 or more) of the resulting
+ * hash, and generation number that allows distinguishing names with
+ * hash collisions. If number of collisions overflows generation
+ * number, we return EEXIST. High order bit is 0 always
+ */
+ __u32 k_offset;
+ __u32 k_uniqueness;
+};
+
+struct offset_v2
+{
+ /*
+ * for regular files this is the offset to the first byte of the
+ * body, contained in the object-item, as measured from the start of
+ * the entire body of the object.
+ *
+ * for directory entries, k_offset consists of hash derived from
+ * hashing the name and using few bits (23 or more) of the resulting
+ * hash, and generation number that allows distinguishing names with
+ * hash collisions. If number of collisions overflows generation
+ * number, we return EEXIST. High order bit is 0 always
+ */
+ __u64 k_offset:60;
+ __u64 k_type: 4;
+};
+
+
+struct key
+{
+ /* packing locality: by default parent directory object id */
+ __u32 k_dir_id;
+ /* object identifier */
+ __u32 k_objectid;
+ /* the offset and node type (old and new form) */
+ union
+ {
+ struct offset_v1 v1;
+ struct offset_v2 v2;
+ }
+ u;
+};
+
+#define KEY_SIZE (sizeof (struct key))
+
+/* Header of a disk block. More precisely, header of a formatted leaf
+ or internal node, and not the header of an unformatted node. */
+struct block_head
+{
+ __u16 blk_level; /* Level of a block in the tree. */
+ __u16 blk_nr_item; /* Number of keys/items in a block. */
+ __u16 blk_free_space; /* Block free space in bytes. */
+ struct key blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes
+ only) */
+};
+#define BLKH_SIZE (sizeof (struct block_head))
+#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */
+
+struct item_head
+{
+ struct key ih_key; /* Everything in the tree is found by searching for it based on its key.*/
+
+ union
+ {
+ __u16 ih_free_space; /* The free space in the last unformatted node of an indirect item if this
+ is an indirect item. This equals 0xFFFF iff this is a direct item or
+ stat data item. Note that the key, not this field, is used to determine
+ the item type, and thus which field this union contains. */
+ __u16 ih_entry_count; /* Iff this is a directory item, this field equals the number of directory
+ entries in the directory item. */
+ }
+ u;
+ __u16 ih_item_len; /* total size of the item body */
+ __u16 ih_item_location; /* an offset to the item body within the block */
+ __u16 ih_version; /* ITEM_VERSION_1 for all old items,
+ ITEM_VERSION_2 for new ones.
+ Highest bit is set by fsck
+ temporary, cleaned after all done */
+};
+/* size of item header */
+#define IH_SIZE (sizeof (struct item_head))
+
+#define ITEM_VERSION_1 0
+#define ITEM_VERSION_2 1
+#define IH_KEY_OFFSET(ih) ((ih)->ih_version == ITEM_VERSION_1 \
+ ? (ih)->ih_key.u.v1.k_offset \
+ : (ih)->ih_key.u.v2.k_offset)
+
+#define IH_KEY_ISTYPE(ih, type) ((ih)->ih_version == ITEM_VERSION_1 \
+ ? (ih)->ih_key.u.v1.k_uniqueness == V1_##type \
+ : (ih)->ih_key.u.v2.k_type == V2_##type)
+
+/* FIXME these types look wrong. */
+struct disk_child
+{
+ unsigned long dc_block_number; /* Disk child's block number. */
+ unsigned short dc_size; /* Disk child's used space. */
+};
+
+#define DC_SIZE (sizeof (struct disk_child))
+
+/* Stat Data on disk.
+ *
+ * Note that reiserfs has two different forms of stat data. Luckily
+ * the fields needed by grub are at the same position.
+ */
+struct stat_data
+{
+ __u16 sd_mode; /* file type, permissions */
+ __u16 sd_notused1[3]; /* fields not needed by reiserfs */
+ __u32 sd_size; /* file size */
+ __u32 sd_size_hi; /* file size high 32 bits (since version 2) */
+};
+
+struct reiserfs_de_head
+{
+ __u32 deh_offset; /* third component of the directory entry key */
+ __u32 deh_dir_id; /* objectid of the parent directory of the
+ object, that is referenced by directory entry */
+ __u32 deh_objectid;/* objectid of the object, that is referenced by
+ directory entry */
+ __u16 deh_location;/* offset of name in the whole item */
+ __u16 deh_state; /* whether 1) entry contains stat data (for
+ future), and 2) whether entry is hidden
+ (unlinked) */
+};
+
+#define DEH_SIZE (sizeof (struct reiserfs_de_head))
+
+#define DEH_Statdata (1 << 0) /* not used now */
+#define DEH_Visible (1 << 2)
+
+#define SD_OFFSET 0
+#define SD_UNIQUENESS 0
+#define DOT_OFFSET 1
+#define DOT_DOT_OFFSET 2
+#define DIRENTRY_UNIQUENESS 500
+
+#define V1_TYPE_STAT_DATA 0x0
+#define V1_TYPE_DIRECT 0xffffffff
+#define V1_TYPE_INDIRECT 0xfffffffe
+#define V1_TYPE_DIRECTORY_MAX 0xfffffffd
+#define V2_TYPE_STAT_DATA 0
+#define V2_TYPE_INDIRECT 1
+#define V2_TYPE_DIRECT 2
+#define V2_TYPE_DIRENTRY 3
+
+#define REISERFS_ROOT_OBJECTID 2
+#define REISERFS_ROOT_PARENT_OBJECTID 1
+#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
+/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
+#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
+#define REISERFS_OLD_BLOCKSIZE 4096
+
+#define S_ISREG(mode) (((mode) & 0170000) == 0100000)
+#define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
+#define S_ISLNK(mode) (((mode) & 0170000) == 0120000)
+
+#define PATH_MAX 1024 /* include/linux/limits.h */
+#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
+
+/* The size of the node cache */
+#define FSYSREISER_CACHE_SIZE 24*1024
+#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
+#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
+
+/* Info about currently opened file */
+struct fsys_reiser_fileinfo
+{
+ __u32 k_dir_id;
+ __u32 k_objectid;
+};
+
+/* In memory info about the currently mounted filesystem */
+struct fsys_reiser_info
+{
+ /* The last read item head */
+ struct item_head *current_ih;
+ /* The last read item */
+ char *current_item;
+ /* The information for the currently opened file */
+ struct fsys_reiser_fileinfo fileinfo;
+ /* The start of the journal */
+ __u32 journal_block;
+ /* The size of the journal */
+ __u32 journal_block_count;
+ /* The first valid descriptor block in journal
+ (relative to journal_block) */
+ __u32 journal_first_desc;
+
+ /* The ReiserFS version. */
+ __u16 version;
+ /* The current depth of the reiser tree. */
+ __u16 tree_depth;
+ /* SECTOR_SIZE << blocksize_shift == blocksize. */
+ __u8 blocksize_shift;
+ /* 1 << full_blocksize_shift == blocksize. */
+ __u8 fullblocksize_shift;
+ /* The reiserfs block size (must be a power of 2) */
+ __u16 blocksize;
+ /* The number of cached tree nodes */
+ __u16 cached_slots;
+ /* The number of valid transactions in journal */
+ __u16 journal_transactions;
+
+ unsigned int blocks[MAX_HEIGHT];
+ unsigned int next_key_nr[MAX_HEIGHT];
+};
+
+/* The cached s+tree blocks in FSYS_BUF, see below
+ * for a more detailed description.
+ */
+#define ROOT ((char *)FSYS_BUF)
+#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
+#define LEAF CACHE (DISK_LEAF_NODE_LEVEL)
+
+#define BLOCKHEAD(cache) ((struct block_head *) cache)
+#define ITEMHEAD ((struct item_head *) ((char *) LEAF + BLKH_SIZE))
+#define KEY(cache) ((struct key *) ((char *) cache + BLKH_SIZE))
+#define DC(cache) ((struct disk_child *) \
+ ((char *) cache + BLKH_SIZE + KEY_SIZE * nr_item))
+/* The fsys_reiser_info block.
+ */
+#define INFO \
+ ((struct fsys_reiser_info *) ((char *) FSYS_BUF + FSYSREISER_CACHE_SIZE))
+/*
+ * The journal cache. For each transaction it contains the number of
+ * blocks followed by the real block numbers of this transaction.
+ *
+ * If the block numbers of some transaction won't fit in this space,
+ * this list is stopped with a 0xffffffff marker and the remaining
+ * uncommitted transactions aren't cached.
+ */
+#define JOURNAL_START ((__u32 *) (INFO + 1))
+#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
+
+static __inline__ int
+is_power_of_two (unsigned long word)
+{
+ return (word & -word) == word;
+}
+
+static int
+journal_read (int block, int len, char *buffer)
+{
+ return devread ((INFO->journal_block + block) << INFO->blocksize_shift,
+ 0, len, buffer);
+}
+
+/* Read a block from ReiserFS file system, taking the journal into
+ * account. If the block nr is in the journal, the block from the
+ * journal taken.
+ */
+static int
+block_read (int blockNr, int start, int len, char *buffer)
+{
+ int transactions = INFO->journal_transactions;
+ int desc_block = INFO->journal_first_desc;
+ int journal_mask = INFO->journal_block_count - 1;
+ int translatedNr = blockNr;
+ __u32 *journal_table = JOURNAL_START;
+ while (transactions-- > 0)
+ {
+ int i = 0;
+ int j_len;
+ if (*journal_table != 0xffffffff)
+ {
+ /* Search for the blockNr in cached journal */
+ j_len = *journal_table++;
+ while (i++ < j_len)
+ {
+ if (*journal_table++ == blockNr)
+ {
+ journal_table += j_len - i;
+ goto found;
+ }
+ }
+ }
+ else
+ {
+ /* This is the end of cached journal marker. The remaining
+ * transactions are still on disk.
+ */
+ struct reiserfs_journal_desc desc;
+ struct reiserfs_journal_commit commit;
+
+ if (! journal_read (desc_block, sizeof (desc), (char *) &desc))
+ return 0;
+
+ j_len = desc.j_len;
+ while (i < j_len && i < JOURNAL_TRANS_HALF)
+ if (desc.j_realblock[i++] == blockNr)
+ goto found;
+
+ if (j_len >= JOURNAL_TRANS_HALF)
+ {
+ int commit_block = (desc_block + 1 + j_len) & journal_mask;
+ if (! journal_read (commit_block,
+ sizeof (commit), (char *) &commit))
+ return 0;
+ while (i < j_len)
+ if (commit.j_realblock[i++ - JOURNAL_TRANS_HALF] == blockNr)
+ goto found;
+ }
+ }
+ goto not_found;
+
+ found:
+ translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
+#ifdef REISERDEBUG
+ printf ("block_read: block %d is mapped to journal block %d.\n",
+ blockNr, translatedNr - INFO->journal_block);
+#endif
+ /* We must continue the search, as this block may be overwritten
+ * in later transactions.
+ */
+ not_found:
+ desc_block = (desc_block + 2 + j_len) & journal_mask;
+ }
+ return devread (translatedNr << INFO->blocksize_shift, start, len, buffer);
+}
+
+/* Init the journal data structure. We try to cache as much as
+ * possible in the JOURNAL_START-JOURNAL_END space, but if it is full
+ * we can still read the rest from the disk on demand.
+ *
+ * The first number of valid transactions and the descriptor block of the
+ * first valid transaction are held in INFO. The transactions are all
+ * adjacent, but we must take care of the journal wrap around.
+ */
+static int
+journal_init (void)
+{
+ unsigned int block_count = INFO->journal_block_count;
+ unsigned int desc_block;
+ unsigned int commit_block;
+ unsigned int next_trans_id;
+ struct reiserfs_journal_header header;
+ struct reiserfs_journal_desc desc;
+ struct reiserfs_journal_commit commit;
+ __u32 *journal_table = JOURNAL_START;
+
+ journal_read (block_count, sizeof (header), (char *) &header);
+ desc_block = header.j_first_unflushed_offset;
+ if (desc_block >= block_count)
+ return 0;
+
+ INFO->journal_first_desc = desc_block;
+ next_trans_id = header.j_last_flush_trans_id + 1;
+
+#ifdef REISERDEBUG
+ printf ("journal_init: last flushed %d\n",
+ header.j_last_flush_trans_id);
+#endif
+
+ while (1)
+ {
+ journal_read (desc_block, sizeof (desc), (char *) &desc);
+ if (substring (JOURNAL_DESC_MAGIC, desc.j_magic) > 0
+ || desc.j_trans_id != next_trans_id
+ || desc.j_mount_id != header.j_mount_id)
+ /* no more valid transactions */
+ break;
+
+ commit_block = (desc_block + desc.j_len + 1) & (block_count - 1);
+ journal_read (commit_block, sizeof (commit), (char *) &commit);
+ if (desc.j_trans_id != commit.j_trans_id
+ || desc.j_len != commit.j_len)
+ /* no more valid transactions */
+ break;
+
+#ifdef REISERDEBUG
+ printf ("Found valid transaction %d/%d at %d.\n",
+ desc.j_trans_id, desc.j_mount_id, desc_block);
+#endif
+
+ next_trans_id++;
+ if (journal_table < JOURNAL_END)
+ {
+ if ((journal_table + 1 + desc.j_len) >= JOURNAL_END)
+ {
+ /* The table is almost full; mark the end of the cached
+ * journal.*/
+ *journal_table = 0xffffffff;
+ journal_table = JOURNAL_END;
+ }
+ else
+ {
+ int i;
+ /* Cache the length and the realblock numbers in the table.
+ * The block number of descriptor can easily be computed.
+ * and need not to be stored here.
+ */
+ *journal_table++ = desc.j_len;
+ for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++)
+ {
+ *journal_table++ = desc.j_realblock[i];
+#ifdef REISERDEBUG
+ printf ("block %d is in journal %d.\n",
+ desc.j_realblock[i], desc_block);
+#endif
+ }
+ for ( ; i < desc.j_len; i++)
+ {
+ *journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
+#ifdef REISERDEBUG
+ printf ("block %d is in journal %d.\n",
+ commit.j_realblock[i-JOURNAL_TRANS_HALF],
+ desc_block);
+#endif
+ }
+ }
+ }
+ desc_block = (commit_block + 1) & (block_count - 1);
+ }
+#ifdef REISERDEBUG
+ printf ("Transaction %d/%d at %d isn't valid.\n",
+ desc.j_trans_id, desc.j_mount_id, desc_block);
+#endif
+
+ INFO->journal_transactions
+ = next_trans_id - header.j_last_flush_trans_id - 1;
+ return errnum == 0;
+}
+
+/* check filesystem types and read superblock into memory buffer */
+int
+reiserfs_mount (void)
+{
+ struct reiserfs_super_block super;
+ int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
+
+ if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
+ || ! devread (superblock, 0, sizeof (struct reiserfs_super_block),
+ (char *) &super)
+ || (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
+ && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
+ || (/* check that this is not a copy inside the journal log */
+ super.s_journal_block * super.s_blocksize
+ <= REISERFS_DISK_OFFSET_IN_BYTES))
+ {
+ /* Try old super block position */
+ superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
+ if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
+ || ! devread (superblock, 0, sizeof (struct reiserfs_super_block),
+ (char *) &super))
+ return 0;
+
+ if (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
+ && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
+ {
+ /* pre journaling super block ? */
+ if (substring (REISERFS_SUPER_MAGIC_STRING,
+ (char*) ((char *) &super + 20)) > 0)
+ return 0;
+
+ super.s_blocksize = REISERFS_OLD_BLOCKSIZE;
+ super.s_journal_block = 0;
+ super.s_version = 0;
+ }
+ }
+
+ /* check the version number. */
+ if (super.s_version > REISERFS_MAX_SUPPORTED_VERSION)
+ return 0;
+
+ INFO->version = super.s_version;
+ INFO->blocksize = super.s_blocksize;
+ INFO->fullblocksize_shift = log2 (super.s_blocksize);
+ INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
+ INFO->cached_slots =
+ (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
+
+#ifdef REISERDEBUG
+ printf ("reiserfs_mount: version=%d, blocksize=%d\n",
+ INFO->version, INFO->blocksize);
+#endif /* REISERDEBUG */
+
+ /* Clear node cache. */
+ memset (INFO->blocks, 0, sizeof (INFO->blocks));
+
+ if (super.s_blocksize < FSYSREISER_MIN_BLOCKSIZE
+ || super.s_blocksize > FSYSREISER_MAX_BLOCKSIZE
+ || (SECTOR_SIZE << INFO->blocksize_shift) != super.s_blocksize)
+ return 0;
+
+ /* Initialize journal code. If something fails we end with zero
+ * journal_transactions, so we don't access the journal at all.
+ */
+ INFO->journal_transactions = 0;
+ if (super.s_journal_block != 0 && super.s_journal_dev == 0)
+ {
+ INFO->journal_block = super.s_journal_block;
+ INFO->journal_block_count = super.s_journal_size;
+ if (is_power_of_two (INFO->journal_block_count))
+ journal_init ();
+
+ /* Read in super block again, maybe it is in the journal */
+ block_read (superblock >> INFO->blocksize_shift,
+ 0, sizeof (struct reiserfs_super_block), (char *) &super);
+ }
+
+ if (! block_read (super.s_root_block, 0, INFO->blocksize, (char*) ROOT))
+ return 0;
+
+ INFO->tree_depth = BLOCKHEAD (ROOT)->blk_level;
+
+#ifdef REISERDEBUG
+ printf ("root read_in: block=%d, depth=%d\n",
+ super.s_root_block, INFO->tree_depth);
+#endif /* REISERDEBUG */
+
+ if (INFO->tree_depth >= MAX_HEIGHT)
+ return 0;
+ if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL)
+ {
+ /* There is only one node in the whole filesystem,
+ * which is simultanously leaf and root */
+ memcpy (LEAF, ROOT, INFO->blocksize);
+ }
+ return 1;
+}
+
+/***************** TREE ACCESSING METHODS *****************************/
+
+/* I assume you are familiar with the ReiserFS tree, if not go to
+ * http://www.namesys.com/content_table.html
+ *
+ * My tree node cache is organized as following
+ * 0 ROOT node
+ * 1 LEAF node (if the ROOT is also a LEAF it is copied here
+ * 2-n other nodes on current path from bottom to top.
+ * if there is not enough space in the cache, the top most are
+ * omitted.
+ *
+ * I have only two methods to find a key in the tree:
+ * search_stat(dir_id, objectid) searches for the stat entry (always
+ * the first entry) of an object.
+ * next_key() gets the next key in tree order.
+ *
+ * This means, that I can only sequential reads of files are
+ * efficient, but this really doesn't hurt for grub.
+ */
+
+/* Read in the node at the current path and depth into the node cache.
+ * You must set INFO->blocks[depth] before.
+ */
+static char *
+read_tree_node (unsigned int blockNr, int depth)
+{
+ char* cache = CACHE(depth);
+ int num_cached = INFO->cached_slots;
+ if (depth < num_cached)
+ {
+ /* This is the cached part of the path. Check if same block is
+ * needed.
+ */
+ if (blockNr == INFO->blocks[depth])
+ return cache;
+ }
+ else
+ cache = CACHE(num_cached);
+
+#ifdef REISERDEBUG
+ printf (" next read_in: block=%d (depth=%d)\n",
+ blockNr, depth);
+#endif /* REISERDEBUG */
+ if (! block_read (blockNr, 0, INFO->blocksize, cache))
+ return NULL;
+ /* Make sure it has the right node level */
+ if (BLOCKHEAD (cache)->blk_level != depth)
+ {
+ errnum = ERR_FSYS_CORRUPT;
+ return NULL;
+ }
+
+ INFO->blocks[depth] = blockNr;
+ return cache;
+}
+
+/* Get the next key, i.e. the key following the last retrieved key in
+ * tree order. INFO->current_ih and
+ * INFO->current_info are adapted accordingly. */
+static int
+next_key (void)
+{
+ int depth;
+ struct item_head *ih = INFO->current_ih + 1;
+ char *cache;
+
+#ifdef REISERDEBUG
+ printf ("next_key:\n old ih: key %d:%d:%d:%d version:%d\n",
+ INFO->current_ih->ih_key.k_dir_id,
+ INFO->current_ih->ih_key.k_objectid,
+ INFO->current_ih->ih_key.u.v1.k_offset,
+ INFO->current_ih->ih_key.u.v1.k_uniqueness,
+ INFO->current_ih->ih_version);
+#endif /* REISERDEBUG */
+
+ if (ih == &ITEMHEAD[BLOCKHEAD (LEAF)->blk_nr_item])
+ {
+ depth = DISK_LEAF_NODE_LEVEL;
+ /* The last item, was the last in the leaf node.
+ * Read in the next block
+ */
+ do
+ {
+ if (depth == INFO->tree_depth)
+ {
+ /* There are no more keys at all.
+ * Return a dummy item with MAX_KEY */
+ ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key;
+ goto found;
+ }
+ depth++;
+#ifdef REISERDEBUG
+ printf (" depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]);
+#endif /* REISERDEBUG */
+ }
+ while (INFO->next_key_nr[depth] == 0);
+
+ if (depth == INFO->tree_depth)
+ cache = ROOT;
+ else if (depth <= INFO->cached_slots)
+ cache = CACHE (depth);
+ else
+ {
+ cache = read_tree_node (INFO->blocks[depth], depth);
+ if (! cache)
+ return 0;
+ }
+
+ do
+ {
+ int nr_item = BLOCKHEAD (cache)->blk_nr_item;
+ int key_nr = INFO->next_key_nr[depth]++;
+#ifdef REISERDEBUG
+ printf (" depth=%d, i=%d/%d\n", depth, key_nr, nr_item);
+#endif /* REISERDEBUG */
+ if (key_nr == nr_item)
+ /* This is the last item in this block, set the next_key_nr to 0 */
+ INFO->next_key_nr[depth] = 0;
+
+ cache = read_tree_node (DC (cache)[key_nr].dc_block_number, --depth);
+ if (! cache)
+ return 0;
+ }
+ while (depth > DISK_LEAF_NODE_LEVEL);
+
+ ih = ITEMHEAD;
+ }
+ found:
+ INFO->current_ih = ih;
+ INFO->current_item = &LEAF[ih->ih_item_location];
+#ifdef REISERDEBUG
+ printf (" new ih: key %d:%d:%d:%d version:%d\n",
+ INFO->current_ih->ih_key.k_dir_id,
+ INFO->current_ih->ih_key.k_objectid,
+ INFO->current_ih->ih_key.u.v1.k_offset,
+ INFO->current_ih->ih_key.u.v1.k_uniqueness,
+ INFO->current_ih->ih_version);
+#endif /* REISERDEBUG */
+ return 1;
+}
+
+/* preconditions: reiserfs_mount already executed, therefore
+ * INFO block is valid
+ * returns: 0 if error (errnum is set),
+ * nonzero iff we were able to find the key successfully.
+ * postconditions: on a nonzero return, the current_ih and
+ * current_item fields describe the key that equals the
+ * searched key. INFO->next_key contains the next key after
+ * the searched key.
+ * side effects: messes around with the cache.
+ */
+static int
+search_stat (__u32 dir_id, __u32 objectid)
+{
+ char *cache;
+ int depth;
+ int nr_item;
+ int i;
+ struct item_head *ih;
+#ifdef REISERDEBUG
+ printf ("search_stat:\n key %d:%d:0:0\n", dir_id, objectid);
+#endif /* REISERDEBUG */
+
+ depth = INFO->tree_depth;
+ cache = ROOT;
+
+ while (depth > DISK_LEAF_NODE_LEVEL)
+ {
+ struct key *key;
+ nr_item = BLOCKHEAD (cache)->blk_nr_item;
+
+ key = KEY (cache);
+
+ for (i = 0; i < nr_item; i++)
+ {
+ if (key->k_dir_id > dir_id
+ || (key->k_dir_id == dir_id
+ && (key->k_objectid > objectid
+ || (key->k_objectid == objectid
+ && (key->u.v1.k_offset
+ | key->u.v1.k_uniqueness) > 0))))
+ break;
+ key++;
+ }
+
+#ifdef REISERDEBUG
+ printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
+#endif /* REISERDEBUG */
+ INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
+ cache = read_tree_node (DC (cache)[i].dc_block_number, --depth);
+ if (! cache)
+ return 0;
+ }
+
+ /* cache == LEAF */
+ nr_item = BLOCKHEAD (LEAF)->blk_nr_item;
+ ih = ITEMHEAD;
+ for (i = 0; i < nr_item; i++)
+ {
+ if (ih->ih_key.k_dir_id == dir_id
+ && ih->ih_key.k_objectid == objectid
+ && ih->ih_key.u.v1.k_offset == 0
+ && ih->ih_key.u.v1.k_uniqueness == 0)
+ {
+#ifdef REISERDEBUG
+ printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
+#endif /* REISERDEBUG */
+ INFO->current_ih = ih;
+ INFO->current_item = &LEAF[ih->ih_item_location];
+ return 1;
+ }
+ ih++;
+ }
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+}
+
+int
+reiserfs_read (char *buf, int len)
+{
+ unsigned int blocksize;
+ unsigned int offset;
+ unsigned int to_read;
+ char *prev_buf = buf;
+
+#ifdef REISERDEBUG
+ printf ("reiserfs_read: filepos=%d len=%d, offset=%x:%x\n",
+ filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);
+#endif /* REISERDEBUG */
+
+ if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid
+ || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1)
+ {
+ search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid);
+ goto get_next_key;
+ }
+
+ while (! errnum)
+ {
+ if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid)
+ break;
+
+ offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1;
+ blocksize = INFO->current_ih->ih_item_len;
+
+#ifdef REISERDEBUG
+ printf (" loop: filepos=%d len=%d, offset=%d blocksize=%d\n",
+ filepos, len, offset, blocksize);
+#endif /* REISERDEBUG */
+
+ if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT)
+ && offset < blocksize)
+ {
+#ifdef REISERDEBUG
+ printf ("direct_read: offset=%d, blocksize=%d\n",
+ offset, blocksize);
+#endif /* REISERDEBUG */
+ to_read = blocksize - offset;
+ if (to_read > len)
+ to_read = len;
+
+ if (disk_read_hook != NULL)
+ {
+ disk_read_func = disk_read_hook;
+
+ block_read (INFO->blocks[DISK_LEAF_NODE_LEVEL],
+ (INFO->current_item - LEAF + offset), to_read, buf);
+
+ disk_read_func = NULL;
+ }
+ else
+ memcpy (buf, INFO->current_item + offset, to_read);
+ goto update_buf_len;
+ }
+ else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT))
+ {
+ blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;
+#ifdef REISERDEBUG
+ printf ("indirect_read: offset=%d, blocksize=%d\n",
+ offset, blocksize);
+#endif /* REISERDEBUG */
+
+ while (offset < blocksize)
+ {
+ __u32 blocknr = ((__u32 *) INFO->current_item)
+ [offset >> INFO->fullblocksize_shift];
+ int blk_offset = offset & (INFO->blocksize-1);
+
+ to_read = INFO->blocksize - blk_offset;
+ if (to_read > len)
+ to_read = len;
+
+ disk_read_func = disk_read_hook;
+
+ /* Journal is only for meta data. Data blocks can be read
+ * directly without using block_read
+ */
+ devread (blocknr << INFO->blocksize_shift,
+ blk_offset, to_read, buf);
+
+ disk_read_func = NULL;
+ update_buf_len:
+ len -= to_read;
+ buf += to_read;
+ offset += to_read;
+ filepos += to_read;
+ if (len == 0)
+ goto done;
+ }
+ }
+ get_next_key:
+ next_key ();
+ }
+ done:
+ return errnum ? 0 : buf - prev_buf;
+}
+
+
+/* preconditions: reiserfs_mount already executed, therefore
+ * INFO block is valid
+ * returns: 0 if error, nonzero iff we were able to find the file successfully
+ * postconditions: on a nonzero return, INFO->fileinfo contains the info
+ * of the file we were trying to look up, filepos is 0 and filemax is
+ * the size of the file.
+ */
+int
+reiserfs_dir (char *dirname)
+{
+ struct reiserfs_de_head *de_head;
+ char *rest, ch;
+ __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
+#ifndef STAGE1_5
+ int do_possibilities = 0;
+#endif /* ! STAGE1_5 */
+ char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
+ int link_count = 0;
+ int mode;
+
+ dir_id = REISERFS_ROOT_PARENT_OBJECTID;
+ objectid = REISERFS_ROOT_OBJECTID;
+
+ while (1)
+ {
+#ifdef REISERDEBUG
+ printf ("dirname=%s\n", dirname);
+#endif /* REISERDEBUG */
+
+ /* Search for the stat info first. */
+ if (! search_stat (dir_id, objectid))
+ return 0;
+
+#ifdef REISERDEBUG
+ printf ("sd_mode=%x sd_size=%d\n",
+ ((struct stat_data *) INFO->current_item)->sd_mode,
+ ((struct stat_data *) INFO->current_item)->sd_size);
+#endif /* REISERDEBUG */
+
+ mode = ((struct stat_data *) INFO->current_item)->sd_mode;
+
+ /* If we've got a symbolic link, then chase it. */
+ if (S_ISLNK (mode))
+ {
+ int len;
+ if (++link_count > MAX_LINK_COUNT)
+ {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ }
+
+ /* Get the symlink size. */
+ filemax = ((struct stat_data *) INFO->current_item)->sd_size;
+
+ /* Find out how long our remaining name is. */
+ len = 0;
+ while (dirname[len] && !isspace (dirname[len]))
+ len++;
+
+ if (filemax + len > sizeof (linkbuf) - 1)
+ {
+ errnum = ERR_FILELENGTH;
+ return 0;
+ }
+
+ /* Copy the remaining name to the end of the symlink data.
+ Note that DIRNAME and LINKBUF may overlap! */
+ grub_memmove (linkbuf + filemax, dirname, len+1);
+
+ INFO->fileinfo.k_dir_id = dir_id;
+ INFO->fileinfo.k_objectid = objectid;
+ filepos = 0;
+ if (! next_key ()
+ || reiserfs_read (linkbuf, filemax) != filemax)
+ {
+ if (! errnum)
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+
+#ifdef REISERDEBUG
+ printf ("symlink=%s\n", linkbuf);
+#endif /* REISERDEBUG */
+
+ dirname = linkbuf;
+ if (*dirname == '/')
+ {
+ /* It's an absolute link, so look it up in root. */
+ dir_id = REISERFS_ROOT_PARENT_OBJECTID;
+ objectid = REISERFS_ROOT_OBJECTID;
+ }
+ else
+ {
+ /* Relative, so look it up in our parent directory. */
+ dir_id = parent_dir_id;
+ objectid = parent_objectid;
+ }
+
+ /* Now lookup the new name. */
+ continue;
+ }
+
+ /* if we have a real file (and we're not just printing possibilities),
+ then this is where we want to exit */
+
+ if (! *dirname || isspace (*dirname))
+ {
+ if (! S_ISREG (mode))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ filepos = 0;
+ filemax = ((struct stat_data *) INFO->current_item)->sd_size;
+
+ /* If this is a new stat data and size is > 4GB set filemax to
+ * maximum
+ */
+ if (INFO->current_ih->ih_version == ITEM_VERSION_2
+ && ((struct stat_data *) INFO->current_item)->sd_size_hi > 0)
+ filemax = 0xffffffff;
+
+ INFO->fileinfo.k_dir_id = dir_id;
+ INFO->fileinfo.k_objectid = objectid;
+ return next_key ();
+ }
+
+ /* continue with the file/directory name interpretation */
+ while (*dirname == '/')
+ dirname++;
+ if (! S_ISDIR (mode))
+ {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++);
+ *rest = 0;
+
+# ifndef STAGE1_5
+ if (print_possibilities && ch != '/')
+ do_possibilities = 1;
+# endif /* ! STAGE1_5 */
+
+ while (1)
+ {
+ char *name_end;
+ int num_entries;
+
+ if (! next_key ())
+ return 0;
+#ifdef REISERDEBUG
+ printf ("ih: key %d:%d:%d:%d version:%d\n",
+ INFO->current_ih->ih_key.k_dir_id,
+ INFO->current_ih->ih_key.k_objectid,
+ INFO->current_ih->ih_key.u.v1.k_offset,
+ INFO->current_ih->ih_key.u.v1.k_uniqueness,
+ INFO->current_ih->ih_version);
+#endif /* REISERDEBUG */
+
+ if (INFO->current_ih->ih_key.k_objectid != objectid)
+ break;
+
+ name_end = INFO->current_item + INFO->current_ih->ih_item_len;
+ de_head = (struct reiserfs_de_head *) INFO->current_item;
+ num_entries = INFO->current_ih->u.ih_entry_count;
+ while (num_entries > 0)
+ {
+ char *filename = INFO->current_item + de_head->deh_location;
+ char tmp = *name_end;
+ if ((de_head->deh_state & DEH_Visible))
+ {
+ int cmp;
+ /* Directory names in ReiserFS are not null
+ * terminated. We write a temporary 0 behind it.
+ * NOTE: that this may overwrite the first block in
+ * the tree cache. That doesn't hurt as long as we
+ * don't call next_key () in between.
+ */
+ *name_end = 0;
+ cmp = substring (dirname, filename);
+ *name_end = tmp;
+# ifndef STAGE1_5
+ if (do_possibilities)
+ {
+ if (cmp <= 0)
+ {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ *name_end = 0;
+ print_a_completion (filename);
+ *name_end = tmp;
+ }
+ }
+ else
+# endif /* ! STAGE1_5 */
+ if (cmp == 0)
+ goto found;
+ }
+ /* The beginning of this name marks the end of the next name.
+ */
+ name_end = filename;
+ de_head++;
+ num_entries--;
+ }
+ }
+
+# ifndef STAGE1_5
+ if (print_possibilities < 0)
+ return 1;
+# endif /* ! STAGE1_5 */
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ return 0;
+
+ found:
+
+ *rest = ch;
+ dirname = rest;
+
+ parent_dir_id = dir_id;
+ parent_objectid = objectid;
+ dir_id = de_head->deh_dir_id;
+ objectid = de_head->deh_objectid;
+ }
+}
+
+int
+reiserfs_embed (int *start_sector, int needed_sectors)
+{
+ struct reiserfs_super_block super;
+ int num_sectors;
+
+ if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0,
+ sizeof (struct reiserfs_super_block), (char *) &super))
+ return 0;
+
+ *start_sector = 1; /* reserve first sector for stage1 */
+ if ((substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) <= 0
+ || substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) <= 0)
+ && (/* check that this is not a super block copy inside
+ * the journal log */
+ super.s_journal_block * super.s_blocksize
+ > REISERFS_DISK_OFFSET_IN_BYTES))
+ num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
+ else
+ num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
+
+ return (needed_sectors <= num_sectors);
+}
+#endif /* FSYS_REISERFS */
diff --git a/roms/openbios/fs/grubfs/fsys_ufs.c b/roms/openbios/fs/grubfs/fsys_ufs.c
new file mode 100644
index 00000000..8e0a0f77
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_ufs.c
@@ -0,0 +1,391 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (c) 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (c) 2005 Rink Springer
+ *
+ * This file is based on FreeBSD 5.4-RELEASE's /sys/boot/common/ufsread.c,
+ * and has some minor patches so it'll work with Cromwell/GRUB.
+ *
+ */
+/*-
+ * Copyright (c) 2002 McAfee, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and McAfee Research,, the Security Research Division of
+ * McAfee, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as
+ * part of the DARPA CHATS research program
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 1998 Robert Nordier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+#ifdef FSYS_UFS
+
+#include "asm/types.h"
+
+#include "shared.h"
+#include "filesys.h"
+
+#include "ufs_dinode.h"
+#include "ufs_fs.h"
+
+#ifdef __i386__
+/* XXX: Revert to old (broken for over 1.5Tb filesystems) version of cgbase
+ (see sys/ufs/ffs/fs.h rev 1.39) so that i386 boot loader (boot2) can
+ support both UFS1 and UFS2 again. */
+#undef cgbase
+#define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c)))
+#endif
+
+/*
+ * We use 4k `virtual' blocks for filesystem data, whatever the actual
+ * filesystem block size. FFS blocks are always a multiple of 4k.
+ */
+#define VBLKSHIFT 12
+#define VBLKSIZE (1 << VBLKSHIFT)
+#define VBLKMASK (VBLKSIZE - 1)
+#define DBPERVBLK (VBLKSIZE / DEV_BSIZE)
+#define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize >> VBLKSHIFT))
+#define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize >> VBLKSHIFT))
+#define INO_TO_VBA(fs, ipervblk, x) \
+ (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \
+ (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK))
+#define INO_TO_VBO(ipervblk, x) ((x) % ipervblk)
+#define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
+ ((off) / VBLKSIZE) * DBPERVBLK)
+#define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
+
+/* Buffers that must not span a 64k boundary. */
+struct dmadat {
+ char blkbuf[VBLKSIZE]; /* filesystem blocks */
+ char indbuf[VBLKSIZE]; /* indir blocks */
+ char sbbuf[SBLOCKSIZE]; /* superblock */
+ char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
+};
+static struct dmadat *dmadat = (struct dmadat*)FSYS_BUF;
+
+#define SUPERBLOCK ((struct fs*)dmadat->sbbuf)
+
+ino_t lookup(const char *);
+ssize_t fsread(ino_t, void *, size_t);
+
+static int dsk_meta;
+static uint32_t fs_off;
+static ino_t cur_ino = 0;
+
+static inline int
+dskread (void* buf, unsigned lba, unsigned nblk)
+{
+ return !devread (lba, 0, nblk * DEV_BSIZE, buf) ? -1 : 0;
+}
+
+#if defined(UFS2_ONLY)
+#define DIP(field) dp2.field
+#elif defined(UFS1_ONLY)
+#define DIP(field) dp1.field
+#else
+#define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field
+#endif
+
+static __inline int
+fsfind(const char *name, ino_t * ino)
+{
+ char buf[DEV_BSIZE];
+ struct ufs_dirent *d;
+ char *s;
+ ssize_t n;
+#ifndef UFS2_ONLY
+ static struct ufs1_dinode dp1;
+#endif
+#ifndef UFS1_ONLY
+ static struct ufs2_dinode dp2;
+#endif
+ char* blkbuf = dmadat->blkbuf;
+ struct fs* fs = (struct fs *)dmadat->sbbuf;
+
+ fs_off = 0;
+ while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)
+ for (s = buf; s < buf + DEV_BSIZE;) {
+ d = (void *)s;
+ if (!strcmp(name, d->d_name)) {
+ *ino = d->d_fileno;
+
+ /* below is for grub, which wants the file size
+ */
+ n = IPERVBLK(fs);
+ if (dskread(blkbuf, INO_TO_VBA(fs, n, (*ino)), DBPERVBLK))
+ return -1;
+ n = INO_TO_VBO(n, (*ino));
+#if defined(UFS1_ONLY)
+ dp1 = ((struct ufs1_dinode *)blkbuf)[n];
+#elif defined(UFS2_ONLY)
+ dp2 = ((struct ufs2_dinode *)blkbuf)[n];
+#else
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ dp1 = ((struct ufs1_dinode *)blkbuf)[n];
+ else
+ dp2 = ((struct ufs2_dinode *)blkbuf)[n];
+#endif
+
+ filemax = DIP(di_size);
+ return d->d_type;
+ }
+ s += d->d_reclen;
+ }
+ return 0;
+}
+
+ino_t
+lookup(const char *path)
+{
+ char name[MAXNAMLEN + 1];
+ const char *s;
+ ino_t ino;
+ ssize_t n;
+ int dt;
+
+ ino = ROOTINO;
+ dt = DT_DIR;
+ name[0] = '/';
+ name[1] = '\0';
+ for (;;) {
+ if (*path == '/')
+ path++;
+ if (!*path)
+ break;
+ for (s = path; *s && *s != '/'; s++);
+ if ((n = s - path) > MAXNAMLEN)
+ return 0;
+ memcpy(name, path, n);
+ name[n] = 0;
+ if (dt != DT_DIR) {
+ printk("%s: not a directory.\n", name);
+ return (0);
+ }
+ if ((dt = fsfind(name, &ino)) <= 0)
+ break;
+ path = s;
+ }
+ return dt == DT_REG ? ino : 0;
+}
+
+/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static const int sblock_try[] = SBLOCKSEARCH;
+
+ssize_t
+fsread(ino_t inode, void *buf, size_t nbyte)
+{
+#ifndef UFS2_ONLY
+ static struct ufs1_dinode dp1;
+#endif
+#ifndef UFS1_ONLY
+ static struct ufs2_dinode dp2;
+#endif
+ static ino_t inomap;
+ char *blkbuf;
+ void *indbuf;
+ struct fs *fs;
+ char *s;
+ size_t n, nb, size, off, vboff;
+ ufs_lbn_t lbn;
+ ufs2_daddr_t addr, vbaddr;
+ static ufs2_daddr_t blkmap, indmap;
+ unsigned int u;
+
+
+ blkbuf = dmadat->blkbuf;
+ indbuf = dmadat->indbuf;
+ fs = (struct fs *)dmadat->sbbuf;
+ if (!dsk_meta) {
+ inomap = 0;
+ for (n = 0; sblock_try[n] != -1; n++) {
+ if (dskread(fs, sblock_try[n] / DEV_BSIZE,
+ SBLOCKSIZE / DEV_BSIZE))
+ return -1;
+ if ((
+#if defined(UFS1_ONLY)
+ fs->fs_magic == FS_UFS1_MAGIC
+#elif defined(UFS2_ONLY)
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == sblock_try[n])
+#else
+ fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == sblock_try[n])
+#endif
+ ) &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[n] == -1) {
+ printk("Not ufs\n");
+ return -1;
+ }
+ dsk_meta++;
+ }
+ if (!inode)
+ return 0;
+ if (inomap != inode) {
+ n = IPERVBLK(fs);
+ if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
+ return -1;
+ n = INO_TO_VBO(n, inode);
+#if defined(UFS1_ONLY)
+ dp1 = ((struct ufs1_dinode *)blkbuf)[n];
+#elif defined(UFS2_ONLY)
+ dp2 = ((struct ufs2_dinode *)blkbuf)[n];
+#else
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ dp1 = ((struct ufs1_dinode *)blkbuf)[n];
+ else
+ dp2 = ((struct ufs2_dinode *)blkbuf)[n];
+#endif
+ inomap = inode;
+ fs_off = 0;
+ blkmap = indmap = 0;
+ }
+ s = buf;
+ size = DIP(di_size);
+ n = size - fs_off;
+ if (nbyte > n)
+ nbyte = n;
+ nb = nbyte;
+ while (nb) {
+ lbn = lblkno(fs, fs_off);
+ off = blkoff(fs, fs_off);
+ if (lbn < NDADDR) {
+ addr = DIP(di_db[lbn]);
+ } else if (lbn < NDADDR + NINDIR(fs)) {
+ n = INDIRPERVBLK(fs);
+ addr = DIP(di_ib[0]);
+ u = (unsigned int)(lbn - NDADDR) / (n * DBPERVBLK);
+ vbaddr = fsbtodb(fs, addr) + u;
+ if (indmap != vbaddr) {
+ if (dskread(indbuf, vbaddr, DBPERVBLK))
+ return -1;
+ indmap = vbaddr;
+ }
+ n = (lbn - NDADDR) & (n - 1);
+#if defined(UFS1_ONLY)
+ addr = ((ufs1_daddr_t *)indbuf)[n];
+#elif defined(UFS2_ONLY)
+ addr = ((ufs2_daddr_t *)indbuf)[n];
+#else
+ if (fs->fs_magic == FS_UFS1_MAGIC)
+ addr = ((ufs1_daddr_t *)indbuf)[n];
+ else
+ addr = ((ufs2_daddr_t *)indbuf)[n];
+#endif
+ } else {
+ return -1;
+ }
+ vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;
+ vboff = off & VBLKMASK;
+ n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);
+ if (n > VBLKSIZE)
+ n = VBLKSIZE;
+ if (blkmap != vbaddr) {
+ if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT))
+ return -1;
+ blkmap = vbaddr;
+ }
+ n -= vboff;
+ if (n > nb)
+ n = nb;
+ memcpy(s, blkbuf + vboff, n);
+ s += n;
+ fs_off += n;
+ nb -= n;
+ }
+ return nbyte;
+}
+
+int
+ufs_mount (void)
+{
+ int i, retval = 0;
+
+ /*
+ * We don't care about stuff being in disklabels or not. If the magic
+ * matches, we're good to go.
+ */
+ for (i = 0; sblock_try[i] != -1; ++i)
+ {
+ if (! (part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE))
+ || ! devread (0, sblock_try[i], SBLOCKSIZE, (char *) SUPERBLOCK)))
+ {
+ if (
+#if defined(UFS1_ONLY)
+ SUPERBLOCK->fs_magic == FS_UFS1_MAGIC
+#elif defined(UFS2_ONLY)
+ (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC &&
+ SUPERBLOCK->fs_sblockloc == sblock_try[i])
+#else
+ SUPERBLOCK->fs_magic == FS_UFS1_MAGIC ||
+ (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC &&
+ SUPERBLOCK->fs_sblockloc == sblock_try[i])
+#endif
+ ) {
+ retval = 1; break;
+ }
+ }
+ }
+ return retval;
+}
+
+int
+ufs_read (char *buf, int len)
+{
+ return fsread(cur_ino, buf, len);
+}
+
+int
+ufs_dir (char *dirname)
+{
+ cur_ino = lookup(dirname);
+ return cur_ino & 0xffffffff;
+}
+
+int
+ufs_embed (int* start_sector, int needed_sectors)
+{
+ /* TODO; unused by Cromwell */
+ return 0;
+}
+
+#endif /* FSYS_UFS */
diff --git a/roms/openbios/fs/grubfs/fsys_vstafs.c b/roms/openbios/fs/grubfs/fsys_vstafs.c
new file mode 100644
index 00000000..e06d3e73
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_vstafs.c
@@ -0,0 +1,254 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifdef FSYS_VSTAFS
+
+#include "shared.h"
+#include "filesys.h"
+#include "vstafs.h"
+
+
+static void get_file_info (int sector);
+static struct dir_entry *vstafs_readdir (long sector);
+static struct dir_entry *vstafs_nextdir (void);
+
+
+#define FIRST_SECTOR ((struct first_sector *) FSYS_BUF)
+#define FILE_INFO ((struct fs_file *) (long) FIRST_SECTOR + 8192)
+#define DIRECTORY_BUF ((struct dir_entry *) (long) FILE_INFO + 512)
+
+#define ROOT_SECTOR 1
+
+/*
+ * In f_sector we store the sector number in which the information about
+ * the found file is.
+ */
+static int f_sector;
+
+int
+vstafs_mount (void)
+{
+ int retval = 1;
+
+ if( (((current_drive & 0x80) || (current_slice != 0))
+ && current_slice != PC_SLICE_TYPE_VSTAFS)
+ || ! devread (0, 0, BLOCK_SIZE, (char *) FSYS_BUF)
+ || FIRST_SECTOR->fs_magic != 0xDEADFACE)
+ retval = 0;
+
+ return retval;
+}
+
+static void
+get_file_info (int sector)
+{
+ devread (sector, 0, BLOCK_SIZE, (char *) FILE_INFO);
+}
+
+static int curr_ext, current_direntry, current_blockpos;
+static struct alloc *a1;
+
+static struct dir_entry *
+vstafs_readdir (long sector)
+{
+ /*
+ * Get some information from the current directory
+ */
+ get_file_info (sector);
+ if (FILE_INFO->type != 2)
+ {
+ errnum = ERR_FILE_NOT_FOUND;
+ return NULL;
+ }
+
+ a1 = FILE_INFO->blocks;
+ curr_ext = 0;
+ devread (a1[curr_ext].a_start, 0, 512, (char *) DIRECTORY_BUF);
+ current_direntry = 11;
+ current_blockpos = 0;
+
+ return &DIRECTORY_BUF[10];
+}
+
+static struct dir_entry *
+vstafs_nextdir (void)
+{
+ if (current_direntry > 15)
+ {
+ current_direntry = 0;
+ if (++current_blockpos > (a1[curr_ext].a_len - 1))
+ {
+ current_blockpos = 0;
+ curr_ext++;
+ }
+
+ if (curr_ext < FILE_INFO->extents)
+ {
+ devread (a1[curr_ext].a_start + current_blockpos, 0,
+ 512, (char *) DIRECTORY_BUF);
+ }
+ else
+ {
+ /* errnum =ERR_FILE_NOT_FOUND; */
+ return NULL;
+ }
+ }
+
+ return &DIRECTORY_BUF[current_direntry++];
+}
+
+int
+vstafs_dir (char *dirname)
+{
+ char *fn, ch;
+ struct dir_entry *d;
+ /* int l, i, s; */
+
+ /*
+ * Read in the entries of the current directory.
+ */
+ f_sector = ROOT_SECTOR;
+ do
+ {
+ if (! (d = vstafs_readdir (f_sector)))
+ {
+ return 0;
+ }
+
+ /*
+ * Find the file in the path
+ */
+ while (*dirname == '/') dirname++;
+ fn = dirname;
+ while ((ch = *fn) && ch != '/' && ! isspace (ch)) fn++;
+ *fn = 0;
+
+ do
+ {
+ if (d->name[0] == 0 || d->name[0] & 0x80)
+ continue;
+
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/'
+ && (! *dirname || strcmp (dirname, d->name) <= 0))
+ {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+
+ printf (" %s", d->name);
+ }
+#endif
+ if (! grub_strcmp (dirname, d->name))
+ {
+ f_sector = d->start;
+ get_file_info (f_sector);
+ filemax = FILE_INFO->len;
+ break;
+ }
+ }
+ while ((d =vstafs_nextdir ()));
+
+ *(dirname = fn) = ch;
+ if (! d)
+ {
+ if (print_possibilities < 0)
+ {
+#ifndef STAGE1_5
+ putchar ('\n');
+#endif
+ return 1;
+ }
+
+ errnum = ERR_FILE_NOT_FOUND;
+ return 0;
+ }
+ }
+ while (*dirname && ! isspace (ch));
+
+ return 1;
+}
+
+int
+vstafs_read (char *addr, int len)
+{
+ struct alloc *a2;
+ int size, ret = 0, offset, curr_len = 0;
+ int curr_ext2;
+ char extent;
+ int ext_size;
+ char *curr_pos;
+
+ get_file_info (f_sector);
+ size = FILE_INFO->len-VSTAFS_START_DATA;
+ a2 = FILE_INFO->blocks;
+
+ if (filepos > 0)
+ {
+ if (filepos < a2[0].a_len * 512 - VSTAFS_START_DATA)
+ {
+ offset = filepos + VSTAFS_START_DATA;
+ extent = 0;
+ curr_len = a2[0].a_len * 512 - offset - filepos;
+ }
+ else
+ {
+ ext_size = a2[0].a_len * 512 - VSTAFS_START_DATA;
+ offset = filepos - ext_size;
+ extent = 1;
+ do
+ {
+ curr_len -= ext_size;
+ offset -= ext_size;
+ ext_size = a2[extent+1].a_len * 512;
+ }
+ while (extent < FILE_INFO->extents && offset>ext_size);
+ }
+ }
+ else
+ {
+ offset = VSTAFS_START_DATA;
+ extent = 0;
+ curr_len = a2[0].a_len * 512 - offset;
+ }
+
+ curr_pos = addr;
+ if (curr_len > len)
+ curr_len = len;
+
+ for (curr_ext2=extent;
+ curr_ext2 < FILE_INFO->extents;
+ curr_len = a2[curr_ext].a_len * 512, curr_pos += curr_len, curr_ext2++)
+ {
+ ret += curr_len;
+ size -= curr_len;
+ if (size < 0)
+ {
+ ret += size;
+ curr_len += size;
+ }
+
+ devread (a2[curr_ext2].a_start,offset, curr_len, curr_pos);
+ offset = 0;
+ }
+
+ return ret;
+}
+
+#endif /* FSYS_VSTAFS */
diff --git a/roms/openbios/fs/grubfs/fsys_xfs.c b/roms/openbios/fs/grubfs/fsys_xfs.c
new file mode 100644
index 00000000..b082621c
--- /dev/null
+++ b/roms/openbios/fs/grubfs/fsys_xfs.c
@@ -0,0 +1,639 @@
+/* fsys_xfs.c - an implementation for the SGI XFS file system */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001,2002 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifdef FSYS_XFS
+
+#include "shared.h"
+#include "filesys.h"
+#include "xfs.h"
+
+#define MAX_LINK_COUNT 8
+
+typedef struct xad {
+ xfs_fileoff_t offset;
+ xfs_fsblock_t start;
+ xfs_filblks_t len;
+} xad_t;
+
+struct xfs_info {
+ int bsize;
+ int dirbsize;
+ int isize;
+ unsigned int agblocks;
+ int bdlog;
+ int blklog;
+ int inopblog;
+ int agblklog;
+ int agnolog;
+ unsigned int nextents;
+ xfs_daddr_t next;
+ xfs_daddr_t daddr;
+ xfs_dablk_t forw;
+ xfs_dablk_t dablk;
+ xfs_bmbt_rec_32_t *xt;
+ xfs_bmbt_ptr_t ptr0;
+ int btnode_ptr0_off;
+ int i8param;
+ int dirpos;
+ int dirmax;
+ int blkoff;
+ int fpos;
+ xfs_ino_t rootino;
+};
+
+static struct xfs_info xfs;
+
+#define dirbuf ((char *)FSYS_BUF)
+#define filebuf ((char *)FSYS_BUF + 4096)
+#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192))
+#define icore (inode->di_core)
+
+#define mask32lo(n) (((__uint32_t)1 << (n)) - 1)
+
+#define XFS_INO_MASK(k) ((__uint32_t)((1ULL << (k)) - 1))
+#define XFS_INO_OFFSET_BITS xfs.inopblog
+#define XFS_INO_AGBNO_BITS xfs.agblklog
+#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog)
+#define XFS_INO_AGNO_BITS xfs.agnolog
+
+static inline xfs_agblock_t
+agino2agbno (xfs_agino_t agino)
+{
+ return agino >> XFS_INO_OFFSET_BITS;
+}
+
+static inline xfs_agnumber_t
+ino2agno (xfs_ino_t ino)
+{
+ return ino >> XFS_INO_AGINO_BITS;
+}
+
+static inline xfs_agino_t
+ino2agino (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS);
+}
+
+static inline int
+ino2offset (xfs_ino_t ino)
+{
+ return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS);
+}
+
+static inline __uint16_t
+le16 (__uint16_t x)
+{
+#ifdef __i386__
+ __asm__("xchgb %b0,%h0" \
+ : "=q" (x) \
+ : "0" (x)); \
+ return x;
+#else
+ return __be16_to_cpu(x);
+#endif
+}
+
+static inline __uint32_t
+le32 (__uint32_t x)
+{
+#ifdef __i386__
+#if 1
+ /* 386 doesn't have bswap. So what. */
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+#else
+ /* This is slower but this works on all x86 architectures. */
+ __asm__("xchgb %b0, %h0" \
+ "\n\troll $16, %0" \
+ "\n\txchgb %b0, %h0" \
+ : "=q" (x) : "0" (x));
+#endif
+ return x;
+#else
+ return __be32_to_cpu(x);
+#endif
+}
+
+static inline __uint64_t
+le64 (__uint64_t x)
+{
+ __uint32_t h = x >> 32;
+ __uint32_t l = x & ((1ULL<<32)-1);
+ return (((__uint64_t)le32(l)) << 32) | ((__uint64_t)(le32(h)));
+}
+
+
+static xfs_fsblock_t
+xt_start (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) |
+ (((xfs_fsblock_t)le32 (r->l2)) << 11) |
+ (((xfs_fsblock_t)le32 (r->l3)) >> 21);
+}
+
+static xfs_fileoff_t
+xt_offset (xfs_bmbt_rec_32_t *r)
+{
+ return (((xfs_fileoff_t)le32 (r->l0) &
+ mask32lo(31)) << 23) |
+ (((xfs_fileoff_t)le32 (r->l1)) >> 9);
+}
+
+static xfs_filblks_t
+xt_len (xfs_bmbt_rec_32_t *r)
+{
+ return le32(r->l3) & mask32lo(21);
+}
+
+static inline int
+xfs_highbit32(__uint32_t v)
+{
+ int i;
+
+ if (--v) {
+ for (i = 0; i < 31; i++, v >>= 1) {
+ if (v == 0)
+ return i;
+ }
+ }
+ return 0;
+}
+
+static int
+isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len)
+{
+ return (key >= offset) ? (key < offset + len ? 1 : 0) : 0;
+}
+
+static xfs_daddr_t
+agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno)
+{
+ return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog;
+}
+
+static xfs_daddr_t
+fsb2daddr (xfs_fsblock_t fsbno)
+{
+ return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog),
+ (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog)));
+}
+
+#undef offsetof
+#define offsetof(t,m) ((long)&(((t *)0)->m))
+
+static inline int
+btroot_maxrecs (void)
+{
+ int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize;
+
+ return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t));
+}
+
+static int
+di_read (xfs_ino_t ino)
+{
+ xfs_agino_t agino;
+ xfs_agnumber_t agno;
+ xfs_agblock_t agbno;
+ xfs_daddr_t daddr;
+ int offset;
+
+ agno = ino2agno (ino);
+ agino = ino2agino (ino);
+ agbno = agino2agbno (agino);
+ offset = ino2offset (ino);
+ daddr = agb2daddr (agno, agbno);
+
+ devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode);
+
+ xfs.ptr0 = *(xfs_bmbt_ptr_t *)
+ (inode->di_u.di_c + sizeof(xfs_bmdr_block_t)
+ + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t));
+
+ return 1;
+}
+
+static void
+init_extents (void)
+{
+ xfs_bmbt_ptr_t ptr0;
+ xfs_btree_lblock_t h;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ xfs.xt = inode->di_u.di_bmx;
+ xfs.nextents = le32 (icore.di_nextents);
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ ptr0 = xfs.ptr0;
+ for (;;) {
+ xfs.daddr = fsb2daddr (le64(ptr0));
+ devread (xfs.daddr, 0,
+ sizeof(xfs_btree_lblock_t), (char *)&h);
+ if (!h.bb_level) {
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_rightsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ return;
+ }
+ devread (xfs.daddr, xfs.btnode_ptr0_off,
+ sizeof(xfs_bmbt_ptr_t), (char *)&ptr0);
+ }
+ }
+}
+
+static xad_t *
+next_extent (void)
+{
+ static xad_t xad;
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_EXTENTS:
+ if (xfs.nextents == 0)
+ return NULL;
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ if (xfs.nextents == 0) {
+ xfs_btree_lblock_t h;
+ if (xfs.next == 0)
+ return NULL;
+ xfs.daddr = xfs.next;
+ devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h);
+ xfs.nextents = le16(h.bb_numrecs);
+ xfs.next = fsb2daddr (le64(h.bb_rightsib));
+ xfs.fpos = sizeof(xfs_btree_block_t);
+ }
+ /* Yeah, I know that's slow, but I really don't care */
+ devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf);
+ xfs.xt = (xfs_bmbt_rec_32_t *)filebuf;
+ xfs.fpos += sizeof(xfs_bmbt_rec_32_t);
+ }
+ xad.offset = xt_offset (xfs.xt);
+ xad.start = xt_start (xfs.xt);
+ xad.len = xt_len (xfs.xt);
+ ++xfs.xt;
+ --xfs.nextents;
+
+ return &xad;
+}
+
+/*
+ * Name lies - the function reads only first 100 bytes
+ */
+static void
+xfs_dabread (void)
+{
+ xad_t *xad;
+ xfs_fileoff_t offset;;
+
+ init_extents ();
+ while ((xad = next_extent ())) {
+ offset = xad->offset;
+ if (isinxt (xfs.dablk, offset, xad->len)) {
+ devread (fsb2daddr (xad->start + xfs.dablk - offset),
+ 0, 100, dirbuf);
+ break;
+ }
+ }
+}
+
+static inline xfs_ino_t
+sf_ino (char *sfe, int namelen)
+{
+ void *p = sfe + namelen + 3;
+
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)p) : le32(*(__uint32_t *)p);
+}
+
+static inline xfs_ino_t
+sf_parent_ino (void)
+{
+ return (xfs.i8param == 0)
+ ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent))
+ : le32(*(__uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent));
+}
+
+static inline int
+roundup8 (int n)
+{
+ return ((n+7)&~7);
+}
+
+static char *
+next_dentry (xfs_ino_t *ino)
+{
+ int namelen = 1;
+ int toread;
+ static char *usual[2];
+ static xfs_dir2_sf_entry_t *sfe;
+ char *name;
+
+ if (!usual[0]) {
+ usual[0] = strdup(".");
+ usual[1] = strdup("..");
+ }
+ name = usual[0];
+
+ if (xfs.dirpos >= xfs.dirmax) {
+ if (xfs.forw == 0)
+ return NULL;
+ xfs.dablk = xfs.forw;
+ xfs_dabread ();
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+#undef h
+ xfs.dirpos = 0;
+ }
+
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ switch (xfs.dirpos) {
+ case -2:
+ *ino = 0;
+ break;
+ case -1:
+ *ino = sf_parent_ino ();
+ ++name;
+ ++namelen;
+ sfe = (xfs_dir2_sf_entry_t *)
+ (inode->di_u.di_c
+ + sizeof(xfs_dir2_sf_hdr_t)
+ - xfs.i8param);
+ break;
+ default:
+ namelen = sfe->namelen;
+ *ino = sf_ino ((char *)sfe, namelen);
+ name = (char *)sfe->name;
+ sfe = (xfs_dir2_sf_entry_t *)
+ ((char *)sfe + namelen + 11 - xfs.i8param);
+ }
+ break;
+ case XFS_DINODE_FMT_BTREE:
+ case XFS_DINODE_FMT_EXTENTS:
+#define dau ((xfs_dir2_data_union_t *)dirbuf)
+ for (;;) {
+ if (xfs.blkoff >= xfs.dirbsize) {
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ filepos &= ~(xfs.dirbsize - 1);
+ filepos |= xfs.blkoff;
+ }
+ xfs_read (dirbuf, 4);
+ xfs.blkoff += 4;
+ if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) {
+ toread = roundup8 (le16(dau->unused.length)) - 4;
+ xfs.blkoff += toread;
+ filepos += toread;
+ continue;
+ }
+ break;
+ }
+ xfs_read ((char *)dirbuf + 4, 5);
+ *ino = le64 (dau->entry.inumber);
+ namelen = dau->entry.namelen;
+#undef dau
+ toread = roundup8 (namelen + 11) - 9;
+ xfs_read (dirbuf, toread);
+ name = (char *)dirbuf;
+ xfs.blkoff += toread + 5;
+ }
+ ++xfs.dirpos;
+ name[namelen] = 0;
+
+ return name;
+}
+
+static char *
+first_dentry (xfs_ino_t *ino)
+{
+ xfs.forw = 0;
+ switch (icore.di_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ xfs.dirmax = inode->di_u.di_dir2sf.hdr.count;
+ xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4;
+ xfs.dirpos = -2;
+ break;
+ case XFS_DINODE_FMT_EXTENTS:
+ case XFS_DINODE_FMT_BTREE:
+ filepos = 0;
+ xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t));
+ if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) {
+#define tail ((xfs_dir2_block_tail_t *)dirbuf)
+ filepos = xfs.dirbsize - sizeof(*tail);
+ xfs_read (dirbuf, sizeof(*tail));
+ xfs.dirmax = le32 (tail->count) - le32 (tail->stale);
+#undef tail
+ } else {
+ xfs.dablk = (1ULL << 35) >> xfs.blklog;
+#define h ((xfs_dir2_leaf_hdr_t *)dirbuf)
+#define n ((xfs_da_intnode_t *)dirbuf)
+ for (;;) {
+ xfs_dabread ();
+ if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC))
+ || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) {
+ xfs.dirmax = le16 (h->count) - le16 (h->stale);
+ xfs.forw = le32 (h->info.forw);
+ break;
+ }
+ xfs.dablk = le32 (n->btree[0].before);
+ }
+#undef n
+#undef h
+ }
+ xfs.blkoff = sizeof(xfs_dir2_data_hdr_t);
+ filepos = xfs.blkoff;
+ xfs.dirpos = 0;
+ }
+ return next_dentry (ino);
+}
+
+int
+xfs_mount (void)
+{
+ xfs_sb_t super;
+
+ if (!devread (0, 0, sizeof(super), (char *)&super)
+ || (le32(super.sb_magicnum) != XFS_SB_MAGIC)
+ || ((le16(super.sb_versionnum)
+ & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) {
+ return 0;
+ }
+
+ xfs.bsize = le32 (super.sb_blocksize);
+ xfs.blklog = super.sb_blocklog;
+ xfs.bdlog = xfs.blklog - SECTOR_BITS;
+ xfs.rootino = le64 (super.sb_rootino);
+ xfs.isize = le16 (super.sb_inodesize);
+ xfs.agblocks = le32 (super.sb_agblocks);
+ xfs.dirbsize = xfs.bsize << super.sb_dirblklog;
+
+ xfs.inopblog = super.sb_inopblog;
+ xfs.agblklog = super.sb_agblklog;
+ xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount));
+
+ xfs.btnode_ptr0_off =
+ ((xfs.bsize - sizeof(xfs_btree_block_t)) /
+ (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)))
+ * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t);
+
+ return 1;
+}
+
+int
+xfs_read (char *buf, int len)
+{
+ xad_t *xad;
+ xfs_fileoff_t endofprev, endofcur, offset;
+ xfs_filblks_t xadlen;
+ int toread, startpos, endpos;
+
+ if (icore.di_format == XFS_DINODE_FMT_LOCAL) {
+ grub_memmove (buf, inode->di_u.di_c + filepos, len);
+ filepos += len;
+ return len;
+ }
+
+ startpos = filepos;
+ endpos = filepos + len;
+ endofprev = (xfs_fileoff_t)-1;
+ init_extents ();
+ while (len > 0 && (xad = next_extent ())) {
+ offset = xad->offset;
+ xadlen = xad->len;
+ if (isinxt (filepos >> xfs.blklog, offset, xadlen)) {
+ endofcur = (offset + xadlen) << xfs.blklog;
+ toread = (endofcur >= endpos)
+ ? len : (endofcur - filepos);
+
+ disk_read_func = disk_read_hook;
+ devread (fsb2daddr (xad->start),
+ filepos - (offset << xfs.blklog), toread, buf);
+ disk_read_func = NULL;
+
+ buf += toread;
+ len -= toread;
+ filepos += toread;
+ } else if (offset > endofprev) {
+ toread = ((offset << xfs.blklog) >= endpos)
+ ? len : ((offset - endofprev) << xfs.blklog);
+ len -= toread;
+ filepos += toread;
+ for (; toread; toread--) {
+ *buf++ = 0;
+ }
+ continue;
+ }
+ endofprev = offset + xadlen;
+ }
+
+ return filepos - startpos;
+}
+
+int
+xfs_dir (char *dirname)
+{
+ xfs_ino_t ino, parent_ino, new_ino;
+ xfs_fsize_t di_size;
+ int di_mode;
+ int cmp, n, link_count;
+ char linkbuf[xfs.bsize];
+ char *rest, *name, ch;
+
+ parent_ino = ino = xfs.rootino;
+ link_count = 0;
+ for (;;) {
+ di_read (ino);
+ di_size = le64 (icore.di_size);
+ di_mode = le16 (icore.di_mode);
+
+ if ((di_mode & IFMT) == IFLNK) {
+ if (++link_count > MAX_LINK_COUNT) {
+ errnum = ERR_SYMLINK_LOOP;
+ return 0;
+ }
+ if (di_size < xfs.bsize - 1) {
+ filepos = 0;
+ filemax = di_size;
+ n = xfs_read (linkbuf, filemax);
+ } else {
+ errnum = ERR_FILELENGTH;
+ return 0;
+ }
+
+ ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino;
+ while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++));
+ linkbuf[n] = 0;
+ dirname = linkbuf;
+ continue;
+ }
+
+ if (!*dirname || isspace (*dirname)) {
+ if ((di_mode & IFMT) != IFREG) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+ filepos = 0;
+ filemax = di_size;
+ return 1;
+ }
+
+ if ((di_mode & IFMT) != IFDIR) {
+ errnum = ERR_BAD_FILETYPE;
+ return 0;
+ }
+
+ for (; *dirname == '/'; dirname++);
+
+ for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
+ *rest = 0;
+
+ name = first_dentry (&new_ino);
+ for (;;) {
+ cmp = (!*dirname) ? -1 : substring (dirname, name);
+#ifndef STAGE1_5
+ if (print_possibilities && ch != '/' && cmp <= 0) {
+ if (print_possibilities > 0)
+ print_possibilities = -print_possibilities;
+ print_a_completion (name);
+ } else
+#endif
+ if (cmp == 0) {
+ parent_ino = ino;
+ if (new_ino)
+ ino = new_ino;
+ *(dirname = rest) = ch;
+ break;
+ }
+ name = next_dentry (&new_ino);
+ if (name == NULL) {
+ if (print_possibilities < 0)
+ return 1;
+
+ errnum = ERR_FILE_NOT_FOUND;
+ *rest = ch;
+ return 0;
+ }
+ }
+ }
+}
+
+#endif /* FSYS_XFS */
diff --git a/roms/openbios/fs/grubfs/glue.h b/roms/openbios/fs/grubfs/glue.h
new file mode 100644
index 00000000..7f212937
--- /dev/null
+++ b/roms/openbios/fs/grubfs/glue.h
@@ -0,0 +1,48 @@
+#ifndef __GLUE_H
+#define __GLUE_H
+
+#include "asm/types.h"
+#include "config.h"
+#include "libc/byteorder.h"
+
+typedef uint64_t sector_t;
+
+int devopen(void);
+
+int devread(unsigned long sector, unsigned long byte_offset,
+ unsigned long byte_len, void *buf);
+
+int file_open(const char *filename);
+int file_read(void *buf, unsigned long len);
+int file_seek(unsigned long offset);
+unsigned long file_size(void);
+void file_close(void);
+
+int mount_fs(void);
+
+extern int using_devsize;
+
+/*
+ * some of the filesystem drivers don't correctly provide their
+ * prototypes. we fix this here so we can leave them untouched.
+ */
+
+int ffs_mount (void);
+int ffs_read (char *buf, int len);
+int ffs_dir (char *dirname);
+int ffs_embed (int *start_sector, int needed_sectors);
+
+int vstafs_mount (void);
+int vstafs_dir (char *dirname);
+int vstafs_read (char *addr, int len);
+
+int ntfs_mount (void);
+int ntfs_dir (char *dirname);
+int ntfs_read (char *addr, int len);
+
+int affs_mount (void);
+int affs_dir (char *dirname);
+int affs_read (char *addr, int len);
+
+
+#endif /* FS_H */
diff --git a/roms/openbios/fs/grubfs/grubfs_fs.c b/roms/openbios/fs/grubfs/grubfs_fs.c
new file mode 100644
index 00000000..acd2a644
--- /dev/null
+++ b/roms/openbios/fs/grubfs/grubfs_fs.c
@@ -0,0 +1,398 @@
+/*
+ * /packages/grubfs-files
+ *
+ * grub vfs
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ * Copyright (C) 2004 Samuel Rydh
+ * Copyright (C) 2010 Mark Cave-Ayland
+ *
+ * inspired by HFS code from Samuel Rydh
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "fs/fs.h"
+#include "filesys.h"
+#include "glue.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+
+extern void grubfs_init( void );
+
+/************************************************************************/
+/* grub GLOBALS (horrible... but difficult to fix) */
+/************************************************************************/
+
+/* the grub drivers want these: */
+int filepos;
+int filemax;
+grub_error_t errnum;
+char FSYS_BUF[FSYS_BUFLEN];
+
+/* these are not even used by us, instead
+ * the grub fs drivers want them:
+ */
+int fsmax;
+void (*disk_read_hook) (int, int, int);
+void (*disk_read_func) (int, int, int);
+
+
+/************************************************************************/
+/* filsystem table */
+/************************************************************************/
+
+typedef struct fsys_entry {
+ const char *name;
+ int (*mount_func) (void);
+ int (*read_func) (char *buf, int len);
+ int (*dir_func) (char *dirname);
+ void (*close_func) (void);
+ int (*embed_func) (int *start_sector, int needed_sectors);
+} fsys_entry_t;
+
+static const struct fsys_entry fsys_table[] = {
+# ifdef CONFIG_FSYS_FAT
+ {"fat", fat_mount, fat_read, fat_dir, NULL, NULL},
+# endif
+# ifdef CONFIG_FSYS_EXT2FS
+ {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, NULL, NULL},
+# endif
+# ifdef CONFIG_FSYS_MINIX
+ {"minix", minix_mount, minix_read, minix_dir, NULL, NULL},
+# endif
+# ifdef CONFIG_FSYS_REISERFS
+ {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, NULL, reiserfs_embed},
+# endif
+# ifdef CONFIG_FSYS_JFS
+ {"jfs", jfs_mount, jfs_read, jfs_dir, NULL, jfs_embed},
+# endif
+# ifdef CONFIG_FSYS_XFS
+ {"xfs", xfs_mount, xfs_read, xfs_dir, NULL, NULL},
+# endif
+# ifdef CONFIG_FSYS_UFS
+ {"ufs", ufs_mount, ufs_read, ufs_dir, NULL, ufs_embed},
+# endif
+# ifdef CONFIG_FSYS_ISO9660
+ {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, NULL, NULL},
+# endif
+# ifdef CONFIG_FSYS_NTFS
+ {"ntfs", ntfs_mount, ntfs_read, ntfs_dir, NULL, NULL},
+# endif
+# ifdef CONFIG_FSYS_AFFS
+ {"affs", affs_mount, affs_read, affs_dir, NULL, NULL},
+# endif
+};
+
+/* We don't provide a file search mechanism (yet) */
+typedef struct {
+ unsigned long pos;
+ unsigned long len;
+ const char *path;
+} grubfile_t;
+
+typedef struct {
+ const struct fsys_entry *fsys;
+ grubfile_t *fd;
+ int dev_fd;
+ long long offset; /* Offset added onto each device read; should only ever be non-zero
+ when probing a partition for a filesystem */
+} grubfs_t;
+
+typedef struct {
+ grubfs_t *gfs;
+} grubfs_info_t;
+
+/* Static block and global pointer required for I/O glue */
+static grubfs_t dummy_fs;
+static grubfs_t *curfs = &dummy_fs;
+
+DECLARE_NODE( grubfs, 0, sizeof(grubfs_info_t), "+/packages/grubfs-files" );
+
+
+/************************************************************************/
+/* I/O glue (called by grub source) */
+/************************************************************************/
+
+int
+devread( unsigned long sector, unsigned long byte_offset,
+ unsigned long byte_len, void *buf )
+{
+ long long offs = (long long)sector * 512 + byte_offset;
+
+#ifdef CONFIG_DEBUG_FS
+ //printk("devread s=%x buf=%x, fd=%x\n",sector, buf, curfs->dev_fd);
+#endif
+
+ if( !curfs ) {
+#ifdef CONFIG_DEBUG_FS
+ printk("devread: fsys == NULL!\n");
+#endif
+ return -1;
+ }
+
+ if( seek_io(curfs->dev_fd, offs + curfs->offset) ) {
+#ifdef CONFIG_DEBUG_FS
+ printk("seek failure\n");
+#endif
+ return -1;
+ }
+ return (read_io(curfs->dev_fd, buf, byte_len) == byte_len) ? 1:0;
+}
+
+int
+file_read( void *buf, unsigned long len )
+{
+ if (filepos < 0 || filepos > filemax)
+ filepos = filemax;
+ if (len > filemax-filepos)
+ len = filemax - filepos;
+ errnum = 0;
+ return curfs->fsys->read_func( buf, len );
+}
+
+
+/************************************************************************/
+/* Standard package methods */
+/************************************************************************/
+
+/* ( -- success? ) */
+static void
+grubfs_files_open( grubfs_info_t *mi )
+{
+ int fd, i;
+ char *path = my_args_copy();
+ char *s;
+
+ fd = open_ih( my_parent() );
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ mi->gfs = &dummy_fs;
+
+ for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) {
+#ifdef CONFIG_DEBUG_FS
+ printk("Trying %s\n", fsys_table[i].name);
+#endif
+ if (fsys_table[i].mount_func()) {
+ const fsys_entry_t *fsys = &fsys_table[i];
+#ifdef CONFIG_DEBUG_FS
+ printk("Mounted %s\n", fsys->name);
+#endif
+ mi->gfs = malloc(sizeof(grubfs_t));
+ mi->gfs->fsys = fsys;
+ mi->gfs->dev_fd = fd;
+ mi->gfs->offset = 0;
+
+ s = path;
+ while (*s) {
+ if(*s=='\\') *s='/';
+ s++;
+ }
+#ifdef CONFIG_DEBUG_FS
+ printk("Path=%s\n",path);
+#endif
+ if (!mi->gfs->fsys->dir_func((char *) path)) {
+ forth_printf("File not found\n");
+ RET( 0 );
+ }
+
+ mi->gfs->fd = malloc(sizeof(grubfile_t));
+ mi->gfs->fd->pos = filepos;
+ mi->gfs->fd->len = filemax;
+ mi->gfs->fd->path = strdup(path);
+
+ RET( -1 );
+ }
+ }
+#ifdef CONFIG_DEBUG_FS
+ printk("Unknown filesystem type\n");
+#endif
+
+ RET( 0 );
+}
+
+/* ( -- ) */
+static void
+grubfs_files_close( grubfs_info_t *mi )
+{
+ grubfile_t *gf = mi->gfs->fd;
+
+ if (gf->path)
+ free((void *)(gf->path));
+ free(gf);
+
+ filepos = 0;
+ filemax = 0;
+}
+
+/* ( buf len -- actlen ) */
+static void
+grubfs_files_read( grubfs_info_t *mi )
+{
+ int count = POP();
+ char *buf = (char *)cell2pointer(POP());
+
+ grubfile_t *file = mi->gfs->fd;
+ int ret;
+
+ filepos = file->pos;
+ filemax = file->len;
+
+ if (count > filemax - filepos)
+ count = filemax - filepos;
+
+ ret = mi->gfs->fsys->read_func(buf, count);
+
+ file->pos = filepos;
+
+ RET( ret );
+}
+
+/* ( pos.d -- status ) */
+static void
+grubfs_files_seek( grubfs_info_t *mi )
+{
+ long long pos = DPOP();
+ int offs = (int)pos;
+ int whence = SEEK_SET;
+
+ grubfile_t *file = mi->gfs->fd;
+ unsigned long newpos;
+
+ switch( whence ) {
+ case SEEK_END:
+ if (offs < 0 && (unsigned long) -offs > file->len)
+ newpos = 0;
+ else
+ newpos = file->len + offs;
+ break;
+ default:
+ case SEEK_SET:
+ newpos = (offs < 0) ? 0 : offs;
+ break;
+ }
+
+ if (newpos > file->len)
+ newpos = file->len;
+
+ file->pos = newpos;
+
+ if (newpos)
+ RET( -1 );
+ else
+ RET( 0 );
+}
+
+/* ( addr -- size ) */
+static void
+grubfs_files_load( grubfs_info_t *mi )
+{
+ char *buf = (char *)cell2pointer(POP());
+ int count, ret;
+
+ grubfile_t *file = mi->gfs->fd;
+ count = file->len;
+
+ ret = mi->gfs->fsys->read_func(buf, count);
+ file->pos = filepos;
+
+ RET( ret );
+}
+
+/* ( -- cstr ) */
+static void
+grubfs_files_get_path( grubfs_info_t *mi )
+{
+ grubfile_t *file = mi->gfs->fd;
+ const char *path = file->path;
+
+ RET( pointer2cell(strdup(path)) );
+}
+
+/* ( -- cstr ) */
+static void
+grubfs_files_get_fstype( grubfs_info_t *mi )
+{
+ grubfs_t *gfs = mi->gfs;
+
+ PUSH( pointer2cell(strdup(gfs->fsys->name)) );
+}
+
+
+/* static method, ( pos.d ih -- flag? ) */
+static void
+grubfs_files_probe( grubfs_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ long long offs = DPOP();
+ int i;
+
+ curfs->dev_fd = open_ih(ih);
+ if (curfs->dev_fd == -1) {
+ RET( -1 );
+ }
+ curfs->offset = offs;
+
+ for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) {
+#ifdef CONFIG_DEBUG_FS
+ printk("Probing for %s\n", fsys_table[i].name);
+#endif
+ if (fsys_table[i].mount_func()) {
+ RET( -1 );
+ }
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ printk("Unknown filesystem type\n");
+#endif
+
+ close_io(curfs->dev_fd);
+
+ RET ( 0 );
+}
+
+/* static method, ( pathstr len ihandle -- ) */
+static void
+grubfs_files_dir( grubfs_info_t *dummy )
+{
+ forth_printf("dir method not implemented for grubfs filesystem\n");
+ POP();
+ POP();
+ POP();
+}
+
+static void
+grubfs_initializer( grubfs_info_t *dummy )
+{
+ fword("register-fs-package");
+}
+
+NODE_METHODS( grubfs ) = {
+ { "probe", grubfs_files_probe },
+ { "open", grubfs_files_open },
+ { "close", grubfs_files_close },
+ { "read", grubfs_files_read },
+ { "seek", grubfs_files_seek },
+ { "load", grubfs_files_load },
+ { "dir", grubfs_files_dir },
+
+ /* special */
+ { "get-path", grubfs_files_get_path },
+ { "get-fstype", grubfs_files_get_fstype },
+
+ { NULL, grubfs_initializer },
+};
+
+void
+grubfs_init( void )
+{
+ REGISTER_NODE( grubfs );
+}
diff --git a/roms/openbios/fs/grubfs/iso9660.h b/roms/openbios/fs/grubfs/iso9660.h
new file mode 100644
index 00000000..6423a8f6
--- /dev/null
+++ b/roms/openbios/fs/grubfs/iso9660.h
@@ -0,0 +1,167 @@
+/*
+ * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
+ * including Rock Ridge Extensions support
+ *
+ * Copyright (C) 1998, 1999 Kousuke Takai <tak@kmc.kyoto-u.ac.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+/*
+ * References:
+ * linux/fs/isofs/rock.[ch]
+ * mkisofs-1.11.1/diag/isoinfo.c
+ * mkisofs-1.11.1/iso9660.h
+ * (all are written by Eric Youngdale)
+ */
+
+/*
+ * Modified by SONE Takeshi to work with FILO
+ */
+
+#ifndef _ISO9660_H_
+#define _ISO9660_H_
+
+#define ISO_SECTOR_BITS (11)
+#define ISO_SECTOR_SIZE (1<<ISO_SECTOR_BITS)
+
+#define ISO_REGULAR 1 /* regular file */
+#define ISO_DIRECTORY 2 /* directory */
+#define ISO_OTHER 0 /* other file (with Rock Ridge) */
+
+#define RR_FLAG_PX 0x01 /* have POSIX file attributes */
+#define RR_FLAG_NM 0x08 /* have alternate file name */
+
+/* POSIX file attributes for Rock Ridge extensions */
+#define POSIX_S_IFMT 0xF000
+#define POSIX_S_IFREG 0x8000
+#define POSIX_S_IFDIR 0x4000
+
+/* volume descriptor types */
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+#ifndef ASM_FILE
+
+typedef union {
+ uint8_t l,b;
+} iso_8bit_t;
+
+typedef struct __iso_16bit {
+ uint16_t l, b;
+} iso_16bit_t;
+
+typedef struct __iso_32bit {
+ uint32_t l, b;
+} iso_32bit_t;
+
+typedef uint8_t iso_date_t[7];
+
+struct iso_directory_record {
+ iso_8bit_t length;
+ iso_8bit_t ext_attr_length;
+ iso_32bit_t extent;
+ iso_32bit_t size;
+ iso_date_t date;
+ iso_8bit_t flags;
+ iso_8bit_t file_unit_size;
+ iso_8bit_t interleave;
+ iso_16bit_t volume_seq_number;
+ iso_8bit_t name_len;
+ uint8_t name[1];
+} __attribute__ ((packed));
+
+struct iso_primary_descriptor {
+ iso_8bit_t type;
+ uint8_t id[5];
+ iso_8bit_t version;
+ uint8_t _unused1[1];
+ uint8_t system_id[32];
+ uint8_t volume_id[32];
+ uint8_t _unused2[8];
+ iso_32bit_t volume_space_size;
+ uint8_t _unused3[32];
+ iso_16bit_t volume_set_size;
+ iso_16bit_t volume_seq_number;
+ iso_16bit_t logical_block_size;
+ iso_32bit_t path_table_size;
+ uint8_t type_l_path_table[4];
+ uint8_t opt_type_l_path_table[4];
+ uint8_t type_m_path_table[4];
+ uint8_t opt_type_m_path_table[4];
+ struct iso_directory_record root_directory_record;
+ uint8_t volume_set_id[128];
+ uint8_t publisher_id[128];
+ uint8_t preparer_id[128];
+ uint8_t application_id[128];
+ uint8_t copyright_file_id[37];
+ uint8_t abstract_file_id[37];
+ uint8_t bibliographic_file_id[37];
+ uint8_t creation_date[17];
+ uint8_t modification_date[17];
+ uint8_t expiration_date[17];
+ uint8_t effective_date[17];
+ iso_8bit_t file_structure_version;
+ uint8_t _unused4[1];
+ uint8_t application_data[512];
+ uint8_t _unused5[653];
+} __attribute__ ((packed));
+
+struct rock_ridge {
+ uint16_t signature;
+ uint8_t len;
+ uint8_t version;
+ union {
+ struct CE {
+ iso_32bit_t extent;
+ iso_32bit_t offset;
+ iso_32bit_t size;
+ } ce;
+ struct NM {
+ iso_8bit_t flags;
+ uint8_t name[0];
+ } nm;
+ struct PX {
+ iso_32bit_t mode;
+ iso_32bit_t nlink;
+ iso_32bit_t uid;
+ iso_32bit_t gid;
+ } px;
+ struct RR {
+ iso_8bit_t flags;
+ } rr;
+ } u;
+} __attribute__ ((packed));
+
+typedef union RR_ptr {
+ struct rock_ridge *rr;
+ char *ptr;
+ int i;
+} RR_ptr_t;
+
+#define CHECK2(ptr, c1, c2) \
+ (*(unsigned char *)(ptr) == (c1) && \
+ *((unsigned char *)(ptr) + 1) == (c2))
+#define CHECK4(ptr, c1, c2, c3, c4) \
+ (*(unsigned char *)(ptr) == (c1) && \
+ *((unsigned char *)(ptr) + 1) == (c2) && \
+ *((unsigned char *)(ptr) + 2) == (c3) && \
+ *((unsigned char *)(ptr) + 3) == (c4))
+
+#endif /* !ASM_FILE */
+
+#endif /* _ISO9660_H_ */
diff --git a/roms/openbios/fs/grubfs/jfs.h b/roms/openbios/fs/grubfs/jfs.h
new file mode 100644
index 00000000..afe7263d
--- /dev/null
+++ b/roms/openbios/fs/grubfs/jfs.h
@@ -0,0 +1,604 @@
+/* jfs.h - an extractions from linux/include/linux/jfs/jfs* into one file */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 International Business Machines Corp.
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef _JFS_H_
+#define _JFS_H_
+
+/* those are from jfs_filsys.h */
+
+/*
+ * file system option (superblock flag)
+ */
+/* platform option (conditional compilation) */
+#define JFS_AIX 0x80000000 /* AIX support */
+/* POSIX name/directory support */
+
+#define JFS_OS2 0x40000000 /* OS/2 support */
+/* case-insensitive name/directory support */
+
+#define JFS_LINUX 0x10000000 /* Linux support */
+/* case-sensitive name/directory support */
+
+/* directory option */
+#define JFS_UNICODE 0x00000001 /* unicode name */
+
+/* bba */
+#define JFS_SWAP_BYTES 0x00100000 /* running on big endian computer */
+
+
+/*
+ * buffer cache configuration
+ */
+/* page size */
+#ifdef PSIZE
+#undef PSIZE
+#endif
+#define PSIZE 4096 /* page size (in byte) */
+
+/*
+ * fs fundamental size
+ *
+ * PSIZE >= file system block size >= PBSIZE >= DISIZE
+ */
+#define PBSIZE 512 /* physical block size (in byte) */
+#define DISIZE 512 /* on-disk inode size (in byte) */
+#define L2DISIZE 9
+#define INOSPERIAG 4096 /* number of disk inodes per iag */
+#define L2INOSPERIAG 12
+#define INOSPEREXT 32 /* number of disk inode per extent */
+#define L2INOSPEREXT 5
+
+/* Minimum number of bytes supported for a JFS partition */
+#define MINJFS (0x1000000)
+
+/*
+ * fixed byte offset address
+ */
+#define SUPER1_OFF 0x8000 /* primary superblock */
+
+#define AITBL_OFF (SUPER1_OFF + PSIZE + (PSIZE << 1))
+
+/*
+ * fixed reserved inode number
+ */
+/* aggregate inode */
+#define AGGREGATE_I 1 /* aggregate inode map inode */
+#define FILESYSTEM_I 16 /* 1st/only fileset inode in ait:
+ * fileset inode map inode
+ */
+
+/* per fileset inode */
+#define ROOT_I 2 /* fileset root inode */
+
+/*
+ * directory configuration
+ */
+#define JFS_NAME_MAX 255
+#define JFS_PATH_MAX PSIZE
+
+#if 0
+typedef unsigned char u8;
+typedef char s8;
+typedef unsigned short u16;
+typedef short s16;
+typedef unsigned int u32;
+typedef int s32;
+typedef unsigned long long u64;
+typedef long long s64;
+#endif
+
+typedef u16 UniChar;
+
+/* these from jfs_btree.h */
+
+/* btpaget_t flag */
+#define BT_TYPE 0x07 /* B+-tree index */
+#define BT_ROOT 0x01 /* root page */
+#define BT_LEAF 0x02 /* leaf page */
+#define BT_INTERNAL 0x04 /* internal page */
+#define BT_RIGHTMOST 0x10 /* rightmost page */
+#define BT_LEFTMOST 0x20 /* leftmost page */
+
+/* those are from jfs_types.h */
+
+struct timestruc_t {
+ u32 tv_sec;
+ u32 tv_nsec;
+};
+
+/*
+ * physical xd (pxd)
+ */
+typedef struct {
+ unsigned len:24;
+ unsigned addr1:8;
+ u32 addr2;
+} pxd_t;
+
+/* xd_t field extraction */
+#define lengthPXD(pxd) ((pxd)->len)
+#define addressPXD(pxd) (((s64)((pxd)->addr1)) << 32 | ((pxd)->addr2))
+
+/*
+ * data extent descriptor (dxd)
+ */
+typedef struct {
+ unsigned flag:8; /* 1: flags */
+ unsigned rsrvd:24; /* 3: */
+ u32 size; /* 4: size in byte */
+ unsigned len:24; /* 3: length in unit of fsblksize */
+ unsigned addr1:8; /* 1: address in unit of fsblksize */
+ u32 addr2; /* 4: address in unit of fsblksize */
+} dxd_t; /* - 16 - */
+
+/*
+ * DASD limit information - stored in directory inode
+ */
+typedef struct dasd {
+ u8 thresh; /* Alert Threshold (in percent) */
+ u8 delta; /* Alert Threshold delta (in percent) */
+ u8 rsrvd1;
+ u8 limit_hi; /* DASD limit (in logical blocks) */
+ u32 limit_lo; /* DASD limit (in logical blocks) */
+ u8 rsrvd2[3];
+ u8 used_hi; /* DASD usage (in logical blocks) */
+ u32 used_lo; /* DASD usage (in logical blocks) */
+} dasd_t;
+
+
+/* from jfs_superblock.h */
+
+#define JFS_MAGIC 0x3153464A /* "JFS1" */
+
+struct jfs_superblock
+{
+ u32 s_magic; /* 4: magic number */
+ u32 s_version; /* 4: version number */
+
+ s64 s_size; /* 8: aggregate size in hardware/LVM blocks;
+ * VFS: number of blocks
+ */
+ s32 s_bsize; /* 4: aggregate block size in bytes;
+ * VFS: fragment size
+ */
+ s16 s_l2bsize; /* 2: log2 of s_bsize */
+ s16 s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */
+ s32 s_pbsize; /* 4: hardware/LVM block size in bytes */
+ s16 s_l2pbsize; /* 2: log2 of s_pbsize */
+ s16 pad; /* 2: padding necessary for alignment */
+
+ u32 s_agsize; /* 4: allocation group size in aggr. blocks */
+
+ u32 s_flag; /* 4: aggregate attributes:
+ * see jfs_filsys.h
+ */
+ u32 s_state; /* 4: mount/unmount/recovery state:
+ * see jfs_filsys.h
+ */
+ s32 s_compress; /* 4: > 0 if data compression */
+
+ pxd_t s_ait2; /* 8: first extent of secondary
+ * aggregate inode table
+ */
+
+ pxd_t s_aim2; /* 8: first extent of secondary
+ * aggregate inode map
+ */
+ u32 s_logdev; /* 4: device address of log */
+ s32 s_logserial; /* 4: log serial number at aggregate mount */
+ pxd_t s_logpxd; /* 8: inline log extent */
+
+ pxd_t s_fsckpxd; /* 8: inline fsck work space extent */
+
+ struct timestruc_t s_time; /* 8: time last updated */
+
+ s32 s_fsckloglen; /* 4: Number of filesystem blocks reserved for
+ * the fsck service log.
+ * N.B. These blocks are divided among the
+ * versions kept. This is not a per
+ * version size.
+ * N.B. These blocks are included in the
+ * length field of s_fsckpxd.
+ */
+ s8 s_fscklog; /* 1: which fsck service log is most recent
+ * 0 => no service log data yet
+ * 1 => the first one
+ * 2 => the 2nd one
+ */
+ char s_fpack[11]; /* 11: file system volume name
+ * N.B. This must be 11 bytes to
+ * conform with the OS/2 BootSector
+ * requirements
+ */
+
+ /* extendfs() parameter under s_state & FM_EXTENDFS */
+ s64 s_xsize; /* 8: extendfs s_size */
+ pxd_t s_xfsckpxd; /* 8: extendfs fsckpxd */
+ pxd_t s_xlogpxd; /* 8: extendfs logpxd */
+ /* - 128 byte boundary - */
+
+ /*
+ * DFS VFS support (preliminary)
+ */
+ char s_attach; /* 1: VFS: flag: set when aggregate is attached
+ */
+ u8 rsrvd4[7]; /* 7: reserved - set to 0 */
+
+ u64 totalUsable; /* 8: VFS: total of 1K blocks which are
+ * available to "normal" (non-root) users.
+ */
+ u64 minFree; /* 8: VFS: # of 1K blocks held in reserve for
+ * exclusive use of root. This value can be 0,
+ * and if it is then totalUsable will be equal
+ * to # of blocks in aggregate. I believe this
+ * means that minFree + totalUsable = # blocks.
+ * In that case, we don't need to store both
+ * totalUsable and minFree since we can compute
+ * one from the other. I would guess minFree
+ * would be the one we should store, and
+ * totalUsable would be the one we should
+ * compute. (Just a guess...)
+ */
+
+ u64 realFree; /* 8: VFS: # of free 1K blocks can be used by
+ * "normal" users. It may be this is something
+ * we should compute when asked for instead of
+ * storing in the superblock. I don't know how
+ * often this information is needed.
+ */
+ /*
+ * graffiti area
+ */
+};
+
+/* from jfs_dtree.h */
+
+/*
+ * entry segment/slot
+ *
+ * an entry consists of type dependent head/only segment/slot and
+ * additional segments/slots linked vi next field;
+ * N.B. last/only segment of entry is terminated by next = -1;
+ */
+/*
+ * directory page slot
+ */
+typedef struct {
+ s8 next; /* 1: */
+ s8 cnt; /* 1: */
+ UniChar name[15]; /* 30: */
+} dtslot_t; /* (32) */
+
+#define DTSLOTDATALEN 15
+
+/*
+ * internal node entry head/only segment
+ */
+typedef struct {
+ pxd_t xd; /* 8: child extent descriptor */
+
+ s8 next; /* 1: */
+ u8 namlen; /* 1: */
+ UniChar name[11]; /* 22: 2-byte aligned */
+} idtentry_t; /* (32) */
+
+/*
+ * leaf node entry head/only segment
+ *
+ * For legacy filesystems, name contains 13 unichars -- no index field
+ */
+typedef struct {
+ u32 inumber; /* 4: 4-byte aligned */
+ s8 next; /* 1: */
+ u8 namlen; /* 1: */
+ UniChar name[11]; /* 22: 2-byte aligned */
+ u32 index; /* 4: index into dir_table */
+} ldtentry_t; /* (32) */
+
+#define DTLHDRDATALEN 11
+
+/*
+ * dir_table used for directory traversal during readdir
+*/
+
+/*
+ * Maximum entry in inline directory table
+ */
+
+typedef struct dir_table_slot {
+ u8 rsrvd; /* 1: */
+ u8 flag; /* 1: 0 if free */
+ u8 slot; /* 1: slot within leaf page of entry */
+ u8 addr1; /* 1: upper 8 bits of leaf page address */
+ u32 addr2; /* 4: lower 32 bits of leaf page address -OR-
+ index of next entry when this entry was deleted */
+} dir_table_slot_t; /* (8) */
+
+/*
+ * directory root page (in-line in on-disk inode):
+ *
+ * cf. dtpage_t below.
+ */
+typedef union {
+ struct {
+ dasd_t DASD; /* 16: DASD limit/usage info F226941 */
+
+ u8 flag; /* 1: */
+ s8 nextindex; /* 1: next free entry in stbl */
+ s8 freecnt; /* 1: free count */
+ s8 freelist; /* 1: freelist header */
+
+ u32 idotdot; /* 4: parent inode number */
+
+ s8 stbl[8]; /* 8: sorted entry index table */
+ } header; /* (32) */
+
+ dtslot_t slot[9];
+} dtroot_t;
+
+/*
+ * directory regular page:
+ *
+ * entry slot array of 32 byte slot
+ *
+ * sorted entry slot index table (stbl):
+ * contiguous slots at slot specified by stblindex,
+ * 1-byte per entry
+ * 512 byte block: 16 entry tbl (1 slot)
+ * 1024 byte block: 32 entry tbl (1 slot)
+ * 2048 byte block: 64 entry tbl (2 slot)
+ * 4096 byte block: 128 entry tbl (4 slot)
+ *
+ * data area:
+ * 512 byte block: 16 - 2 = 14 slot
+ * 1024 byte block: 32 - 2 = 30 slot
+ * 2048 byte block: 64 - 3 = 61 slot
+ * 4096 byte block: 128 - 5 = 123 slot
+ *
+ * N.B. index is 0-based; index fields refer to slot index
+ * except nextindex which refers to entry index in stbl;
+ * end of entry stot list or freelist is marked with -1.
+ */
+typedef union {
+ struct {
+ s64 next; /* 8: next sibling */
+ s64 prev; /* 8: previous sibling */
+
+ u8 flag; /* 1: */
+ s8 nextindex; /* 1: next entry index in stbl */
+ s8 freecnt; /* 1: */
+ s8 freelist; /* 1: slot index of head of freelist */
+
+ u8 maxslot; /* 1: number of slots in page slot[] */
+ s8 stblindex; /* 1: slot index of start of stbl */
+ u8 rsrvd[2]; /* 2: */
+
+ pxd_t self; /* 8: self pxd */
+ } header; /* (32) */
+
+ dtslot_t slot[128];
+} dtpage_t;
+
+/* from jfs_xtree.h */
+
+/*
+ * extent allocation descriptor (xad)
+ */
+typedef struct xad {
+ unsigned flag:8; /* 1: flag */
+ unsigned rsvrd:16; /* 2: reserved */
+ unsigned off1:8; /* 1: offset in unit of fsblksize */
+ u32 off2; /* 4: offset in unit of fsblksize */
+ unsigned len:24; /* 3: length in unit of fsblksize */
+ unsigned addr1:8; /* 1: address in unit of fsblksize */
+ u32 addr2; /* 4: address in unit of fsblksize */
+} xad_t; /* (16) */
+
+/* xad_t field extraction */
+#define offsetXAD(xad) (((s64)((xad)->off1)) << 32 | ((xad)->off2))
+#define addressXAD(xad) (((s64)((xad)->addr1)) << 32 | ((xad)->addr2))
+#define lengthXAD(xad) ((xad)->len)
+
+/* possible values for maxentry */
+#define XTPAGEMAXSLOT 256
+#define XTENTRYSTART 2
+
+/*
+ * xtree page:
+ */
+typedef union {
+ struct xtheader {
+ s64 next; /* 8: */
+ s64 prev; /* 8: */
+
+ u8 flag; /* 1: */
+ u8 rsrvd1; /* 1: */
+ s16 nextindex; /* 2: next index = number of entries */
+ s16 maxentry; /* 2: max number of entries */
+ s16 rsrvd2; /* 2: */
+
+ pxd_t self; /* 8: self */
+ } header; /* (32) */
+
+ xad_t xad[XTPAGEMAXSLOT]; /* 16 * maxentry: xad array */
+} xtpage_t;
+
+/* from jfs_dinode.h */
+
+struct dinode {
+ /*
+ * I. base area (128 bytes)
+ * ------------------------
+ *
+ * define generic/POSIX attributes
+ */
+ u32 di_inostamp; /* 4: stamp to show inode belongs to fileset */
+ s32 di_fileset; /* 4: fileset number */
+ u32 di_number; /* 4: inode number, aka file serial number */
+ u32 di_gen; /* 4: inode generation number */
+
+ pxd_t di_ixpxd; /* 8: inode extent descriptor */
+
+ s64 di_size; /* 8: size */
+ s64 di_nblocks; /* 8: number of blocks allocated */
+
+ u32 di_nlink; /* 4: number of links to the object */
+
+ u32 di_uid; /* 4: user id of owner */
+ u32 di_gid; /* 4: group id of owner */
+
+ u32 di_mode; /* 4: attribute, format and permission */
+
+ struct timestruc_t di_atime; /* 8: time last data accessed */
+ struct timestruc_t di_ctime; /* 8: time last status changed */
+ struct timestruc_t di_mtime; /* 8: time last data modified */
+ struct timestruc_t di_otime; /* 8: time created */
+
+ dxd_t di_acl; /* 16: acl descriptor */
+
+ dxd_t di_ea; /* 16: ea descriptor */
+
+ s32 di_next_index; /* 4: Next available dir_table index */
+
+ s32 di_acltype; /* 4: Type of ACL */
+
+ /*
+ * Extension Areas.
+ *
+ * Historically, the inode was partitioned into 4 128-byte areas,
+ * the last 3 being defined as unions which could have multiple
+ * uses. The first 96 bytes had been completely unused until
+ * an index table was added to the directory. It is now more
+ * useful to describe the last 3/4 of the inode as a single
+ * union. We would probably be better off redesigning the
+ * entire structure from scratch, but we don't want to break
+ * commonality with OS/2's JFS at this time.
+ */
+ union {
+ struct {
+ /*
+ * This table contains the information needed to
+ * find a directory entry from a 32-bit index.
+ * If the index is small enough, the table is inline,
+ * otherwise, an x-tree root overlays this table
+ */
+ dir_table_slot_t _table[12]; /* 96: inline */
+
+ dtroot_t _dtroot; /* 288: dtree root */
+ } _dir; /* (384) */
+#define di_dirtable u._dir._table
+#define di_dtroot u._dir._dtroot
+#define di_parent di_dtroot.header.idotdot
+#define di_DASD di_dtroot.header.DASD
+
+ struct {
+ union {
+ u8 _data[96]; /* 96: unused */
+ struct {
+ void *_imap; /* 4: unused */
+ u32 _gengen; /* 4: generator */
+ } _imap;
+ } _u1; /* 96: */
+#define di_gengen u._file._u1._imap._gengen
+
+ union {
+ xtpage_t _xtroot;
+ struct {
+ u8 unused[16]; /* 16: */
+ dxd_t _dxd; /* 16: */
+ union {
+ u32 _rdev; /* 4: */
+ u8 _fastsymlink[128];
+ } _u;
+ u8 _inlineea[128];
+ } _special;
+ } _u2;
+ } _file;
+#define di_xtroot u._file._u2._xtroot
+#define di_dxd u._file._u2._special._dxd
+#define di_btroot di_xtroot
+#define di_inlinedata u._file._u2._special._u
+#define di_rdev u._file._u2._special._u._rdev
+#define di_fastsymlink u._file._u2._special._u._fastsymlink
+#define di_inlineea u._file._u2._special._inlineea
+ } u;
+};
+
+typedef struct dinode dinode_t;
+
+/* di_mode */
+#define IFMT 0xF000 /* S_IFMT - mask of file type */
+#define IFDIR 0x4000 /* S_IFDIR - directory */
+#define IFREG 0x8000 /* S_IFREG - regular file */
+#define IFLNK 0xA000 /* S_IFLNK - symbolic link */
+
+/* extended mode bits (on-disk inode di_mode) */
+#define INLINEEA 0x00040000 /* inline EA area free */
+
+/* from jfs_imap.h */
+
+#define EXTSPERIAG 128 /* number of disk inode extent per iag */
+#define SMAPSZ 4 /* number of words per summary map */
+#define MAXAG 128 /* maximum number of allocation groups */
+
+/*
+ * inode allocation map:
+ *
+ * inode allocation map consists of
+ * . the inode map control page and
+ * . inode allocation group pages (per 4096 inodes)
+ * which are addressed by standard JFS xtree.
+ */
+/*
+ * inode allocation group page (per 4096 inodes of an AG)
+ */
+typedef struct {
+ s64 agstart; /* 8: starting block of ag */
+ s32 iagnum; /* 4: inode allocation group number */
+ s32 inofreefwd; /* 4: ag inode free list forward */
+ s32 inofreeback; /* 4: ag inode free list back */
+ s32 extfreefwd; /* 4: ag inode extent free list forward */
+ s32 extfreeback; /* 4: ag inode extent free list back */
+ s32 iagfree; /* 4: iag free list */
+
+ /* summary map: 1 bit per inode extent */
+ s32 inosmap[SMAPSZ]; /* 16: sum map of mapwords w/ free inodes;
+ * note: this indicates free and backed
+ * inodes, if the extent is not backed the
+ * value will be 1. if the extent is
+ * backed but all inodes are being used the
+ * value will be 1. if the extent is
+ * backed but at least one of the inodes is
+ * free the value will be 0.
+ */
+ s32 extsmap[SMAPSZ]; /* 16: sum map of mapwords w/ free extents */
+ s32 nfreeinos; /* 4: number of free inodes */
+ s32 nfreeexts; /* 4: number of free extents */
+ /* (72) */
+ u8 pad[1976]; /* 1976: pad to 2048 bytes */
+ /* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */
+ u32 wmap[EXTSPERIAG]; /* 512: working allocation map */
+ u32 pmap[EXTSPERIAG]; /* 512: persistent allocation map */
+ pxd_t inoext[EXTSPERIAG]; /* 1024: inode extent addresses */
+} iag_t; /* (4096) */
+
+#endif /* _JFS_H_ */
diff --git a/roms/openbios/fs/grubfs/shared.h b/roms/openbios/fs/grubfs/shared.h
new file mode 100644
index 00000000..b3034e03
--- /dev/null
+++ b/roms/openbios/fs/grubfs/shared.h
@@ -0,0 +1,3 @@
+/* Sorry, nothing is shared here ;) Just for GRUB compatibility. */
+
+#include "glue.h"
diff --git a/roms/openbios/fs/grubfs/ufs_dinode.h b/roms/openbios/fs/grubfs/ufs_dinode.h
new file mode 100644
index 00000000..f3f7fca0
--- /dev/null
+++ b/roms/openbios/fs/grubfs/ufs_dinode.h
@@ -0,0 +1,191 @@
+/*-
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)dinode.h 8.3 (Berkeley) 1/21/94
+ * $FreeBSD: src/sys/ufs/ufs/dinode.h,v 1.13.2.1 2005/01/31 23:27:01 imp Exp $
+ */
+
+#ifndef _UFS_UFS_DINODE_H_
+#define _UFS_UFS_DINODE_H_
+
+/*
+ * The root inode is the root of the filesystem. Inode 0 can't be used for
+ * normal purposes and historically bad blocks were linked to inode 1, thus
+ * the root inode is 2. (Inode 1 is no longer used for this purpose, however
+ * numerous dump tapes make this assumption, so we are stuck with it).
+ */
+#define ROOTINO ((ino_t)2)
+
+/*
+ * The Whiteout inode# is a dummy non-zero inode number which will
+ * never be allocated to a real file. It is used as a place holder
+ * in the directory entry which has been tagged as a DT_W entry.
+ * See the comments about ROOTINO above.
+ */
+#define WINO ((ino_t)1)
+
+/*
+ * The size of physical and logical block numbers and time fields in UFS.
+ */
+typedef int32_t ufs1_daddr_t;
+typedef int64_t ufs2_daddr_t;
+typedef int64_t ufs_lbn_t;
+typedef int64_t ufs_time_t;
+
+/* File permissions. */
+#define IEXEC 0000100 /* Executable. */
+#define IWRITE 0000200 /* Writeable. */
+#define IREAD 0000400 /* Readable. */
+#define ISVTX 0001000 /* Sticky bit. */
+#define ISGID 0002000 /* Set-gid. */
+#define ISUID 0004000 /* Set-uid. */
+
+/* File types. */
+#define IFMT 0170000 /* Mask of file type. */
+#define IFIFO 0010000 /* Named pipe (fifo). */
+#define IFCHR 0020000 /* Character device. */
+#define IFDIR 0040000 /* Directory file. */
+#define IFBLK 0060000 /* Block device. */
+#define IFREG 0100000 /* Regular file. */
+#define IFLNK 0120000 /* Symbolic link. */
+#define IFSOCK 0140000 /* UNIX domain socket. */
+#define IFWHT 0160000 /* Whiteout. */
+
+/*
+ * A dinode contains all the meta-data associated with a UFS2 file.
+ * This structure defines the on-disk format of a dinode. Since
+ * this structure describes an on-disk structure, all its fields
+ * are defined by types with precise widths.
+ */
+
+#define NXADDR 2 /* External addresses in inode. */
+#define NDADDR 12 /* Direct addresses in inode. */
+#define NIADDR 3 /* Indirect addresses in inode. */
+
+struct ufs2_dinode {
+ uint16_t di_mode; /* 0: IFMT, permissions; see below. */
+ int16_t di_nlink; /* 2: File link count. */
+ uint32_t di_uid; /* 4: File owner. */
+ uint32_t di_gid; /* 8: File group. */
+ uint32_t di_blksize; /* 12: Inode blocksize. */
+ uint64_t di_size; /* 16: File byte count. */
+ uint64_t di_blocks; /* 24: Bytes actually held. */
+ ufs_time_t di_atime; /* 32: Last access time. */
+ ufs_time_t di_mtime; /* 40: Last modified time. */
+ ufs_time_t di_ctime; /* 48: Last inode change time. */
+ ufs_time_t di_birthtime; /* 56: Inode creation time. */
+ int32_t di_mtimensec; /* 64: Last modified time. */
+ int32_t di_atimensec; /* 68: Last access time. */
+ int32_t di_ctimensec; /* 72: Last inode change time. */
+ int32_t di_birthnsec; /* 76: Inode creation time. */
+ int32_t di_gen; /* 80: Generation number. */
+ uint32_t di_kernflags; /* 84: Kernel flags. */
+ uint32_t di_flags; /* 88: Status flags (chflags). */
+ int32_t di_extsize; /* 92: External attributes block. */
+ ufs2_daddr_t di_extb[NXADDR];/* 96: External attributes block. */
+ ufs2_daddr_t di_db[NDADDR]; /* 112: Direct disk blocks. */
+ ufs2_daddr_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */
+ int64_t di_spare[3]; /* 232: Reserved; currently unused */
+};
+
+/*
+ * The di_db fields may be overlaid with other information for
+ * file types that do not have associated disk storage. Block
+ * and character devices overlay the first data block with their
+ * dev_t value. Short symbolic links place their path in the
+ * di_db area.
+ */
+#define di_rdev di_db[0]
+
+/*
+ * A UFS1 dinode contains all the meta-data associated with a UFS1 file.
+ * This structure defines the on-disk format of a UFS1 dinode. Since
+ * this structure describes an on-disk structure, all its fields
+ * are defined by types with precise widths.
+ */
+struct ufs1_dinode {
+ uint16_t di_mode; /* 0: IFMT, permissions; see below. */
+ int16_t di_nlink; /* 2: File link count. */
+ union {
+ uint16_t oldids[2]; /* 4: Ffs: old user and group ids. */
+ } di_u;
+ uint64_t di_size; /* 8: File byte count. */
+ int32_t di_atime; /* 16: Last access time. */
+ int32_t di_atimensec; /* 20: Last access time. */
+ int32_t di_mtime; /* 24: Last modified time. */
+ int32_t di_mtimensec; /* 28: Last modified time. */
+ int32_t di_ctime; /* 32: Last inode change time. */
+ int32_t di_ctimensec; /* 36: Last inode change time. */
+ ufs1_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
+ ufs1_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
+ uint32_t di_flags; /* 100: Status flags (chflags). */
+ int32_t di_blocks; /* 104: Blocks actually held. */
+ int32_t di_gen; /* 108: Generation number. */
+ uint32_t di_uid; /* 112: File owner. */
+ uint32_t di_gid; /* 116: File group. */
+ int32_t di_spare[2]; /* 120: Reserved; currently unused */
+};
+#define di_ogid di_u.oldids[1]
+#define di_ouid di_u.oldids[0]
+
+#endif /* _UFS_UFS_DINODE_H_ */
diff --git a/roms/openbios/fs/grubfs/ufs_fs.h b/roms/openbios/fs/grubfs/ufs_fs.h
new file mode 100644
index 00000000..bd11cc96
--- /dev/null
+++ b/roms/openbios/fs/grubfs/ufs_fs.h
@@ -0,0 +1,635 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fs.h 8.13 (Berkeley) 3/21/95
+ * $FreeBSD: src/sys/ufs/ffs/fs.h,v 1.43.2.3 2005/02/28 16:04:53 delphij Exp $
+ */
+
+#ifndef _UFS_FFS_FS_H_
+#define _UFS_FFS_FS_H_
+
+/*
+ * Each disk drive contains some number of filesystems.
+ * A filesystem consists of a number of cylinder groups.
+ * Each cylinder group has inodes and data.
+ *
+ * A filesystem is described by its super-block, which in turn
+ * describes the cylinder groups. The super-block is critical
+ * data and is replicated in each cylinder group to protect against
+ * catastrophic loss. This is done at `newfs' time and the critical
+ * super-block data does not change, so the copies need not be
+ * referenced further unless disaster strikes.
+ *
+ * For filesystem fs, the offsets of the various blocks of interest
+ * are given in the super block as:
+ * [fs->fs_sblkno] Super-block
+ * [fs->fs_cblkno] Cylinder group block
+ * [fs->fs_iblkno] Inode blocks
+ * [fs->fs_dblkno] Data blocks
+ * The beginning of cylinder group cg in fs, is given by
+ * the ``cgbase(fs, cg)'' macro.
+ *
+ * Depending on the architecture and the media, the superblock may
+ * reside in any one of four places. For tiny media where every block
+ * counts, it is placed at the very front of the partition. Historically,
+ * UFS1 placed it 8K from the front to leave room for the disk label and
+ * a small bootstrap. For UFS2 it got moved to 64K from the front to leave
+ * room for the disk label and a bigger bootstrap, and for really piggy
+ * systems we check at 256K from the front if the first three fail. In
+ * all cases the size of the superblock will be SBLOCKSIZE. All values are
+ * given in byte-offset form, so they do not imply a sector size. The
+ * SBLOCKSEARCH specifies the order in which the locations should be searched.
+ */
+#define SBLOCK_FLOPPY 0
+#define SBLOCK_UFS1 8192
+#define SBLOCK_UFS2 65536
+#define SBLOCK_PIGGY 262144
+#define SBLOCKSIZE 8192
+#define SBLOCKSEARCH \
+ { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
+
+/*
+ * Max number of fragments per block. This value is NOT tweakable.
+ */
+#define MAXFRAG 8
+
+/*
+ * Addresses stored in inodes are capable of addressing fragments
+ * of `blocks'. File system blocks of at most size MAXBSIZE can
+ * be optionally broken into 2, 4, or 8 pieces, each of which is
+ * addressable; these pieces may be DEV_BSIZE, or some multiple of
+ * a DEV_BSIZE unit.
+ *
+ * Large files consist of exclusively large data blocks. To avoid
+ * undue wasted disk space, the last data block of a small file may be
+ * allocated as only as many fragments of a large block as are
+ * necessary. The filesystem format retains only a single pointer
+ * to such a fragment, which is a piece of a single large block that
+ * has been divided. The size of such a fragment is determinable from
+ * information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
+ *
+ * The filesystem records space availability at the fragment level;
+ * to determine block availability, aligned fragments are examined.
+ */
+
+/*
+ * MINBSIZE is the smallest allowable block size.
+ * In order to insure that it is possible to create files of size
+ * 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
+ * MINBSIZE must be big enough to hold a cylinder group block,
+ * thus changes to (struct cg) must keep its size within MINBSIZE.
+ * Note that super blocks are always of size SBSIZE,
+ * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
+ */
+#define MINBSIZE 4096
+
+/*
+ * The path name on which the filesystem is mounted is maintained
+ * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
+ * the super block for this name.
+ */
+#define MAXMNTLEN 468
+
+/*
+ * The volume name for this filesystem is maintained in fs_volname.
+ * MAXVOLLEN defines the length of the buffer allocated.
+ */
+#define MAXVOLLEN 32
+
+/*
+ * There is a 128-byte region in the superblock reserved for in-core
+ * pointers to summary information. Originally this included an array
+ * of pointers to blocks of struct csum; now there are just a few
+ * pointers and the remaining space is padded with fs_ocsp[].
+ *
+ * NOCSPTRS determines the size of this padding. One pointer (fs_csp)
+ * is taken away to point to a contiguous array of struct csum for
+ * all cylinder groups; a second (fs_maxcluster) points to an array
+ * of cluster sizes that is computed as cylinder groups are inspected,
+ * and the third points to an array that tracks the creation of new
+ * directories. A fourth pointer, fs_active, is used when creating
+ * snapshots; it points to a bitmap of cylinder groups for which the
+ * free-block bitmap has changed since the snapshot operation began.
+ */
+#define NOCSPTRS ((128 / sizeof(void *)) - 4)
+
+/*
+ * A summary of contiguous blocks of various sizes is maintained
+ * in each cylinder group. Normally this is set by the initial
+ * value of fs_maxcontig. To conserve space, a maximum summary size
+ * is set by FS_MAXCONTIG.
+ */
+#define FS_MAXCONTIG 16
+
+/*
+ * MINFREE gives the minimum acceptable percentage of filesystem
+ * blocks which may be free. If the freelist drops below this level
+ * only the superuser may continue to allocate blocks. This may
+ * be set to 0 if no reserve of free blocks is deemed necessary,
+ * however throughput drops by fifty percent if the filesystem
+ * is run at between 95% and 100% full; thus the minimum default
+ * value of fs_minfree is 5%. However, to get good clustering
+ * performance, 10% is a better choice. hence we use 10% as our
+ * default value. With 10% free space, fragmentation is not a
+ * problem, so we choose to optimize for time.
+ */
+#define MINFREE 8
+#define DEFAULTOPT FS_OPTTIME
+
+/*
+ * Grigoriy Orlov <gluk@ptci.ru> has done some extensive work to fine
+ * tune the layout preferences for directories within a filesystem.
+ * His algorithm can be tuned by adjusting the following parameters
+ * which tell the system the average file size and the average number
+ * of files per directory. These defaults are well selected for typical
+ * filesystems, but may need to be tuned for odd cases like filesystems
+ * being used for squid caches or news spools.
+ */
+#define AVFILESIZ 16384 /* expected average file size */
+#define AFPDIR 64 /* expected number of files per directory */
+
+/*
+ * The maximum number of snapshot nodes that can be associated
+ * with each filesystem. This limit affects only the number of
+ * snapshot files that can be recorded within the superblock so
+ * that they can be found when the filesystem is mounted. However,
+ * maintaining too many will slow the filesystem performance, so
+ * having this limit is a good idea.
+ */
+#define FSMAXSNAP 20
+
+/*
+ * Used to identify special blocks in snapshots:
+ *
+ * BLK_NOCOPY - A block that was unallocated at the time the snapshot
+ * was taken, hence does not need to be copied when written.
+ * BLK_SNAP - A block held by another snapshot that is not needed by this
+ * snapshot. When the other snapshot is freed, the BLK_SNAP entries
+ * are converted to BLK_NOCOPY. These are needed to allow fsck to
+ * identify blocks that are in use by other snapshots (which are
+ * expunged from this snapshot).
+ */
+#define BLK_NOCOPY ((ufs2_daddr_t)(1))
+#define BLK_SNAP ((ufs2_daddr_t)(2))
+
+/*
+ * Sysctl values for the fast filesystem.
+ */
+#define FFS_ADJ_REFCNT 1 /* adjust inode reference count */
+#define FFS_ADJ_BLKCNT 2 /* adjust inode used block count */
+#define FFS_BLK_FREE 3 /* free range of blocks in map */
+#define FFS_DIR_FREE 4 /* free specified dir inodes in map */
+#define FFS_FILE_FREE 5 /* free specified file inodes in map */
+#define FFS_SET_FLAGS 6 /* set filesystem flags */
+#define FFS_ADJ_NDIR 7 /* adjust number of directories */
+#define FFS_ADJ_NBFREE 8 /* adjust number of free blocks */
+#define FFS_ADJ_NIFREE 9 /* adjust number of free inodes */
+#define FFS_ADJ_NFFREE 10 /* adjust number of free frags */
+#define FFS_ADJ_NUMCLUSTERS 11 /* adjust number of free clusters */
+#define FFS_MAXID 12 /* number of valid ffs ids */
+
+/*
+ * Command structure passed in to the filesystem to adjust filesystem values.
+ */
+#define FFS_CMD_VERSION 0x19790518 /* version ID */
+struct fsck_cmd {
+ int32_t version; /* version of command structure */
+ int32_t handle; /* reference to filesystem to be changed */
+ int64_t value; /* inode or block number to be affected */
+ int64_t size; /* amount or range to be adjusted */
+ int64_t spare; /* reserved for future use */
+};
+
+/*
+ * Per cylinder group information; summarized in blocks allocated
+ * from first cylinder group data blocks. These blocks have to be
+ * read in from fs_csaddr (size fs_cssize) in addition to the
+ * super block.
+ */
+struct csum {
+ int32_t cs_ndir; /* number of directories */
+ int32_t cs_nbfree; /* number of free blocks */
+ int32_t cs_nifree; /* number of free inodes */
+ int32_t cs_nffree; /* number of free frags */
+};
+struct csum_total {
+ int64_t cs_ndir; /* number of directories */
+ int64_t cs_nbfree; /* number of free blocks */
+ int64_t cs_nifree; /* number of free inodes */
+ int64_t cs_nffree; /* number of free frags */
+ int64_t cs_numclusters; /* number of free clusters */
+ int64_t cs_spare[3]; /* future expansion */
+};
+
+/*
+ * Super block for an FFS filesystem.
+ */
+struct fs {
+ int32_t fs_firstfield; /* historic filesystem linked list, */
+ int32_t fs_unused_1; /* used for incore super blocks */
+ int32_t fs_sblkno; /* offset of super-block in filesys */
+ int32_t fs_cblkno; /* offset of cyl-block in filesys */
+ int32_t fs_iblkno; /* offset of inode-blocks in filesys */
+ int32_t fs_dblkno; /* offset of first data after cg */
+ int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */
+ int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */
+ int32_t fs_old_time; /* last time written */
+ int32_t fs_old_size; /* number of blocks in fs */
+ int32_t fs_old_dsize; /* number of data blocks in fs */
+ int32_t fs_ncg; /* number of cylinder groups */
+ int32_t fs_bsize; /* size of basic blocks in fs */
+ int32_t fs_fsize; /* size of frag blocks in fs */
+ int32_t fs_frag; /* number of frags in a block in fs */
+/* these are configuration parameters */
+ int32_t fs_minfree; /* minimum percentage of free blocks */
+ int32_t fs_old_rotdelay; /* num of ms for optimal next block */
+ int32_t fs_old_rps; /* disk revolutions per second */
+/* these fields can be computed from the others */
+ int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */
+ int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */
+ int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */
+ int32_t fs_fshift; /* ``numfrags'' calc number of frags */
+/* these are configuration parameters */
+ int32_t fs_maxcontig; /* max number of contiguous blks */
+ int32_t fs_maxbpg; /* max number of blks per cyl group */
+/* these fields can be computed from the others */
+ int32_t fs_fragshift; /* block to frag shift */
+ int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+ int32_t fs_sbsize; /* actual size of super block */
+ int32_t fs_spare1[2]; /* old fs_csmask */
+ /* old fs_csshift */
+ int32_t fs_nindir; /* value of NINDIR */
+ int32_t fs_inopb; /* value of INOPB */
+ int32_t fs_old_nspf; /* value of NSPF */
+/* yet another configuration parameter */
+ int32_t fs_optim; /* optimization preference, see below */
+ int32_t fs_old_npsect; /* # sectors/track including spares */
+ int32_t fs_old_interleave; /* hardware sector interleave */
+ int32_t fs_old_trackskew; /* sector 0 skew, per track */
+ int32_t fs_id[2]; /* unique filesystem id */
+/* sizes determined by number of cylinder groups and their sizes */
+ int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */
+ int32_t fs_cssize; /* size of cyl grp summary area */
+ int32_t fs_cgsize; /* cylinder group size */
+ int32_t fs_spare2; /* old fs_ntrak */
+ int32_t fs_old_nsect; /* sectors per track */
+ int32_t fs_old_spc; /* sectors per cylinder */
+ int32_t fs_old_ncyl; /* cylinders in filesystem */
+ int32_t fs_old_cpg; /* cylinders per group */
+ int32_t fs_ipg; /* inodes per group */
+ int32_t fs_fpg; /* blocks per group * fs_frag */
+/* this data must be re-computed after crashes */
+ struct csum fs_old_cstotal; /* cylinder summary information */
+/* these fields are cleared at mount time */
+ int8_t fs_fmod; /* super block modified flag */
+ int8_t fs_clean; /* filesystem is clean flag */
+ int8_t fs_ronly; /* mounted read-only flag */
+ int8_t fs_old_flags; /* old FS_ flags */
+ char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
+ char fs_volname[MAXVOLLEN]; /* volume name */
+ uint64_t fs_swuid; /* system-wide uid */
+ int32_t fs_pad; /* due to alignment of fs_swuid */
+/* these fields retain the current block allocation info */
+ int32_t fs_cgrotor; /* last cg searched */
+ void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */
+ uint8_t *fs_contigdirs; /* # of contiguously allocated dirs */
+ struct csum *fs_csp; /* cg summary info buffer for fs_cs */
+ int32_t *fs_maxcluster; /* max cluster in each cyl group */
+ unsigned int *fs_active; /* used by snapshots to track fs */
+ int32_t fs_old_cpc; /* cyl per cycle in postbl */
+ int32_t fs_maxbsize; /* maximum blocking factor permitted */
+ int64_t fs_sparecon64[17]; /* old rotation block list head */
+ int64_t fs_sblockloc; /* byte offset of standard superblock */
+ struct csum_total fs_cstotal; /* cylinder summary information */
+ ufs_time_t fs_time; /* last time written */
+ int64_t fs_size; /* number of blocks in fs */
+ int64_t fs_dsize; /* number of data blocks in fs */
+ ufs2_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
+ int64_t fs_pendingblocks; /* blocks in process of being freed */
+ int32_t fs_pendinginodes; /* inodes in process of being freed */
+ int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */
+ int32_t fs_avgfilesize; /* expected average file size */
+ int32_t fs_avgfpdir; /* expected # of files per directory */
+ int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */
+ int32_t fs_sparecon32[26]; /* reserved for future constants */
+ int32_t fs_flags; /* see FS_ flags below */
+ int32_t fs_contigsumsize; /* size of cluster summary array */
+ int32_t fs_maxsymlinklen; /* max length of an internal symlink */
+ int32_t fs_old_inodefmt; /* format of on-disk inodes */
+ uint64_t fs_maxfilesize; /* maximum representable file size */
+ int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */
+ int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */
+ int32_t fs_state; /* validate fs_clean field */
+ int32_t fs_old_postblformat; /* format of positional layout tables */
+ int32_t fs_old_nrpos; /* number of rotational positions */
+ int32_t fs_spare5[2]; /* old fs_postbloff */
+ /* old fs_rotbloff */
+ int32_t fs_magic; /* magic number */
+};
+
+/* Sanity checking. */
+#ifdef CTASSERT
+CTASSERT(sizeof(struct fs) == 1376);
+#endif
+
+/*
+ * Filesystem identification
+ */
+#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast filesystem magic number */
+#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast filesystem magic number */
+#define FS_BAD_MAGIC 0x19960408 /* UFS incomplete newfs magic number */
+#define FS_OKAY 0x7c269d38 /* superblock checksum */
+#define FS_42INODEFMT -1 /* 4.2BSD inode format */
+#define FS_44INODEFMT 2 /* 4.4BSD inode format */
+
+/*
+ * Preference for optimization.
+ */
+#define FS_OPTTIME 0 /* minimize allocation time */
+#define FS_OPTSPACE 1 /* minimize disk fragmentation */
+
+/*
+ * Filesystem flags.
+ *
+ * The FS_UNCLEAN flag is set by the kernel when the filesystem was
+ * mounted with fs_clean set to zero. The FS_DOSOFTDEP flag indicates
+ * that the filesystem should be managed by the soft updates code.
+ * Note that the FS_NEEDSFSCK flag is set and cleared only by the
+ * fsck utility. It is set when background fsck finds an unexpected
+ * inconsistency which requires a traditional foreground fsck to be
+ * run. Such inconsistencies should only be found after an uncorrectable
+ * disk error. A foreground fsck will clear the FS_NEEDSFSCK flag when
+ * it has successfully cleaned up the filesystem. The kernel uses this
+ * flag to enforce that inconsistent filesystems be mounted read-only.
+ * The FS_INDEXDIRS flag when set indicates that the kernel maintains
+ * on-disk auxiliary indexes (such as B-trees) for speeding directory
+ * accesses. Kernels that do not support auxiliary indicies clear the
+ * flag to indicate that the indicies need to be rebuilt (by fsck) before
+ * they can be used.
+ *
+ * FS_ACLS indicates that ACLs are administratively enabled for the
+ * file system, so they should be loaded from extended attributes,
+ * observed for access control purposes, and be administered by object
+ * owners. FS_MULTILABEL indicates that the TrustedBSD MAC Framework
+ * should attempt to back MAC labels into extended attributes on the
+ * file system rather than maintain a single mount label for all
+ * objects.
+ */
+#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */
+#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */
+#define FS_NEEDSFSCK 0x04 /* filesystem needs sync fsck before mount */
+#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */
+#define FS_ACLS 0x10 /* file system has ACLs enabled */
+#define FS_MULTILABEL 0x20 /* file system is MAC multi-label */
+#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */
+
+/*
+ * Macros to access bits in the fs_active array.
+ */
+#define ACTIVECGNUM(fs, cg) ((fs)->fs_active[(cg) / (NBBY * sizeof(int))])
+#define ACTIVECGOFF(cg) (1 << ((cg) % (NBBY * sizeof(int))))
+
+/*
+ * The size of a cylinder group is calculated by CGSIZE. The maximum size
+ * is limited by the fact that cylinder groups are at most one block.
+ * Its size is derived from the size of the maps maintained in the
+ * cylinder group and the (struct cg) size.
+ */
+#define CGSIZE(fs) \
+ /* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \
+ /* old btotoff */ (fs)->fs_old_cpg * sizeof(int32_t) + \
+ /* old boff */ (fs)->fs_old_cpg * sizeof(uint16_t) + \
+ /* inode map */ howmany((fs)->fs_ipg, NBBY) + \
+ /* block map */ howmany((fs)->fs_fpg, NBBY) +\
+ /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \
+ /* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \
+ /* cluster map */ howmany(fragstoblks(fs, (fs)->fs_fpg), NBBY)))
+
+/*
+ * The minimal number of cylinder groups that should be created.
+ */
+#define MINCYLGRPS 4
+
+/*
+ * Convert cylinder group to base address of its global summary info.
+ */
+#define fs_cs(fs, indx) fs_csp[indx]
+
+/*
+ * Cylinder group block for a filesystem.
+ */
+#define CG_MAGIC 0x090255
+struct cg {
+ int32_t cg_firstfield; /* historic cyl groups linked list */
+ int32_t cg_magic; /* magic number */
+ int32_t cg_old_time; /* time last written */
+ int32_t cg_cgx; /* we are the cgx'th cylinder group */
+ int16_t cg_old_ncyl; /* number of cyl's this cg */
+ int16_t cg_old_niblk; /* number of inode blocks this cg */
+ int32_t cg_ndblk; /* number of data blocks this cg */
+ struct csum cg_cs; /* cylinder summary information */
+ int32_t cg_rotor; /* position of last used block */
+ int32_t cg_frotor; /* position of last used frag */
+ int32_t cg_irotor; /* position of last used inode */
+ int32_t cg_frsum[MAXFRAG]; /* counts of available frags */
+ int32_t cg_old_btotoff; /* (int32) block totals per cylinder */
+ int32_t cg_old_boff; /* (uint16) free block positions */
+ int32_t cg_iusedoff; /* (uint8) used inode map */
+ int32_t cg_freeoff; /* (uint8) free block map */
+ int32_t cg_nextfreeoff; /* (uint8) next available space */
+ int32_t cg_clustersumoff; /* (uint32) counts of avail clusters */
+ int32_t cg_clusteroff; /* (uint8) free cluster map */
+ int32_t cg_nclusterblks; /* number of clusters this cg */
+ int32_t cg_niblk; /* number of inode blocks this cg */
+ int32_t cg_initediblk; /* last initialized inode */
+ int32_t cg_sparecon32[3]; /* reserved for future use */
+ ufs_time_t cg_time; /* time last written */
+ int64_t cg_sparecon64[3]; /* reserved for future use */
+ uint8_t cg_space[1]; /* space for cylinder group maps */
+/* actually longer */
+};
+
+/*
+ * Macros for access to cylinder group array structures
+ */
+#define cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)
+#define cg_inosused(cgp) \
+ ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_iusedoff))
+#define cg_blksfree(cgp) \
+ ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_freeoff))
+#define cg_clustersfree(cgp) \
+ ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_clusteroff))
+#define cg_clustersum(cgp) \
+ ((int32_t *)((uintptr_t)(cgp) + (cgp)->cg_clustersumoff))
+
+/*
+ * Turn filesystem block numbers into disk block addresses.
+ * This maps filesystem blocks to device size blocks.
+ */
+#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb)
+#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb)
+
+/*
+ * Cylinder group macros to locate things in cylinder groups.
+ * They calc filesystem addresses of cylinder group data structures.
+ */
+#define cgbase(fs, c) (((ufs2_daddr_t)(fs)->fs_fpg) * (c))
+#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
+#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
+#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
+#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */
+#define cgstart(fs, c) \
+ ((fs)->fs_magic == FS_UFS2_MAGIC ? cgbase(fs, c) : \
+ (cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask))))
+
+/*
+ * Macros for handling inode numbers:
+ * inode number to filesystem block offset.
+ * inode number to cylinder group number.
+ * inode number to filesystem block address.
+ */
+#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg)
+#define ino_to_fsba(fs, x) \
+ ((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
+ (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
+#define ino_to_fsbo(fs, x) ((x) % INOPB(fs))
+
+/*
+ * Give cylinder group number for a filesystem block.
+ * Give cylinder group block number for a filesystem block.
+ */
+#define dtog(fs, d) ((d) / (fs)->fs_fpg)
+#define dtogd(fs, d) ((d) % (fs)->fs_fpg)
+
+/*
+ * Extract the bits for a block from a map.
+ * Compute the cylinder and rotational position of a cyl block addr.
+ */
+#define blkmap(fs, map, loc) \
+ (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
+
+/*
+ * The following macros optimize certain frequently calculated
+ * quantities by using shifts and masks in place of divisions
+ * modulos and multiplications.
+ */
+#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
+ ((loc) & (fs)->fs_qbmask)
+#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \
+ ((loc) & (fs)->fs_qfmask)
+#define lfragtosize(fs, frag) /* calculates ((off_t)frag * fs->fs_fsize) */ \
+ (((off_t)(frag)) << (fs)->fs_fshift)
+#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \
+ (((off_t)(blk)) << (fs)->fs_bshift)
+/* Use this only when `blk' is known to be small, e.g., < NDADDR. */
+#define smalllblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \
+ ((blk) << (fs)->fs_bshift)
+#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
+ ((loc) >> (fs)->fs_bshift)
+#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
+ ((loc) >> (fs)->fs_fshift)
+#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \
+ (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask)
+#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
+ (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask)
+#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \
+ ((frags) >> (fs)->fs_fragshift)
+#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \
+ ((blks) << (fs)->fs_fragshift)
+#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \
+ ((fsb) & ((fs)->fs_frag - 1))
+#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \
+ ((fsb) &~ ((fs)->fs_frag - 1))
+
+/*
+ * Determine the number of available frags given a
+ * percentage to hold in reserve.
+ */
+#define freespace(fs, percentreserved) \
+ (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
+ (fs)->fs_cstotal.cs_nffree - \
+ (((off_t)((fs)->fs_dsize)) * (percentreserved) / 100))
+
+/*
+ * Determining the size of a file block in the filesystem.
+ */
+#define blksize(fs, ip, lbn) \
+ (((lbn) >= NDADDR || (ip)->i_size >= smalllblktosize(fs, (lbn) + 1)) \
+ ? (fs)->fs_bsize \
+ : (fragroundup(fs, blkoff(fs, (ip)->i_size))))
+#define sblksize(fs, size, lbn) \
+ (((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \
+ ? (fs)->fs_bsize \
+ : (fragroundup(fs, blkoff(fs, (size)))))
+
+
+/*
+ * Number of inodes in a secondary storage block/fragment.
+ */
+#define INOPB(fs) ((fs)->fs_inopb)
+#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift)
+
+/*
+ * Number of indirects in a filesystem block.
+ */
+#define NINDIR(fs) ((fs)->fs_nindir)
+
+extern int inside[], around[];
+extern char *fragtbl[];
+
+struct ufs_dirent {
+ uint32_t d_fileno; /* file number of entry */
+ uint16_t d_reclen; /* length of this record */
+ uint8_t d_type; /* file type, see below */
+ uint8_t d_namlen; /* length of string in d_name */
+#define MAXNAMLEN 255
+ char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
+};
+
+/*
+ * File types
+ */
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+/* XXX: We hardcode BSIZE and BSIZE_SHIFT here. fsys_ffs seems to do the same,
+ * so we should get away with it :-) */
+#define DEV_BSIZE 512
+#define DEV_BSHIFT 9 /* 2**9 = 512 */
+#define MAXBSIZE 8192
+
+typedef unsigned int ino_t;
+
+#endif
diff --git a/roms/openbios/fs/grubfs/vstafs.h b/roms/openbios/fs/grubfs/vstafs.h
new file mode 100644
index 00000000..f240ffc4
--- /dev/null
+++ b/roms/openbios/fs/grubfs/vstafs.h
@@ -0,0 +1,89 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+
+#ifndef VSTAFS_H
+#define VSTAFS_H 1
+
+
+#define LINE 16
+#define BLOCK_SIZE 512
+#define VSTAFS_START_DATA 320
+
+struct bootrecord
+{
+ unsigned char flag;
+ unsigned char s_sector;
+ unsigned char s_head;
+ unsigned char s_cylinder;
+ unsigned char p_type;
+ unsigned char e_sector;
+ unsigned char e_head;
+ unsigned char e_cylinder;
+ unsigned long start_lba;
+ unsigned long nr_sector_lba;
+};
+
+struct alloc
+{
+ unsigned long a_start;
+ unsigned long a_len;
+};
+
+struct first_sector
+{
+ unsigned long fs_magic;
+ unsigned long fs_size;
+ unsigned long fs_extsize;
+ unsigned long fs_free;
+ struct alloc fs_freesecs[0];
+};
+
+struct prot
+{
+ unsigned char len;
+ unsigned char pdefault;
+ unsigned char id[7];
+ unsigned char bits[7];
+};
+
+struct fs_file
+{
+ unsigned long prev;
+ unsigned long rev;
+ unsigned long len;
+ unsigned short type;
+ unsigned short nlink;
+ struct prot pprot;
+ unsigned int owner;
+ unsigned int extents;
+ struct alloc blocks[32];
+ long fs_ctime, fs_mtime; /* it is not lon but time_t */
+ char pad[16];
+ char data[0];
+};
+
+struct dir_entry
+{
+ char name[28];
+ unsigned long start;
+};
+
+#endif /* ! VSTAFS_H */
diff --git a/roms/openbios/fs/grubfs/xfs.h b/roms/openbios/fs/grubfs/xfs.h
new file mode 100644
index 00000000..0ed07042
--- /dev/null
+++ b/roms/openbios/fs/grubfs/xfs.h
@@ -0,0 +1,546 @@
+/* xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#ifndef _BITS_TYPES_H
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef short __int16_t;
+typedef unsigned short __uint16_t;
+typedef int __int32_t;
+typedef unsigned int __uint32_t;
+typedef long long __int64_t;
+typedef unsigned long long __uint64_t;
+#endif
+
+typedef __uint64_t xfs_ino_t;
+typedef __uint32_t xfs_agino_t;
+typedef __int64_t xfs_daddr_t;
+typedef __int64_t xfs_off_t;
+typedef __uint8_t uuid_t[16];
+
+
+/* those are from xfs_types.h */
+
+typedef __uint32_t xfs_agblock_t; /* blockno in alloc. group */
+typedef __uint32_t xfs_extlen_t; /* extent length in blocks */
+typedef __uint32_t xfs_agnumber_t; /* allocation group number */
+typedef __int32_t xfs_extnum_t; /* # of extents in a file */
+typedef __int16_t xfs_aextnum_t; /* # extents in an attribute fork */
+typedef __int64_t xfs_fsize_t; /* bytes in a file */
+
+typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
+typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */
+
+/*
+ * Disk based types:
+ */
+typedef __uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */
+typedef __uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */
+typedef __uint64_t xfs_drtbno_t; /* extent (block) in realtime area */
+typedef __uint64_t xfs_dfiloff_t; /* block number in a file */
+
+typedef __uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */
+typedef __uint64_t xfs_fileoff_t; /* block number in a file */
+typedef __uint64_t xfs_filblks_t; /* number of blocks in a file */
+
+
+/* those are from xfs_sb.h */
+
+#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/
+#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */
+#define XFS_SB_VERSION_NUMBITS 0x000f
+
+typedef struct xfs_sb
+{
+ __uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
+ __uint32_t sb_blocksize; /* logical block size, bytes */
+ xfs_drfsbno_t sb_dblocks; /* number of data blocks */
+ xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */
+ xfs_drtbno_t sb_rextents; /* number of realtime extents */
+ uuid_t sb_uuid; /* file system unique id */
+ xfs_dfsbno_t sb_logstart; /* starting block of log if internal */
+ xfs_ino_t sb_rootino; /* root inode number */
+ xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */
+ xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */
+ xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */
+ xfs_agblock_t sb_agblocks; /* size of an allocation group */
+ xfs_agnumber_t sb_agcount; /* number of allocation groups */
+ xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */
+ xfs_extlen_t sb_logblocks; /* number of log blocks */
+ __uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */
+ __uint16_t sb_sectsize; /* volume sector size, bytes */
+ __uint16_t sb_inodesize; /* inode size, bytes */
+ __uint16_t sb_inopblock; /* inodes per block */
+ char sb_fname[12]; /* file system name */
+ __uint8_t sb_blocklog; /* log2 of sb_blocksize */
+ __uint8_t sb_sectlog; /* log2 of sb_sectsize */
+ __uint8_t sb_inodelog; /* log2 of sb_inodesize */
+ __uint8_t sb_inopblog; /* log2 of sb_inopblock */
+ __uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */
+ __uint8_t sb_rextslog; /* log2 of sb_rextents */
+ __uint8_t sb_inprogress; /* mkfs is in progress, don't mount */
+ __uint8_t sb_imax_pct; /* max % of fs for inode space */
+ /* statistics */
+ /*
+ * These fields must remain contiguous. If you really
+ * want to change their layout, make sure you fix the
+ * code in xfs_trans_apply_sb_deltas().
+ */
+ __uint64_t sb_icount; /* allocated inodes */
+ __uint64_t sb_ifree; /* free inodes */
+ __uint64_t sb_fdblocks; /* free data blocks */
+ __uint64_t sb_frextents; /* free realtime extents */
+ /*
+ * End contiguous fields.
+ */
+ xfs_ino_t sb_uquotino; /* user quota inode */
+ xfs_ino_t sb_gquotino; /* group quota inode */
+ __uint16_t sb_qflags; /* quota flags */
+ __uint8_t sb_flags; /* misc. flags */
+ __uint8_t sb_shared_vn; /* shared version number */
+ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */
+ __uint32_t sb_unit; /* stripe or raid unit */
+ __uint32_t sb_width; /* stripe or raid width */
+ __uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */
+ __uint8_t sb_dummy[7]; /* padding */
+} xfs_sb_t;
+
+
+/* those are from xfs_btree.h */
+
+/*
+ * Long form header: bmap btrees.
+ */
+typedef struct xfs_btree_lblock
+{
+ __uint32_t bb_magic; /* magic number for block type */
+ __uint16_t bb_level; /* 0 is a leaf */
+ __uint16_t bb_numrecs; /* current # of data records */
+ xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */
+ xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */
+} xfs_btree_lblock_t;
+
+/*
+ * Combined header and structure, used by common code.
+ */
+typedef struct xfs_btree_hdr
+{
+ __uint32_t bb_magic; /* magic number for block type */
+ __uint16_t bb_level; /* 0 is a leaf */
+ __uint16_t bb_numrecs; /* current # of data records */
+} xfs_btree_hdr_t;
+
+typedef struct xfs_btree_block
+{
+ xfs_btree_hdr_t bb_h; /* header */
+ union {
+ struct {
+ xfs_agblock_t bb_leftsib;
+ xfs_agblock_t bb_rightsib;
+ } s; /* short form pointers */
+ struct {
+ xfs_dfsbno_t bb_leftsib;
+ xfs_dfsbno_t bb_rightsib;
+ } l; /* long form pointers */
+ } bb_u; /* rest */
+} xfs_btree_block_t;
+
+/* those are from xfs_bmap_btree.h */
+
+/*
+ * Bmap root header, on-disk form only.
+ */
+typedef struct xfs_bmdr_block
+{
+ __uint16_t bb_level; /* 0 is a leaf */
+ __uint16_t bb_numrecs; /* current # of data records */
+} xfs_bmdr_block_t;
+
+/*
+ * Bmap btree record and extent descriptor.
+ * For 32-bit kernels,
+ * l0:31 is an extent flag (value 1 indicates non-normal).
+ * l0:0-30 and l1:9-31 are startoff.
+ * l1:0-8, l2:0-31, and l3:21-31 are startblock.
+ * l3:0-20 are blockcount.
+ * For 64-bit kernels,
+ * l0:63 is an extent flag (value 1 indicates non-normal).
+ * l0:9-62 are startoff.
+ * l0:0-8 and l1:21-63 are startblock.
+ * l1:0-20 are blockcount.
+ */
+
+#define BMBT_USE_64 1
+
+typedef struct xfs_bmbt_rec_32
+{
+ __uint32_t l0, l1, l2, l3;
+} xfs_bmbt_rec_32_t;
+typedef struct xfs_bmbt_rec_64
+{
+ __uint64_t l0, l1;
+} xfs_bmbt_rec_64_t;
+
+#if BMBT_USE_64
+typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#else /* !BMBT_USE_64 */
+typedef __uint32_t xfs_bmbt_rec_base_t; /* use this for casts */
+typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+#endif /* BMBT_USE_64 */
+
+/*
+ * Key structure for non-leaf levels of the tree.
+ */
+typedef struct xfs_bmbt_key
+{
+ xfs_dfiloff_t br_startoff; /* starting file offset */
+} xfs_bmbt_key_t, xfs_bmdr_key_t;
+
+typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */
+ /* btree block header type */
+typedef struct xfs_btree_lblock xfs_bmbt_block_t;
+
+
+/* those are from xfs_dir2.h */
+/*
+ * Directory version 2.
+ * There are 4 possible formats:
+ * shortform
+ * single block - data with embedded leaf at the end
+ * multiple data blocks, single leaf+freeindex block
+ * data blocks, node&leaf blocks (btree), freeindex blocks
+ *
+ * The shortform format is in xfs_dir2_sf.h.
+ * The single block format is in xfs_dir2_block.h.
+ * The data block format is in xfs_dir2_data.h.
+ * The leaf and freeindex block formats are in xfs_dir2_leaf.h.
+ * Node blocks are the same as the other version, in xfs_da_btree.h.
+ */
+
+/*
+ * Byte offset in data block and shortform entry.
+ */
+typedef __uint16_t xfs_dir2_data_off_t;
+
+/*
+ * Byte offset in a directory.
+ */
+typedef xfs_off_t xfs_dir2_off_t;
+
+/* those are from xfs_da_btree.h */
+/*========================================================================
+ * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
+ *========================================================================*/
+
+/*
+ * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
+ *
+ * Is is used to manage a doubly linked list of all blocks at the same
+ * level in the Btree, and to identify which type of block this is.
+ */
+#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
+#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
+
+typedef struct xfs_da_blkinfo {
+ xfs_dablk_t forw; /* previous block in list */
+ xfs_dablk_t back; /* following block in list */
+ __uint16_t magic; /* validity check on block */
+ __uint16_t pad; /* unused */
+} xfs_da_blkinfo_t;
+
+/*
+ * This is the structure of the root and intermediate nodes in the Btree.
+ * The leaf nodes are defined above.
+ *
+ * Entries are not packed.
+ *
+ * Since we have duplicate keys, use a binary search but always follow
+ * all match in the block, not just the first match found.
+ */
+
+typedef struct xfs_da_intnode {
+ struct xfs_da_node_hdr { /* constant-structure header block */
+ xfs_da_blkinfo_t info; /* block type, links, etc. */
+ __uint16_t count; /* count of active entries */
+ __uint16_t level; /* level above leaves (leaf == 0) */
+ } hdr;
+ struct xfs_da_node_entry {
+ xfs_dahash_t hashval; /* hash value for this descendant */
+ xfs_dablk_t before; /* Btree block before this key */
+ } btree[1]; /* variable sized array of keys */
+} xfs_da_intnode_t;
+
+
+/* those are from xfs_dir2_data.h */
+/*
+ * Directory format 2, data block structures.
+ */
+
+/*
+ * Constants.
+ */
+#define XFS_DIR2_DATA_FREE_TAG 0xffff
+#define XFS_DIR2_DATA_FD_COUNT 3
+
+/*
+ * Structures.
+ */
+
+/*
+ * Describe a free area in the data block.
+ * The freespace will be formatted as a xfs_dir2_data_unused_t.
+ */
+typedef struct xfs_dir2_data_free {
+ xfs_dir2_data_off_t offset; /* start of freespace */
+ xfs_dir2_data_off_t length; /* length of freespace */
+} xfs_dir2_data_free_t;
+
+/*
+ * Header for the data blocks.
+ * Always at the beginning of a directory-sized block.
+ * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
+ */
+typedef struct xfs_dir2_data_hdr {
+ __uint32_t magic; /* XFS_DIR2_DATA_MAGIC */
+ /* or XFS_DIR2_BLOCK_MAGIC */
+ xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
+} xfs_dir2_data_hdr_t;
+
+/*
+ * Active entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_entry {
+ xfs_ino_t inumber; /* inode number */
+ __uint8_t namelen; /* name length */
+ __uint8_t name[1]; /* name bytes, no null */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_entry_t;
+
+/*
+ * Unused entry in a data block. Aligned to 8 bytes.
+ * Tag appears as the last 2 bytes.
+ */
+typedef struct xfs_dir2_data_unused {
+ __uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */
+ xfs_dir2_data_off_t length; /* total free length */
+ /* variable offset */
+ xfs_dir2_data_off_t tag; /* starting offset of us */
+} xfs_dir2_data_unused_t;
+
+typedef union {
+ xfs_dir2_data_entry_t entry;
+ xfs_dir2_data_unused_t unused;
+} xfs_dir2_data_union_t;
+
+
+/* those are from xfs_dir2_leaf.h */
+/*
+ * Directory version 2, leaf block structures.
+ */
+
+/*
+ * Leaf block header.
+ */
+typedef struct xfs_dir2_leaf_hdr {
+ xfs_da_blkinfo_t info; /* header for da routines */
+ __uint16_t count; /* count of entries */
+ __uint16_t stale; /* count of stale entries */
+} xfs_dir2_leaf_hdr_t;
+
+
+/* those are from xfs_dir2_block.h */
+/*
+ * xfs_dir2_block.h
+ * Directory version 2, single block format structures
+ */
+
+/*
+ * The single block format is as follows:
+ * xfs_dir2_data_hdr_t structure
+ * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
+ * xfs_dir2_leaf_entry_t structures
+ * xfs_dir2_block_tail_t structure
+ */
+
+#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */
+
+typedef struct xfs_dir2_block_tail {
+ __uint32_t count; /* count of leaf entries */
+ __uint32_t stale; /* count of stale lf entries */
+} xfs_dir2_block_tail_t;
+
+
+/* those are from xfs_dir2_sf.h */
+
+/*
+ * Directory layout when stored internal to an inode.
+ *
+ * Small directories are packed as tightly as possible so as to
+ * fit into the literal area of the inode.
+ */
+
+/*
+ * Inode number stored as 8 8-bit values.
+ */
+typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
+
+/*
+ * Inode number stored as 4 8-bit values.
+ * Works a lot of the time, when all the inode numbers in a directory
+ * fit in 32 bits.
+ */
+typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
+
+typedef union {
+ xfs_dir2_ino8_t i8;
+ xfs_dir2_ino4_t i4;
+} xfs_dir2_inou_t;
+
+/*
+ * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
+ * Only need 16 bits, this is the byte offset into the single block form.
+ */
+typedef struct { __uint8_t i[2]; } xfs_dir2_sf_off_t;
+
+/*
+ * The parent directory has a dedicated field, and the self-pointer must
+ * be calculated on the fly.
+ *
+ * Entries are packed toward the top as tightly as possible. The header
+ * and the elements must be bcopy()'d out into a work area to get correct
+ * alignment for the inode number fields.
+ */
+typedef struct xfs_dir2_sf_hdr {
+ __uint8_t count; /* count of entries */
+ __uint8_t i8count; /* count of 8-byte inode #s */
+ xfs_dir2_inou_t parent; /* parent dir inode number */
+} xfs_dir2_sf_hdr_t;
+
+typedef struct xfs_dir2_sf_entry {
+ __uint8_t namelen; /* actual name length */
+ xfs_dir2_sf_off_t offset; /* saved offset */
+ __uint8_t name[1]; /* name, variable size */
+ xfs_dir2_inou_t inumber; /* inode number, var. offset */
+} xfs_dir2_sf_entry_t;
+
+typedef struct xfs_dir2_sf {
+ xfs_dir2_sf_hdr_t hdr; /* shortform header */
+ xfs_dir2_sf_entry_t list[1]; /* shortform entries */
+} xfs_dir2_sf_t;
+
+/* those are from xfs_dinode.h */
+
+#define XFS_DINODE_VERSION_1 1
+#define XFS_DINODE_VERSION_2 2
+#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
+
+/*
+ * Disk inode structure.
+ * This is just the header; the inode is expanded to fill a variable size
+ * with the last field expanding. It is split into the core and "other"
+ * because we only need the core part in the in-core inode.
+ */
+typedef struct xfs_timestamp {
+ __int32_t t_sec; /* timestamp seconds */
+ __int32_t t_nsec; /* timestamp nanoseconds */
+} xfs_timestamp_t;
+
+/*
+ * Note: Coordinate changes to this structure with the XFS_DI_* #defines
+ * below and the offsets table in xfs_ialloc_log_di().
+ */
+typedef struct xfs_dinode_core
+{
+ __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
+ __uint16_t di_mode; /* mode and type of file */
+ __int8_t di_version; /* inode version */
+ __int8_t di_format; /* format of di_c data */
+ __uint16_t di_onlink; /* old number of links to file */
+ __uint32_t di_uid; /* owner's user id */
+ __uint32_t di_gid; /* owner's group id */
+ __uint32_t di_nlink; /* number of links to file */
+ __uint16_t di_projid; /* owner's project id */
+ __uint8_t di_pad[10]; /* unused, zeroed space */
+ xfs_timestamp_t di_atime; /* time last accessed */
+ xfs_timestamp_t di_mtime; /* time last modified */
+ xfs_timestamp_t di_ctime; /* time created/inode modified */
+ xfs_fsize_t di_size; /* number of bytes in file */
+ xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
+ xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
+ xfs_extnum_t di_nextents; /* number of extents in data fork */
+ xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
+ __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
+ __int8_t di_aformat; /* format of attr fork's data */
+ __uint32_t di_dmevmask; /* DMIG event mask */
+ __uint16_t di_dmstate; /* DMIG state info */
+ __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
+ __uint32_t di_gen; /* generation number */
+} xfs_dinode_core_t;
+
+typedef struct xfs_dinode
+{
+ xfs_dinode_core_t di_core;
+ xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
+ union {
+ xfs_bmdr_block_t di_bmbt; /* btree root block */
+ xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
+ xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
+ char di_c[1]; /* local contents */
+ } di_u;
+} xfs_dinode_t;
+
+/*
+ * Values for di_format
+ */
+typedef enum xfs_dinode_fmt
+{
+ XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */
+ XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */
+ /* LNK: di_symlink */
+ XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */
+ XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */
+ XFS_DINODE_FMT_UUID /* MNT: di_uuid */
+} xfs_dinode_fmt_t;
+
+/*
+ * File types (mode field)
+ */
+#define IFMT 0170000 /* type of file */
+#define IFDIR 0040000 /* directory */
+#define IFREG 0100000 /* regular */
+#define IFLNK 0120000 /* symbolic link */
diff --git a/roms/openbios/fs/hfs/block.c b/roms/openbios/fs/hfs/block.c
new file mode 100644
index 00000000..0b65a1f3
--- /dev/null
+++ b/roms/openbios/fs/hfs/block.c
@@ -0,0 +1,612 @@
+/*
+* libhfs - library for reading and writing Macintosh HFS volumes
+* Copyright (C) 1996-1998 Robert Leslie
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+* MA 02110-1301, USA.
+*
+* $Id: block.c,v 1.11 1998/11/02 22:08:52 rob Exp $
+*/
+
+#include "config.h"
+
+#include "libhfs.h"
+#include "volume.h"
+#include "block.h"
+#include "os.h"
+
+#define INUSE(b) ((b)->flags & HFS_BUCKET_INUSE)
+#define DIRTY(b) ((b)->flags & HFS_BUCKET_DIRTY)
+
+/*
+ * NAME: block->init()
+ * DESCRIPTION: initialize a volume's block cache
+ */
+int b_init(hfsvol *vol)
+{
+ bcache *cache;
+ int i;
+
+ ASSERT(vol->cache == 0);
+
+ cache = ALLOC(bcache, 1);
+ if (cache == NULL)
+ ERROR(ENOMEM, NULL);
+
+ vol->cache = cache;
+
+ cache->vol = vol;
+ cache->tail = &cache->chain[HFS_CACHESZ - 1];
+
+ cache->hits = 0;
+ cache->misses = 0;
+
+ for (i = 0; i < HFS_CACHESZ; ++i)
+ {
+ bucket *b = &cache->chain[i];
+
+ b->flags = 0;
+ b->count = 0;
+
+ b->bnum = 0;
+ b->data = &cache->pool[i];
+
+ b->cnext = b + 1;
+ b->cprev = b - 1;
+
+ b->hnext = NULL;
+ b->hprev = NULL;
+ }
+
+ cache->chain[0].cprev = cache->tail;
+ cache->tail->cnext = &cache->chain[0];
+
+ for (i = 0; i < HFS_HASHSZ; ++i)
+ cache->hash[i] = NULL;
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+# ifdef DEBUG
+/*
+ * NAME: block->showstats()
+ * DESCRIPTION: output cache hit/miss ratio
+ */
+void b_showstats(const bcache *cache)
+{
+ fprintf(stderr, "BLOCK: CACHE vol 0x%lx \"%s\" hit/miss ratio = %.3f\n",
+ (unsigned long) cache->vol, cache->vol->mdb.drVN,
+ (float) cache->hits / (float) cache->misses);
+}
+
+/*
+ * NAME: block->dumpcache()
+ * DESCRIPTION: dump the cache tables for a volume
+ */
+void b_dumpcache(const bcache *cache)
+{
+ const bucket *b;
+ int i;
+
+ fprintf(stderr, "BLOCK CACHE DUMP:\n");
+
+ for (i = 0, b = cache->tail->cnext; i < HFS_CACHESZ; ++i, b = b->cnext)
+ {
+ if (INUSE(b))
+ {
+ fprintf(stderr, "\t %lu", b->bnum);
+ if (DIRTY(b))
+ fprintf(stderr, "*");
+
+ fprintf(stderr, ":%u", b->count);
+ }
+ }
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "BLOCK HASH DUMP:\n");
+
+ for (i = 0; i < HFS_HASHSZ; ++i)
+ {
+ int seen = 0;
+
+ for (b = cache->hash[i]; b; b = b->hnext)
+ {
+ if (! seen)
+ fprintf(stderr, " %d:", i);
+
+ if (INUSE(b))
+ {
+ fprintf(stderr, " %lu", b->bnum);
+ if (DIRTY(b))
+ fprintf(stderr, "*");
+
+ fprintf(stderr, ":%u", b->count);
+ }
+
+ seen = 1;
+ }
+
+ if (seen)
+ fprintf(stderr, "\n");
+ }
+}
+# endif
+
+/*
+ * NAME: fillchain()
+ * DESCRIPTION: fill a chain of bucket buffers with a single read
+ */
+static
+int fillchain(hfsvol *vol, bucket **bptr, unsigned int *count)
+{
+ bucket *blist[HFS_BLOCKBUFSZ], **start = bptr;
+ unsigned long bnum=-2; // XXX
+ unsigned int len, i;
+
+ for (len = 0; len < HFS_BLOCKBUFSZ &&
+ (unsigned int) (bptr - start) < *count; ++bptr)
+ {
+ if (INUSE(*bptr))
+ continue;
+
+ if (len > 0 && (*bptr)->bnum != bnum)
+ break;
+
+ blist[len++] = *bptr;
+ bnum = (*bptr)->bnum + 1;
+ }
+
+ *count = bptr - start;
+
+ if (len == 0)
+ goto done;
+ else if (len == 1)
+ {
+ if (b_readpb(vol, vol->vstart + blist[0]->bnum,
+ blist[0]->data, 1) == -1)
+ goto fail;
+ }
+ else
+ {
+ block buffer[HFS_BLOCKBUFSZ];
+
+ if (b_readpb(vol, vol->vstart + blist[0]->bnum, buffer, len) == -1)
+ goto fail;
+
+ for (i = 0; i < len; ++i)
+ memcpy(blist[i]->data, buffer[i], HFS_BLOCKSZ);
+ }
+
+ for (i = 0; i < len; ++i)
+ {
+ blist[i]->flags |= HFS_BUCKET_INUSE;
+ blist[i]->flags &= ~HFS_BUCKET_DIRTY;
+ }
+
+done:
+ return 0;
+
+fail:
+ return -1;
+}
+
+
+/*
+ * NAME: compare()
+ * DESCRIPTION: comparison function for qsort of cache bucket pointers
+ */
+static
+int compare(const bucket **b1, const bucket **b2)
+{
+ long diff;
+
+ diff = (*b1)->bnum - (*b2)->bnum;
+
+ if (diff < 0)
+ return -1;
+ else if (diff > 0)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * NAME: dobuckets()
+ * DESCRIPTION: fill or flush an array of cache buckets to a volume
+ */
+static
+int dobuckets(hfsvol *vol, bucket **chain, unsigned int len,
+ int (*func)(hfsvol *, bucket **, unsigned int *))
+{
+ unsigned int count, i;
+ int result = 0;
+
+ qsort(chain, len, sizeof(*chain),
+ (int (*)(const void *, const void *)) compare);
+
+ for (i = 0; i < len; i += count)
+ {
+ count = len - i;
+ if (func(vol, chain + i, &count) == -1)
+ result = -1;
+ }
+
+ return result;
+}
+
+# define fillbuckets(vol, chain, len) dobuckets(vol, chain, len, fillchain)
+
+/*
+ * NAME: block->finish()
+ * DESCRIPTION: commit and free a volume's block cache
+ */
+int b_finish(hfsvol *vol)
+{
+ int result = 0;
+
+ if (vol->cache == NULL)
+ goto done;
+
+# ifdef DEBUG
+ b_dumpcache(vol->cache);
+# endif
+
+ FREE(vol->cache);
+ vol->cache = NULL;
+
+done:
+ return result;
+}
+
+/*
+ * NAME: findbucket()
+ * DESCRIPTION: locate a bucket in the cache, and/or its hash slot
+ */
+static
+bucket *findbucket(bcache *cache, unsigned long bnum, bucket ***hslot)
+{
+ bucket *b;
+
+ *hslot = &cache->hash[bnum & (HFS_HASHSZ - 1)];
+
+ for (b = **hslot; b; b = b->hnext)
+ {
+ if (INUSE(b) && b->bnum == bnum)
+ break;
+ }
+
+ return b;
+}
+
+/*
+ * NAME: reuse()
+ * DESCRIPTION: free a bucket for reuse, flushing if necessary
+ */
+static
+int reuse(bcache *cache, bucket *b, unsigned long bnum)
+{
+ bucket *bptr;
+ int i;
+
+# ifdef DEBUG
+ if (INUSE(b))
+ fprintf(stderr, "BLOCK: CACHE reusing bucket containing "
+ "vol 0x%lx block %lu:%u\n",
+ (unsigned long) cache->vol, b->bnum, b->count);
+# endif
+
+ if (INUSE(b) && DIRTY(b))
+ {
+ /* flush most recently unused buckets */
+
+ for (bptr = b, i = 0; i < HFS_BLOCKBUFSZ; ++i)
+ {
+ bptr = bptr->cprev;
+ }
+ }
+
+ b->flags &= ~HFS_BUCKET_INUSE;
+ b->count = 1;
+ b->bnum = bnum;
+
+ return 0;
+}
+
+/*
+ * NAME: cplace()
+ * DESCRIPTION: move a bucket to an appropriate place near head of the chain
+ */
+static
+void cplace(bcache *cache, bucket *b)
+{
+ bucket *p;
+
+ for (p = cache->tail->cnext; p->count > 1; p = p->cnext)
+ --p->count;
+
+ b->cnext->cprev = b->cprev;
+ b->cprev->cnext = b->cnext;
+
+ if (cache->tail == b)
+ cache->tail = b->cprev;
+
+ b->cprev = p->cprev;
+ b->cnext = p;
+
+ p->cprev->cnext = b;
+ p->cprev = b;
+}
+
+/*
+ * NAME: hplace()
+ * DESCRIPTION: move a bucket to the head of its hash slot
+ */
+static
+void hplace(bucket **hslot, bucket *b)
+{
+ if (*hslot != b)
+ {
+ if (b->hprev)
+ *b->hprev = b->hnext;
+ if (b->hnext)
+ b->hnext->hprev = b->hprev;
+
+ b->hprev = hslot;
+ b->hnext = *hslot;
+
+ if (*hslot)
+ (*hslot)->hprev = &b->hnext;
+
+ *hslot = b;
+ }
+}
+
+/*
+ * NAME: getbucket()
+ * DESCRIPTION: fetch a bucket from the cache, or an empty one to be filled
+ */
+static
+bucket *getbucket(bcache *cache, unsigned long bnum, int fill)
+{
+ bucket **hslot, *b, *p, *bptr,
+ *chain[HFS_BLOCKBUFSZ], **slots[HFS_BLOCKBUFSZ];
+
+ b = findbucket(cache, bnum, &hslot);
+
+ if (b)
+ {
+ /* cache hit; move towards head of cache chain */
+
+ ++cache->hits;
+
+ if (++b->count > b->cprev->count &&
+ b != cache->tail->cnext)
+ {
+ p = b->cprev;
+
+ p->cprev->cnext = b;
+ b->cnext->cprev = p;
+
+ p->cnext = b->cnext;
+ b->cprev = p->cprev;
+
+ p->cprev = b;
+ b->cnext = p;
+
+ if (cache->tail == b)
+ cache->tail = p;
+ }
+ }
+ else
+ {
+ /* cache miss; reuse least-used cache bucket */
+
+ ++cache->misses;
+
+ b = cache->tail;
+
+ if (reuse(cache, b, bnum) == -1)
+ goto fail;
+
+ if (fill)
+ {
+ unsigned int len = 0;
+
+ chain[len] = b;
+ slots[len++] = hslot;
+
+ for (bptr = b->cprev;
+ len < (HFS_BLOCKBUFSZ >> 1) && ++bnum < cache->vol->vlen;
+ bptr = bptr->cprev)
+ {
+ if (findbucket(cache, bnum, &hslot))
+ break;
+
+ if (reuse(cache, bptr, bnum) == -1)
+ goto fail;
+
+ chain[len] = bptr;
+ slots[len++] = hslot;
+ }
+
+ if (fillbuckets(cache->vol, chain, len) == -1)
+ goto fail;
+
+ while (--len)
+ {
+ cplace(cache, chain[len]);
+ hplace(slots[len], chain[len]);
+ }
+
+ hslot = slots[0];
+ }
+
+ /* move bucket to appropriate place in chain */
+
+ cplace(cache, b);
+ }
+
+ /* insert at front of hash chain */
+
+ hplace(hslot, b);
+
+ return b;
+
+fail:
+ return NULL;
+}
+
+/*
+ * NAME: block->readpb()
+ * DESCRIPTION: read blocks from the physical medium (bypassing cache)
+ */
+int b_readpb(hfsvol *vol, unsigned long bnum, block *bp, unsigned int blen)
+{
+ unsigned long nblocks;
+
+# ifdef DEBUG
+ fprintf(stderr, "BLOCK: READ vol 0x%lx block %lu",
+ (unsigned long) vol, bnum);
+ if (blen > 1)
+ fprintf(stderr, "+%u[..%lu]\n", blen - 1, bnum + blen - 1);
+ else
+ fprintf(stderr, "\n");
+# endif
+
+ nblocks = os_seek(vol->os_fd, bnum, HFS_BLOCKSZ_BITS );
+ if (nblocks == (unsigned long) -1)
+ goto fail;
+
+ if (nblocks != bnum)
+ ERROR(EIO, "block seek failed for read");
+
+ nblocks = os_read(vol->os_fd, bp, blen, HFS_BLOCKSZ_BITS);
+ if (nblocks == (unsigned long) -1)
+ goto fail;
+
+ if (nblocks != blen)
+ ERROR(EIO, "incomplete block read");
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+
+/*
+ * NAME: block->readlb()
+ * DESCRIPTION: read a logical block from a volume (or from the cache)
+ */
+int b_readlb(hfsvol *vol, unsigned long bnum, block *bp)
+{
+ if (vol->vlen > 0 && bnum >= vol->vlen)
+ ERROR(EIO, "read nonexistent logical block");
+
+ if (vol->cache)
+ {
+ bucket *b;
+
+ b = getbucket(vol->cache, bnum, 1);
+ if (b == NULL)
+ goto fail;
+
+ memcpy(bp, b->data, HFS_BLOCKSZ);
+ }
+ else
+ {
+ if (b_readpb(vol, vol->vstart + bnum, bp, 1) == -1)
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: block->readab()
+ * DESCRIPTION: read a block from an allocation block from a volume
+ */
+int b_readab(hfsvol *vol, unsigned int anum, unsigned int index, block *bp)
+{
+ /* verify the allocation block exists and is marked as in-use */
+
+ if (anum >= vol->mdb.drNmAlBlks)
+ ERROR(EIO, "read nonexistent allocation block");
+ else if (vol->vbm && ! BMTST(vol->vbm, anum))
+ ERROR(EIO, "read unallocated block");
+
+ return b_readlb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + index, bp);
+
+fail:
+ return -1;
+}
+
+
+/*
+ * NAME: block->size()
+ * DESCRIPTION: return the number of physical blocks on a volume's medium
+ */
+unsigned long b_size(hfsvol *vol)
+{
+ unsigned long low, high, mid;
+ block b;
+
+ high = os_seek(vol->os_fd, -1, HFS_BLOCKSZ_BITS);
+
+ if (high != (unsigned long) -1 && high > 0)
+ return high;
+
+ /* manual size detection: first check there is at least 1 block in medium */
+
+ if (b_readpb(vol, 0, &b, 1) == -1)
+ ERROR(EIO, "size of medium indeterminable or empty");
+
+ for (low = 0, high = 2880;
+ high > 0 && b_readpb(vol, high - 1, &b, 1) != -1;
+ high <<= 1)
+ low = high - 1;
+
+ if (high == 0)
+ ERROR(EIO, "size of medium indeterminable or too large");
+
+ /* common case: 1440K floppy */
+
+ if (low == 2879 && b_readpb(vol, 2880, &b, 1) == -1)
+ return 2880;
+
+ /* binary search for other sizes */
+
+ while (low < high - 1)
+ {
+ mid = (low + high) >> 1;
+
+ if (b_readpb(vol, mid, &b, 1) == -1)
+ high = mid;
+ else
+ low = mid;
+ }
+
+ return low + 1;
+
+fail:
+ return 0;
+}
diff --git a/roms/openbios/fs/hfs/btree.c b/roms/openbios/fs/hfs/btree.c
new file mode 100644
index 00000000..cd5c8534
--- /dev/null
+++ b/roms/openbios/fs/hfs/btree.c
@@ -0,0 +1,230 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: btree.c,v 1.10 1998/11/02 22:08:54 rob Exp $
+ */
+
+#include "config.h"
+
+#include "libhfs.h"
+#include "btree.h"
+#include "data.h"
+#include "file.h"
+#include "block.h"
+#include "node.h"
+
+/*
+ * NAME: btree->getnode()
+ * DESCRIPTION: retrieve a numbered node from a B*-tree file
+ */
+int bt_getnode(node *np, btree *bt, unsigned long nnum)
+{
+ block *bp = &np->data;
+ const byte *ptr;
+ int i;
+
+ np->bt = bt;
+ np->nnum = nnum;
+
+# if 0
+ fprintf(stderr, "BTREE: GET vol \"%s\" btree \"%s\" node %lu\n",
+ bt->f.vol->mdb.drVN, bt->f.name, np->nnum);
+# endif
+
+ /* verify the node exists and is marked as in-use */
+
+ if (nnum > 0 && nnum >= bt->hdr.bthNNodes)
+ ERROR(EIO, "read nonexistent b*-tree node");
+ else if (bt->map && ! BMTST(bt->map, nnum))
+ ERROR(EIO, "read unallocated b*-tree node");
+
+ if (f_getblock(&bt->f, nnum, bp) == -1)
+ goto fail;
+
+ ptr = *bp;
+
+ d_fetchul(&ptr, &np->nd.ndFLink);
+ d_fetchul(&ptr, &np->nd.ndBLink);
+ d_fetchsb(&ptr, &np->nd.ndType);
+ d_fetchsb(&ptr, &np->nd.ndNHeight);
+ d_fetchuw(&ptr, &np->nd.ndNRecs);
+ d_fetchsw(&ptr, &np->nd.ndResv2);
+
+ if (np->nd.ndNRecs > HFS_MAX_NRECS)
+ ERROR(EIO, "too many b*-tree node records");
+
+ i = np->nd.ndNRecs + 1;
+
+ ptr = *bp + HFS_BLOCKSZ - (2 * i);
+
+ while (i--)
+ d_fetchuw(&ptr, &np->roff[i]);
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+
+/*
+ * NAME: btree->readhdr()
+ * DESCRIPTION: read the header node of a B*-tree
+ */
+int bt_readhdr(btree *bt)
+{
+ const byte *ptr;
+ byte *map = NULL;
+ int i;
+ unsigned long nnum;
+
+ if (bt_getnode(&bt->hdrnd, bt, 0) == -1)
+ goto fail;
+
+ if (bt->hdrnd.nd.ndType != ndHdrNode ||
+ bt->hdrnd.nd.ndNRecs != 3 ||
+ bt->hdrnd.roff[0] != 0x00e ||
+ bt->hdrnd.roff[1] != 0x078 ||
+ bt->hdrnd.roff[2] != 0x0f8 ||
+ bt->hdrnd.roff[3] != 0x1f8)
+ ERROR(EIO, "malformed b*-tree header node");
+
+ /* read header record */
+
+ ptr = HFS_NODEREC(bt->hdrnd, 0);
+
+ d_fetchuw(&ptr, &bt->hdr.bthDepth);
+ d_fetchul(&ptr, &bt->hdr.bthRoot);
+ d_fetchul(&ptr, &bt->hdr.bthNRecs);
+ d_fetchul(&ptr, &bt->hdr.bthFNode);
+ d_fetchul(&ptr, &bt->hdr.bthLNode);
+ d_fetchuw(&ptr, &bt->hdr.bthNodeSize);
+ d_fetchuw(&ptr, &bt->hdr.bthKeyLen);
+ d_fetchul(&ptr, &bt->hdr.bthNNodes);
+ d_fetchul(&ptr, &bt->hdr.bthFree);
+
+ for (i = 0; i < 76; ++i)
+ d_fetchsb(&ptr, &bt->hdr.bthResv[i]);
+
+ if (bt->hdr.bthNodeSize != HFS_BLOCKSZ)
+ ERROR(EINVAL, "unsupported b*-tree node size");
+
+ /* read map record; construct btree bitmap */
+ /* don't set bt->map until we're done, since getnode() checks it */
+
+ map = ALLOC(byte, HFS_MAP1SZ);
+ if (map == NULL)
+ ERROR(ENOMEM, NULL);
+
+ memcpy(map, HFS_NODEREC(bt->hdrnd, 2), HFS_MAP1SZ);
+ bt->mapsz = HFS_MAP1SZ;
+
+ /* read continuation map records, if any */
+
+ nnum = bt->hdrnd.nd.ndFLink;
+
+ while (nnum)
+ {
+ node n;
+ byte *newmap;
+
+ if (bt_getnode(&n, bt, nnum) == -1)
+ goto fail;
+
+ if (n.nd.ndType != ndMapNode ||
+ n.nd.ndNRecs != 1 ||
+ n.roff[0] != 0x00e ||
+ n.roff[1] != 0x1fa)
+ ERROR(EIO, "malformed b*-tree map node");
+
+ newmap = REALLOC(map, byte, bt->mapsz + HFS_MAPXSZ);
+ if (newmap == NULL)
+ ERROR(ENOMEM, NULL);
+
+ map = newmap;
+
+ memcpy(map + bt->mapsz, HFS_NODEREC(n, 0), HFS_MAPXSZ);
+ bt->mapsz += HFS_MAPXSZ;
+
+ nnum = n.nd.ndFLink;
+ }
+
+ bt->map = map;
+
+ return 0;
+
+fail:
+ FREE(map);
+ return -1;
+}
+
+
+/*
+ * NAME: btree->search()
+ * DESCRIPTION: locate a data record given a search key
+ */
+int bt_search(btree *bt, const byte *key, node *np)
+{
+ int found = 0;
+ unsigned long nnum;
+
+ nnum = bt->hdr.bthRoot;
+
+ if (nnum == 0)
+ ERROR(ENOENT, NULL);
+
+ while (1)
+ {
+ const byte *rec;
+
+ if (bt_getnode(np, bt, nnum) == -1)
+ {
+ found = -1;
+ goto fail;
+ }
+
+ found = n_search(np, key);
+
+ switch (np->nd.ndType)
+ {
+ case ndIndxNode:
+ if (np->rnum == -1)
+ ERROR(ENOENT, NULL);
+
+ rec = HFS_NODEREC(*np, np->rnum);
+ nnum = d_getul(HFS_RECDATA(rec));
+
+ break;
+
+ case ndLeafNode:
+ if (! found)
+ ERROR(ENOENT, NULL);
+
+ goto done;
+
+ default:
+ found = -1;
+ ERROR(EIO, "unexpected b*-tree node");
+ }
+ }
+
+done:
+fail:
+ return found;
+}
diff --git a/roms/openbios/fs/hfs/build.xml b/roms/openbios/fs/hfs/build.xml
new file mode 100644
index 00000000..2ac6fdbb
--- /dev/null
+++ b/roms/openbios/fs/hfs/build.xml
@@ -0,0 +1,15 @@
+<build>
+ <library name="fs" type="static" target="target">
+ <object source="block.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="btree.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="data.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="file.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="hfs.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="low.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="medium.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="node.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="record.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="volume.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ <object source="hfs_fs.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/>
+ </library>
+</build>
diff --git a/roms/openbios/fs/hfs/data.c b/roms/openbios/fs/hfs/data.c
new file mode 100644
index 00000000..a0e4a8ea
--- /dev/null
+++ b/roms/openbios/fs/hfs/data.c
@@ -0,0 +1,476 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: data.c,v 1.7 1998/11/02 22:08:57 rob Exp $
+ */
+
+#include "config.h"
+#include "data.h"
+
+#define TIMEDIFF 2082844800UL
+
+static
+time_t tzdiff = -1;
+
+static const
+unsigned char hfs_charorder[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+
+ 0x20, 0x22, 0x23, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
+ 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+ 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+ 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+
+ 0x47, 0x48, 0x58, 0x5a, 0x5e, 0x60, 0x67, 0x69,
+ 0x6b, 0x6d, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7f,
+ 0x8d, 0x8f, 0x91, 0x93, 0x96, 0x98, 0x9f, 0xa1,
+ 0xa3, 0xa5, 0xa8, 0xaa, 0xab, 0xac, 0xad, 0xae,
+
+ 0x54, 0x48, 0x58, 0x5a, 0x5e, 0x60, 0x67, 0x69,
+ 0x6b, 0x6d, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7f,
+ 0x8d, 0x8f, 0x91, 0x93, 0x96, 0x98, 0x9f, 0xa1,
+ 0xa3, 0xa5, 0xa8, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
+
+ 0x4c, 0x50, 0x5c, 0x62, 0x7d, 0x81, 0x9a, 0x55,
+ 0x4a, 0x56, 0x4c, 0x4e, 0x50, 0x5c, 0x62, 0x64,
+ 0x65, 0x66, 0x6f, 0x70, 0x71, 0x72, 0x7d, 0x89,
+ 0x8a, 0x8b, 0x81, 0x83, 0x9c, 0x9d, 0x9e, 0x9a,
+
+ 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0x95,
+ 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0x52, 0x85,
+ 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+ 0xc9, 0xca, 0xcb, 0x57, 0x8c, 0xcc, 0x52, 0x85,
+
+ 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0x26,
+ 0x27, 0xd4, 0x20, 0x4a, 0x4e, 0x83, 0x87, 0x87,
+ 0xd5, 0xd6, 0x24, 0x25, 0x2d, 0x2e, 0xd7, 0xd8,
+ 0xa7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+/*
+ * NAME: data->getsb()
+ * DESCRIPTION: marshal 1 signed byte into local host format
+ */
+signed char d_getsb(register const unsigned char *ptr)
+{
+ return ptr[0];
+}
+
+/*
+ * NAME: data->getub()
+ * DESCRIPTION: marshal 1 unsigned byte into local host format
+ */
+unsigned char d_getub(register const unsigned char *ptr)
+{
+ return ptr[0];
+}
+
+/*
+ * NAME: data->getsw()
+ * DESCRIPTION: marshal 2 signed bytes into local host format
+ */
+signed short d_getsw(register const unsigned char *ptr)
+{
+ return
+ ((( signed short) ptr[0] << 8) |
+ ((unsigned short) ptr[1] << 0));
+}
+
+/*
+ * NAME: data->getuw()
+ * DESCRIPTION: marshal 2 unsigned bytes into local host format
+ */
+unsigned short d_getuw(register const unsigned char *ptr)
+{
+ return
+ (((unsigned short) ptr[0] << 8) |
+ ((unsigned short) ptr[1] << 0));
+}
+
+/*
+ * NAME: data->getsl()
+ * DESCRIPTION: marshal 4 signed bytes into local host format
+ */
+signed long d_getsl(register const unsigned char *ptr)
+{
+ return
+ ((( signed long) ptr[0] << 24) |
+ ((unsigned long) ptr[1] << 16) |
+ ((unsigned long) ptr[2] << 8) |
+ ((unsigned long) ptr[3] << 0));
+}
+
+/*
+ * NAME: data->getul()
+ * DESCRIPTION: marshal 4 unsigned bytes into local host format
+ */
+unsigned long d_getul(register const unsigned char *ptr)
+{
+ return
+ (((unsigned long) ptr[0] << 24) |
+ ((unsigned long) ptr[1] << 16) |
+ ((unsigned long) ptr[2] << 8) |
+ ((unsigned long) ptr[3] << 0));
+}
+
+/*
+ * NAME: data->putsb()
+ * DESCRIPTION: marshal 1 signed byte out in big-endian format
+ */
+void d_putsb(register unsigned char *ptr,
+ register signed char data)
+{
+ *ptr = data;
+}
+
+/*
+ * NAME: data->putub()
+ * DESCRIPTION: marshal 1 unsigned byte out in big-endian format
+ */
+void d_putub(register unsigned char *ptr,
+ register unsigned char data)
+{
+ *ptr = data;
+}
+
+/*
+ * NAME: data->putsw()
+ * DESCRIPTION: marshal 2 signed bytes out in big-endian format
+ */
+void d_putsw(register unsigned char *ptr,
+ register signed short data)
+{
+ *ptr++ = ((unsigned short) data & 0xff00) >> 8;
+ *ptr = ((unsigned short) data & 0x00ff) >> 0;
+}
+
+/*
+ * NAME: data->putuw()
+ * DESCRIPTION: marshal 2 unsigned bytes out in big-endian format
+ */
+void d_putuw(register unsigned char *ptr,
+ register unsigned short data)
+{
+ *ptr++ = (data & 0xff00) >> 8;
+ *ptr = (data & 0x00ff) >> 0;
+}
+
+/*
+ * NAME: data->putsl()
+ * DESCRIPTION: marshal 4 signed bytes out in big-endian format
+ */
+void d_putsl(register unsigned char *ptr,
+ register signed long data)
+{
+ *ptr++ = ((unsigned long) data & 0xff000000UL) >> 24;
+ *ptr++ = ((unsigned long) data & 0x00ff0000UL) >> 16;
+ *ptr++ = ((unsigned long) data & 0x0000ff00UL) >> 8;
+ *ptr = ((unsigned long) data & 0x000000ffUL) >> 0;
+}
+
+/*
+ * NAME: data->putul()
+ * DESCRIPTION: marshal 4 unsigned bytes out in big-endian format
+ */
+void d_putul(register unsigned char *ptr,
+ register unsigned long data)
+{
+ *ptr++ = (data & 0xff000000UL) >> 24;
+ *ptr++ = (data & 0x00ff0000UL) >> 16;
+ *ptr++ = (data & 0x0000ff00UL) >> 8;
+ *ptr = (data & 0x000000ffUL) >> 0;
+}
+
+/*
+ * NAME: data->fetchsb()
+ * DESCRIPTION: incrementally retrieve a signed byte of data
+ */
+void d_fetchsb(register const unsigned char **ptr,
+ register signed char *dest)
+{
+ *dest = *(*ptr)++;
+}
+
+/*
+ * NAME: data->fetchub()
+ * DESCRIPTION: incrementally retrieve an unsigned byte of data
+ */
+void d_fetchub(register const unsigned char **ptr,
+ register unsigned char *dest)
+{
+ *dest = *(*ptr)++;
+}
+
+/*
+ * NAME: data->fetchsw()
+ * DESCRIPTION: incrementally retrieve a signed word of data
+ */
+void d_fetchsw(register const unsigned char **ptr,
+ register signed short *dest)
+{
+ *dest =
+ ((( signed short) (*ptr)[0] << 8) |
+ ((unsigned short) (*ptr)[1] << 0));
+ *ptr += 2;
+}
+
+/*
+ * NAME: data->fetchuw()
+ * DESCRIPTION: incrementally retrieve an unsigned word of data
+ */
+void d_fetchuw(register const unsigned char **ptr,
+ register unsigned short *dest)
+{
+ *dest =
+ (((unsigned short) (*ptr)[0] << 8) |
+ ((unsigned short) (*ptr)[1] << 0));
+ *ptr += 2;
+}
+
+/*
+ * NAME: data->fetchsl()
+ * DESCRIPTION: incrementally retrieve a signed long word of data
+ */
+void d_fetchsl(register const unsigned char **ptr,
+ register signed long *dest)
+{
+ *dest =
+ ((( signed long) (*ptr)[0] << 24) |
+ ((unsigned long) (*ptr)[1] << 16) |
+ ((unsigned long) (*ptr)[2] << 8) |
+ ((unsigned long) (*ptr)[3] << 0));
+ *ptr += 4;
+}
+
+/*
+ * NAME: data->fetchul()
+ * DESCRIPTION: incrementally retrieve an unsigned long word of data
+ */
+void d_fetchul(register const unsigned char **ptr,
+ register unsigned long *dest)
+{
+ *dest =
+ (((unsigned long) (*ptr)[0] << 24) |
+ ((unsigned long) (*ptr)[1] << 16) |
+ ((unsigned long) (*ptr)[2] << 8) |
+ ((unsigned long) (*ptr)[3] << 0));
+ *ptr += 4;
+}
+
+/*
+ * NAME: data->storesb()
+ * DESCRIPTION: incrementally store a signed byte of data
+ */
+void d_storesb(register unsigned char **ptr,
+ register signed char data)
+{
+ *(*ptr)++ = data;
+}
+
+/*
+ * NAME: data->storeub()
+ * DESCRIPTION: incrementally store an unsigned byte of data
+ */
+void d_storeub(register unsigned char **ptr,
+ register unsigned char data)
+{
+ *(*ptr)++ = data;
+}
+
+/*
+ * NAME: data->storesw()
+ * DESCRIPTION: incrementally store a signed word of data
+ */
+void d_storesw(register unsigned char **ptr,
+ register signed short data)
+{
+ *(*ptr)++ = ((unsigned short) data & 0xff00) >> 8;
+ *(*ptr)++ = ((unsigned short) data & 0x00ff) >> 0;
+}
+
+/*
+ * NAME: data->storeuw()
+ * DESCRIPTION: incrementally store an unsigned word of data
+ */
+void d_storeuw(register unsigned char **ptr,
+ register unsigned short data)
+{
+ *(*ptr)++ = (data & 0xff00) >> 8;
+ *(*ptr)++ = (data & 0x00ff) >> 0;
+}
+
+/*
+ * NAME: data->storesl()
+ * DESCRIPTION: incrementally store a signed long word of data
+ */
+void d_storesl(register unsigned char **ptr,
+ register signed long data)
+{
+ *(*ptr)++ = ((unsigned long) data & 0xff000000UL) >> 24;
+ *(*ptr)++ = ((unsigned long) data & 0x00ff0000UL) >> 16;
+ *(*ptr)++ = ((unsigned long) data & 0x0000ff00UL) >> 8;
+ *(*ptr)++ = ((unsigned long) data & 0x000000ffUL) >> 0;
+}
+
+/*
+ * NAME: data->storeul()
+ * DESCRIPTION: incrementally store an unsigned long word of data
+ */
+void d_storeul(register unsigned char **ptr,
+ register unsigned long data)
+{
+ *(*ptr)++ = (data & 0xff000000UL) >> 24;
+ *(*ptr)++ = (data & 0x00ff0000UL) >> 16;
+ *(*ptr)++ = (data & 0x0000ff00UL) >> 8;
+ *(*ptr)++ = (data & 0x000000ffUL) >> 0;
+}
+
+/*
+ * NAME: data->fetchstr()
+ * DESCRIPTION: incrementally retrieve a string
+ */
+void d_fetchstr(const unsigned char **ptr, char *dest, unsigned size)
+{
+ unsigned len;
+
+ len = d_getub(*ptr);
+
+ if (len > 0 && len < size)
+ memcpy(dest, *ptr + 1, len);
+ else
+ len = 0;
+
+ dest[len] = 0;
+
+ *ptr += size;
+}
+
+/*
+ * NAME: data->storestr()
+ * DESCRIPTION: incrementally store a string
+ */
+void d_storestr(unsigned char **ptr, const char *src, unsigned size)
+{
+ unsigned len;
+
+ len = strlen(src);
+ if (len > --size)
+ len = 0;
+
+ d_storeub(ptr, len);
+
+ memcpy(*ptr, src, len);
+ memset(*ptr + len, 0, size - len);
+
+ *ptr += size;
+}
+
+/*
+ * NAME: data->relstring()
+ * DESCRIPTION: compare two strings as per MacOS for HFS
+ */
+int d_relstring(const char *str1, const char *str2)
+{
+ register int diff;
+
+ while (*str1 && *str2)
+ {
+ diff = hfs_charorder[(unsigned char) *str1] -
+ hfs_charorder[(unsigned char) *str2];
+
+ if (diff)
+ return diff;
+
+ ++str1, ++str2;
+ }
+
+ if (! *str1 && *str2)
+ return -1;
+ else if (*str1 && ! *str2)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * NAME: calctzdiff()
+ * DESCRIPTION: calculate the timezone difference between local time and UTC
+ */
+static
+void calctzdiff(void)
+{
+# ifdef HAVE_MKTIME
+
+ time_t t;
+ int isdst;
+ struct tm tm;
+ const struct tm *tmp;
+
+ time(&t);
+ isdst = localtime(&t)->tm_isdst;
+
+ tmp = gmtime(&t);
+ if (tmp)
+ {
+ tm = *tmp;
+ tm.tm_isdst = isdst;
+
+ tzdiff = t - mktime(&tm);
+ }
+ else
+ tzdiff = 0;
+
+# else
+
+ tzdiff = 0;
+
+# endif
+}
+
+/*
+ * NAME: data->ltime()
+ * DESCRIPTION: convert MacOS time to local time
+ */
+time_t d_ltime(unsigned long mtime)
+{
+ if (tzdiff == -1)
+ calctzdiff();
+
+ return (time_t) (mtime - TIMEDIFF) - tzdiff;
+}
+
+/*
+ * NAME: data->mtime()
+ * DESCRIPTION: convert local time to MacOS time
+ */
+unsigned long d_mtime(time_t ltime)
+{
+ if (tzdiff == -1)
+ calctzdiff();
+
+ return (unsigned long) (ltime + tzdiff) + TIMEDIFF;
+}
diff --git a/roms/openbios/fs/hfs/file.c b/roms/openbios/fs/hfs/file.c
new file mode 100644
index 00000000..a6ddb893
--- /dev/null
+++ b/roms/openbios/fs/hfs/file.c
@@ -0,0 +1,191 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: file.c,v 1.9 1998/11/02 22:08:59 rob Exp $
+ */
+
+#include "config.h"
+#include "libhfs.h"
+#include "file.h"
+#include "btree.h"
+#include "record.h"
+#include "volume.h"
+
+/*
+ * NAME: file->init()
+ * DESCRIPTION: initialize file structure
+ */
+void f_init(hfsfile *file, hfsvol *vol, long cnid, const char *name)
+{
+ int i;
+
+ file->vol = vol;
+ file->parid = 0;
+
+ strcpy(file->name, name);
+
+ file->cat.cdrType = cdrFilRec;
+ file->cat.cdrResrv2 = 0;
+
+ file->cat.u.fil.filFlags = 0;
+ file->cat.u.fil.filTyp = 0;
+
+ file->cat.u.fil.filUsrWds.fdType = 0;
+ file->cat.u.fil.filUsrWds.fdCreator = 0;
+ file->cat.u.fil.filUsrWds.fdFlags = 0;
+ file->cat.u.fil.filUsrWds.fdLocation.v = 0;
+ file->cat.u.fil.filUsrWds.fdLocation.h = 0;
+ file->cat.u.fil.filUsrWds.fdFldr = 0;
+
+ file->cat.u.fil.filFlNum = cnid;
+ file->cat.u.fil.filStBlk = 0;
+ file->cat.u.fil.filLgLen = 0;
+ file->cat.u.fil.filPyLen = 0;
+ file->cat.u.fil.filRStBlk = 0;
+ file->cat.u.fil.filRLgLen = 0;
+ file->cat.u.fil.filRPyLen = 0;
+ file->cat.u.fil.filCrDat = 0;
+ file->cat.u.fil.filMdDat = 0;
+ file->cat.u.fil.filBkDat = 0;
+
+ file->cat.u.fil.filFndrInfo.fdIconID = 0;
+ for (i = 0; i < 4; ++i)
+ file->cat.u.fil.filFndrInfo.fdUnused[i] = 0;
+ file->cat.u.fil.filFndrInfo.fdComment = 0;
+ file->cat.u.fil.filFndrInfo.fdPutAway = 0;
+
+ file->cat.u.fil.filClpSize = 0;
+
+ for (i = 0; i < 3; ++i)
+ {
+ file->cat.u.fil.filExtRec[i].xdrStABN = 0;
+ file->cat.u.fil.filExtRec[i].xdrNumABlks = 0;
+
+ file->cat.u.fil.filRExtRec[i].xdrStABN = 0;
+ file->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
+ }
+
+ file->cat.u.fil.filResrv = 0;
+
+ f_selectfork(file, fkData);
+
+ file->flags = 0;
+
+ file->prev = NULL;
+ file->next = NULL;
+}
+
+/*
+ * NAME: file->selectfork()
+ * DESCRIPTION: choose a fork for file operations
+ */
+void f_selectfork(hfsfile *file, int fork)
+{
+ file->fork = fork;
+
+ memcpy(&file->ext, fork == fkData ?
+ &file->cat.u.fil.filExtRec : &file->cat.u.fil.filRExtRec,
+ sizeof(ExtDataRec));
+
+ file->fabn = 0;
+ file->pos = 0;
+}
+
+/*
+ * NAME: file->getptrs()
+ * DESCRIPTION: make pointers to the current fork's lengths and extents
+ */
+void f_getptrs(hfsfile *file, ExtDataRec **extrec,
+ unsigned long **lglen, unsigned long **pylen)
+{
+ if (file->fork == fkData)
+ {
+ if (extrec)
+ *extrec = &file->cat.u.fil.filExtRec;
+ if (lglen)
+ *lglen = &file->cat.u.fil.filLgLen;
+ if (pylen)
+ *pylen = &file->cat.u.fil.filPyLen;
+ }
+ else
+ {
+ if (extrec)
+ *extrec = &file->cat.u.fil.filRExtRec;
+ if (lglen)
+ *lglen = &file->cat.u.fil.filRLgLen;
+ if (pylen)
+ *pylen = &file->cat.u.fil.filRPyLen;
+ }
+}
+
+/*
+ * NAME: file->doblock()
+ * DESCRIPTION: read or write a numbered block from a file
+ */
+int f_doblock(hfsfile *file, unsigned long num, block *bp,
+ int (*func)(hfsvol *, unsigned int, unsigned int, block *))
+{
+ unsigned int abnum;
+ unsigned int blnum;
+ unsigned int fabn;
+ int i;
+
+ abnum = num / file->vol->lpa;
+ blnum = num % file->vol->lpa;
+
+ /* locate the appropriate extent record */
+
+ fabn = file->fabn;
+
+ if (abnum < fabn)
+ {
+ ExtDataRec *extrec;
+
+ f_getptrs(file, &extrec, NULL, NULL);
+
+ fabn = file->fabn = 0;
+ memcpy(&file->ext, extrec, sizeof(ExtDataRec));
+ }
+ else
+ abnum -= fabn;
+
+ while (1)
+ {
+ unsigned int n;
+
+ for (i = 0; i < 3; ++i)
+ {
+ n = file->ext[i].xdrNumABlks;
+
+ if (abnum < n)
+ return func(file->vol, file->ext[i].xdrStABN + abnum, blnum, bp);
+
+ fabn += n;
+ abnum -= n;
+ }
+
+ if (v_extsearch(file, fabn, &file->ext, NULL) <= 0)
+ goto fail;
+
+ file->fabn = fabn;
+ }
+
+fail:
+ return -1;
+}
diff --git a/roms/openbios/fs/hfs/hfs.c b/roms/openbios/fs/hfs/hfs.c
new file mode 100644
index 00000000..0c5fefb4
--- /dev/null
+++ b/roms/openbios/fs/hfs/hfs.c
@@ -0,0 +1,747 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: hfs.c,v 1.15 1998/11/02 22:09:00 rob Exp $
+ */
+
+#include "config.h"
+#include "libhfs.h"
+#include "data.h"
+#include "block.h"
+#include "medium.h"
+#include "file.h"
+#include "btree.h"
+#include "node.h"
+#include "record.h"
+#include "volume.h"
+
+const char *hfs_error = "no error"; /* static error string */
+
+hfsvol *hfs_mounts; /* linked list of mounted volumes */
+
+static
+hfsvol *curvol; /* current volume */
+
+
+/*
+ * NAME: getvol()
+ * DESCRIPTION: validate a volume reference
+ */
+static
+int getvol(hfsvol **vol)
+{
+ if (*vol == NULL)
+ {
+ if (curvol == NULL)
+ ERROR(EINVAL, "no volume is current");
+
+ *vol = curvol;
+ }
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/* High-Level Volume Routines ============================================== */
+
+/*
+ * NAME: hfs->mount()
+ * DESCRIPTION: open an HFS volume; return volume descriptor or 0 (error)
+ */
+hfsvol *hfs_mount( int os_fd, int pnum)
+{
+ hfsvol *vol, *check;
+ int mode = HFS_MODE_RDONLY;
+
+ /* see if the volume is already mounted */
+ for (check = hfs_mounts; check; check = check->next)
+ {
+ if (check->pnum == pnum && v_same(check, os_fd) == 1)
+ {
+ vol = check;
+ goto done;
+ }
+ }
+
+ vol = ALLOC(hfsvol, 1);
+ if (vol == NULL)
+ ERROR(ENOMEM, NULL);
+
+ v_init(vol, mode);
+
+ vol->flags |= HFS_VOL_READONLY;
+ if( v_open(vol, os_fd) == -1 )
+ goto fail;
+
+ /* mount the volume */
+
+ if (v_geometry(vol, pnum) == -1 ||
+ v_mount(vol) == -1)
+ goto fail;
+
+ /* add to linked list of volumes */
+
+ vol->prev = NULL;
+ vol->next = hfs_mounts;
+
+ if (hfs_mounts)
+ hfs_mounts->prev = vol;
+
+ hfs_mounts = vol;
+
+done:
+ ++vol->refs;
+ curvol = vol;
+
+ return vol;
+
+fail:
+ if (vol)
+ {
+ v_close(vol);
+ FREE(vol);
+ }
+
+ return NULL;
+}
+
+
+/*
+ * NAME: hfs->umount()
+ * DESCRIPTION: close an HFS volume
+ */
+int hfs_umount(hfsvol *vol)
+{
+ int result = 0;
+
+ if (getvol(&vol) == -1)
+ goto fail;
+
+ if (--vol->refs)
+ {
+ goto done;
+ }
+
+ /* close all open files and directories */
+
+ while (vol->files)
+ {
+ if (hfs_close(vol->files) == -1)
+ result = -1;
+ }
+
+ while (vol->dirs)
+ {
+ if (hfs_closedir(vol->dirs) == -1)
+ result = -1;
+ }
+
+ /* close medium */
+
+ if (v_close(vol) == -1)
+ result = -1;
+
+ /* remove from linked list of volumes */
+
+ if (vol->prev)
+ vol->prev->next = vol->next;
+ if (vol->next)
+ vol->next->prev = vol->prev;
+
+ if (vol == hfs_mounts)
+ hfs_mounts = vol->next;
+ if (vol == curvol)
+ curvol = NULL;
+
+ FREE(vol);
+
+done:
+ return result;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: hfs->umountall()
+ * DESCRIPTION: unmount all mounted volumes
+ */
+void hfs_umountall(void)
+{
+ while (hfs_mounts)
+ hfs_umount(hfs_mounts);
+}
+
+/*
+ * NAME: hfs->getvol()
+ * DESCRIPTION: return a pointer to a mounted volume
+ */
+hfsvol *hfs_getvol(const char *name)
+{
+ hfsvol *vol;
+
+ if (name == NULL)
+ return curvol;
+
+ for (vol = hfs_mounts; vol; vol = vol->next)
+ {
+ if (d_relstring(name, vol->mdb.drVN) == 0)
+ return vol;
+ }
+
+ return NULL;
+}
+
+/*
+ * NAME: hfs->setvol()
+ * DESCRIPTION: change the current volume
+ */
+void hfs_setvol(hfsvol *vol)
+{
+ curvol = vol;
+}
+
+/*
+ * NAME: hfs->vstat()
+ * DESCRIPTION: return volume statistics
+ */
+int hfs_vstat(hfsvol *vol, hfsvolent *ent)
+{
+ if (getvol(&vol) == -1)
+ goto fail;
+
+ strcpy(ent->name, vol->mdb.drVN);
+
+ ent->flags = (vol->flags & HFS_VOL_READONLY) ? HFS_ISLOCKED : 0;
+
+ ent->totbytes = vol->mdb.drNmAlBlks * vol->mdb.drAlBlkSiz;
+ ent->freebytes = vol->mdb.drFreeBks * vol->mdb.drAlBlkSiz;
+
+ ent->alblocksz = vol->mdb.drAlBlkSiz;
+ ent->clumpsz = vol->mdb.drClpSiz;
+
+ ent->numfiles = vol->mdb.drFilCnt;
+ ent->numdirs = vol->mdb.drDirCnt;
+
+ ent->crdate = d_ltime(vol->mdb.drCrDate);
+ ent->mddate = d_ltime(vol->mdb.drLsMod);
+ ent->bkdate = d_ltime(vol->mdb.drVolBkUp);
+
+ ent->blessed = vol->mdb.drFndrInfo[0];
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+
+/* High-Level Directory Routines =========================================== */
+
+/*
+ * NAME: hfs->chdir()
+ * DESCRIPTION: change current HFS directory
+ */
+int hfs_chdir(hfsvol *vol, const char *path)
+{
+ CatDataRec data;
+
+ if (getvol(&vol) == -1 ||
+ v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0)
+ goto fail;
+
+ if (data.cdrType != cdrDirRec)
+ ERROR(ENOTDIR, NULL);
+
+ vol->cwd = data.u.dir.dirDirID;
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: hfs->getcwd()
+ * DESCRIPTION: return the current working directory ID
+ */
+unsigned long hfs_getcwd(hfsvol *vol)
+{
+ if (getvol(&vol) == -1)
+ return 0;
+
+ return vol->cwd;
+}
+
+/*
+ * NAME: hfs->setcwd()
+ * DESCRIPTION: set the current working directory ID
+ */
+int hfs_setcwd(hfsvol *vol, unsigned long id)
+{
+ if (getvol(&vol) == -1)
+ goto fail;
+
+ if (id == vol->cwd)
+ goto done;
+
+ /* make sure the directory exists */
+
+ if (v_getdthread(vol, id, NULL, NULL) <= 0)
+ goto fail;
+
+ vol->cwd = id;
+
+done:
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: hfs->dirinfo()
+ * DESCRIPTION: given a directory ID, return its (name and) parent ID
+ */
+int hfs_dirinfo(hfsvol *vol, unsigned long *id, char *name)
+{
+ CatDataRec thread;
+
+ if (getvol(&vol) == -1 ||
+ v_getdthread(vol, *id, &thread, NULL) <= 0)
+ goto fail;
+
+ *id = thread.u.dthd.thdParID;
+
+ if (name)
+ strcpy(name, thread.u.dthd.thdCName);
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: hfs->opendir()
+ * DESCRIPTION: prepare to read the contents of a directory
+ */
+hfsdir *hfs_opendir(hfsvol *vol, const char *path)
+{
+ hfsdir *dir = NULL;
+ CatKeyRec key;
+ CatDataRec data;
+ byte pkey[HFS_CATKEYLEN];
+
+ if (getvol(&vol) == -1)
+ goto fail;
+
+ dir = ALLOC(hfsdir, 1);
+ if (dir == NULL)
+ ERROR(ENOMEM, NULL);
+
+ dir->vol = vol;
+
+ if (*path == 0)
+ {
+ /* meta-directory containing root dirs from all mounted volumes */
+
+ dir->dirid = 0;
+ dir->vptr = hfs_mounts;
+ }
+ else
+ {
+ if (v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0)
+ goto fail;
+
+ if (data.cdrType != cdrDirRec)
+ ERROR(ENOTDIR, NULL);
+
+ dir->dirid = data.u.dir.dirDirID;
+ dir->vptr = NULL;
+
+ r_makecatkey(&key, dir->dirid, "");
+ r_packcatkey(&key, pkey, NULL);
+
+ if (bt_search(&vol->cat, pkey, &dir->n) <= 0)
+ goto fail;
+ }
+
+ dir->prev = NULL;
+ dir->next = vol->dirs;
+
+ if (vol->dirs)
+ vol->dirs->prev = dir;
+
+ vol->dirs = dir;
+
+ return dir;
+
+fail:
+ FREE(dir);
+ return NULL;
+}
+
+/*
+ * NAME: hfs->readdir()
+ * DESCRIPTION: return the next entry in the directory
+ */
+int hfs_readdir(hfsdir *dir, hfsdirent *ent)
+{
+ CatKeyRec key;
+ CatDataRec data;
+ const byte *ptr;
+
+ if (dir->dirid == 0)
+ {
+ hfsvol *vol;
+ char cname[HFS_MAX_FLEN + 1];
+
+ for (vol = hfs_mounts; vol; vol = vol->next)
+ {
+ if (vol == dir->vptr)
+ break;
+ }
+
+ if (vol == NULL)
+ ERROR(ENOENT, "no more entries");
+
+ if (v_getdthread(vol, HFS_CNID_ROOTDIR, &data, NULL) <= 0 ||
+ v_catsearch(vol, HFS_CNID_ROOTPAR, data.u.dthd.thdCName,
+ &data, cname, NULL) <= 0)
+ goto fail;
+
+ r_unpackdirent(HFS_CNID_ROOTPAR, cname, &data, ent);
+
+ dir->vptr = vol->next;
+
+ goto done;
+ }
+
+ if (dir->n.rnum == -1)
+ ERROR(ENOENT, "no more entries");
+
+ while (1)
+ {
+ ++dir->n.rnum;
+
+ while (dir->n.rnum >= dir->n.nd.ndNRecs)
+ {
+ if (dir->n.nd.ndFLink == 0)
+ {
+ dir->n.rnum = -1;
+ ERROR(ENOENT, "no more entries");
+ }
+
+ if (bt_getnode(&dir->n, dir->n.bt, dir->n.nd.ndFLink) == -1)
+ {
+ dir->n.rnum = -1;
+ goto fail;
+ }
+
+ dir->n.rnum = 0;
+ }
+
+ ptr = HFS_NODEREC(dir->n, dir->n.rnum);
+
+ r_unpackcatkey(ptr, &key);
+
+ if (key.ckrParID != dir->dirid)
+ {
+ dir->n.rnum = -1;
+ ERROR(ENOENT, "no more entries");
+ }
+
+ r_unpackcatdata(HFS_RECDATA(ptr), &data);
+
+ switch (data.cdrType)
+ {
+ case cdrDirRec:
+ case cdrFilRec:
+ r_unpackdirent(key.ckrParID, key.ckrCName, &data, ent);
+ goto done;
+
+ case cdrThdRec:
+ case cdrFThdRec:
+ break;
+
+ default:
+ dir->n.rnum = -1;
+ ERROR(EIO, "unexpected directory entry found");
+ }
+ }
+
+done:
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: hfs->closedir()
+ * DESCRIPTION: stop reading a directory
+ */
+int hfs_closedir(hfsdir *dir)
+{
+ hfsvol *vol = dir->vol;
+
+ if (dir->prev)
+ dir->prev->next = dir->next;
+ if (dir->next)
+ dir->next->prev = dir->prev;
+ if (dir == vol->dirs)
+ vol->dirs = dir->next;
+
+ FREE(dir);
+
+ return 0;
+}
+
+/* High-Level File Routines ================================================ */
+
+/*
+ * NAME: hfs->open()
+ * DESCRIPTION: prepare a file for I/O
+ */
+hfsfile *hfs_open(hfsvol *vol, const char *path)
+{
+ hfsfile *file = NULL;
+
+ if (getvol(&vol) == -1)
+ goto fail;
+
+ file = ALLOC(hfsfile, 1);
+ if (file == NULL)
+ ERROR(ENOMEM, NULL);
+
+ if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, NULL) <= 0)
+ goto fail;
+
+ if (file->cat.cdrType != cdrFilRec)
+ ERROR(EISDIR, NULL);
+
+ /* package file handle for user */
+
+ file->vol = vol;
+ file->flags = 0;
+
+ f_selectfork(file, fkData);
+
+ file->prev = NULL;
+ file->next = vol->files;
+
+ if (vol->files)
+ vol->files->prev = file;
+
+ vol->files = file;
+
+ return file;
+
+fail:
+ FREE(file);
+ return NULL;
+}
+
+/*
+ * NAME: hfs->setfork()
+ * DESCRIPTION: select file fork for I/O operations
+ */
+int hfs_setfork(hfsfile *file, int fork)
+{
+ int result = 0;
+
+ f_selectfork(file, fork ? fkRsrc : fkData);
+
+ return result;
+}
+
+/*
+ * NAME: hfs->getfork()
+ * DESCRIPTION: return the current fork for I/O operations
+ */
+int hfs_getfork(hfsfile *file)
+{
+ return file->fork != fkData;
+}
+
+/*
+ * NAME: hfs->read()
+ * DESCRIPTION: read from an open file
+ */
+unsigned long hfs_read(hfsfile *file, void *buf, unsigned long len)
+{
+ unsigned long *lglen, count;
+ byte *ptr = buf;
+
+ f_getptrs(file, NULL, &lglen, NULL);
+
+ if (file->pos + len > *lglen)
+ len = *lglen - file->pos;
+
+ count = len;
+ while (count)
+ {
+ unsigned long bnum, offs, chunk;
+
+ bnum = file->pos >> HFS_BLOCKSZ_BITS;
+ offs = file->pos & (HFS_BLOCKSZ - 1);
+
+ chunk = HFS_BLOCKSZ - offs;
+ if (chunk > count)
+ chunk = count;
+
+ if (offs == 0 && chunk == HFS_BLOCKSZ)
+ {
+ if (f_getblock(file, bnum, (block *) ptr) == -1)
+ goto fail;
+ }
+ else
+ {
+ block b;
+
+ if (f_getblock(file, bnum, &b) == -1)
+ goto fail;
+
+ memcpy(ptr, b + offs, chunk);
+ }
+
+ ptr += chunk;
+
+ file->pos += chunk;
+ count -= chunk;
+ }
+
+ return len;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: hfs->seek()
+ * DESCRIPTION: change file seek pointer
+ */
+unsigned long hfs_seek(hfsfile *file, long offset, int from)
+{
+ unsigned long *lglen, newpos;
+
+ f_getptrs(file, NULL, &lglen, NULL);
+
+ switch (from)
+ {
+ case HFS_SEEK_SET:
+ newpos = (offset < 0) ? 0 : offset;
+ break;
+
+ case HFS_SEEK_CUR:
+ if (offset < 0 && (unsigned long) -offset > file->pos)
+ newpos = 0;
+ else
+ newpos = file->pos + offset;
+ break;
+
+ case HFS_SEEK_END:
+ if (offset < 0 && (unsigned long) -offset > *lglen)
+ newpos = 0;
+ else
+ newpos = *lglen + offset;
+ break;
+
+ default:
+ ERROR(EINVAL, NULL);
+ }
+
+ if (newpos > *lglen)
+ newpos = *lglen;
+
+ file->pos = newpos;
+
+ return newpos;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: hfs->close()
+ * DESCRIPTION: close a file
+ */
+int hfs_close(hfsfile *file)
+{
+ hfsvol *vol = file->vol;
+ int result = 0;
+
+ if (file->prev)
+ file->prev->next = file->next;
+ if (file->next)
+ file->next->prev = file->prev;
+ if (file == vol->files)
+ vol->files = file->next;
+
+ FREE(file);
+
+ return result;
+}
+
+/* High-Level Catalog Routines ============================================= */
+
+/*
+ * NAME: hfs->stat()
+ * DESCRIPTION: return catalog information for an arbitrary path
+ */
+int hfs_stat(hfsvol *vol, const char *path, hfsdirent *ent)
+{
+ CatDataRec data;
+ unsigned long parid;
+ char name[HFS_MAX_FLEN + 1];
+
+ if (getvol(&vol) == -1 ||
+ v_resolve(&vol, path, &data, &parid, name, NULL) <= 0)
+ goto fail;
+
+ r_unpackdirent(parid, name, &data, ent);
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: hfs->fstat()
+ * DESCRIPTION: return catalog information for an open file
+ */
+int hfs_fstat(hfsfile *file, hfsdirent *ent)
+{
+ r_unpackdirent(file->parid, file->name, &file->cat, ent);
+
+ return 0;
+}
+
+/*
+ * NAME: hfs->probe()
+ * DESCRIPTION: return whether a HFS filesystem is present at the given offset
+ */
+int hfs_probe(int fd, long long offset)
+{
+ return v_probe(fd, offset);
+}
diff --git a/roms/openbios/fs/hfs/hfs_fs.c b/roms/openbios/fs/hfs/hfs_fs.c
new file mode 100644
index 00000000..2d62ec0c
--- /dev/null
+++ b/roms/openbios/fs/hfs/hfs_fs.c
@@ -0,0 +1,593 @@
+/*
+ * Creation Date: <2001/05/06 22:47:23 samuel>
+ * Time-stamp: <2004/01/12 10:24:35 samuel>
+ *
+ * /packages/hfs-files
+ *
+ * HFS world interface
+ *
+ * Copyright (C) 2001-2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "fs/fs.h"
+#include "libc/vsprintf.h"
+#include "libc/diskio.h"
+#include "libhfs.h"
+
+#define MAC_OS_ROM_CREATOR 0x63687270 /* 'chrp' */
+#define MAC_OS_ROM_TYPE 0x74627869 /* 'tbxi' */
+#define MAC_OS_ROM_NAME "Mac OS ROM"
+
+#define FINDER_TYPE 0x464E4452 /* 'FNDR' */
+#define FINDER_CREATOR 0x4D414353 /* 'MACS' */
+#define SYSTEM_TYPE 0x7A737973 /* 'zsys' */
+#define SYSTEM_CREATOR 0x4D414353 /* 'MACS' */
+
+#define VOLNAME_SIZE 64
+
+extern void hfs_init( void );
+
+typedef struct {
+ enum { FILE, DIR } type;
+ union {
+ hfsdir *dir;
+ hfsfile *file;
+ };
+} hfscommon;
+
+typedef struct {
+ hfsvol *vol;
+ hfscommon *common;
+} hfs_info_t;
+
+DECLARE_NODE( hfs, 0, sizeof(hfs_info_t), "+/packages/hfs-files" );
+
+/************************************************************************/
+/* Search Functions */
+/************************************************************************/
+
+static int
+_find_file( hfsvol *vol, const char *path, unsigned long type, unsigned long creator )
+{
+ hfsdirent ent;
+ hfsdir *dir;
+ int ret=1;
+
+ if( !(dir=hfs_opendir(vol, path)) )
+ return 1;
+
+ while( ret && !hfs_readdir(dir, &ent) ) {
+ if( ent.flags & HFS_ISDIR )
+ continue;
+ ret = !(*(unsigned long*)ent.u.file.type == type && *(unsigned long*)ent.u.file.creator == creator );
+ }
+
+ hfs_closedir( dir );
+ return ret;
+}
+
+
+/* ret: 0=success, 1=not_found, 2=not_a_dir */
+static int
+_search( hfsvol *vol, const char *path, const char *sname, hfsfile **ret_fd )
+{
+ hfsdir *dir;
+ hfsdirent ent;
+ int topdir=0, status = 1;
+ char *p, buf[256];
+
+ strncpy( buf, path, sizeof(buf) );
+ if( buf[strlen(buf)-1] != ':' )
+ strncat( buf, ":", sizeof(buf) );
+ buf[sizeof(buf)-1] = 0;
+ p = buf + strlen( buf );
+
+ if( !(dir=hfs_opendir(vol, path)) )
+ return 2;
+
+ /* printk("DIRECTORY: %s\n", path ); */
+
+ while( status && !hfs_readdir(dir, &ent) ) {
+ unsigned long type, creator;
+
+ *p = 0;
+ topdir = 0;
+
+ strncat( buf, ent.name, sizeof(buf) );
+ if( (status=_search(vol, buf, sname, ret_fd)) != 2 )
+ continue;
+ topdir = 1;
+
+ /* name search? */
+ if( sname ) {
+ status = strcasecmp( ent.name, sname );
+ continue;
+ }
+
+ type = *(unsigned long*)ent.u.file.type;
+ creator = *(unsigned long*)ent.u.file.creator;
+
+ /* look for Mac OS ROM, System and Finder in the same directory */
+ if( type == MAC_OS_ROM_TYPE && creator == MAC_OS_ROM_CREATOR ) {
+ if( strcasecmp(ent.name, MAC_OS_ROM_NAME) )
+ continue;
+
+ status = _find_file( vol, path, FINDER_TYPE, FINDER_CREATOR )
+ || _find_file( vol, path, SYSTEM_TYPE, SYSTEM_CREATOR );
+ }
+ }
+ if( !status && topdir && ret_fd && !(*ret_fd=hfs_open(vol, buf)) ) {
+ printk("Unexpected error: failed to open matched ROM\n");
+ status = 1;
+ }
+
+ hfs_closedir( dir );
+ return status;
+}
+
+static hfsfile *
+_do_search( hfs_info_t *mi, const char *sname )
+{
+ hfsvol *vol = hfs_getvol( NULL );
+
+ mi->common->type = FILE;
+ (void)_search( vol, ":", sname, &mi->common->file );
+
+ return mi->common->file;
+}
+
+
+static const int days_month[12] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static const int days_month_leap[12] =
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static inline int is_leap(int year)
+{
+ return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
+}
+
+static void
+print_date(time_t sec)
+{
+ unsigned int second, minute, hour, month, day, year;
+ int current;
+ const int *days;
+
+ second = sec % 60;
+ sec /= 60;
+
+ minute = sec % 60;
+ sec /= 60;
+
+ hour = sec % 24;
+ sec /= 24;
+
+ year = sec * 100 / 36525;
+ sec -= year * 36525 / 100;
+ year += 1970;
+
+ days = is_leap(year) ? days_month_leap : days_month;
+
+ current = 0;
+ month = 0;
+ while (month < 12) {
+ if (sec <= current + days[month]) {
+ break;
+ }
+ current += days[month];
+ month++;
+ }
+ month++;
+
+ day = sec - current + 1;
+
+ forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
+ year, month, day, hour, minute, second);
+}
+
+/*
+static void
+dir_fs( file_desc_t *fd )
+{
+ hfscommon *common = (hfscommon*)fd;
+ hfsdirent ent;
+
+ if (common->type != DIR)
+ return;
+
+ forth_printf("\n");
+ while( !hfs_readdir(common->dir, &ent) ) {
+ forth_printf("% 10d ", ent.u.file.dsize);
+ print_date(ent.mddate);
+ if( ent.flags & HFS_ISDIR )
+ forth_printf("%s\\\n", ent.name);
+ else
+ forth_printf("%s\n", ent.name);
+ }
+}
+*/
+
+/************************************************************************/
+/* Standard package methods */
+/************************************************************************/
+
+/* ( -- success? ) */
+static void
+hfs_files_open( hfs_info_t *mi )
+{
+ int fd;
+ char *path = my_args_copy();
+
+ const char *s;
+ char buf[256];
+
+ fd = open_ih( my_parent() );
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ mi->vol = hfs_mount(fd, 0);
+ if (!mi->vol) {
+ RET( 0 );
+ }
+
+ if( !strncmp(path, "\\\\", 2) ) {
+ hfsvolent ent;
+
+ /* \\ is an alias for the (blessed) system folder */
+ if( hfs_vstat(mi->vol, &ent) < 0 || hfs_setcwd(mi->vol, ent.blessed) ) {
+ free(path);
+ RET( -1 );
+ }
+ path += 2;
+ } else {
+ hfs_chdir( mi->vol, ":" );
+ }
+
+ mi->common = malloc(sizeof(hfscommon));
+ if (!mi->common) {
+ free(path);
+ RET( 0 );
+ }
+
+ if (strcmp(path, "\\") == 0) {
+ /* root directory is in fact ":" */
+ mi->common->dir = hfs_opendir(mi->vol, ":");
+ mi->common->type = DIR;
+ free(path);
+ RET( -1 );
+ }
+
+ if (path[strlen(path) - 1] == '\\') {
+ path[strlen(path) - 1] = 0;
+ }
+
+ for( path-- ;; ) {
+ int n;
+
+ s = ++path;
+ path = strchr(s, '\\');
+ if( !path || !path[1])
+ break;
+ n = MIN( sizeof(buf)-1, (path-s) );
+ if( !n )
+ continue;
+
+ strncpy( buf, s, n );
+ buf[n] = 0;
+ if( hfs_chdir(mi->vol, buf) ) {
+ free(mi->common);
+ free(path);
+ RET( 0 );
+ }
+ }
+
+ /* support the ':filetype' syntax */
+ if( *s == ':' ) {
+ unsigned long id, oldid = hfs_getcwd(mi->vol);
+ hfsdirent ent;
+ hfsdir *dir;
+
+ s++;
+ id = oldid;
+ hfs_dirinfo( mi->vol, &id, buf );
+ hfs_setcwd( mi->vol, id );
+
+ if( !(dir=hfs_opendir(mi->vol, buf)) ) {
+ free(mi->common);
+ free(path);
+ RET( 0 );
+ }
+ hfs_setcwd( mi->vol, oldid );
+
+ while( !hfs_readdir(dir, &ent) ) {
+ if( ent.flags & HFS_ISDIR )
+ continue;
+ if( !strncmp(s, ent.u.file.type, 4) ) {
+ mi->common->type = FILE;
+ mi->common->file = hfs_open( mi->vol, ent.name );
+ break;
+ }
+ }
+ hfs_closedir( dir );
+ free(path);
+ RET( -1 );
+ }
+
+ mi->common->dir = hfs_opendir(mi->vol, s);
+ if (!mi->common->dir) {
+ mi->common->file = hfs_open( mi->vol, s );
+ if (mi->common->file == NULL) {
+ free(mi->common);
+ free(path);
+ RET( 0 );
+ }
+ mi->common->type = FILE;
+ free(path);
+ RET( -1 );
+ }
+ mi->common->type = DIR;
+ free(path);
+
+ RET( -1 );
+}
+
+/* ( -- ) */
+static void
+hfs_files_close( hfs_info_t *mi )
+{
+ hfscommon *common = mi->common;
+ if (common->type == FILE)
+ hfs_close( common->file );
+ else if (common->type == DIR)
+ hfs_closedir( common->dir );
+ free(common);
+}
+
+/* ( buf len -- actlen ) */
+static void
+hfs_files_read( hfs_info_t *mi )
+{
+ int count = POP();
+ char *buf = (char *)cell2pointer(POP());
+
+ hfscommon *common = mi->common;
+ if (common->type != FILE)
+ RET( -1 );
+
+ RET ( hfs_read( common->file, buf, count ) );
+}
+
+/* ( pos.d -- status ) */
+static void
+hfs_files_seek( hfs_info_t *mi )
+{
+ long long pos = DPOP();
+ int offs = (int)pos;
+ int whence = SEEK_SET;
+ int ret;
+ hfscommon *common = mi->common;
+
+ if (common->type != FILE)
+ RET( -1 );
+
+ switch( whence ) {
+ case SEEK_END:
+ whence = HFS_SEEK_END;
+ break;
+ default:
+ case SEEK_SET:
+ whence = HFS_SEEK_SET;
+ break;
+ }
+
+ ret = hfs_seek( common->file, offs, whence );
+ if (ret != -1)
+ RET( 0 );
+ else
+ RET( -1 );
+}
+
+/* ( addr -- size ) */
+static void
+hfs_files_load( hfs_info_t *mi )
+{
+ char *buf = (char *)cell2pointer(POP());
+ int count;
+
+ hfscommon *common = mi->common;
+ if (common->type != FILE)
+ RET( -1 );
+
+ /* Seek to the end in order to get the file size */
+ hfs_seek(common->file, 0, HFS_SEEK_END);
+ count = common->file->pos;
+ hfs_seek(common->file, 0, HFS_SEEK_SET);
+
+ RET ( hfs_read( common->file, buf, count ) );
+}
+
+/* ( -- success? ) */
+static void
+hfs_files_open_nwrom( hfs_info_t *mi )
+{
+ /* Switch to an existing ROM image file on the fs! */
+ if ( _do_search( mi, NULL ) )
+ RET( -1 );
+
+ RET( 0 );
+}
+
+/* ( -- cstr ) */
+static void
+hfs_files_get_path( hfs_info_t *mi )
+{
+ char buf[256], buf2[256];
+ hfscommon *common = mi->common;
+ hfsvol *vol = hfs_getvol( NULL );
+ hfsdirent ent;
+ int start, ns;
+ unsigned long id;
+
+ if (common->type != FILE)
+ RET( 0 );
+
+ hfs_fstat( common->file, &ent );
+ start = sizeof(buf) - strlen(ent.name) - 1;
+ if( start <= 0 )
+ RET ( 0 );
+ strcpy( buf+start, ent.name );
+ buf[--start] = '\\';
+
+ ns = start;
+ for( id=ent.parid ; !hfs_dirinfo(vol, &id, buf2) ; ) {
+ start = ns;
+ ns -= strlen(buf2);
+ if( ns <= 0 )
+ RET( 0 );
+ strcpy( buf+ns, buf2 );
+ buf[--ns] = buf[start] = '\\';
+ }
+ if( strlen(buf) >= sizeof(buf) )
+ RET( 0 );
+
+ RET( pointer2cell(strdup(buf+start)) );
+}
+
+/* ( -- cstr ) */
+static void
+hfs_files_get_fstype( hfs_info_t *mi )
+{
+ PUSH( pointer2cell(strdup("HFS")) );
+}
+
+/* ( -- cstr|0 ) */
+static void
+hfs_files_volume_name( hfs_info_t *mi )
+{
+ int fd;
+ char *volname = malloc(VOLNAME_SIZE);
+
+ fd = open_ih(my_self());
+ if (fd >= 0) {
+ get_hfs_vol_name(fd, volname, VOLNAME_SIZE);
+ close_io(fd);
+ } else {
+ volname[0] = '\0';
+ }
+
+ PUSH(pointer2cell(volname));
+}
+
+/* static method, ( pathstr len ihandle -- ) */
+static void
+hfs_files_dir( hfs_info_t *dummy )
+{
+ hfsvol *volume;
+ hfscommon *common;
+ hfsdirent ent;
+ int i;
+ int fd;
+
+ ihandle_t ih = POP();
+ char *path = pop_fstr_copy();
+
+ fd = open_ih( ih );
+ if ( fd == -1 ) {
+ free( path );
+ return;
+ }
+
+ volume = hfs_mount(fd, 0);
+ if (!volume) {
+ return;
+ }
+
+ common = malloc(sizeof(hfscommon));
+
+ /* HFS paths are colon separated, not backslash separated */
+ for (i = 0; i < strlen(path); i++)
+ if (path[i] == '\\')
+ path[i] = ':';
+
+ common->dir = hfs_opendir(volume, path);
+
+ forth_printf("\n");
+ while( !hfs_readdir(common->dir, &ent) ) {
+ forth_printf("% 10ld ", ent.u.file.dsize);
+ print_date(ent.mddate);
+ if( ent.flags & HFS_ISDIR )
+ forth_printf("%s\\\n", ent.name);
+ else
+ forth_printf("%s\n", ent.name);
+ }
+
+ hfs_closedir( common->dir );
+ hfs_umount( volume );
+
+ close_io( fd );
+
+ free( common );
+ free( path );
+}
+
+/* static method, ( pos.d ih -- flag? ) */
+static void
+hfs_files_probe( hfs_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ long long offs = DPOP();
+ int fd, ret = 0;
+
+ fd = open_ih(ih);
+ if (fd >= 0) {
+ if (hfs_probe(fd, offs)) {
+ ret = -1;
+ }
+ close_io(fd);
+ } else {
+ ret = -1;
+ }
+
+ RET (ret);
+}
+
+static void
+hfs_initializer( hfs_info_t *dummy )
+{
+ fword("register-fs-package");
+}
+
+NODE_METHODS( hfs ) = {
+ { "probe", hfs_files_probe },
+ { "open", hfs_files_open },
+ { "close", hfs_files_close },
+ { "read", hfs_files_read },
+ { "seek", hfs_files_seek },
+ { "load", hfs_files_load },
+ { "dir", hfs_files_dir },
+
+ /* special */
+ { "open-nwrom", hfs_files_open_nwrom },
+ { "get-path", hfs_files_get_path },
+ { "get-fstype", hfs_files_get_fstype },
+ { "volume-name", hfs_files_volume_name },
+
+ { NULL, hfs_initializer },
+};
+
+void
+hfs_init( void )
+{
+ REGISTER_NODE( hfs );
+}
diff --git a/roms/openbios/fs/hfs/include/apple.h b/roms/openbios/fs/hfs/include/apple.h
new file mode 100644
index 00000000..3de581d8
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/apple.h
@@ -0,0 +1,273 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: apple.h,v 1.1 1998/04/11 08:27:11 rob Exp $
+ */
+
+typedef signed char Char;
+typedef unsigned char UChar;
+typedef signed char SignedByte;
+typedef signed short Integer;
+typedef unsigned short UInteger;
+typedef signed long LongInt;
+typedef unsigned long ULongInt;
+typedef char Str15[16];
+typedef char Str31[32];
+typedef long OSType;
+
+typedef struct {
+ Integer sbSig; /* device signature (should be 0x4552) */
+ Integer sbBlkSize; /* block size of the device (in bytes) */
+ LongInt sbBlkCount; /* number of blocks on the device */
+ Integer sbDevType; /* reserved */
+ Integer sbDevId; /* reserved */
+ LongInt sbData; /* reserved */
+ Integer sbDrvrCount; /* number of driver descriptor entries */
+ LongInt ddBlock; /* first driver's starting block */
+ Integer ddSize; /* size of the driver, in 512-byte blocks */
+ Integer ddType; /* driver operating system type (MacOS = 1) */
+ Integer ddPad[243]; /* additional drivers, if any */
+} Block0;
+
+typedef struct {
+ Integer pmSig; /* partition signature (0x504d or 0x5453) */
+ Integer pmSigPad; /* reserved */
+ LongInt pmMapBlkCnt; /* number of blocks in partition map */
+ LongInt pmPyPartStart; /* first physical block of partition */
+ LongInt pmPartBlkCnt; /* number of blocks in partition */
+ Char pmPartName[33]; /* partition name */
+ Char pmParType[33]; /* partition type */
+ LongInt pmLgDataStart; /* first logical block of data area */
+ LongInt pmDataCnt; /* number of blocks in data area */
+ LongInt pmPartStatus; /* partition status information */
+ LongInt pmLgBootStart; /* first logical block of boot code */
+ LongInt pmBootSize; /* size of boot code, in bytes */
+ LongInt pmBootAddr; /* boot code load address */
+ LongInt pmBootAddr2; /* reserved */
+ LongInt pmBootEntry; /* boot code entry point */
+ LongInt pmBootEntry2; /* reserved */
+ LongInt pmBootCksum; /* boot code checksum */
+ Char pmProcessor[17];/* processor type */
+ Integer pmPad[188]; /* reserved */
+} Partition;
+
+typedef struct {
+ Integer bbID; /* boot blocks signature */
+ LongInt bbEntry; /* entry point to boot code */
+ Integer bbVersion; /* boot blocks version number */
+ Integer bbPageFlags; /* used internally */
+ Str15 bbSysName; /* System filename */
+ Str15 bbShellName; /* Finder filename */
+ Str15 bbDbg1Name; /* debugger filename */
+ Str15 bbDbg2Name; /* debugger filename */
+ Str15 bbScreenName; /* name of startup screen */
+ Str15 bbHelloName; /* name of startup program */
+ Str15 bbScrapName; /* name of system scrap file */
+ Integer bbCntFCBs; /* number of FCBs to allocate */
+ Integer bbCntEvts; /* number of event queue elements */
+ LongInt bb128KSHeap; /* system heap size on 128K Mac */
+ LongInt bb256KSHeap; /* used internally */
+ LongInt bbSysHeapSize; /* system heap size on all machines */
+ Integer filler; /* reserved */
+ LongInt bbSysHeapExtra; /* additional system heap space */
+ LongInt bbSysHeapFract; /* fraction of RAM for system heap */
+} BootBlkHdr;
+
+typedef struct {
+ UInteger xdrStABN; /* first allocation block */
+ UInteger xdrNumABlks; /* number of allocation blocks */
+} ExtDescriptor;
+
+typedef ExtDescriptor ExtDataRec[3];
+
+typedef struct {
+ SignedByte xkrKeyLen; /* key length */
+ SignedByte xkrFkType; /* fork type (0x00/0xff == data/resource */
+ ULongInt xkrFNum; /* file number */
+ UInteger xkrFABN; /* starting file allocation block */
+} ExtKeyRec;
+
+typedef struct {
+ SignedByte ckrKeyLen; /* key length */
+ SignedByte ckrResrv1; /* reserved */
+ ULongInt ckrParID; /* parent directory ID */
+ Str31 ckrCName; /* catalog node name */
+} CatKeyRec;
+
+typedef struct {
+ Integer v; /* vertical coordinate */
+ Integer h; /* horizontal coordinate */
+} Point;
+
+typedef struct {
+ Integer top; /* top edge of rectangle */
+ Integer left; /* left edge */
+ Integer bottom; /* bottom edge */
+ Integer right; /* right edge */
+} Rect;
+
+typedef struct {
+ Rect frRect; /* folder's rectangle */
+ Integer frFlags; /* flags */
+ Point frLocation; /* folder's location */
+ Integer frView; /* folder's view */
+} DInfo;
+
+typedef struct {
+ Point frScroll; /* scroll position */
+ LongInt frOpenChain; /* directory ID chain of open folders */
+ Integer frUnused; /* reserved */
+ Integer frComment; /* comment ID */
+ LongInt frPutAway; /* directory ID */
+} DXInfo;
+
+typedef struct {
+ OSType fdType; /* file type */
+ OSType fdCreator; /* file's creator */
+ Integer fdFlags; /* flags */
+ Point fdLocation; /* file's location */
+ Integer fdFldr; /* file's window */
+} FInfo;
+
+typedef struct {
+ Integer fdIconID; /* icon ID */
+ Integer fdUnused[4]; /* reserved */
+ Integer fdComment; /* comment ID */
+ LongInt fdPutAway; /* home directory ID */
+} FXInfo;
+
+typedef struct {
+ Integer drSigWord; /* volume signature (0x4244 for HFS) */
+ LongInt drCrDate; /* date and time of volume creation */
+ LongInt drLsMod; /* date and time of last modification */
+ Integer drAtrb; /* volume attributes */
+ UInteger drNmFls; /* number of files in root directory */
+ UInteger drVBMSt; /* first block of volume bit map (always 3) */
+ UInteger drAllocPtr; /* start of next allocation search */
+ UInteger drNmAlBlks; /* number of allocation blocks in volume */
+ ULongInt drAlBlkSiz; /* size (in bytes) of allocation blocks */
+ ULongInt drClpSiz; /* default clump size */
+ UInteger drAlBlSt; /* first allocation block in volume */
+ LongInt drNxtCNID; /* next unused catalog node ID (dir/file ID) */
+ UInteger drFreeBks; /* number of unused allocation blocks */
+ char drVN[28]; /* volume name (1-27 chars) */
+ LongInt drVolBkUp; /* date and time of last backup */
+ Integer drVSeqNum; /* volume backup sequence number */
+ ULongInt drWrCnt; /* volume write count */
+ ULongInt drXTClpSiz; /* clump size for extents overflow file */
+ ULongInt drCTClpSiz; /* clump size for catalog file */
+ UInteger drNmRtDirs; /* number of directories in root directory */
+ ULongInt drFilCnt; /* number of files in volume */
+ ULongInt drDirCnt; /* number of directories in volume */
+ LongInt drFndrInfo[8]; /* information used by the Finder */
+ UInteger drEmbedSigWord; /* type of embedded volume */
+ ExtDescriptor drEmbedExtent; /* location of embedded volume */
+ ULongInt drXTFlSize; /* size (in bytes) of extents overflow file */
+ ExtDataRec drXTExtRec; /* first extent record for extents file */
+ ULongInt drCTFlSize; /* size (in bytes) of catalog file */
+ ExtDataRec drCTExtRec; /* first extent record for catalog file */
+} MDB;
+
+typedef enum {
+ cdrDirRec = 1,
+ cdrFilRec = 2,
+ cdrThdRec = 3,
+ cdrFThdRec = 4
+} CatDataType;
+
+typedef struct {
+ SignedByte cdrType; /* record type */
+ SignedByte cdrResrv2; /* reserved */
+ union {
+ struct { /* cdrDirRec */
+ Integer dirFlags; /* directory flags */
+ UInteger dirVal; /* directory valence */
+ ULongInt dirDirID; /* directory ID */
+ LongInt dirCrDat; /* date and time of creation */
+ LongInt dirMdDat; /* date and time of last modification */
+ LongInt dirBkDat; /* date and time of last backup */
+ DInfo dirUsrInfo; /* Finder information */
+ DXInfo dirFndrInfo; /* additional Finder information */
+ LongInt dirResrv[4]; /* reserved */
+ } dir;
+ struct { /* cdrFilRec */
+ SignedByte
+ filFlags; /* file flags */
+ SignedByte
+ filTyp; /* file type */
+ FInfo filUsrWds; /* Finder information */
+ ULongInt filFlNum; /* file ID */
+ UInteger filStBlk; /* first alloc block of data fork */
+ ULongInt filLgLen; /* logical EOF of data fork */
+ ULongInt filPyLen; /* physical EOF of data fork */
+ UInteger filRStBlk; /* first alloc block of resource fork */
+ ULongInt filRLgLen; /* logical EOF of resource fork */
+ ULongInt filRPyLen; /* physical EOF of resource fork */
+ LongInt filCrDat; /* date and time of creation */
+ LongInt filMdDat; /* date and time of last modification */
+ LongInt filBkDat; /* date and time of last backup */
+ FXInfo filFndrInfo; /* additional Finder information */
+ UInteger filClpSize; /* file clump size */
+ ExtDataRec
+ filExtRec; /* first data fork extent record */
+ ExtDataRec
+ filRExtRec; /* first resource fork extent record */
+ LongInt filResrv; /* reserved */
+ } fil;
+ struct { /* cdrThdRec */
+ LongInt thdResrv[2]; /* reserved */
+ ULongInt thdParID; /* parent ID for this directory */
+ Str31 thdCName; /* name of this directory */
+ } dthd;
+ struct { /* cdrFThdRec */
+ LongInt fthdResrv[2]; /* reserved */
+ ULongInt fthdParID; /* parent ID for this file */
+ Str31 fthdCName; /* name of this file */
+ } fthd;
+ } u;
+} CatDataRec;
+
+typedef struct {
+ ULongInt ndFLink; /* forward link */
+ ULongInt ndBLink; /* backward link */
+ SignedByte ndType; /* node type */
+ SignedByte ndNHeight; /* node level */
+ UInteger ndNRecs; /* number of records in node */
+ Integer ndResv2; /* reserved */
+} NodeDescriptor;
+
+enum {
+ ndIndxNode = (SignedByte) 0x00,
+ ndHdrNode = (SignedByte) 0x01,
+ ndMapNode = (SignedByte) 0x02,
+ ndLeafNode = (SignedByte) 0xff
+};
+
+typedef struct {
+ UInteger bthDepth; /* current depth of tree */
+ ULongInt bthRoot; /* number of root node */
+ ULongInt bthNRecs; /* number of leaf records in tree */
+ ULongInt bthFNode; /* number of first leaf node */
+ ULongInt bthLNode; /* number of last leaf node */
+ UInteger bthNodeSize; /* size of a node */
+ UInteger bthKeyLen; /* maximum length of a key */
+ ULongInt bthNNodes; /* total number of nodes in tree */
+ ULongInt bthFree; /* number of free nodes */
+ SignedByte bthResv[76]; /* reserved */
+} BTHdrRec;
diff --git a/roms/openbios/fs/hfs/include/block.h b/roms/openbios/fs/hfs/include/block.h
new file mode 100644
index 00000000..d7e76451
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/block.h
@@ -0,0 +1,41 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: block.h,v 1.10 1998/11/02 22:08:53 rob Exp $
+ */
+
+int b_init(hfsvol *);
+int b_flush(hfsvol *);
+int b_finish(hfsvol *);
+
+int b_readpb(hfsvol *, unsigned long, block *, unsigned int);
+int b_writepb(hfsvol *, unsigned long, const block *, unsigned int);
+
+int b_readlb(hfsvol *, unsigned long, block *);
+int b_writelb(hfsvol *, unsigned long, const block *);
+
+int b_readab(hfsvol *, unsigned int, unsigned int, block *);
+int b_writeab(hfsvol *, unsigned int, unsigned int, const block *);
+
+unsigned long b_size(hfsvol *);
+
+# ifdef DEBUG
+void b_showstats(const bcache *);
+void b_dumpcache(const bcache *);
+# endif
diff --git a/roms/openbios/fs/hfs/include/btree.h b/roms/openbios/fs/hfs/include/btree.h
new file mode 100644
index 00000000..36660f53
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/btree.h
@@ -0,0 +1,34 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: btree.h,v 1.8 1998/11/02 22:08:55 rob Exp $
+ */
+
+int bt_getnode(node *, btree *, unsigned long);
+int bt_putnode(node *);
+
+int bt_readhdr(btree *);
+int bt_writehdr(btree *);
+
+int bt_space(btree *, unsigned int);
+
+int bt_insert(btree *, const byte *, unsigned int);
+int bt_delete(btree *, const byte *);
+
+int bt_search(btree *, const byte *, node *);
diff --git a/roms/openbios/fs/hfs/include/data.h b/roms/openbios/fs/hfs/include/data.h
new file mode 100644
index 00000000..f3e20008
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/data.h
@@ -0,0 +1,57 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: data.h,v 1.7 1998/11/02 22:08:58 rob Exp $
+ */
+
+ signed char d_getsb(register const unsigned char *);
+unsigned char d_getub(register const unsigned char *);
+ signed short d_getsw(register const unsigned char *);
+unsigned short d_getuw(register const unsigned char *);
+ signed long d_getsl(register const unsigned char *);
+unsigned long d_getul(register const unsigned char *);
+
+void d_putsb(register unsigned char *, register signed char);
+void d_putub(register unsigned char *, register unsigned char);
+void d_putsw(register unsigned char *, register signed short);
+void d_putuw(register unsigned char *, register unsigned short);
+void d_putsl(register unsigned char *, register signed long);
+void d_putul(register unsigned char *, register unsigned long);
+
+void d_fetchsb(register const unsigned char **, register signed char *);
+void d_fetchub(register const unsigned char **, register unsigned char *);
+void d_fetchsw(register const unsigned char **, register signed short *);
+void d_fetchuw(register const unsigned char **, register unsigned short *);
+void d_fetchsl(register const unsigned char **, register signed long *);
+void d_fetchul(register const unsigned char **, register unsigned long *);
+
+void d_storesb(register unsigned char **, register signed char);
+void d_storeub(register unsigned char **, register unsigned char);
+void d_storesw(register unsigned char **, register signed short);
+void d_storeuw(register unsigned char **, register unsigned short);
+void d_storesl(register unsigned char **, register signed long);
+void d_storeul(register unsigned char **, register unsigned long);
+
+void d_fetchstr(const unsigned char **, char *, unsigned);
+void d_storestr(unsigned char **, const char *, unsigned);
+
+int d_relstring(const char *, const char *);
+
+time_t d_ltime(unsigned long);
+unsigned long d_mtime(time_t);
diff --git a/roms/openbios/fs/hfs/include/file.h b/roms/openbios/fs/hfs/include/file.h
new file mode 100644
index 00000000..dacdc480
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/file.h
@@ -0,0 +1,46 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: file.h,v 1.6 1998/04/11 08:27:12 rob Exp $
+ */
+
+enum {
+ fkData = 0x00,
+ fkRsrc = 0xff
+};
+
+void f_init(hfsfile *, hfsvol *, long, const char *);
+void f_selectfork(hfsfile *, int);
+void f_getptrs(hfsfile *, ExtDataRec **, unsigned long **, unsigned long **);
+
+int f_doblock(hfsfile *, unsigned long, block *,
+ int (*)(hfsvol *, unsigned int, unsigned int, block *));
+
+# define f_getblock(file, num, bp) \
+ f_doblock((file), (num), (bp), b_readab)
+# define f_putblock(file, num, bp) \
+ f_doblock((file), (num), (bp), \
+ (int (*)(hfsvol *, unsigned int, unsigned int, block *)) \
+ b_writeab)
+
+int f_addextent(hfsfile *, ExtDescriptor *);
+long f_alloc(hfsfile *);
+
+int f_trunc(hfsfile *);
+int f_flush(hfsfile *);
diff --git a/roms/openbios/fs/hfs/include/hfs.h b/roms/openbios/fs/hfs/include/hfs.h
new file mode 100644
index 00000000..9996cc8d
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/hfs.h
@@ -0,0 +1,180 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: hfs.h,v 1.11 1998/11/02 22:09:01 rob Exp $
+ */
+
+# define HFS_BLOCKSZ 512
+# define HFS_BLOCKSZ_BITS 9
+
+# define HFS_MAX_FLEN 31
+# define HFS_MAX_VLEN 27
+
+typedef struct _hfsvol_ hfsvol;
+typedef struct _hfsfile_ hfsfile;
+typedef struct _hfsdir_ hfsdir;
+
+typedef struct {
+ char name[HFS_MAX_VLEN + 1]; /* name of volume (MacOS Standard Roman) */
+ int flags; /* volume flags */
+
+ unsigned long totbytes; /* total bytes on volume */
+ unsigned long freebytes; /* free bytes on volume */
+
+ unsigned long alblocksz; /* volume allocation block size */
+ unsigned long clumpsz; /* default file clump size */
+
+ unsigned long numfiles; /* number of files in volume */
+ unsigned long numdirs; /* number of directories in volume */
+
+ time_t crdate; /* volume creation date */
+ time_t mddate; /* last volume modification date */
+ time_t bkdate; /* last volume backup date */
+
+ unsigned long blessed; /* CNID of MacOS System Folder */
+} hfsvolent;
+
+typedef struct {
+ char name[HFS_MAX_FLEN + 1]; /* catalog name (MacOS Standard Roman) */
+ int flags; /* bit flags */
+ unsigned long cnid; /* catalog node id (CNID) */
+ unsigned long parid; /* CNID of parent directory */
+
+ time_t crdate; /* date of creation */
+ time_t mddate; /* date of last modification */
+ time_t bkdate; /* date of last backup */
+
+ short fdflags; /* Macintosh Finder flags */
+
+ struct {
+ signed short v; /* Finder icon vertical coordinate */
+ signed short h; /* horizontal coordinate */
+ } fdlocation;
+
+ union {
+ struct {
+ unsigned long dsize; /* size of data fork */
+ unsigned long rsize; /* size of resource fork */
+
+ char type[5]; /* file type code (plus null) */
+ char creator[5]; /* file creator code (plus null) */
+ } file;
+
+ struct {
+ unsigned short valence; /* number of items in directory */
+
+ struct {
+ signed short top; /* top edge of folder's rectangle */
+ signed short left; /* left edge */
+ signed short bottom; /* bottom edge */
+ signed short right; /* right edge */
+ } rect;
+ } dir;
+ } u;
+} hfsdirent;
+
+# define HFS_ISDIR 0x0001
+# define HFS_ISLOCKED 0x0002
+
+# define HFS_CNID_ROOTPAR 1
+# define HFS_CNID_ROOTDIR 2
+# define HFS_CNID_EXT 3
+# define HFS_CNID_CAT 4
+# define HFS_CNID_BADALLOC 5
+
+# define HFS_FNDR_ISONDESK (1 << 0)
+# define HFS_FNDR_COLOR 0x0e
+# define HFS_FNDR_COLORRESERVED (1 << 4)
+# define HFS_FNDR_REQUIRESSWITCHLAUNCH (1 << 5)
+# define HFS_FNDR_ISSHARED (1 << 6)
+# define HFS_FNDR_HASNOINITS (1 << 7)
+# define HFS_FNDR_HASBEENINITED (1 << 8)
+# define HFS_FNDR_RESERVED (1 << 9)
+# define HFS_FNDR_HASCUSTOMICON (1 << 10)
+# define HFS_FNDR_ISSTATIONERY (1 << 11)
+# define HFS_FNDR_NAMELOCKED (1 << 12)
+# define HFS_FNDR_HASBUNDLE (1 << 13)
+# define HFS_FNDR_ISINVISIBLE (1 << 14)
+# define HFS_FNDR_ISALIAS (1 << 15)
+
+extern const char *hfs_error;
+extern const unsigned char hfs_charorder[];
+
+# define HFS_MODE_RDONLY 0
+# define HFS_MODE_RDWR 1
+# define HFS_MODE_ANY 2
+
+# define HFS_MODE_MASK 0x0003
+
+# define HFS_OPT_NOCACHE 0x0100
+# define HFS_OPT_2048 0x0200
+# define HFS_OPT_ZERO 0x0400
+
+# define HFS_SEEK_SET 0
+# define HFS_SEEK_CUR 1
+# define HFS_SEEK_END 2
+
+hfsvol *hfs_mount( int os_fd, int);
+int hfs_flush(hfsvol *);
+void hfs_flushall(void);
+int hfs_umount(hfsvol *);
+void hfs_umountall(void);
+hfsvol *hfs_getvol(const char *);
+void hfs_setvol(hfsvol *);
+
+int hfs_vstat(hfsvol *, hfsvolent *);
+int hfs_vsetattr(hfsvol *, hfsvolent *);
+
+int hfs_chdir(hfsvol *, const char *);
+unsigned long hfs_getcwd(hfsvol *);
+int hfs_setcwd(hfsvol *, unsigned long);
+int hfs_dirinfo(hfsvol *, unsigned long *, char *);
+
+hfsdir *hfs_opendir(hfsvol *, const char *);
+int hfs_readdir(hfsdir *, hfsdirent *);
+int hfs_closedir(hfsdir *);
+
+hfsfile *hfs_create(hfsvol *, const char *, const char *, const char *);
+hfsfile *hfs_open(hfsvol *, const char *);
+int hfs_setfork(hfsfile *, int);
+int hfs_getfork(hfsfile *);
+unsigned long hfs_read(hfsfile *, void *, unsigned long);
+unsigned long hfs_write(hfsfile *, const void *, unsigned long);
+int hfs_truncate(hfsfile *, unsigned long);
+unsigned long hfs_seek(hfsfile *, long, int);
+int hfs_close(hfsfile *);
+
+int hfs_stat(hfsvol *, const char *, hfsdirent *);
+int hfs_fstat(hfsfile *, hfsdirent *);
+int hfs_setattr(hfsvol *, const char *, const hfsdirent *);
+int hfs_fsetattr(hfsfile *, const hfsdirent *);
+
+int hfs_mkdir(hfsvol *, const char *);
+int hfs_rmdir(hfsvol *, const char *);
+
+int hfs_delete(hfsvol *, const char *);
+int hfs_rename(hfsvol *, const char *, const char *);
+
+int hfs_zero(const char *, unsigned int, unsigned long *);
+int hfs_mkpart(const char *, unsigned long);
+int hfs_nparts(const char *);
+
+int hfs_format(const char *, int, int,
+ const char *, unsigned int, const unsigned long []);
+int hfs_probe(int fd, long long offset);
diff --git a/roms/openbios/fs/hfs/include/libhfs.h b/roms/openbios/fs/hfs/include/libhfs.h
new file mode 100644
index 00000000..f46f4383
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/libhfs.h
@@ -0,0 +1,225 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: libhfs.h,v 1.7 1998/11/02 22:09:02 rob Exp $
+ */
+
+# include "hfs.h"
+# include "apple.h"
+
+# define ERROR(code, str) \
+ do { hfs_error = (str), errno = (code); goto fail; } while (0)
+
+# ifdef DEBUG
+# define ASSERT(cond) do { if (! (cond)) abort(); } while (0)
+# else
+# define ASSERT(cond) /* nothing */
+# endif
+
+# define SIZE(type, n) ((size_t) (sizeof(type) * (n)))
+# define ALLOC(type, n) ((type *) malloc(SIZE(type, n)))
+# define ALLOCX(type, n) ((n) ? ALLOC(type, n) : (type *) 0)
+# define FREE(ptr) ((ptr) ? (void) free((void *) ptr) : (void) 0)
+
+# define REALLOC(ptr, type, n) \
+ ((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n))))
+# define REALLOCX(ptr, type, n) \
+ ((n) ? REALLOC(ptr, type, n) : (FREE(ptr), (type *) 0))
+
+# define BMTST(bm, num) \
+ (((const byte *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07)))
+# define BMSET(bm, num) \
+ (((byte *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07)))
+# define BMCLR(bm, num) \
+ (((byte *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07)))
+
+# define STRINGIZE(x) #x
+# define STR(x) STRINGIZE(x)
+
+typedef unsigned char byte;
+typedef byte block[HFS_BLOCKSZ];
+
+typedef struct _bucket_ {
+ int flags; /* bit flags */
+ unsigned int count; /* number of times this block is requested */
+
+ unsigned long bnum; /* logical block number */
+ block *data; /* pointer to block contents */
+
+ struct _bucket_ *cnext; /* next bucket in cache chain */
+ struct _bucket_ *cprev; /* previous bucket in cache chain */
+
+ struct _bucket_ *hnext; /* next bucket in hash chain */
+ struct _bucket_ **hprev; /* previous bucket's pointer to this bucket */
+} bucket;
+
+# define HFS_BUCKET_INUSE 0x01
+# define HFS_BUCKET_DIRTY 0x02
+
+# define HFS_CACHESZ 128
+# define HFS_HASHSZ 32
+# define HFS_BLOCKBUFSZ 16
+
+typedef struct {
+ struct _hfsvol_ *vol; /* volume to which cache belongs */
+ bucket *tail; /* end of bucket chain */
+
+ unsigned int hits; /* number of cache hits */
+ unsigned int misses; /* number of cache misses */
+
+ bucket chain[HFS_CACHESZ]; /* cache bucket chain */
+ bucket *hash[HFS_HASHSZ]; /* hash table for bucket chain */
+
+ block pool[HFS_CACHESZ]; /* physical blocks in cache */
+} bcache;
+
+# define HFS_MAP1SZ 256
+# define HFS_MAPXSZ 492
+
+# define HFS_NODEREC(nd, rnum) ((nd).data + (nd).roff[rnum])
+# define HFS_RECLEN(nd, rnum) ((nd).roff[(rnum) + 1] - (nd).roff[rnum])
+
+# define HFS_RECKEYLEN(ptr) (*(const byte *) (ptr))
+# define HFS_RECKEYSKIP(ptr) ((size_t) ((1 + HFS_RECKEYLEN(ptr) + 1) & ~1))
+# define HFS_RECDATA(ptr) ((ptr) + HFS_RECKEYSKIP(ptr))
+
+# define HFS_SETKEYLEN(ptr, x) (*(byte *) (ptr) = (x))
+
+# define HFS_CATDATALEN sizeof(CatDataRec)
+# define HFS_EXTDATALEN sizeof(ExtDataRec)
+# define HFS_MAX_DATALEN (HFS_CATDATALEN > HFS_EXTDATALEN ? \
+ HFS_CATDATALEN : HFS_EXTDATALEN)
+
+# define HFS_CATKEYLEN sizeof(CatKeyRec)
+# define HFS_EXTKEYLEN sizeof(ExtKeyRec)
+# define HFS_MAX_KEYLEN (HFS_CATKEYLEN > HFS_EXTKEYLEN ? \
+ HFS_CATKEYLEN : HFS_EXTKEYLEN)
+
+# define HFS_MAX_CATRECLEN (HFS_CATKEYLEN + HFS_CATDATALEN)
+# define HFS_MAX_EXTRECLEN (HFS_EXTKEYLEN + HFS_EXTDATALEN)
+# define HFS_MAX_RECLEN (HFS_MAX_KEYLEN + HFS_MAX_DATALEN)
+
+# define HFS_SIGWORD 0x4244
+# define HFS_SIGWORD_MFS ((Integer) 0xd2d7)
+
+# define HFS_ATRB_BUSY (1 << 6)
+# define HFS_ATRB_HLOCKED (1 << 7)
+# define HFS_ATRB_UMOUNTED (1 << 8)
+# define HFS_ATRB_BBSPARED (1 << 9)
+# define HFS_ATRB_BVINCONSIS (1 << 11)
+# define HFS_ATRB_COPYPROT (1 << 14)
+# define HFS_ATRB_SLOCKED (1 << 15)
+
+struct _hfsfile_ {
+ struct _hfsvol_ *vol; /* pointer to volume descriptor */
+ unsigned long parid; /* parent directory ID of this file */
+ char name[HFS_MAX_FLEN + 1]; /* catalog name of this file */
+ CatDataRec cat; /* catalog information */
+ ExtDataRec ext; /* current extent record */
+ unsigned int fabn; /* starting file allocation block number */
+ int fork; /* current selected fork for I/O */
+ unsigned long pos; /* current file seek pointer */
+ int flags; /* bit flags */
+
+ struct _hfsfile_ *prev;
+ struct _hfsfile_ *next;
+};
+
+# define HFS_FILE_UPDATE_CATREC 0x01
+
+# define HFS_MAX_NRECS 35 /* maximum based on minimum record size */
+
+typedef struct _node_ {
+ struct _btree_ *bt; /* btree to which this node belongs */
+ unsigned long nnum; /* node index */
+ NodeDescriptor nd; /* node descriptor */
+ int rnum; /* current record index */
+ UInteger roff[HFS_MAX_NRECS + 1];
+ /* record offsets */
+ block data; /* raw contents of node */
+} node;
+
+struct _hfsdir_ {
+ struct _hfsvol_ *vol; /* associated volume */
+ unsigned long dirid; /* directory ID of interest (or 0) */
+
+ node n; /* current B*-tree node */
+ struct _hfsvol_ *vptr; /* current volume pointer */
+
+ struct _hfsdir_ *prev;
+ struct _hfsdir_ *next;
+};
+
+typedef void (*keyunpackfunc)(const byte *, void *);
+typedef int (*keycomparefunc)(const void *, const void *);
+
+typedef struct _btree_ {
+ hfsfile f; /* subset file information */
+ node hdrnd; /* header node */
+ BTHdrRec hdr; /* header record */
+ byte *map; /* usage bitmap */
+ unsigned long mapsz; /* number of bytes in bitmap */
+ int flags; /* bit flags */
+
+ keyunpackfunc keyunpack; /* key unpacking function */
+ keycomparefunc keycompare; /* key comparison function */
+} btree;
+
+# define HFS_BT_UPDATE_HDR 0x01
+
+struct _hfsvol_ {
+ int os_fd; /* OS-dependent private descriptor data */
+ int flags; /* bit flags */
+
+ int pnum; /* ordinal HFS partition number */
+ unsigned long vstart; /* logical block offset to start of volume */
+ unsigned long vlen; /* number of logical blocks in volume */
+ unsigned int lpa; /* number of logical blocks per allocation block */
+
+ bcache *cache; /* cache of recently used blocks */
+
+ MDB mdb; /* master directory block */
+ block *vbm; /* volume bitmap */
+ unsigned short vbmsz; /* number of blocks in bitmap */
+
+ btree ext; /* B*-tree control block for extents overflow file */
+ btree cat; /* B*-tree control block for catalog file */
+
+ unsigned long cwd; /* directory id of current working directory */
+
+ int refs; /* number of external references to this volume */
+ hfsfile *files; /* list of open files */
+ hfsdir *dirs; /* list of open directories */
+
+ struct _hfsvol_ *prev;
+ struct _hfsvol_ *next;
+};
+
+# define HFS_VOL_OPEN 0x0001
+# define HFS_VOL_MOUNTED 0x0002
+# define HFS_VOL_READONLY 0x0004
+# define HFS_VOL_USINGCACHE 0x0008
+
+# define HFS_VOL_UPDATE_MDB 0x0010
+# define HFS_VOL_UPDATE_ALTMDB 0x0020
+# define HFS_VOL_UPDATE_VBM 0x0040
+
+# define HFS_VOL_OPT_MASK 0xff00
+
+extern hfsvol *hfs_mounts;
diff --git a/roms/openbios/fs/hfs/include/low.h b/roms/openbios/fs/hfs/include/low.h
new file mode 100644
index 00000000..56d049a8
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/low.h
@@ -0,0 +1,45 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: low.h,v 1.6 1998/04/11 08:27:13 rob Exp $
+ */
+
+# define HFS_DDR_SIGWORD 0x4552
+
+# define HFS_PM_SIGWORD 0x504d
+# define HFS_PM_SIGWORD_OLD 0x5453
+
+# define HFS_BB_SIGWORD 0x4c4b
+
+# define HFS_BOOTCODE1LEN (HFS_BLOCKSZ - 148)
+# define HFS_BOOTCODE2LEN HFS_BLOCKSZ
+
+# define HFS_BOOTCODELEN (HFS_BOOTCODE1LEN + HFS_BOOTCODE2LEN)
+
+int l_getddr(hfsvol *, Block0 *);
+int l_putddr(hfsvol *, const Block0 *);
+
+int l_getpmentry(hfsvol *, Partition *, unsigned long);
+int l_putpmentry(hfsvol *, const Partition *, unsigned long);
+
+int l_getbb(hfsvol *, BootBlkHdr *, byte *);
+int l_putbb(hfsvol *, const BootBlkHdr *, const byte *);
+
+int l_getmdb(hfsvol *, MDB *, int);
+int l_putmdb(hfsvol *, const MDB *, int);
diff --git a/roms/openbios/fs/hfs/include/medium.h b/roms/openbios/fs/hfs/include/medium.h
new file mode 100644
index 00000000..29d97a4e
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/medium.h
@@ -0,0 +1,43 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: medium.h,v 1.3 1998/04/11 08:27:13 rob Exp $
+ */
+
+/*
+ * Partition Types:
+ *
+ * "Apple_partition_map" partition map
+ * "Apple_Driver" device driver
+ * "Apple_Driver43" SCSI Manager 4.3 device driver
+ * "Apple_MFS" Macintosh 64K ROM filesystem
+ * "Apple_HFS" Macintosh hierarchical filesystem
+ * "Apple_Unix_SVR2" Unix filesystem
+ * "Apple_PRODOS" ProDOS filesystem
+ * "Apple_Free" unused
+ * "Apple_Scratch" empty
+ */
+
+int m_zeroddr(hfsvol *);
+
+int m_zeropm(hfsvol *, unsigned int);
+int m_findpmentry(hfsvol *, const char *, Partition *, unsigned long *);
+int m_mkpart(hfsvol *, const char *, const char *, unsigned long);
+
+int m_zerobb(hfsvol *);
diff --git a/roms/openbios/fs/hfs/include/node.h b/roms/openbios/fs/hfs/include/node.h
new file mode 100644
index 00000000..d7367fd5
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/node.h
@@ -0,0 +1,35 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: node.h,v 1.7 1998/11/02 22:09:06 rob Exp $
+ */
+
+void n_init(node *, btree *, int, int);
+
+int n_new(node *);
+int n_free(node *);
+
+int n_search(node *, const byte *);
+
+void n_index(const node *, byte *, unsigned int *);
+
+void n_insertx(node *, const byte *, unsigned int);
+int n_insert(node *, byte *, unsigned int *);
+
+int n_delete(node *, byte *, int *);
diff --git a/roms/openbios/fs/hfs/include/record.h b/roms/openbios/fs/hfs/include/record.h
new file mode 100644
index 00000000..283e809f
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/record.h
@@ -0,0 +1,48 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: record.h,v 1.7 1998/11/02 22:09:08 rob Exp $
+ */
+
+void r_packcatkey(const CatKeyRec *, byte *, unsigned int *);
+void r_unpackcatkey(const byte *, CatKeyRec *);
+
+void r_packextkey(const ExtKeyRec *, byte *, unsigned int *);
+void r_unpackextkey(const byte *, ExtKeyRec *);
+
+int r_comparecatkeys(const CatKeyRec *, const CatKeyRec *);
+int r_compareextkeys(const ExtKeyRec *, const ExtKeyRec *);
+
+void r_packcatdata(const CatDataRec *, byte *, unsigned int *);
+void r_unpackcatdata(const byte *, CatDataRec *);
+
+void r_packextdata(const ExtDataRec *, byte *, unsigned int *);
+void r_unpackextdata(const byte *, ExtDataRec *);
+
+void r_makecatkey(CatKeyRec *, unsigned long, const char *);
+void r_makeextkey(ExtKeyRec *, int, unsigned long, unsigned int);
+
+void r_packcatrec(const CatKeyRec *, const CatDataRec *,
+ byte *, unsigned int *);
+void r_packextrec(const ExtKeyRec *, const ExtDataRec *,
+ byte *, unsigned int *);
+
+void r_packdirent(CatDataRec *, const hfsdirent *);
+void r_unpackdirent(unsigned long, const char *,
+ const CatDataRec *, hfsdirent *);
diff --git a/roms/openbios/fs/hfs/include/volume.h b/roms/openbios/fs/hfs/include/volume.h
new file mode 100644
index 00000000..562c2d19
--- /dev/null
+++ b/roms/openbios/fs/hfs/include/volume.h
@@ -0,0 +1,71 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: volume.h,v 1.7 1998/11/02 22:09:12 rob Exp $
+ */
+
+#ifndef _H_VOLUME
+#define _H_VOLUME
+
+void v_init(hfsvol *, int);
+
+int v_open(hfsvol *, int os_fd);
+int v_flush(hfsvol *);
+int v_close(hfsvol *);
+
+int v_same(hfsvol *, int os_fd);
+int v_geometry(hfsvol *, int);
+
+int v_readmdb(hfsvol *);
+int v_writemdb(hfsvol *);
+
+int v_readvbm(hfsvol *);
+int v_writevbm(hfsvol *);
+
+int v_mount(hfsvol *);
+int v_dirty(hfsvol *);
+
+int v_catsearch(hfsvol *, unsigned long, const char *,
+ CatDataRec *, char *, node *);
+int v_extsearch(hfsfile *, unsigned int, ExtDataRec *, node *);
+
+int v_getthread(hfsvol *, unsigned long, CatDataRec *, node *, int);
+
+# define v_getdthread(vol, id, thread, np) \
+ v_getthread(vol, id, thread, np, cdrThdRec)
+# define v_getfthread(vol, id, thread, np) \
+ v_getthread(vol, id, thread, np, cdrFThdRec)
+
+int v_putcatrec(const CatDataRec *, node *);
+int v_putextrec(const ExtDataRec *, node *);
+
+int v_allocblocks(hfsvol *, ExtDescriptor *);
+int v_freeblocks(hfsvol *, const ExtDescriptor *);
+
+int v_resolve(hfsvol **vol, const char *path,
+ CatDataRec *data, unsigned long *parid, char *fname, node *np);
+
+int v_adjvalence(hfsvol *, unsigned long, int, int);
+int v_mkdir(hfsvol *, unsigned long, const char *);
+
+int v_scavenge(hfsvol *);
+
+int v_probe(int fd, long long offset);
+
+#endif /* _H_VOLUME */
diff --git a/roms/openbios/fs/hfs/low.c b/roms/openbios/fs/hfs/low.c
new file mode 100644
index 00000000..e0f7cb0e
--- /dev/null
+++ b/roms/openbios/fs/hfs/low.c
@@ -0,0 +1,157 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998, 2001 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: low.c,v 1.8 1998/11/02 22:09:03 rob Exp $
+ */
+
+#include "config.h"
+#include "libhfs.h"
+#include "low.h"
+#include "data.h"
+#include "block.h"
+#include "file.h"
+
+/*
+ * NAME: low->getpmentry()
+ * DESCRIPTION: read a partition map entry
+ */
+int l_getpmentry(hfsvol *vol, Partition *map, unsigned long bnum)
+{
+ block b;
+ const byte *ptr = b;
+ int i;
+
+ if (b_readpb(vol, bnum, &b, 1) == -1)
+ goto fail;
+
+ d_fetchsw(&ptr, &map->pmSig);
+ d_fetchsw(&ptr, &map->pmSigPad);
+ d_fetchsl(&ptr, &map->pmMapBlkCnt);
+ d_fetchsl(&ptr, &map->pmPyPartStart);
+ d_fetchsl(&ptr, &map->pmPartBlkCnt);
+
+ strncpy((char *) map->pmPartName, (const char *) ptr, 32);
+ map->pmPartName[32] = 0;
+ ptr += 32;
+
+ strncpy((char *) map->pmParType, (const char *) ptr, 32);
+ map->pmParType[32] = 0;
+ ptr += 32;
+
+ d_fetchsl(&ptr, &map->pmLgDataStart);
+ d_fetchsl(&ptr, &map->pmDataCnt);
+ d_fetchsl(&ptr, &map->pmPartStatus);
+ d_fetchsl(&ptr, &map->pmLgBootStart);
+ d_fetchsl(&ptr, &map->pmBootSize);
+ d_fetchsl(&ptr, &map->pmBootAddr);
+ d_fetchsl(&ptr, &map->pmBootAddr2);
+ d_fetchsl(&ptr, &map->pmBootEntry);
+ d_fetchsl(&ptr, &map->pmBootEntry2);
+ d_fetchsl(&ptr, &map->pmBootCksum);
+
+ strncpy((char *) map->pmProcessor, (const char *) ptr, 16);
+ map->pmProcessor[16] = 0;
+ ptr += 16;
+
+ for (i = 0; i < 188; ++i)
+ d_fetchsw(&ptr, &map->pmPad[i]);
+
+ ASSERT(ptr - b == HFS_BLOCKSZ);
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+
+/*
+ * NAME: low->getmdb()
+ * DESCRIPTION: read a master directory block
+ */
+int l_getmdb(hfsvol *vol, MDB *mdb, int backup)
+{
+ block b;
+ const byte *ptr = b;
+ int i;
+
+ if (b_readlb(vol, backup ? vol->vlen - 2 : 2, &b) == -1)
+ goto fail;
+
+ d_fetchsw(&ptr, &mdb->drSigWord);
+ d_fetchsl(&ptr, &mdb->drCrDate);
+ d_fetchsl(&ptr, &mdb->drLsMod);
+ d_fetchsw(&ptr, &mdb->drAtrb);
+ d_fetchuw(&ptr, &mdb->drNmFls);
+ d_fetchuw(&ptr, &mdb->drVBMSt);
+ d_fetchuw(&ptr, &mdb->drAllocPtr);
+ d_fetchuw(&ptr, &mdb->drNmAlBlks);
+ d_fetchul(&ptr, &mdb->drAlBlkSiz);
+ d_fetchul(&ptr, &mdb->drClpSiz);
+ d_fetchuw(&ptr, &mdb->drAlBlSt);
+ d_fetchsl(&ptr, &mdb->drNxtCNID);
+ d_fetchuw(&ptr, &mdb->drFreeBks);
+
+ d_fetchstr(&ptr, mdb->drVN, sizeof(mdb->drVN));
+
+ ASSERT(ptr - b == 64);
+
+ d_fetchsl(&ptr, &mdb->drVolBkUp);
+ d_fetchsw(&ptr, &mdb->drVSeqNum);
+ d_fetchul(&ptr, &mdb->drWrCnt);
+ d_fetchul(&ptr, &mdb->drXTClpSiz);
+ d_fetchul(&ptr, &mdb->drCTClpSiz);
+ d_fetchuw(&ptr, &mdb->drNmRtDirs);
+ d_fetchul(&ptr, &mdb->drFilCnt);
+ d_fetchul(&ptr, &mdb->drDirCnt);
+
+ for (i = 0; i < 8; ++i)
+ d_fetchsl(&ptr, &mdb->drFndrInfo[i]);
+
+ ASSERT(ptr - b == 124);
+
+ d_fetchuw(&ptr, &mdb->drEmbedSigWord);
+ d_fetchuw(&ptr, &mdb->drEmbedExtent.xdrStABN);
+ d_fetchuw(&ptr, &mdb->drEmbedExtent.xdrNumABlks);
+
+ d_fetchul(&ptr, &mdb->drXTFlSize);
+
+ for (i = 0; i < 3; ++i)
+ {
+ d_fetchuw(&ptr, &mdb->drXTExtRec[i].xdrStABN);
+ d_fetchuw(&ptr, &mdb->drXTExtRec[i].xdrNumABlks);
+ }
+
+ ASSERT(ptr - b == 146);
+
+ d_fetchul(&ptr, &mdb->drCTFlSize);
+
+ for (i = 0; i < 3; ++i)
+ {
+ d_fetchuw(&ptr, &mdb->drCTExtRec[i].xdrStABN);
+ d_fetchuw(&ptr, &mdb->drCTExtRec[i].xdrNumABlks);
+ }
+
+ ASSERT(ptr - b == 162);
+
+ return 0;
+
+fail:
+ return -1;
+}
diff --git a/roms/openbios/fs/hfs/medium.c b/roms/openbios/fs/hfs/medium.c
new file mode 100644
index 00000000..171ba80d
--- /dev/null
+++ b/roms/openbios/fs/hfs/medium.c
@@ -0,0 +1,84 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: medium.c,v 1.4 1998/11/02 22:09:04 rob Exp $
+ */
+
+#include "config.h"
+#include "libhfs.h"
+#include "block.h"
+#include "low.h"
+#include "medium.h"
+
+
+/*
+ * NAME: medium->findpmentry()
+ * DESCRIPTION: locate a partition map entry
+ */
+int m_findpmentry(hfsvol *vol, const char *type,
+ Partition *map, unsigned long *start)
+{
+ unsigned long bnum;
+ int found = 0;
+
+ if (start && *start > 0)
+ {
+ bnum = *start;
+
+ if (bnum++ >= (unsigned long) map->pmMapBlkCnt)
+ ERROR(EINVAL, "partition not found");
+ }
+ else
+ bnum = 1;
+
+ while (1)
+ {
+ if (l_getpmentry(vol, map, bnum) == -1)
+ {
+ found = -1;
+ goto fail;
+ }
+
+ if (map->pmSig != HFS_PM_SIGWORD)
+ {
+ found = -1;
+
+ if (map->pmSig == HFS_PM_SIGWORD_OLD)
+ ERROR(EINVAL, "old partition map format not supported");
+ else
+ ERROR(EINVAL, "invalid partition map");
+ }
+
+ if (strcmp((char *) map->pmParType, type) == 0)
+ {
+ found = 1;
+ goto done;
+ }
+
+ if (bnum++ >= (unsigned long) map->pmMapBlkCnt)
+ ERROR(EINVAL, "partition not found");
+ }
+
+done:
+ if (start)
+ *start = bnum;
+
+fail:
+ return found;
+}
diff --git a/roms/openbios/fs/hfs/node.c b/roms/openbios/fs/hfs/node.c
new file mode 100644
index 00000000..1670f038
--- /dev/null
+++ b/roms/openbios/fs/hfs/node.c
@@ -0,0 +1,60 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: node.c,v 1.9 1998/11/02 22:09:05 rob Exp $
+ */
+
+#include "config.h"
+#include "libhfs.h"
+#include "node.h"
+#include "data.h"
+#include "btree.h"
+
+/*
+ * NAME: node->search()
+ * DESCRIPTION: locate a record in a node, or the record it should follow
+ */
+int n_search(node *np, const byte *pkey)
+{
+ const btree *bt = np->bt;
+ byte key1[HFS_MAX_KEYLEN], key2[HFS_MAX_KEYLEN];
+ int i, comp = -1;
+
+ bt->keyunpack(pkey, key2);
+
+ for (i = np->nd.ndNRecs; i--; )
+ {
+ const byte *rec;
+
+ rec = HFS_NODEREC(*np, i);
+
+ if (HFS_RECKEYLEN(rec) == 0)
+ continue; /* deleted record */
+
+ bt->keyunpack(rec, key1);
+ comp = bt->keycompare(key1, key2);
+
+ if (comp <= 0)
+ break;
+ }
+
+ np->rnum = i;
+
+ return comp == 0;
+}
diff --git a/roms/openbios/fs/hfs/record.c b/roms/openbios/fs/hfs/record.c
new file mode 100644
index 00000000..92a3addd
--- /dev/null
+++ b/roms/openbios/fs/hfs/record.c
@@ -0,0 +1,553 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: record.c,v 1.9 1998/11/02 22:09:07 rob Exp $
+ */
+
+#include "config.h"
+#include "libhfs.h"
+#include "record.h"
+#include "data.h"
+
+/*
+ * NAME: record->packcatkey()
+ * DESCRIPTION: pack a catalog record key
+ */
+void r_packcatkey(const CatKeyRec *key, byte *pkey, unsigned int *len)
+{
+ const byte *start = pkey;
+
+ d_storesb(&pkey, key->ckrKeyLen);
+ d_storesb(&pkey, key->ckrResrv1);
+ d_storeul(&pkey, key->ckrParID);
+
+ d_storestr(&pkey, key->ckrCName, sizeof(key->ckrCName));
+
+ if (len)
+ *len = HFS_RECKEYSKIP(start);
+}
+
+/*
+ * NAME: record->unpackcatkey()
+ * DESCRIPTION: unpack a catalog record key
+ */
+void r_unpackcatkey(const byte *pkey, CatKeyRec *key)
+{
+ d_fetchsb(&pkey, &key->ckrKeyLen);
+ d_fetchsb(&pkey, &key->ckrResrv1);
+ d_fetchul(&pkey, &key->ckrParID);
+
+ d_fetchstr(&pkey, key->ckrCName, sizeof(key->ckrCName));
+}
+
+/*
+ * NAME: record->packextkey()
+ * DESCRIPTION: pack an extents record key
+ */
+void r_packextkey(const ExtKeyRec *key, byte *pkey, unsigned int *len)
+{
+ const byte *start = pkey;
+
+ d_storesb(&pkey, key->xkrKeyLen);
+ d_storesb(&pkey, key->xkrFkType);
+ d_storeul(&pkey, key->xkrFNum);
+ d_storeuw(&pkey, key->xkrFABN);
+
+ if (len)
+ *len = HFS_RECKEYSKIP(start);
+}
+
+/*
+ * NAME: record->unpackextkey()
+ * DESCRIPTION: unpack an extents record key
+ */
+void r_unpackextkey(const byte *pkey, ExtKeyRec *key)
+{
+ d_fetchsb(&pkey, &key->xkrKeyLen);
+ d_fetchsb(&pkey, &key->xkrFkType);
+ d_fetchul(&pkey, &key->xkrFNum);
+ d_fetchuw(&pkey, &key->xkrFABN);
+}
+
+/*
+ * NAME: record->comparecatkeys()
+ * DESCRIPTION: compare two (packed) catalog record keys
+ */
+int r_comparecatkeys(const CatKeyRec *key1, const CatKeyRec *key2)
+{
+ int diff;
+
+ diff = key1->ckrParID - key2->ckrParID;
+ if (diff)
+ return diff;
+
+ return d_relstring(key1->ckrCName, key2->ckrCName);
+}
+
+/*
+ * NAME: record->compareextkeys()
+ * DESCRIPTION: compare two (packed) extents record keys
+ */
+int r_compareextkeys(const ExtKeyRec *key1, const ExtKeyRec *key2)
+{
+ int diff;
+
+ diff = key1->xkrFNum - key2->xkrFNum;
+ if (diff)
+ return diff;
+
+ diff = (unsigned char) key1->xkrFkType -
+ (unsigned char) key2->xkrFkType;
+ if (diff)
+ return diff;
+
+ return key1->xkrFABN - key2->xkrFABN;
+}
+
+/*
+ * NAME: record->packcatdata()
+ * DESCRIPTION: pack catalog record data
+ */
+void r_packcatdata(const CatDataRec *data, byte *pdata, unsigned int *len)
+{
+ const byte *start = pdata;
+ int i;
+
+ d_storesb(&pdata, data->cdrType);
+ d_storesb(&pdata, data->cdrResrv2);
+
+ switch (data->cdrType)
+ {
+ case cdrDirRec:
+ d_storesw(&pdata, data->u.dir.dirFlags);
+ d_storeuw(&pdata, data->u.dir.dirVal);
+ d_storeul(&pdata, data->u.dir.dirDirID);
+ d_storesl(&pdata, data->u.dir.dirCrDat);
+ d_storesl(&pdata, data->u.dir.dirMdDat);
+ d_storesl(&pdata, data->u.dir.dirBkDat);
+
+ d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.top);
+ d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.left);
+ d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.bottom);
+ d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.right);
+ d_storesw(&pdata, data->u.dir.dirUsrInfo.frFlags);
+ d_storesw(&pdata, data->u.dir.dirUsrInfo.frLocation.v);
+ d_storesw(&pdata, data->u.dir.dirUsrInfo.frLocation.h);
+ d_storesw(&pdata, data->u.dir.dirUsrInfo.frView);
+
+ d_storesw(&pdata, data->u.dir.dirFndrInfo.frScroll.v);
+ d_storesw(&pdata, data->u.dir.dirFndrInfo.frScroll.h);
+ d_storesl(&pdata, data->u.dir.dirFndrInfo.frOpenChain);
+ d_storesw(&pdata, data->u.dir.dirFndrInfo.frUnused);
+ d_storesw(&pdata, data->u.dir.dirFndrInfo.frComment);
+ d_storesl(&pdata, data->u.dir.dirFndrInfo.frPutAway);
+
+ for (i = 0; i < 4; ++i)
+ d_storesl(&pdata, data->u.dir.dirResrv[i]);
+
+ break;
+
+ case cdrFilRec:
+ d_storesb(&pdata, data->u.fil.filFlags);
+ d_storesb(&pdata, data->u.fil.filTyp);
+
+ d_storesl(&pdata, data->u.fil.filUsrWds.fdType);
+ d_storesl(&pdata, data->u.fil.filUsrWds.fdCreator);
+ d_storesw(&pdata, data->u.fil.filUsrWds.fdFlags);
+ d_storesw(&pdata, data->u.fil.filUsrWds.fdLocation.v);
+ d_storesw(&pdata, data->u.fil.filUsrWds.fdLocation.h);
+ d_storesw(&pdata, data->u.fil.filUsrWds.fdFldr);
+
+ d_storeul(&pdata, data->u.fil.filFlNum);
+
+ d_storeuw(&pdata, data->u.fil.filStBlk);
+ d_storeul(&pdata, data->u.fil.filLgLen);
+ d_storeul(&pdata, data->u.fil.filPyLen);
+
+ d_storeuw(&pdata, data->u.fil.filRStBlk);
+ d_storeul(&pdata, data->u.fil.filRLgLen);
+ d_storeul(&pdata, data->u.fil.filRPyLen);
+
+ d_storesl(&pdata, data->u.fil.filCrDat);
+ d_storesl(&pdata, data->u.fil.filMdDat);
+ d_storesl(&pdata, data->u.fil.filBkDat);
+
+ d_storesw(&pdata, data->u.fil.filFndrInfo.fdIconID);
+ for (i = 0; i < 4; ++i)
+ d_storesw(&pdata, data->u.fil.filFndrInfo.fdUnused[i]);
+ d_storesw(&pdata, data->u.fil.filFndrInfo.fdComment);
+ d_storesl(&pdata, data->u.fil.filFndrInfo.fdPutAway);
+
+ d_storeuw(&pdata, data->u.fil.filClpSize);
+
+ for (i = 0; i < 3; ++i)
+ {
+ d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrStABN);
+ d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrNumABlks);
+ }
+
+ for (i = 0; i < 3; ++i)
+ {
+ d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrStABN);
+ d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrNumABlks);
+ }
+
+ d_storesl(&pdata, data->u.fil.filResrv);
+
+ break;
+
+ case cdrThdRec:
+ for (i = 0; i < 2; ++i)
+ d_storesl(&pdata, data->u.dthd.thdResrv[i]);
+
+ d_storeul(&pdata, data->u.dthd.thdParID);
+
+ d_storestr(&pdata, data->u.dthd.thdCName,
+ sizeof(data->u.dthd.thdCName));
+
+ break;
+
+ case cdrFThdRec:
+ for (i = 0; i < 2; ++i)
+ d_storesl(&pdata, data->u.fthd.fthdResrv[i]);
+
+ d_storeul(&pdata, data->u.fthd.fthdParID);
+
+ d_storestr(&pdata, data->u.fthd.fthdCName,
+ sizeof(data->u.fthd.fthdCName));
+
+ break;
+
+ default:
+ ASSERT(0);
+ }
+
+ if (len)
+ *len += pdata - start;
+}
+
+/*
+ * NAME: record->unpackcatdata()
+ * DESCRIPTION: unpack catalog record data
+ */
+void r_unpackcatdata(const byte *pdata, CatDataRec *data)
+{
+ int i;
+
+ d_fetchsb(&pdata, &data->cdrType);
+ d_fetchsb(&pdata, &data->cdrResrv2);
+
+ switch (data->cdrType)
+ {
+ case cdrDirRec:
+ d_fetchsw(&pdata, &data->u.dir.dirFlags);
+ d_fetchuw(&pdata, &data->u.dir.dirVal);
+ d_fetchul(&pdata, &data->u.dir.dirDirID);
+ d_fetchsl(&pdata, &data->u.dir.dirCrDat);
+ d_fetchsl(&pdata, &data->u.dir.dirMdDat);
+ d_fetchsl(&pdata, &data->u.dir.dirBkDat);
+
+ d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.top);
+ d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.left);
+ d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.bottom);
+ d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.right);
+ d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frFlags);
+ d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frLocation.v);
+ d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frLocation.h);
+ d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frView);
+
+ d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frScroll.v);
+ d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frScroll.h);
+ d_fetchsl(&pdata, &data->u.dir.dirFndrInfo.frOpenChain);
+ d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frUnused);
+ d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frComment);
+ d_fetchsl(&pdata, &data->u.dir.dirFndrInfo.frPutAway);
+
+ for (i = 0; i < 4; ++i)
+ d_fetchsl(&pdata, &data->u.dir.dirResrv[i]);
+
+ break;
+
+ case cdrFilRec:
+ d_fetchsb(&pdata, &data->u.fil.filFlags);
+ d_fetchsb(&pdata, &data->u.fil.filTyp);
+
+ d_fetchsl(&pdata, &data->u.fil.filUsrWds.fdType);
+ d_fetchsl(&pdata, &data->u.fil.filUsrWds.fdCreator);
+ d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdFlags);
+ d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdLocation.v);
+ d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdLocation.h);
+ d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdFldr);
+
+ d_fetchul(&pdata, &data->u.fil.filFlNum);
+
+ d_fetchuw(&pdata, &data->u.fil.filStBlk);
+ d_fetchul(&pdata, &data->u.fil.filLgLen);
+ d_fetchul(&pdata, &data->u.fil.filPyLen);
+
+ d_fetchuw(&pdata, &data->u.fil.filRStBlk);
+ d_fetchul(&pdata, &data->u.fil.filRLgLen);
+ d_fetchul(&pdata, &data->u.fil.filRPyLen);
+
+ d_fetchsl(&pdata, &data->u.fil.filCrDat);
+ d_fetchsl(&pdata, &data->u.fil.filMdDat);
+ d_fetchsl(&pdata, &data->u.fil.filBkDat);
+
+ d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdIconID);
+ for (i = 0; i < 4; ++i)
+ d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdUnused[i]);
+ d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdComment);
+ d_fetchsl(&pdata, &data->u.fil.filFndrInfo.fdPutAway);
+
+ d_fetchuw(&pdata, &data->u.fil.filClpSize);
+
+ for (i = 0; i < 3; ++i)
+ {
+ d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrStABN);
+ d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrNumABlks);
+ }
+
+ for (i = 0; i < 3; ++i)
+ {
+ d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrStABN);
+ d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrNumABlks);
+ }
+
+ d_fetchsl(&pdata, &data->u.fil.filResrv);
+
+ break;
+
+ case cdrThdRec:
+ for (i = 0; i < 2; ++i)
+ d_fetchsl(&pdata, &data->u.dthd.thdResrv[i]);
+
+ d_fetchul(&pdata, &data->u.dthd.thdParID);
+
+ d_fetchstr(&pdata, data->u.dthd.thdCName,
+ sizeof(data->u.dthd.thdCName));
+
+ break;
+
+ case cdrFThdRec:
+ for (i = 0; i < 2; ++i)
+ d_fetchsl(&pdata, &data->u.fthd.fthdResrv[i]);
+
+ d_fetchul(&pdata, &data->u.fthd.fthdParID);
+
+ d_fetchstr(&pdata, data->u.fthd.fthdCName,
+ sizeof(data->u.fthd.fthdCName));
+
+ break;
+
+ default:
+ ASSERT(0);
+ }
+}
+
+/*
+ * NAME: record->packextdata()
+ * DESCRIPTION: pack extent record data
+ */
+void r_packextdata(const ExtDataRec *data, byte *pdata, unsigned int *len)
+{
+ const byte *start = pdata;
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ {
+ d_storeuw(&pdata, (*data)[i].xdrStABN);
+ d_storeuw(&pdata, (*data)[i].xdrNumABlks);
+ }
+
+ if (len)
+ *len += pdata - start;
+}
+
+/*
+ * NAME: record->unpackextdata()
+ * DESCRIPTION: unpack extent record data
+ */
+void r_unpackextdata(const byte *pdata, ExtDataRec *data)
+{
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ {
+ d_fetchuw(&pdata, &(*data)[i].xdrStABN);
+ d_fetchuw(&pdata, &(*data)[i].xdrNumABlks);
+ }
+}
+
+/*
+ * NAME: record->makecatkey()
+ * DESCRIPTION: construct a catalog record key
+ */
+void r_makecatkey(CatKeyRec *key, unsigned long parid, const char *name)
+{
+ int len;
+
+ len = strlen(name) + 1;
+
+ key->ckrKeyLen = 0x05 + len + (len & 1);
+ key->ckrResrv1 = 0;
+ key->ckrParID = parid;
+
+ strcpy(key->ckrCName, name);
+}
+
+/*
+ * NAME: record->makeextkey()
+ * DESCRIPTION: construct an extents record key
+ */
+void r_makeextkey(ExtKeyRec *key,
+ int fork, unsigned long fnum, unsigned int fabn)
+{
+ key->xkrKeyLen = 0x07;
+ key->xkrFkType = fork;
+ key->xkrFNum = fnum;
+ key->xkrFABN = fabn;
+}
+
+/*
+ * NAME: record->packcatrec()
+ * DESCRIPTION: create a packed catalog record
+ */
+void r_packcatrec(const CatKeyRec *key, const CatDataRec *data,
+ byte *precord, unsigned int *len)
+{
+ r_packcatkey(key, precord, len);
+ r_packcatdata(data, HFS_RECDATA(precord), len);
+}
+
+/*
+ * NAME: record->packextrec()
+ * DESCRIPTION: create a packed extents record
+ */
+void r_packextrec(const ExtKeyRec *key, const ExtDataRec *data,
+ byte *precord, unsigned int *len)
+{
+ r_packextkey(key, precord, len);
+ r_packextdata(data, HFS_RECDATA(precord), len);
+}
+
+/*
+ * NAME: record->packdirent()
+ * DESCRIPTION: make changes to a catalog record
+ */
+void r_packdirent(CatDataRec *data, const hfsdirent *ent)
+{
+ switch (data->cdrType)
+ {
+ case cdrDirRec:
+ data->u.dir.dirCrDat = d_mtime(ent->crdate);
+ data->u.dir.dirMdDat = d_mtime(ent->mddate);
+ data->u.dir.dirBkDat = d_mtime(ent->bkdate);
+
+ data->u.dir.dirUsrInfo.frFlags = ent->fdflags;
+ data->u.dir.dirUsrInfo.frLocation.v = ent->fdlocation.v;
+ data->u.dir.dirUsrInfo.frLocation.h = ent->fdlocation.h;
+
+ data->u.dir.dirUsrInfo.frRect.top = ent->u.dir.rect.top;
+ data->u.dir.dirUsrInfo.frRect.left = ent->u.dir.rect.left;
+ data->u.dir.dirUsrInfo.frRect.bottom = ent->u.dir.rect.bottom;
+ data->u.dir.dirUsrInfo.frRect.right = ent->u.dir.rect.right;
+
+ break;
+
+ case cdrFilRec:
+ if (ent->flags & HFS_ISLOCKED)
+ data->u.fil.filFlags |= (1 << 0);
+ else
+ data->u.fil.filFlags &= ~(1 << 0);
+
+ data->u.fil.filCrDat = d_mtime(ent->crdate);
+ data->u.fil.filMdDat = d_mtime(ent->mddate);
+ data->u.fil.filBkDat = d_mtime(ent->bkdate);
+
+ data->u.fil.filUsrWds.fdFlags = ent->fdflags;
+ data->u.fil.filUsrWds.fdLocation.v = ent->fdlocation.v;
+ data->u.fil.filUsrWds.fdLocation.h = ent->fdlocation.h;
+
+ data->u.fil.filUsrWds.fdType =
+ d_getsl((const unsigned char *) ent->u.file.type);
+ data->u.fil.filUsrWds.fdCreator =
+ d_getsl((const unsigned char *) ent->u.file.creator);
+
+ break;
+ }
+}
+
+/*
+ * NAME: record->unpackdirent()
+ * DESCRIPTION: unpack catalog information into hfsdirent structure
+ */
+void r_unpackdirent(unsigned long parid, const char *name,
+ const CatDataRec *data, hfsdirent *ent)
+{
+ strcpy(ent->name, name);
+ ent->parid = parid;
+
+ switch (data->cdrType)
+ {
+ case cdrDirRec:
+ ent->flags = HFS_ISDIR;
+ ent->cnid = data->u.dir.dirDirID;
+
+ ent->crdate = d_ltime(data->u.dir.dirCrDat);
+ ent->mddate = d_ltime(data->u.dir.dirMdDat);
+ ent->bkdate = d_ltime(data->u.dir.dirBkDat);
+
+ ent->fdflags = data->u.dir.dirUsrInfo.frFlags;
+ ent->fdlocation.v = data->u.dir.dirUsrInfo.frLocation.v;
+ ent->fdlocation.h = data->u.dir.dirUsrInfo.frLocation.h;
+
+ ent->u.dir.valence = data->u.dir.dirVal;
+
+ ent->u.dir.rect.top = data->u.dir.dirUsrInfo.frRect.top;
+ ent->u.dir.rect.left = data->u.dir.dirUsrInfo.frRect.left;
+ ent->u.dir.rect.bottom = data->u.dir.dirUsrInfo.frRect.bottom;
+ ent->u.dir.rect.right = data->u.dir.dirUsrInfo.frRect.right;
+
+ break;
+
+ case cdrFilRec:
+ ent->flags = (data->u.fil.filFlags & (1 << 0)) ? HFS_ISLOCKED : 0;
+ ent->cnid = data->u.fil.filFlNum;
+
+ ent->crdate = d_ltime(data->u.fil.filCrDat);
+ ent->mddate = d_ltime(data->u.fil.filMdDat);
+ ent->bkdate = d_ltime(data->u.fil.filBkDat);
+
+ ent->fdflags = data->u.fil.filUsrWds.fdFlags;
+ ent->fdlocation.v = data->u.fil.filUsrWds.fdLocation.v;
+ ent->fdlocation.h = data->u.fil.filUsrWds.fdLocation.h;
+
+ ent->u.file.dsize = data->u.fil.filLgLen;
+ ent->u.file.rsize = data->u.fil.filRLgLen;
+
+ d_putsl((unsigned char *) ent->u.file.type,
+ data->u.fil.filUsrWds.fdType);
+ d_putsl((unsigned char *) ent->u.file.creator,
+ data->u.fil.filUsrWds.fdCreator);
+
+ ent->u.file.type[4] = ent->u.file.creator[4] = 0;
+
+ break;
+ }
+}
diff --git a/roms/openbios/fs/hfs/volume.c b/roms/openbios/fs/hfs/volume.c
new file mode 100644
index 00000000..4faf7e6c
--- /dev/null
+++ b/roms/openbios/fs/hfs/volume.c
@@ -0,0 +1,612 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: volume.c,v 1.12 1998/11/02 22:09:10 rob Exp $
+ */
+
+#include "config.h"
+#include "libhfs.h"
+#include "volume.h"
+#include "data.h"
+#include "block.h"
+#include "low.h"
+#include "medium.h"
+#include "file.h"
+#include "btree.h"
+#include "record.h"
+#include "os.h"
+
+#include "libc/byteorder.h"
+
+/*
+ * NAME: vol->init()
+ * DESCRIPTION: initialize volume structure
+ */
+void v_init(hfsvol *vol, int flags)
+{
+ btree *ext = &vol->ext;
+ btree *cat = &vol->cat;
+
+ vol->os_fd = 0;
+ vol->flags = flags & HFS_VOL_OPT_MASK;
+
+ vol->pnum = -1;
+ vol->vstart = 0;
+ vol->vlen = 0;
+ vol->lpa = 0;
+
+ vol->cache = NULL;
+
+ vol->vbm = NULL;
+ vol->vbmsz = 0;
+
+ f_init(&ext->f, vol, HFS_CNID_EXT, "extents overflow");
+
+ ext->map = NULL;
+ ext->mapsz = 0;
+ ext->flags = 0;
+
+ ext->keyunpack = (keyunpackfunc) r_unpackextkey;
+ ext->keycompare = (keycomparefunc) r_compareextkeys;
+
+ f_init(&cat->f, vol, HFS_CNID_CAT, "catalog");
+
+ cat->map = NULL;
+ cat->mapsz = 0;
+ cat->flags = 0;
+
+ cat->keyunpack = (keyunpackfunc) r_unpackcatkey;
+ cat->keycompare = (keycomparefunc) r_comparecatkeys;
+
+ vol->cwd = HFS_CNID_ROOTDIR;
+
+ vol->refs = 0;
+ vol->files = NULL;
+ vol->dirs = NULL;
+
+ vol->prev = NULL;
+ vol->next = NULL;
+}
+
+/*
+ * NAME: vol->open()
+ * DESCRIPTION: open volume source and lock against concurrent updates
+ */
+int v_open(hfsvol *vol, int os_fd )
+{
+ if (vol->flags & HFS_VOL_OPEN)
+ ERROR(EINVAL, "volume already open");
+
+ vol->flags |= HFS_VOL_OPEN;
+ vol->os_fd = os_fd;
+
+ /* initialize volume block cache (OK to fail) */
+
+ if (! (vol->flags & HFS_OPT_NOCACHE) &&
+ b_init(vol) != -1)
+ vol->flags |= HFS_VOL_USINGCACHE;
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: vol->close()
+ * DESCRIPTION: close access path to volume source
+ */
+int v_close(hfsvol *vol)
+{
+ int result = 0;
+
+ if (! (vol->flags & HFS_VOL_OPEN))
+ goto done;
+
+ if ((vol->flags & HFS_VOL_USINGCACHE) &&
+ b_finish(vol) == -1)
+ result = -1;
+
+ vol->flags &= ~(HFS_VOL_OPEN | HFS_VOL_MOUNTED | HFS_VOL_USINGCACHE);
+
+ /* free dynamically allocated structures */
+
+ FREE(vol->vbm);
+
+ vol->vbm = NULL;
+ vol->vbmsz = 0;
+
+ FREE(vol->ext.map);
+ FREE(vol->cat.map);
+
+ vol->ext.map = NULL;
+ vol->cat.map = NULL;
+
+done:
+ return result;
+}
+
+/*
+ * NAME: vol->same()
+ * DESCRIPTION: return 1 iff path is same as open volume
+ */
+int v_same(hfsvol *vol, int os_fd )
+{
+ return vol->os_fd == os_fd;
+}
+
+/*
+ * NAME: vol->geometry()
+ * DESCRIPTION: determine volume location and size (possibly in a partition)
+ */
+int v_geometry(hfsvol *vol, int pnum)
+{
+ Partition map;
+ unsigned long bnum = 0;
+ int found;
+
+ vol->pnum = pnum;
+
+ if (pnum == 0)
+ {
+ vol->vstart = 0;
+ vol->vlen = b_size(vol);
+
+ if (vol->vlen == 0)
+ goto fail;
+ }
+ else
+ {
+ while (pnum--)
+ {
+ found = m_findpmentry(vol, "Apple_HFS", &map, &bnum);
+ if (found == -1 || ! found)
+ goto fail;
+ }
+
+ vol->vstart = map.pmPyPartStart;
+ vol->vlen = map.pmPartBlkCnt;
+
+ if (map.pmDataCnt)
+ {
+ if ((unsigned long) map.pmLgDataStart +
+ (unsigned long) map.pmDataCnt > vol->vlen)
+ ERROR(EINVAL, "partition data overflows partition");
+
+ vol->vstart += (unsigned long) map.pmLgDataStart;
+ vol->vlen = map.pmDataCnt;
+ }
+
+ if (vol->vlen == 0)
+ ERROR(EINVAL, "volume partition is empty");
+ }
+
+ if (vol->vlen < 800 * (1024 >> HFS_BLOCKSZ_BITS))
+ ERROR(EINVAL, "volume is smaller than 800K");
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: vol->readmdb()
+ * DESCRIPTION: load Master Directory Block into memory
+ */
+int v_readmdb(hfsvol *vol)
+{
+ if (l_getmdb(vol, &vol->mdb, 0) == -1)
+ goto fail;
+
+ if (vol->mdb.drSigWord != HFS_SIGWORD)
+ {
+ if (vol->mdb.drSigWord == HFS_SIGWORD_MFS)
+ ERROR(EINVAL, "MFS volume format not supported");
+ else
+ ERROR(EINVAL, "not a Macintosh HFS volume");
+ }
+
+ if (vol->mdb.drAlBlkSiz % HFS_BLOCKSZ != 0)
+ ERROR(EINVAL, "bad volume allocation block size");
+
+ vol->lpa = vol->mdb.drAlBlkSiz >> HFS_BLOCKSZ_BITS;
+
+ /* extents pseudo-file structs */
+
+ vol->ext.f.cat.u.fil.filStBlk = vol->mdb.drXTExtRec[0].xdrStABN;
+ vol->ext.f.cat.u.fil.filLgLen = vol->mdb.drXTFlSize;
+ vol->ext.f.cat.u.fil.filPyLen = vol->mdb.drXTFlSize;
+
+ vol->ext.f.cat.u.fil.filCrDat = vol->mdb.drCrDate;
+ vol->ext.f.cat.u.fil.filMdDat = vol->mdb.drLsMod;
+
+ memcpy(&vol->ext.f.cat.u.fil.filExtRec,
+ &vol->mdb.drXTExtRec, sizeof(ExtDataRec));
+
+ f_selectfork(&vol->ext.f, fkData);
+
+ /* catalog pseudo-file structs */
+
+ vol->cat.f.cat.u.fil.filStBlk = vol->mdb.drCTExtRec[0].xdrStABN;
+ vol->cat.f.cat.u.fil.filLgLen = vol->mdb.drCTFlSize;
+ vol->cat.f.cat.u.fil.filPyLen = vol->mdb.drCTFlSize;
+
+ vol->cat.f.cat.u.fil.filCrDat = vol->mdb.drCrDate;
+ vol->cat.f.cat.u.fil.filMdDat = vol->mdb.drLsMod;
+
+ memcpy(&vol->cat.f.cat.u.fil.filExtRec,
+ &vol->mdb.drCTExtRec, sizeof(ExtDataRec));
+
+ f_selectfork(&vol->cat.f, fkData);
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: vol->readvbm()
+ * DESCRIPTION: read volume bitmap into memory
+ */
+int v_readvbm(hfsvol *vol)
+{
+ unsigned int vbmst = vol->mdb.drVBMSt;
+ unsigned int vbmsz = (vol->mdb.drNmAlBlks + 0x0fff) >> 12;
+ block *bp;
+
+ ASSERT(vol->vbm == 0);
+
+ if (vol->mdb.drAlBlSt - vbmst < vbmsz)
+ ERROR(EIO, "volume bitmap collides with volume data");
+
+ vol->vbm = ALLOC(block, vbmsz);
+ if (vol->vbm == NULL)
+ ERROR(ENOMEM, NULL);
+
+ vol->vbmsz = vbmsz;
+
+ for (bp = vol->vbm; vbmsz--; ++bp)
+ {
+ if (b_readlb(vol, vbmst++, bp) == -1)
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ FREE(vol->vbm);
+
+ vol->vbm = NULL;
+ vol->vbmsz = 0;
+
+ return -1;
+}
+
+/*
+ * NAME: vol->mount()
+ * DESCRIPTION: load volume information into memory
+ */
+int v_mount(hfsvol *vol)
+{
+ /* read the MDB, volume bitmap, and extents/catalog B*-tree headers */
+
+ if (v_readmdb(vol) == -1 ||
+ v_readvbm(vol) == -1 ||
+ bt_readhdr(&vol->ext) == -1 ||
+ bt_readhdr(&vol->cat) == -1)
+ goto fail;
+
+ if (vol->mdb.drAtrb & HFS_ATRB_SLOCKED)
+ vol->flags |= HFS_VOL_READONLY;
+ else if (vol->flags & HFS_VOL_READONLY)
+ vol->mdb.drAtrb |= HFS_ATRB_HLOCKED;
+ else
+ vol->mdb.drAtrb &= ~HFS_ATRB_HLOCKED;
+
+ vol->flags |= HFS_VOL_MOUNTED;
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+/*
+ * NAME: vol->catsearch()
+ * DESCRIPTION: search catalog tree
+ */
+int v_catsearch(hfsvol *vol, unsigned long parid, const char *name,
+ CatDataRec *data, char *cname, node *np)
+{
+ CatKeyRec key;
+ byte pkey[HFS_CATKEYLEN];
+ const byte *ptr;
+ node n;
+ int found;
+
+ if (np == NULL)
+ np = &n;
+
+ r_makecatkey(&key, parid, name);
+ r_packcatkey(&key, pkey, NULL);
+
+ found = bt_search(&vol->cat, pkey, np);
+ if (found <= 0)
+ return found;
+
+ ptr = HFS_NODEREC(*np, np->rnum);
+
+ if (cname)
+ {
+ r_unpackcatkey(ptr, &key);
+ strcpy(cname, key.ckrCName);
+ }
+
+ if (data)
+ r_unpackcatdata(HFS_RECDATA(ptr), data);
+
+ return 1;
+}
+
+/*
+ * NAME: vol->extsearch()
+ * DESCRIPTION: search extents tree
+ */
+int v_extsearch(hfsfile *file, unsigned int fabn,
+ ExtDataRec *data, node *np)
+{
+ ExtKeyRec key;
+ ExtDataRec extsave;
+ unsigned int fabnsave;
+ byte pkey[HFS_EXTKEYLEN];
+ const byte *ptr;
+ node n;
+ int found;
+
+ if (np == NULL)
+ np = &n;
+
+ r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, fabn);
+ r_packextkey(&key, pkey, NULL);
+
+ /* in case bt_search() clobbers these */
+
+ memcpy(&extsave, &file->ext, sizeof(ExtDataRec));
+ fabnsave = file->fabn;
+
+ found = bt_search(&file->vol->ext, pkey, np);
+
+ memcpy(&file->ext, &extsave, sizeof(ExtDataRec));
+ file->fabn = fabnsave;
+
+ if (found <= 0)
+ return found;
+
+ if (data)
+ {
+ ptr = HFS_NODEREC(*np, np->rnum);
+ r_unpackextdata(HFS_RECDATA(ptr), data);
+ }
+
+ return 1;
+}
+
+/*
+ * NAME: vol->getthread()
+ * DESCRIPTION: retrieve catalog thread information for a file or directory
+ */
+int v_getthread(hfsvol *vol, unsigned long id,
+ CatDataRec *thread, node *np, int type)
+{
+ CatDataRec rec;
+ int found;
+
+ if (thread == NULL)
+ thread = &rec;
+
+ found = v_catsearch(vol, id, "", thread, NULL, np);
+ if (found == 1 && thread->cdrType != type)
+ ERROR(EIO, "bad thread record");
+
+ return found;
+
+fail:
+ return -1;
+}
+
+
+/*
+ * NAME: vol->resolve()
+ * DESCRIPTION: translate a pathname; return catalog information
+ */
+int v_resolve(hfsvol **vol, const char *path,
+ CatDataRec *data, unsigned long *parid, char *fname, node *np)
+{
+ unsigned long dirid;
+ char name[HFS_MAX_FLEN + 1], *nptr;
+ int found = 0;
+
+ if (*path == 0)
+ ERROR(ENOENT, "empty path");
+
+ if (parid)
+ *parid = 0;
+
+ nptr = strchr(path, ':');
+
+ if (*path == ':' || nptr == NULL)
+ {
+ dirid = (*vol)->cwd; /* relative path */
+
+ if (*path == ':')
+ ++path;
+
+ if (*path == 0)
+ {
+ found = v_getdthread(*vol, dirid, data, NULL);
+ if (found == -1)
+ goto fail;
+
+ if (found)
+ {
+ if (parid)
+ *parid = data->u.dthd.thdParID;
+
+ found = v_catsearch(*vol, data->u.dthd.thdParID,
+ data->u.dthd.thdCName, data, fname, np);
+ if (found == -1)
+ goto fail;
+ }
+
+ goto done;
+ }
+ }
+ else
+ {
+ hfsvol *check;
+
+ dirid = HFS_CNID_ROOTPAR; /* absolute path */
+
+ if (nptr - path > HFS_MAX_VLEN)
+ ERROR(ENAMETOOLONG, NULL);
+
+ strncpy(name, path, nptr - path);
+ name[nptr - path] = 0;
+
+ for (check = hfs_mounts; check; check = check->next)
+ {
+ if (d_relstring(check->mdb.drVN, name) == 0)
+ {
+ *vol = check;
+ break;
+ }
+ }
+ }
+
+ while (1)
+ {
+ while (*path == ':')
+ {
+ ++path;
+
+ found = v_getdthread(*vol, dirid, data, NULL);
+ if (found == -1)
+ goto fail;
+ else if (! found)
+ goto done;
+
+ dirid = data->u.dthd.thdParID;
+ }
+
+ if (*path == 0)
+ {
+ found = v_getdthread(*vol, dirid, data, NULL);
+ if (found == -1)
+ goto fail;
+
+ if (found)
+ {
+ if (parid)
+ *parid = data->u.dthd.thdParID;
+
+ found = v_catsearch(*vol, data->u.dthd.thdParID,
+ data->u.dthd.thdCName, data, fname, np);
+ if (found == -1)
+ goto fail;
+ }
+
+ goto done;
+ }
+
+ nptr = name;
+ while (nptr < name + sizeof(name) - 1 && *path && *path != ':')
+ *nptr++ = *path++;
+
+ if (*path && *path != ':')
+ ERROR(ENAMETOOLONG, NULL);
+
+ *nptr = 0;
+ if (*path == ':')
+ ++path;
+
+ if (parid)
+ *parid = dirid;
+
+ found = v_catsearch(*vol, dirid, name, data, fname, np);
+ if (found == -1)
+ goto fail;
+
+ if (! found)
+ {
+ if (*path && parid)
+ *parid = 0;
+
+ if (*path == 0 && fname)
+ strcpy(fname, name);
+
+ goto done;
+ }
+
+ switch (data->cdrType)
+ {
+ case cdrDirRec:
+ if (*path == 0)
+ goto done;
+
+ dirid = data->u.dir.dirDirID;
+ break;
+
+ case cdrFilRec:
+ if (*path == 0)
+ goto done;
+
+ ERROR(ENOTDIR, "invalid pathname");
+
+ default:
+ ERROR(EIO, "unexpected catalog record");
+ }
+ }
+
+done:
+ return found;
+
+fail:
+ return -1;
+}
+
+/* Determine whether the volume is a HFS volume */
+int
+v_probe(int fd, long long offset)
+{
+ MDB *mdb;
+
+ mdb = (MDB*)malloc(2 * 512);
+ os_seek_offset( fd, 2 * 512 + offset );
+ os_read(fd, mdb, 2, 9);
+
+ if (__be16_to_cpu(mdb->drSigWord) != HFS_SIGWORD) {
+ free(mdb);
+ return 0;
+ }
+
+ free(mdb);
+ return -1;
+}
diff --git a/roms/openbios/fs/hfs_mdb.h b/roms/openbios/fs/hfs_mdb.h
new file mode 100644
index 00000000..652525d9
--- /dev/null
+++ b/roms/openbios/fs/hfs_mdb.h
@@ -0,0 +1,118 @@
+/*
+ * Creation Date: <2000/09/03 23:04:27 samuel>
+ * Time-stamp: <2000/09/04 01:23:55 samuel>
+ *
+ * <hfs_mdb.h>
+ *
+ * HFS Master Directory Block (MDB)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_HFS_MDB
+#define _H_HFS_MDB
+
+#include "libc/byteorder.h"
+
+typedef unsigned char hfs_char_t;
+typedef unsigned char hfs_ushort_t[2];
+typedef unsigned char hfs_uint_t[4];
+
+static inline unsigned short hfs_get_ushort(hfs_ushort_t addr)
+{
+ return __be16_to_cpu(*((unsigned short *)(addr)));
+}
+
+static inline unsigned int hfs_get_uint(hfs_uint_t addr)
+{
+ return __be32_to_cpu(*((unsigned int *)(addr)));
+}
+
+/*
+ * The HFS Master Directory Block (MDB).
+ *
+ * Also known as the Volume Information Block (VIB), this structure is
+ * the HFS equivalent of a superblock.
+ *
+ * Reference: _Inside Macintosh: Files_ pages 2-59 through 2-62
+ *
+ * modified for HFS Extended
+ */
+
+typedef struct hfs_mdb {
+ hfs_ushort_t drSigWord; /* Signature word indicating fs type */
+ hfs_uint_t drCrDate; /* fs creation date/time */
+ hfs_uint_t drLsMod; /* fs modification date/time */
+ hfs_ushort_t drAtrb; /* fs attributes */
+ hfs_ushort_t drNmFls; /* number of files in root directory */
+ hfs_ushort_t drVBMSt; /* location (in 512-byte blocks)
+ of the volume bitmap */
+ hfs_ushort_t drAllocPtr; /* location (in allocation blocks)
+ to begin next allocation search */
+ hfs_ushort_t drNmAlBlks; /* number of allocation blocks */
+ hfs_uint_t drAlBlkSiz; /* bytes in an allocation block */
+ hfs_uint_t drClpSiz; /* clumpsize, the number of bytes to
+ allocate when extending a file */
+ hfs_ushort_t drAlBlSt; /* location (in 512-byte blocks)
+ of the first allocation block */
+ hfs_uint_t drNxtCNID; /* CNID to assign to the next
+ file or directory created */
+ hfs_ushort_t drFreeBks; /* number of free allocation blocks */
+ hfs_char_t drVN[28]; /* the volume label */
+ hfs_uint_t drVolBkUp; /* fs backup date/time */
+ hfs_ushort_t drVSeqNum; /* backup sequence number */
+ hfs_uint_t drWrCnt; /* fs write count */
+ hfs_uint_t drXTClpSiz; /* clumpsize for the extents B-tree */
+ hfs_uint_t drCTClpSiz; /* clumpsize for the catalog B-tree */
+ hfs_ushort_t drNmRtDirs; /* number of directories in
+ the root directory */
+ hfs_uint_t drFilCnt; /* number of files in the fs */
+ hfs_uint_t drDirCnt; /* number of directories in the fs */
+ hfs_char_t drFndrInfo[32]; /* data used by the Finder */
+ hfs_ushort_t drEmbedSigWord; /* embedded volume signature */
+ hfs_uint_t drEmbedExtent; /* starting block number (xdrStABN)
+ and number of allocation blocks
+ (xdrNumABlks) occupied by embedded
+ volume */
+ hfs_uint_t drXTFlSize; /* bytes in the extents B-tree */
+ hfs_char_t drXTExtRec[12]; /* extents B-tree's first 3 extents */
+ hfs_uint_t drCTFlSize; /* bytes in the catalog B-tree */
+ hfs_char_t drCTExtRec[12]; /* catalog B-tree's first 3 extents */
+} hfs_mdb_t;
+
+#define HFS_PLUS_SIGNATURE 0x482b /* 'H+' */
+#define HFS_SIGNATURE 0x4244 /* HFS / embedded HFS+ */
+
+
+typedef struct hfs_plus_mdb
+{
+ unsigned short signature;
+ unsigned short version;
+ unsigned int attributes;
+ unsigned int lastMountedVersion;
+ unsigned int reserved;
+
+ unsigned int createDate;
+ unsigned int modifyDate;
+ unsigned int backupDate;
+ unsigned int checkedDate;
+
+ unsigned int fileCount;
+ unsigned int folderCount;
+
+ unsigned int blockSize;
+ unsigned int totalBlocks;
+ unsigned int freeBlocks;
+
+ unsigned int nextAllocation;
+ unsigned int rsrcClumpSize;
+ unsigned int dataClumpSize;
+
+ /* ... there are more fields here ... */
+} hfs_plus_mdb_t;
+
+
+#endif /* _H_HFS_MDB */
diff --git a/roms/openbios/fs/hfsplus/build.xml b/roms/openbios/fs/hfsplus/build.xml
new file mode 100644
index 00000000..5f4c2886
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/build.xml
@@ -0,0 +1,11 @@
+<build>
+ <library name="fs" type="static" target="target">
+ <object source="hfsp_blockiter.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_btree.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="libhfsp.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_record.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_unicode.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_volume.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ <object source="hfsp_fs.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+ </library>
+</build>
diff --git a/roms/openbios/fs/hfsplus/hfsp_blockiter.c b/roms/openbios/fs/hfsplus/hfsp_blockiter.c
new file mode 100644
index 00000000..e9100922
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/hfsp_blockiter.c
@@ -0,0 +1,141 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * The iterator shown here iterates over the blocks of a fork.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original work by 1996-1998 Robert Leslie <rob@mars.org>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: blockiter.c,v 1.2 2000/10/17 05:58:46 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "blockiter.h"
+#include "volume.h"
+#include "record.h"
+#include "btree.h"
+#include "os.h"
+#include "swab.h"
+#include "hfstime.h"
+
+/* Initialize iterator for a given fork */
+void
+blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f,
+ UInt8 forktype, UInt32 fileId)
+{
+ b->vol = vol;
+ b->curr_block = 0;
+ b->block = 0;
+ b->max_block = f->total_blocks;
+ b->fileId = fileId;
+ b->index = 0;
+ b->file = f->extents;
+ b->e = f->extents;
+ b->forktype = forktype;
+ b->in_extent = 0;
+}
+
+/* get next extent record when needed */
+static int
+blockiter_next_extent(blockiter *b)
+{
+ btree* extents_tree = volume_get_extents_tree(b->vol);
+ int err;
+
+ b->index = 0;
+ if (b->in_extent) // already using extents record ?
+ {
+ err = record_next_extent(&b->er);
+ // Hope there is no need to check this ...
+ // if (b->er.key.start_block != b->curr_block)
+ // HFSP_ERROR(ENOENT,
+ // "Extents record inconistent");
+ }
+ else
+ {
+ err = record_init_file(&b->er, extents_tree, b->forktype,
+ b->fileId, b->curr_block);
+ b->in_extent = -1; // true
+ }
+ b->e = b->er.extent;
+ return err;
+}
+
+/* find next block of the fork iterating over */
+int
+blockiter_next(blockiter *b)
+{
+ b->curr_block ++;
+ b->block ++;
+ if (b->curr_block >= b->max_block)
+ return -1; // end of Blocks, but no error
+ // in current part of extent ?
+ if (b->block >= b->e->block_count)
+ {
+ b->index++;
+ b->block = 0; // reset relative position
+ b->e++;
+ if (b -> index >= 8) // need to fetch another extent
+ {
+ if (blockiter_next_extent(b))
+ HFSP_ERROR(ENOENT, "Extends record not found.");
+ }
+ }
+ return 0;
+
+ fail:
+ return -1;
+}
+
+/* skip the indicated number of blocks */
+int
+blockiter_skip(blockiter *b, UInt32 skip)
+{
+ while (skip > 0)
+ {
+ // Skip to skip or end of current extent
+ UInt32 diff = b->e->block_count - b->block;
+ if (skip < diff)
+ {
+ diff = skip;
+ skip = 0;
+ }
+ else
+ skip -= diff;
+ b->curr_block += diff;
+ b->block += diff;
+ if (b->curr_block >= b->max_block)
+ return -1; // end of Blocks, but no error
+ if (b->block >= b->e->block_count)
+ {
+ b->index++;
+ b->block = 0; // reset relative position
+ b->e++;
+ if (b -> index >= 8) // need to fetch another extent
+ {
+ if (blockiter_next_extent(b))
+ HFSP_ERROR(ENOENT, "Extends record not found.");
+ }
+ }
+ } // we are here when skip was null, thats ok
+ return 0;
+ fail:
+ return -1;
+}
diff --git a/roms/openbios/fs/hfsplus/hfsp_btree.c b/roms/openbios/fs/hfsplus/hfsp_btree.c
new file mode 100644
index 00000000..24eca924
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/hfsp_btree.c
@@ -0,0 +1,372 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * The fucntions are used to handle the various forms of btrees
+ * found on HFS+ volumes.
+ *
+ * The fucntions are used to handle the various forms of btrees
+ * found on HFS+ volumes.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * Additional work by Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: btree.c,v 1.14 2000/10/25 05:43:04 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "volume.h"
+#include "btree.h"
+#include "record.h"
+#include "swab.h"
+
+/* Read the node from the given buffer and swap the bytes.
+ *
+ * return pointer after reading the structure
+ */
+static void* btree_readnode(btree_node_desc* node, void *p)
+{
+ node->next = bswabU32_inc(p);
+ node->prev = bswabU32_inc(p);
+ node->kind = bswabU8_inc(p);
+ node->height = bswabU8_inc(p);
+ node->num_rec = bswabU16_inc(p);
+ node->reserved = bswabU16_inc(p);
+ return p;
+}
+
+/* read a btree header from the given buffer and swap the bytes.
+ *
+ * return pointer after reading the structure
+ */
+static void* btree_readhead(btree_head* head, void *p)
+{
+ UInt32 *q;
+ head->depth = bswabU16_inc(p);
+ head->root = bswabU32_inc(p);
+ head->leaf_count = bswabU32_inc(p);
+ head->leaf_head = bswabU32_inc(p);
+ head->leaf_tail = bswabU32_inc(p);
+ head->node_size = bswabU16_inc(p);
+ head->max_key_len = bswabU16_inc(p);
+ head->node_count = bswabU32_inc(p);
+ head->free_nodes = bswabU32_inc(p);
+ head->reserved1 = bswabU16_inc(p);
+ head->clump_size = bswabU32_inc(p);
+ head->btree_type = bswabU8_inc(p);
+ head->reserved2 = bswabU8_inc(p);
+ head->attributes = bswabU32_inc(p);
+ // skip reserved bytes
+ q=((UInt32*) p);
+ // ((UInt32*) p) += 16;
+ q+=16;
+ return q;
+}
+
+/* Priority of the depth of the node compared to LRU value.
+ * Should be the average number of keys per node but these vary. */
+#define DEPTH_FACTOR 1000
+
+/* Cache size is height of tree + this value
+ * Really big numbers wont help in case of ls -R
+ */
+#define EXTRA_CACHESIZE 3
+
+/* Not in use by now ... */
+#define CACHE_DIRTY 0x0001
+
+/* Intialize cache with default cache Size,
+ * must call node_cache_close to deallocate memory */
+static int node_cache_init(node_cache* cache, btree* tree, int size)
+{
+ int nodebufsize;
+ char * buf;
+
+ cache->size = size;
+ cache->currindex = 0;
+ nodebufsize = tree->head.node_size + sizeof(node_buf);
+ buf = malloc(size *(sizeof(node_entry) + nodebufsize));
+ if (!buf)
+ return -1;
+ cache -> nodebufsize = nodebufsize;
+ cache -> entries = (node_entry*) buf;
+ cache -> buffers = (char*) &cache->entries[size];
+ bzero(cache->entries, size*sizeof(node_entry));
+ return 0;
+}
+
+/* Like cache->buffers[i], since size of node_buf is variable */
+static inline node_buf* node_buf_get(node_cache* cache, int i)
+{
+ return (node_buf*) (cache->buffers + (i * cache->nodebufsize));
+}
+
+/* flush the node at index */
+static void node_cache_flush_node(node_cache* cache, int index)
+{
+ // NYI
+ cache -> entries[index].index = 0; // invalidate entry
+}
+
+static void node_cache_close(node_cache* cache)
+{
+ if (!cache->entries) // not (fully) intialized ?
+ return;
+ free(cache->entries);
+}
+
+/* Load the cach node indentified by index with
+ * the node identified by node_index */
+
+static node_buf* node_cache_load_buf
+ (btree* bt, node_cache* cache, int index, UInt16 node_index)
+{
+ node_buf *result = node_buf_get(cache ,index);
+ UInt32 blkpernode = bt->blkpernode;
+ UInt32 block = node_index * blkpernode;
+ void* p = volume_readfromfork(bt->vol, result->node, bt->fork,
+ block, blkpernode, HFSP_EXTENT_DATA, bt->cnid);
+ node_entry *e = &cache->entries[index];
+
+ if (!p)
+ return NULL; // evil ...
+
+ result->index = node_index;
+ btree_readnode(&result->desc, p);
+
+ e -> priority = result->desc.height * DEPTH_FACTOR;
+ e -> index = node_index;
+ return result;
+}
+
+/* Read node at given index, using cache.
+ */
+node_buf* btree_node_by_index(btree* bt, UInt16 index)
+{
+ node_cache* cache = &bt->cache;
+ int oldindex, lruindex;
+ int currindex = cache->currindex;
+ UInt32 prio;
+ node_entry *e;
+
+ // Shortcut acces to current node, will not change priorities
+ if (cache->entries[currindex].index == index)
+ return node_buf_get(cache ,currindex);
+ oldindex = currindex;
+ if (currindex == 0)
+ currindex = cache->size;
+ currindex--;
+ lruindex = oldindex; // entry to be flushed when needed
+ prio = 0; // current priority
+ while (currindex != oldindex) // round robin
+ {
+ e = &cache->entries[currindex];
+ if (e->index == index) // got it
+ {
+ if (e->priority != 0) // already top, uuh
+ e->priority--;
+ cache->currindex = currindex;
+ return node_buf_get(cache ,currindex);
+ }
+ else
+ {
+ if (!e->index)
+ {
+ lruindex = currindex;
+ break; // empty entry, load it
+ }
+ if (e->priority != UINT_MAX) // already least, uuh
+ e->priority++;
+ }
+ if (prio < e->priority)
+ {
+ lruindex = currindex;
+ prio = e->priority;
+ }
+ if (currindex == 0)
+ currindex = cache->size;
+ currindex--;
+ }
+ e = &cache->entries[lruindex];
+ cache->currindex = lruindex;
+ if (e->flags & CACHE_DIRTY)
+ node_cache_flush_node( cache, lruindex);
+ return node_cache_load_buf (bt, cache, lruindex, index);
+}
+
+/** intialize the btree with the first entry in the fork */
+static int btree_init(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+ void *p;
+ char buf[vol->blksize];
+ UInt16 node_size;
+ btree_node_desc node;
+
+ bt->vol = vol;
+ bt->fork = fork;
+ p = volume_readfromfork(vol, buf, fork, 0, 1,
+ HFSP_EXTENT_DATA, bt->cnid);
+ if (!p)
+ return -1;
+ p = btree_readnode(&node, p);
+ if (node.kind != HFSP_NODE_HEAD)
+ return -1; // should not happen ?
+ btree_readhead(&bt->head, p);
+
+ node_size = bt->head.node_size;
+ bt->blkpernode = node_size / vol->blksize;
+
+ if (bt->blkpernode == 0 || vol->blksize *
+ bt->blkpernode != node_size)
+ return -1; // should never happen ...
+
+ node_cache_init(&bt->cache, bt, bt->head.depth + EXTRA_CACHESIZE);
+
+ // Allocate buffer
+ // bt->buf = malloc(node_size);
+ // if (!bt->buf)
+ // return ENOMEM;
+
+ return 0;
+}
+
+/** Intialize catalog btree, so that btree_close can safely be called. */
+void btree_reset(btree* bt)
+{
+ bt->cache.entries = NULL;
+}
+
+/** Intialize catalog btree */
+int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+ int result = btree_init(bt,vol,fork); // super (...)
+ bt->cnid = HFSP_CAT_CNID;
+ bt->kcomp = record_key_compare;
+ bt->kread = record_readkey;
+ return result;
+}
+
+/** Intialize catalog btree */
+int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+ int result = btree_init(bt,vol,fork); // super (...)
+ bt->cnid = HFSP_EXT_CNID;
+ bt->kcomp = record_extent_key_compare;
+ bt->kread = record_extent_readkey;
+ return result;
+}
+
+/** close the btree and free any resources */
+void btree_close(btree* bt)
+{
+ node_cache_close(&bt->cache);
+ // free(bt->buf);
+}
+
+/* returns pointer to key given by index in current node.
+ *
+ * Assumes that current node is not NODE_HEAD ...
+ */
+void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index)
+{
+ UInt16 node_size = bt->head.node_size;
+ // The offsets are found at the end of the node ...
+ UInt16 off_pos = node_size - (index +1) * sizeof(btree_record_offset);
+ // position of offset at end of node
+ btree_record_offset* offset =
+ (btree_record_offset*) (buf->node + off_pos);
+
+ // now we have the offset and can read the key ...
+#ifdef CONFIG_LITTLE_ENDIAN
+ return buf->node + bswabU16(*offset);
+#else
+ return buf->node + *offset;
+#endif
+}
+
+
+#ifdef DEBUG
+
+/* print btree header node information */
+void btree_printhead(btree_head* head)
+{
+ UInt32 attr;
+ printf(" depth : %#X\n", head->depth);
+ printf(" root : %#lX\n", head->root);
+ printf(" leaf_count : %#lX\n", head->leaf_count);
+ printf(" leaf_head : %#lX\n", head->leaf_head);
+ printf(" leaf_tail : %#lX\n", head->leaf_tail);
+ printf(" node_size : %#X\n", head->node_size);
+ printf(" max_key_len : %#X\n", head->max_key_len);
+ printf(" node_count : %#lX\n", head->node_count);
+ printf(" free_nodes : %#lX\n", head->free_nodes);
+ printf(" reserved1 : %#X\n", head->reserved1);
+ printf(" clump_size : %#lX\n", head->clump_size);
+ printf(" btree_type : %#X\n", head->btree_type);
+ attr = head->attributes;
+ printf(" reserved2 : %#X\n", head->reserved2);
+ if (attr & HFSPLUS_BAD_CLOSE)
+ printf(" HFSPLUS_BAD_CLOSE *** ");
+ else
+ printf(" !HFSPLUS_BAD_CLOSE");
+ if (attr & HFSPLUS_TREE_BIGKEYS)
+ printf(" HFSPLUS_TREE_BIGKEYS ");
+ else
+ printf(" !HFSPLUS_TREE_BIGKEYS");
+ if (attr & HFSPLUS_TREE_VAR_NDXKEY_SIZE)
+ printf(" HFSPLUS_TREE_VAR_NDXKEY_SIZE");
+ else
+ printf(" !HFSPLUS_TREE_VAR_NDXKEY_SIZE");
+ if (attr & HFSPLUS_TREE_UNUSED)
+ printf(" HFSPLUS_TREE_UNUSED ***\n");
+ printf("\n");
+}
+
+/* Dump all the node information to stdout */
+void btree_print(btree* bt)
+{
+ btree_node_desc* node;
+
+ btree_printhead(&bt->head);
+
+ node = &bt->node;
+ printf("next : %#lX\n", node->next);
+ printf("prev : %#lX\n", node->prev);
+ printf("height : %#X\n", node->height);
+ printf("num_rec : %#X\n", node->num_rec);
+ printf("reserved : %#X\n", node->reserved);
+ printf("height : %#X\n", node->height); switch(node->kind)
+ {
+ case HFSP_NODE_NDX :
+ printf("HFSP_NODE_NDX\n");
+ break;
+ case HFSP_NODE_HEAD :
+ printf("HFSP_NODE_HEAD\n");
+ break;
+ case HFSP_NODE_MAP :
+ printf("HFSP_NODE_MAP\n");
+ break;
+ case HFSP_NODE_LEAF :
+ printf("HFSP_NODE_LEAF\n");
+ break;
+ default:
+ printf("*** Unknown Node type ***\n");
+ }
+}
+
+#endif
diff --git a/roms/openbios/fs/hfsplus/hfsp_fs.c b/roms/openbios/fs/hfsplus/hfsp_fs.c
new file mode 100644
index 00000000..df234bb0
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/hfsp_fs.c
@@ -0,0 +1,632 @@
+/*
+ * Creation Date: <2001/05/05 23:33:49 samuel>
+ * Time-stamp: <2004/01/12 10:25:39 samuel>
+ *
+ * /package/hfsplus-files
+ *
+ * HFS+ file system interface (and ROM lookup support)
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "fs/fs.h"
+#include "libhfsp.h"
+#include "volume.h"
+#include "record.h"
+#include "unicode.h"
+#include "blockiter.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+
+#define MAC_OS_ROM_CREATOR 0x63687270 /* 'chrp' */
+#define MAC_OS_ROM_TYPE 0x74627869 /* 'tbxi' */
+#define MAC_OS_ROM_NAME "Mac OS ROM"
+
+#define FINDER_TYPE 0x464E4452 /* 'FNDR' */
+#define FINDER_CREATOR 0x4D414353 /* 'MACS' */
+#define SYSTEM_TYPE 0x7A737973 /* 'zsys' */
+#define SYSTEM_CREATOR 0x4D414353 /* 'MACS' */
+
+#define VOLNAME_SIZE 64
+
+extern void hfsp_init( void );
+
+typedef struct {
+ record rec;
+ char *path;
+ off_t pos;
+} hfsp_file_t;
+
+typedef struct {
+ volume *vol;
+ hfsp_file_t *hfspfile;
+} hfsp_info_t;
+
+DECLARE_NODE( hfsp, 0, sizeof(hfsp_info_t), "+/packages/hfsplus-files" );
+
+
+/************************************************************************/
+/* Search implementation */
+/************************************************************************/
+
+typedef int (*match_proc_t)( record *r, record *parent, const void *match_data, hfsp_file_t *pt );
+
+static int
+search_files( record *par, int recursive, match_proc_t proc, const void *match_data, hfsp_file_t *pt )
+{
+ hfsp_file_t t;
+ record r;
+ int ret = 1;
+
+ t.path = NULL;
+
+ record_init_parent( &r, par );
+ do{
+ if( r.record.type == HFSP_FOLDER || r.record.type == HFSP_FILE )
+ ret = (*proc)( &r, par, match_data, &t );
+
+ if( ret && r.record.type == HFSP_FOLDER && recursive )
+ ret = search_files( &r, 1, proc, match_data, &t );
+
+ } while( ret && !record_next(&r) );
+
+ if( !ret && pt ) {
+ char name[256];
+ const char *s2 = t.path ? t.path : "";
+
+ unicode_uni2asc( name, &r.key.name, sizeof(name));
+
+ pt->rec = t.rec;
+ pt->path = malloc( strlen(name) + strlen(s2) + 2 );
+ strcpy( pt->path, name );
+ if( strlen(s2) ) {
+ strcat( pt->path, "\\" );
+ strcat( pt->path, s2 );
+ }
+ }
+
+ if( t.path )
+ free( t.path );
+
+ return ret;
+}
+
+static int
+root_search_files( volume *vol, int recursive, match_proc_t proc, const void *match_data, hfsp_file_t *pt )
+{
+ record r;
+
+ record_init_root( &r, &vol->catalog );
+ return search_files( &r, recursive, proc, match_data, pt );
+}
+
+static int
+match_file( record *r, record *parent, const void *match_data, hfsp_file_t *pt )
+{
+ const char *p = (const char*)match_data;
+ char name[256];
+ int ret=1;
+
+ if( r->record.type != HFSP_FILE )
+ return 1;
+
+ (void) unicode_uni2asc(name, &r->key.name, sizeof(name));
+ if( !(ret=strcasecmp(p, name)) && pt )
+ pt->rec = *r;
+
+ return ret;
+}
+
+static int
+match_rom( record *r, record *par, const void *match_data, hfsp_file_t *pt )
+{
+ hfsp_cat_file *file = &r->record.u.file;
+ FInfo *fi = &file->user_info;
+ int ret = 1;
+ char buf[256];
+
+ if( r->record.type == HFSP_FILE && fi->fdCreator == MAC_OS_ROM_CREATOR && fi->fdType == MAC_OS_ROM_TYPE ) {
+ ret = search_files( par, 0, match_file, "System", NULL )
+ || search_files( par, 0, match_file, "Finder", NULL );
+
+ (void) unicode_uni2asc(buf, &r->key.name, sizeof(buf));
+ if( !strcasecmp("BootX", buf) )
+ return 1;
+
+ if( !ret && pt )
+ pt->rec = *r;
+ }
+ return ret;
+}
+
+static int
+match_path( record *r, record *par, const void *match_data, hfsp_file_t *pt )
+{
+ char name[256], *s, *next, *org;
+ int ret=1;
+
+ next = org = strdup( (char*)match_data );
+ while( (s=strsep( &next, "\\/" )) && !strlen(s) )
+ ;
+ if( !s ) {
+ free( org );
+ return 1;
+ }
+
+ if( *s == ':' && strlen(s) == 5 ) {
+ if( r->record.type == HFSP_FILE && !next ) {
+ /* match type */
+ hfsp_cat_file *file = &r->record.u.file;
+ FInfo *fi = &file->user_info;
+ int i, type=0;
+ for( i=1; s[i] && i<=4; i++ )
+ type = (type << 8) | s[i];
+ /* printk("fi->fdType: %s / %s\n", s+1, b ); */
+ if( fi->fdType == type ) {
+ if( pt )
+ pt->rec = *r;
+ ret = 0;
+ }
+ }
+ } else {
+ (void) unicode_uni2asc(name, &r->key.name, sizeof(name));
+
+ if( !strcasecmp(s, name) ) {
+ if( r->record.type == HFSP_FILE && !next ) {
+ if( pt )
+ pt->rec = *r;
+ ret = 0;
+ } else /* must be a directory */
+ ret = search_files( r, 0, match_path, next, pt );
+ }
+ }
+ free( org );
+ return ret;
+}
+
+
+/************************************************************************/
+/* Standard package methods */
+/************************************************************************/
+
+/* ( -- success? ) */
+static void
+hfsp_files_open( hfsp_info_t *mi )
+{
+ int fd;
+ char *path = my_args_copy();
+
+ if ( ! path )
+ RET( 0 );
+
+ fd = open_ih( my_parent() );
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ mi->vol = malloc( sizeof(volume) );
+ if (volume_open(mi->vol, fd)) {
+ free( path );
+ close_io( fd );
+ RET( 0 );
+ }
+
+ mi->hfspfile = malloc( sizeof(hfsp_file_t) );
+
+ /* Leading \\ means system folder. The finder info block has
+ * the following meaning.
+ *
+ * [0] Prefered boot directory ID
+ * [3] MacOS 9 boot directory ID
+ * [5] MacOS X boot directory ID
+ */
+ if( !strncmp(path, "\\\\", 2) ) {
+ int *p = (int*)&(mi->vol)->vol.finder_info[0];
+ int cnid = p[0];
+ /* printk(" p[0] = %x, p[3] = %x, p[5] = %x\n", p[0], p[3], p[5] ); */
+ if( p[0] == p[5] && p[3] )
+ cnid = p[3];
+ if( record_init_cnid(&(mi->hfspfile->rec), &(mi->vol)->catalog, cnid) )
+ RET ( 0 );
+ path += 2;
+ } else {
+ record_init_root( &(mi->hfspfile->rec), &(mi->vol)->catalog );
+ }
+
+ if( !search_files(&(mi->hfspfile->rec), 0, match_path, path, mi->hfspfile ) )
+ RET ( -1 );
+
+ RET ( -1 );
+}
+
+/* ( -- ) */
+static void
+hfsp_files_close( hfsp_info_t *mi )
+{
+ volume_close(mi->vol);
+
+ if( mi->hfspfile->path )
+ free( mi->hfspfile->path );
+ free( mi->hfspfile );
+}
+
+/* ( buf len -- actlen ) */
+static void
+hfsp_files_read( hfsp_info_t *mi )
+{
+ int count = POP();
+ char *buf = (char *)cell2pointer(POP());
+
+ hfsp_file_t *t = mi->hfspfile;
+ volume *vol = t->rec.tree->vol;
+ UInt32 blksize = vol->blksize;
+ hfsp_cat_file *file = &t->rec.record.u.file;
+ blockiter iter;
+ char buf2[blksize];
+ int act_count, curpos=0;
+
+ blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id );
+ while( curpos + blksize < t->pos ) {
+ if( blockiter_next( &iter ) ) {
+ RET ( -1 );
+ return;
+ }
+ curpos += blksize;
+ }
+ act_count = 0;
+
+ while( act_count < count ){
+ UInt32 block = blockiter_curr(&iter);
+ int max = blksize, add = 0, size;
+
+ if( volume_readinbuf( vol, buf2, block ) )
+ break;
+
+ if( curpos < t->pos ){
+ add += t->pos - curpos;
+ max -= t->pos - curpos;
+ }
+ size = (count-act_count > max)? max : count-act_count;
+ memcpy( (char *)buf + act_count, &buf2[add], size );
+
+ curpos += blksize;
+ act_count += size;
+
+ if( blockiter_next( &iter ) )
+ break;
+ }
+
+ t->pos += act_count;
+
+ RET ( act_count );
+}
+
+/* ( pos.d -- status ) */
+static void
+hfsp_files_seek( hfsp_info_t *mi )
+{
+ long long pos = DPOP();
+ int offs = (int)pos;
+ int whence = SEEK_SET;
+
+ hfsp_file_t *t = mi->hfspfile;
+ hfsp_cat_file *file = &t->rec.record.u.file;
+ int total = file->data_fork.total_size;
+
+ if( offs == -1 ) {
+ offs = 0;
+ whence = SEEK_END;
+ }
+
+ switch( whence ){
+ case SEEK_END:
+ t->pos = total + offs;
+ break;
+ default:
+ case SEEK_SET:
+ t->pos = offs;
+ break;
+ }
+
+ if( t->pos < 0 )
+ t->pos = 0;
+
+ if( t->pos > total )
+ t->pos = total;
+
+ RET ( 0 );
+}
+
+/* ( addr -- size ) */
+static void
+hfsp_files_load( hfsp_info_t *mi )
+{
+ char *buf = (char *)cell2pointer(POP());
+
+ hfsp_file_t *t = mi->hfspfile;
+ volume *vol = t->rec.tree->vol;
+ UInt32 blksize = vol->blksize;
+ hfsp_cat_file *file = &t->rec.record.u.file;
+ int total = file->data_fork.total_size;
+ blockiter iter;
+ char buf2[blksize];
+ int act_count;
+
+ blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id );
+
+ act_count = 0;
+
+ while( act_count < total ){
+ UInt32 block = blockiter_curr(&iter);
+ int max = blksize, size;
+
+ if( volume_readinbuf( vol, buf2, block ) )
+ break;
+
+ size = (total-act_count > max)? max : total-act_count;
+ memcpy( (char *)buf + act_count, &buf2, size );
+
+ act_count += size;
+
+ if( blockiter_next( &iter ) )
+ break;
+ }
+
+ RET ( act_count );
+}
+
+/* ( -- cstr ) */
+static void
+hfsp_files_get_fstype( hfsp_info_t *mi )
+{
+ PUSH( pointer2cell(strdup("HFS+")) );
+}
+
+/* ( -- cstr ) */
+static void
+hfsp_files_get_path( hfsp_info_t *mi )
+{
+ char *buf;
+ hfsp_file_t *t = mi->hfspfile;
+
+ if( !t->path )
+ RET ( 0 );
+
+ buf = malloc(strlen(t->path) + 1);
+ strncpy( buf, t->path, strlen(t->path) );
+ buf[strlen(t->path)] = 0;
+
+ PUSH(pointer2cell(buf));
+}
+
+/* ( -- success? ) */
+static void
+hfsp_files_open_nwrom( hfsp_info_t *mi )
+{
+ /* Switch to an existing ROM image file on the fs! */
+ if( !root_search_files(mi->vol, 1, match_rom, NULL, mi->hfspfile) )
+ RET ( -1 );
+
+ RET ( 0 );
+}
+
+/* ( -- cstr|0 ) */
+static void
+hfsp_files_volume_name( hfsp_info_t *mi )
+{
+ int fd;
+ char *volname = malloc(VOLNAME_SIZE);
+
+ fd = open_ih(my_self());
+ if (fd >= 0) {
+ get_hfs_vol_name(fd, volname, VOLNAME_SIZE);
+ close_io(fd);
+ } else {
+ volname[0] = '\0';
+ }
+
+ PUSH(pointer2cell(volname));
+}
+
+static const int days_month[12] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static const int days_month_leap[12] =
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static inline int is_leap(int year)
+{
+ return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
+}
+
+static void
+print_date(uint32_t sec)
+{
+ unsigned int second, minute, hour, month, day, year;
+ int current;
+ const int *days;
+
+ second = sec % 60;
+ sec /= 60;
+
+ minute = sec % 60;
+ sec /= 60;
+
+ hour = sec % 24;
+ sec /= 24;
+
+ year = sec * 100 / 36525;
+ sec -= year * 36525 / 100;
+ year += 1904;
+
+ days = is_leap(year) ? days_month_leap : days_month;
+
+ current = 0;
+ month = 0;
+ while (month < 12) {
+ if (sec <= current + days[month]) {
+ break;
+ }
+ current += days[month];
+ month++;
+ }
+ month++;
+
+ day = sec - current + 1;
+
+ forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
+ year, month, day, hour, minute, second);
+}
+
+/* static method, ( pathstr len ihandle -- ) */
+static void
+hfsp_files_dir( hfsp_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ char *path = pop_fstr_copy();
+ int fd, found;
+ volume *vol;
+ record rec, r, folrec;
+ char name[256], *curfol, *tmppath;
+
+ fd = open_ih(ih);
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ vol = malloc( sizeof(volume) );
+ if (volume_open(vol, fd)) {
+ free( path );
+ close_io( fd );
+ RET( 0 );
+ }
+
+ /* First move to the specified folder */
+ tmppath = strdup(path);
+ record_init_root( &rec, &vol->catalog );
+ record_init_parent( &r, &rec );
+
+ /* Remove initial \ or / */
+ curfol = strsep(&tmppath, "\\//");
+ curfol = strsep(&tmppath, "\\//");
+ forth_printf("\n");
+
+ while (curfol && strlen(curfol)) {
+ found = 0;
+ do {
+ if (r.record.type == HFSP_FOLDER) {
+ unicode_uni2asc(name, &r.key.name, sizeof(name));
+
+ if (!strcmp(name, curfol)) {
+ folrec = r;
+ found = -1;
+ }
+ }
+ } while ( !record_next(&r) );
+
+ if (!found) {
+ forth_printf("Unable to locate path %s on filesystem\n", path);
+ goto done;
+ } else {
+ record_init_parent( &r, &folrec );
+ }
+
+ curfol = strsep(&tmppath, "\\//");
+ }
+
+ /* Output the directory contents */
+ found = 0;
+ do {
+ unicode_uni2asc(name, &r.key.name, sizeof(name));
+
+ if (r.record.type == HFSP_FILE) {
+ /* Grab the file entry */
+ hfsp_cat_file *file = &r.record.u.file;
+ forth_printf("% 10lld ", file->data_fork.total_size);
+ print_date(file->create_date);
+ forth_printf(" %s\n", name);
+ found = -1;
+ }
+
+ if (r.record.type == HFSP_FOLDER) {
+ /* Grab the directory entry */
+ hfsp_cat_folder *folder = &r.record.u.folder;
+ forth_printf(" 0 ");
+ print_date(folder->create_date);
+ forth_printf(" %s\\\n", name);
+ found = -1;
+ }
+
+ } while ( !record_next(&r) );
+
+ if (!found) {
+ forth_printf(" (Empty folder)\n");
+ }
+
+done:
+ volume_close(vol);
+ free(vol);
+ free(path);
+ if (tmppath)
+ free(tmppath);
+}
+
+/* static method, ( pos.d ih -- flag? ) */
+static void
+hfsp_files_probe( hfsp_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ long long offs = DPOP();
+ int fd, ret = 0;
+
+ fd = open_ih(ih);
+ if (fd >= 0) {
+ if (volume_probe(fd, offs)) {
+ ret = -1;
+ }
+ close_io(fd);
+ } else {
+ ret = -1;
+ }
+
+ RET (ret);
+}
+
+static void
+hfsp_initializer( hfsp_info_t *dummy )
+{
+ fword("register-fs-package");
+}
+
+NODE_METHODS( hfsp ) = {
+ { "probe", hfsp_files_probe },
+ { "open", hfsp_files_open },
+ { "close", hfsp_files_close },
+ { "read", hfsp_files_read },
+ { "seek", hfsp_files_seek },
+ { "load", hfsp_files_load },
+ { "dir", hfsp_files_dir },
+
+ /* special */
+ { "open-nwrom", hfsp_files_open_nwrom },
+ { "get-path", hfsp_files_get_path },
+ { "get-fstype", hfsp_files_get_fstype },
+ { "volume-name", hfsp_files_volume_name },
+
+ { NULL, hfsp_initializer },
+};
+
+void
+hfsp_init( void )
+{
+ REGISTER_NODE( hfsp );
+}
diff --git a/roms/openbios/fs/hfsplus/hfsp_record.c b/roms/openbios/fs/hfsplus/hfsp_record.c
new file mode 100644
index 00000000..d4e7af1b
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/hfsp_record.c
@@ -0,0 +1,759 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes.
+ *
+ * a record contains a key and a folder or file and is part
+ * of a btree.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * Additional work by Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: record.c,v 1.24 2000/10/17 05:58:46 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "hfstime.h"
+#include "record.h"
+#include "volume.h"
+#include "btree.h"
+#include "unicode.h"
+#include "swab.h"
+
+/* read a hfsp_cat_key from memory */
+void* record_readkey(void* p, void* buf)
+{
+ hfsp_cat_key* key = (hfsp_cat_key*) buf;
+ const void* check;
+ UInt16 key_length, len,i;
+ UInt16* cp;
+
+ key->key_length = key_length = bswabU16_inc(p);
+ check = p;
+ key->parent_cnid = bswabU32_inc(p);
+ key->name.strlen = len = bswabU16_inc(p);
+ cp = key->name.name;
+ for (i=0; i < len; i++, cp++)
+ *cp = bswabU16_inc(p);
+ /* check if keylenght was correct */
+ if (key_length != ((char*) p) - ((char*) check))
+ HFSP_ERROR(EINVAL, "Invalid key length in record_readkey");
+ return p;
+ fail:
+ return NULL;
+}
+
+/* read a hfsp_extent_key from memory */
+void* record_extent_readkey(void* p, void* buf)
+{
+ hfsp_extent_key* key = (hfsp_extent_key*) buf;
+ UInt16 key_length;
+
+ key->key_length = key_length = bswabU16_inc(p);
+ key->fork_type = bswabU8_inc(p);
+ key->filler = bswabU8_inc(p);
+ if (key_length != 10)
+ HFSP_ERROR(-1, "Invalid key length in record_extent_readkey");
+ key->file_id = bswabU32_inc(p);
+ key->start_block = bswabU32_inc(p);
+ return p;
+ fail:
+ return NULL;
+}
+
+
+/* read posix permission from memory */
+static inline void* record_readperm(void *p, hfsp_perm* perm)
+{
+ perm->owner= bswabU32_inc(p);
+ perm->group= bswabU32_inc(p);
+ perm->mode = bswabU32_inc(p);
+ perm->dev = bswabU32_inc(p);
+ return p;
+}
+
+/* read directory info */
+static inline void* record_readDInfo(void *p, DInfo* info)
+{
+ info->frRect.top = bswabU16_inc(p);
+ info->frRect.left = bswabU16_inc(p);
+ info->frRect.bottom = bswabU16_inc(p);
+ info->frRect.right = bswabU16_inc(p);
+ info->frFlags = bswabU16_inc(p);
+ info->frLocation.v = bswabU16_inc(p);
+ info->frLocation.h = bswabU16_inc(p);
+ info->frView = bswabU16_inc(p);
+ return p;
+}
+
+/* read extra Directory info */
+static inline void* record_readDXInfo(void *p, DXInfo* xinfo)
+{
+ xinfo->frScroll.v = bswabU16_inc(p);
+ xinfo->frScroll.h = bswabU16_inc(p);
+ xinfo->frOpenChain = bswabU32_inc(p);
+ xinfo->frUnused = bswabU16_inc(p);
+ xinfo->frComment = bswabU16_inc(p);
+ xinfo->frPutAway = bswabU32_inc(p);
+ return p;
+}
+
+/* read a hfsp_cat_folder from memory */
+static void* record_readfolder(void *p, hfsp_cat_folder* folder)
+{
+ folder->flags = bswabU16_inc(p);
+ folder->valence = bswabU32_inc(p);
+ folder->id = bswabU32_inc(p);
+ folder->create_date = bswabU32_inc(p);
+ folder->content_mod_date = bswabU32_inc(p);
+ folder->attribute_mod_date = bswabU32_inc(p);
+ folder->access_date = bswabU32_inc(p);
+ folder->backup_date = bswabU32_inc(p);
+ p = record_readperm (p, &folder->permissions);
+ p = record_readDInfo (p, &folder->user_info);
+ p = record_readDXInfo (p, &folder->finder_info);
+ folder->text_encoding = bswabU32_inc(p);
+ folder->reserved = bswabU32_inc(p);
+ return p;
+}
+
+/* read file info */
+static inline void* record_readFInfo(void *p, FInfo* info)
+{
+ info->fdType = bswabU32_inc(p);
+ info->fdCreator = bswabU32_inc(p);
+ info->fdFlags = bswabU16_inc(p);
+ info->fdLocation.v = bswabU16_inc(p);
+ info->fdLocation.h = bswabU16_inc(p);
+ info->fdFldr = bswabU16_inc(p);
+ return p;
+}
+
+/* read extra File info */
+static inline void* record_readFXInfo(void *p, FXInfo* xinfo)
+{
+ SInt16 *q;
+ xinfo->fdIconID = bswabU16_inc(p);
+ q=(SInt16*) p;
+ q+=4; // skip unused
+ p=(void *)q;
+ xinfo->fdComment = bswabU16_inc(p);
+ xinfo->fdPutAway = bswabU32_inc(p);
+ return p;
+}
+
+/* read a hfsp_cat_file from memory */
+static void* record_readfile(void *p, hfsp_cat_file* file)
+{
+ file->flags = bswabU16_inc(p);
+ file->reserved1 = bswabU32_inc(p);
+ file->id = bswabU32_inc(p);
+ file->create_date = bswabU32_inc(p);
+ file->content_mod_date = bswabU32_inc(p);
+ file->attribute_mod_date = bswabU32_inc(p);
+ file->access_date = bswabU32_inc(p);
+ file->backup_date = bswabU32_inc(p);
+ p = record_readperm (p, &file->permissions);
+ p = record_readFInfo (p, &file->user_info);
+ p = record_readFXInfo (p, &file->finder_info);
+ file->text_encoding = bswabU32_inc(p);
+ file->reserved2 = bswabU32_inc(p);
+ p = volume_readfork (p, &file->data_fork);
+ return volume_readfork (p, &file->res_fork);
+}
+
+/* read a hfsp_cat_thread from memory */
+static void* record_readthread(void *p, hfsp_cat_thread* entry)
+{
+ int i;
+ UInt16 len;
+ UInt16* cp;
+
+ entry-> reserved = bswabU16_inc(p);
+ entry-> parentID = bswabU32_inc(p);
+ entry->nodeName.strlen = len= bswabU16_inc(p);
+ cp = entry->nodeName.name;
+ if (len > 255)
+ HFSP_ERROR(-1, "Invalid key length in record thread");
+ for (i=0; i < len; i++, cp++)
+ *cp = bswabU16_inc(p);
+ return p;
+ fail:
+ return NULL;
+}
+
+/* read a hfsp_cat_entry from memory */
+static void* record_readentry(void *p, hfsp_cat_entry* entry)
+{
+ UInt16 type = bswabU16_inc(p);
+ entry->type = type;
+ switch (type)
+ {
+ case HFSP_FOLDER:
+ return record_readfolder(p, &entry->u.folder);
+ case HFSP_FILE:
+ return record_readfile (p, &entry->u.file);
+ case HFSP_FOLDER_THREAD:
+ case HFSP_FILE_THREAD:
+ return record_readthread(p, &entry->u.thread);
+ default:
+ HFSP_ERROR(-1, "Unexpected record type in record_readentry");
+ } ;
+ fail:
+ return NULL;
+}
+
+
+/* Most of the functions here will not change the node in the btree,
+ But this must be changed in the future ... */
+
+
+/* intialize the record with the given index entry in the btree. */
+static int record_init(record* r, btree* bt, node_buf* buf, UInt16 index)
+{
+ void *p;
+ r-> tree = bt;
+ p = btree_key_by_index(bt,buf,index);
+ if (!p)
+ return -1;
+ p = record_readkey (p, &r->key);
+ if (!p)
+ return -1;
+ p = record_readentry(p, &r->record);
+ if (!p)
+ return -1;
+ r->node_index = buf->index;
+ r-> keyind = index;
+
+ return 0;
+}
+
+/* intialize the record with the given index entry in the btree. */
+static int record_init_extent(extent_record* r, btree* bt, node_buf* buf, UInt16 index)
+{
+ void *p;
+ r-> tree = bt;
+ p = btree_key_by_index(bt, buf,index);
+ if (!p)
+ return -1;
+ p = record_extent_readkey(p, &r->key);
+ if (!p)
+ return -1;
+ p = volume_readextent(p, r->extent);
+ if (!p)
+ return -1;
+ r->node_index = buf->index;
+ r-> keyind = index;
+
+ return 0;
+}
+
+/* intialize the record to the first record of the tree
+ * which is (per design) the root node.
+ */
+int record_init_root(record* r, btree* tree)
+{
+ // Position to first leaf node ...
+ UInt32 leaf_head = tree->head.leaf_head;
+ node_buf* buf = btree_node_by_index(tree, leaf_head);
+ if (!buf)
+ return -1;
+ return record_init(r, tree, buf, 0);
+}
+
+/* Compare two cat_keys ... */
+int record_key_compare(void* k1, void* k2)
+{
+ hfsp_cat_key* key1 = (hfsp_cat_key*) k1;
+ hfsp_cat_key* key2 = (hfsp_cat_key*) k2;
+ int diff = key2->parent_cnid - key1->parent_cnid;
+ if (!diff) // same parent
+ diff = fast_unicode_compare(&key1->name, &key2->name);
+ return diff;
+}
+
+/* Compare two extent_keys ... */
+int record_extent_key_compare(void* k1, void* k2)
+{
+ hfsp_extent_key* key1 = (hfsp_extent_key*) k1;
+ hfsp_extent_key* key2 = (hfsp_extent_key*) k2;
+ int diff = key2->fork_type - key1->fork_type;
+ if (!diff) // same type
+ {
+ diff = key2->file_id - key1->file_id;
+ if (!diff) // same file
+ diff = key2->start_block - key1->start_block;
+ }
+ return diff;
+}
+
+/* Position node in btree so that key might be inside */
+static node_buf* record_find_node(btree* tree, void *key)
+{
+ int start, end, mid, comp; // components of a binary search
+ void *p = NULL;
+ char curr_key[tree->head.max_key_len];
+ // The current key under examination
+ hfsp_key_read readkey = tree->kread;
+ hfsp_key_compare key_compare = tree->kcomp;
+ UInt32 index;
+ node_buf* node = btree_node_by_index(tree, tree->head.root);
+ if (!node)
+ HFSP_ERROR(-1, "record_find_node: Cant position to root node");
+ while (node->desc.kind == HFSP_NODE_NDX)
+ {
+ mid = start = 0;
+ end = node->desc.num_rec;
+ comp = -1;
+ while (start < end)
+ {
+ mid = (start + end) >> 1;
+ p = btree_key_by_index(tree, node, mid);
+ if (!p)
+ HFSP_ERROR(-1, "record_find_node: unexpected error");
+ p = readkey (p, curr_key);
+ if (!p)
+ HFSP_ERROR(-1, "record_find_node: unexpected error");
+ comp = key_compare(curr_key, key);
+ if (comp > 0)
+ start = mid + 1;
+ else if (comp < 0)
+ end = mid;
+ else
+ break;
+ }
+ if (!p) // Empty tree, fascinating ...
+ HFSP_ERROR(-1, "record_find_node: unexpected empty node");
+ if (comp < 0) // mmh interesting key is before this key ...
+ {
+ if (mid == 0)
+ return NULL; // nothing before this key ..
+ p = btree_key_by_index(tree, node, mid-1);
+ if (!p)
+ HFSP_ERROR(-1, "record_find_node: unexpected error");
+ p = readkey (p, curr_key);
+ if (!p)
+ HFSP_ERROR(-1, "record_find_node: unexpected error");
+ }
+
+ index = bswabU32_inc(p);
+ node = btree_node_by_index(tree, index);
+ }
+ return node; // go on and use the found node
+ fail:
+ return NULL;
+}
+
+/* search for the given key in the btree.
+ *
+ * returns pointer to memory just after key or NULL
+ * In any case *keyind recives the index where the
+ * key was found (or could be inserted.)
+ */
+static void *
+record_find_key(btree* tree, void* key, int* keyind, UInt16* node_index)
+{
+ node_buf* buf = record_find_node(tree, key);
+ if (buf)
+ {
+ int comp = -1;
+ int start = 0; // components of a binary search
+ int end = buf->desc.num_rec;
+ int mid = -1;
+ void *p = NULL;
+ char curr_key[tree->head.max_key_len];
+ hfsp_key_read readkey = tree->kread;
+ hfsp_key_compare key_compare = tree->kcomp;
+ while (start < end)
+ {
+ mid = (start + end) >> 1;
+ p = btree_key_by_index(tree, buf, mid);
+ if (!p)
+ HFSP_ERROR(-1, "record_init_key: unexpected error");
+ p = readkey (p, curr_key);
+ if (!p)
+ HFSP_ERROR(-1, "record_init_cat_key: unexpected error");
+ comp = key_compare(curr_key, key);
+ if (comp > 0)
+ start = mid + 1;
+ else if (comp < 0)
+ end = mid;
+ else
+ break;
+ }
+ if (!p) // Empty tree, fascinating ...
+ HFSP_ERROR(ENOENT, "record_init_key: unexpected empty node");
+ *keyind = mid;
+ *node_index = buf->index;
+ if (!comp) // found something ...
+ return p;
+ }
+ HFSP_ERROR(ENOENT, NULL);
+ fail:
+ return NULL;
+}
+
+/* intialize the record by searching for the given key in the btree.
+ *
+ * r is umodified on error.
+ */
+static int
+record_init_key(record* r, btree* tree, hfsp_cat_key* key)
+{
+ int keyind;
+ UInt16 node_index;
+ void *p = record_find_key(tree, key, &keyind, &node_index);
+
+ if (p)
+ {
+ r -> tree = tree;
+ r -> node_index= node_index;
+ r -> keyind = keyind;
+ r -> key = *key; // Better use a record_key_copy ...
+ p = record_readentry(p, &r->record);
+ if (!p)
+ HFSP_ERROR(-1, "record_init_key: unexpected error");
+ return 0;
+ }
+ fail:
+ return -1;
+}
+
+/* intialize the extent_record to the extent identified by the
+ * (first) blockindex.
+ *
+ * forktype: either HFSP_EXTEND_DATA or HFSP_EXTEND_RSRC
+ */
+int record_init_file(extent_record* r, btree* tree,
+ UInt8 forktype, UInt32 fileId, UInt32 blockindex)
+{
+ int keyind;
+ UInt16 node_index;
+ hfsp_extent_key key = { 10, forktype, 0, fileId, blockindex };
+ void *p = record_find_key(tree, &key, &keyind, &node_index);
+
+ if (p)
+ {
+ r -> tree = tree;
+ r -> node_index= node_index;
+ r -> keyind = keyind;
+ r -> key = key; // Better use a record_key_copy ...
+ p = volume_readextent(p, r->extent);
+ if (!p)
+ HFSP_ERROR(-1, "record_init_file: unexpected error");
+ return 0;
+ }
+ fail:
+ return -1;
+}
+
+/* intialize the record to the folder identified by cnid
+ */
+int record_init_cnid(record* r, btree* tree, UInt32 cnid)
+{
+ hfsp_cat_key thread_key; // the thread is the first record
+
+ thread_key.key_length = 6; // null name (like '.' in unix )
+ thread_key.parent_cnid = cnid;
+ thread_key.name.strlen = 0;
+
+ return record_init_key(r, tree, &thread_key);
+}
+
+/* intialize the record to the first record of the parent.
+ */
+int record_init_parent(record* r, record* parent)
+{
+ if (parent->record.type == HFSP_FOLDER)
+ return record_init_cnid(r, parent->tree, parent->record.u.folder.id);
+ else if(parent->record.type == HFSP_FOLDER_THREAD)
+ {
+ if (r != parent)
+ *r = *parent; // The folder thread is in fact the first entry, like '.'
+ return 0;
+ }
+ HFSP_ERROR(EINVAL,
+ "record_init_parent: parent is neither folder nor folder thread.");
+
+ fail:
+ return EINVAL;
+}
+
+
+/* find correct node record for given node and *pindex.
+ *
+ * index of record in this (or next) node
+ * */
+static node_buf* prepare_next(btree* tree, UInt16 node_index, UInt16* pindex)
+{
+ node_buf* buf = btree_node_by_index(tree, node_index);
+ btree_node_desc* desc = &buf->desc;
+ UInt32 numrec = desc->num_rec;
+ if (*pindex >= numrec) // move on to next node
+ {
+ UInt16 next = desc->next;
+ *pindex = 0;
+ if (!next /* is there a next node ? */
+ || !( buf = btree_node_by_index(tree, next)))
+ return NULL;
+ }
+ return buf;
+}
+/* move record foreward to next entry.
+ *
+ * In case of an error the value of *r is undefined !
+ */
+int record_next(record* r)
+{
+ btree* tree = r->tree;
+ UInt16 index = r->keyind +1;
+ UInt32 parent;
+ node_buf* buf = prepare_next(tree, r->node_index, &index);
+
+ if (!buf)
+ return ENOENT; // No (more) such file or directory
+
+ parent = r->key.parent_cnid;
+
+ if (record_init(r, tree, buf, index))
+ return -1;
+
+ if (r->key.parent_cnid != parent || // end of current directory
+ index != r->keyind) // internal error ?
+ return ENOENT; // No (more) such file or directory
+
+ return 0;
+}
+
+/* move record foreward to next extent record.
+ *
+ * In case of an error the value of *r is undefined !
+ */
+int record_next_extent(extent_record* r)
+{
+ btree* tree = r->tree;
+ UInt16 index = r->keyind +1;
+ UInt32 file_id;
+ UInt8 fork_type;
+ node_buf* buf = prepare_next(tree, r->node_index, &index);
+
+ if (!buf)
+ return ENOENT; // No (more) such file or directory
+
+ file_id = r->key.file_id;
+ fork_type = r->key.fork_type;
+
+ if (record_init_extent(r, tree, buf, index))
+ return -1;
+
+ if (r->key.file_id != file_id || // end of current file
+ r->key.fork_type != fork_type || // end of current fork
+ index != r->keyind) // internal error ?
+ return ENOENT; // No (more) such file or directory
+
+ return 0;
+}
+
+/* intialize the record by searching for the given string in the given folder.
+ *
+ * parent and r may be the same.
+ */
+int record_init_string_parent(record* r, record* parent, char* name)
+{
+ hfsp_cat_key key;
+
+ if (parent->record.type == HFSP_FOLDER)
+ key.parent_cnid = parent->record.u.folder.id;
+ else if(parent->record.type == HFSP_FOLDER_THREAD)
+ key.parent_cnid = parent->key.parent_cnid;
+ else
+ HFSP_ERROR(-1, "record_init_string_parent: parent is not a folder.");
+
+ key.key_length = 6 + unicode_asc2uni(&key.name,name); // 6 for minumum size
+ return record_init_key(r, parent->tree, &key);
+
+ fail:
+ return -1;
+}
+
+/* move record up in folder hierarchy (if possible) */
+int record_up(record* r)
+{
+ if (r->record.type == HFSP_FOLDER)
+ {
+ // locate folder thread
+ if (record_init_cnid(r, r->tree, r->record.u.folder.id))
+ return -1;
+ }
+ else if(r->record.type == HFSP_FOLDER_THREAD)
+ {
+ // do nothing were are already where we want to be
+ }
+ else
+ HFSP_ERROR(-1, "record_up: record is neither folder nor folder thread.");
+
+ if(r->record.type != HFSP_FOLDER_THREAD)
+ HFSP_ERROR(-1, "record_up: unable to locate parent");
+ return record_init_cnid(r, r->tree, r->record.u.thread.parentID);
+
+ fail:
+ return -1;
+}
+
+#ifdef DEBUG
+
+/* print Quickdraw Point */
+static void record_print_Point(Point* p)
+{
+ printf("[ v=%d, h=%d ]", p->v, p->h);
+}
+
+/* print Quickdraw Rect */
+static void record_print_Rect(Rect* r)
+{
+ printf("[ top=%d, left=%d, bottom=%d, right=%d ]",
+ r->top, r->left, r->bottom, r->right);
+}
+
+/* print the key of a record */
+static void record_print_key(hfsp_cat_key* key)
+{
+ char buf[255]; // mh this _might_ overflow
+ unicode_uni2asc(buf, &key->name, 255);
+ printf("parent cnid : %ld\n", key->parent_cnid);
+ printf("name : %s\n", buf);
+}
+
+/* print permissions */
+static void record_print_perm(hfsp_perm* perm)
+{
+ printf("owner :\t%ld\n", perm->owner);
+ printf("group :\t%ld\n", perm->group);
+ printf("perm :\t0x%lX\n",perm->mode);
+ printf("dev :\t%ld\n", perm->dev);
+}
+
+/* print Directory info */
+static void record_print_DInfo(DInfo* dinfo)
+{
+ printf( "frRect :\t"); record_print_Rect(&dinfo->frRect);
+ printf("\nfrFlags :\t0X%X\n", dinfo->frFlags);
+ printf( "frLocation :\t"); record_print_Point(&dinfo->frLocation);
+ printf("\nfrView :\t0X%X\n", dinfo->frView);
+}
+
+/* print extended Directory info */
+static void record_print_DXInfo(DXInfo* xinfo)
+{
+ printf( "frScroll :\t"); record_print_Point(&xinfo->frScroll);
+ printf("\nfrOpenChain :\t%ld\n", xinfo->frOpenChain);
+ printf( "frUnused :\t%d\n", xinfo->frUnused);
+ printf( "frComment :\t%d\n", xinfo->frComment);
+ printf( "frPutAway :\t%ld\n", xinfo->frPutAway);
+}
+
+static void record_print_folder(hfsp_cat_folder* folder)
+{
+ printf("flags :\t0x%X\n", folder->flags);
+ printf("valence :\t0x%lX\n", folder->valence);
+ printf("id :\t%ld\n", folder->id);
+ record_print_perm (&folder->permissions);
+ record_print_DInfo (&folder->user_info);
+ record_print_DXInfo (&folder->finder_info);
+ printf("text_encoding :\t0x%lX\n", folder->text_encoding);
+ printf("reserved :\t0x%lX\n", folder->reserved);
+}
+
+/* print File info */
+static void record_print_FInfo(FInfo* finfo)
+{
+ printf( "fdType :\t%4.4s\n", (char*) &finfo->fdType);
+ printf( "fdCreator :\t%4.4s\n", (char*) &finfo->fdCreator);
+ printf( "fdFlags :\t0X%X\n", finfo->fdFlags);
+ printf( "fdLocation :\t"); record_print_Point(&finfo->fdLocation);
+ printf("\nfdFldr :\t%d\n", finfo->fdFldr);
+}
+
+/* print extended File info */
+static void record_print_FXInfo(FXInfo* xinfo)
+{
+ printf( "fdIconID :\t%d\n", xinfo->fdIconID);
+ // xinfo -> fdUnused;
+ printf( "fdComment :\t%d\n", xinfo->fdComment);
+ printf( "fdPutAway :\t%ld\n", xinfo->fdPutAway);
+}
+
+/* print folder entry */
+
+/* print file entry */
+static void record_print_file(hfsp_cat_file* file)
+{
+ printf("flags :\t0x%X\n", file->flags);
+ printf("reserved1 :\t0x%lX\n", file->reserved1);
+ printf("id :\t%ld\n", file->id);
+ record_print_perm (&file->permissions);
+ record_print_FInfo (&file->user_info);
+ record_print_FXInfo (&file->finder_info);
+ printf("text_encoding :\t0x%lX\n", file->text_encoding);
+ printf("reserved :\t0x%lX\n", file->reserved2);
+ printf("Datafork:\n");
+ volume_print_fork (&file->data_fork);
+ printf("Rsrcfork:\n");
+ volume_print_fork (&file->res_fork);
+}
+
+/* print info for a file or folder thread */
+static void record_print_thread(hfsp_cat_thread* entry)
+{
+ char buf[255]; // mh this _might_ overflow
+ unicode_uni2asc(buf, &entry->nodeName, 255);
+ printf("parent cnid :\t%ld\n", entry->parentID);
+ printf("name :\t%s\n" , buf);
+}
+
+/* print the information for a record */
+static void record_print_entry(hfsp_cat_entry* entry)
+{
+ switch (entry->type)
+ {
+ case HFSP_FOLDER:
+ printf("=== Folder ===\n");
+ return record_print_folder(&entry->u.folder);
+ case HFSP_FILE:
+ printf("=== File ===\n");
+ return record_print_file (&entry->u.file);
+ case HFSP_FOLDER_THREAD:
+ printf("=== Folder Thread ===\n");
+ return record_print_thread(&entry->u.thread);
+ case HFSP_FILE_THREAD:
+ printf("=== File Thread ==\n");
+ return record_print_thread(&entry->u.thread);
+ default:
+ printf("=== Unknown Record Type ===\n");
+ } ;
+}
+
+ /* Dump all the record information to stdout */
+void record_print(record* r)
+{
+ printf ("keyind : %u\n", r->keyind);
+ record_print_key (&r->key);
+ record_print_entry(&r->record);
+}
+
+#endif
diff --git a/roms/openbios/fs/hfsplus/hfsp_unicode.c b/roms/openbios/fs/hfsplus/hfsp_unicode.c
new file mode 100644
index 00000000..7a34affa
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/hfsp_unicode.c
@@ -0,0 +1,511 @@
+/*
+ * linux/fs/hfsplus/unicode.c
+ *
+ * Copyright (C) 1999-2000 Brad Boyer (flar@pants.nu)
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ * The routines found here convert hfs-unicode string into ascii Strings
+ * and vice versa. And the correct comparison between Strings.
+ */
+
+
+#include "config.h"
+#include "libhfsp.h"
+#include "unicode.h"
+
+/* ISO-8859-1 -> unicode */
+static int
+asc2uni( unsigned char *ustr, const char *astr, int maxlen )
+{
+ int len;
+
+ if( maxlen <= 0 )
+ return 0;
+
+ for( len=0; *astr && len < maxlen-1 ; astr++, len++ ) {
+ *ustr++ = 0;
+ *ustr++ = *astr;
+ }
+ ustr[0] = ustr[1] = 0;
+ return len;
+}
+
+/* unicode -> ISO-8859-1 */
+static int
+uni2asc( char *astr, const unsigned char *ustr, int ustrlen, int maxlen )
+{
+ int len;
+
+ if( maxlen <= 0 )
+ return 0;
+
+ for( len=0; ustrlen-- > 0 && len < maxlen-1 ; ustr += 2 ) {
+ /* might be unrepresentable (or too complicated for us) */
+ if( ustr[0] || !ustr[1] )
+ continue;
+ if( ustr[1] < 0x20 || ustr[1] >= 0x7f )
+ *astr++ = '?';
+ else
+ *astr++ = ustr[1];
+ len++;
+ }
+ *astr = 0;
+ return len;
+}
+
+int
+unicode_asc2uni( hfsp_unistr255 *ustr, const char* astr )
+{
+ return ustr->strlen = asc2uni( (u8*)ustr->name, astr, 255 );
+}
+
+int
+unicode_uni2asc(char *astr, const hfsp_unistr255 *ustr, int maxlen)
+{
+ return uni2asc( astr, (u8*)ustr->name, ustr->strlen, maxlen );
+}
+
+/* The following code is almost as published by Apple, only
+ small modifications where made to match some linux styles ...
+
+fastUnicodeCompare - Compare two Unicode strings; produce a relative ordering
+*/
+
+static const UInt16 gLowerCaseTable[];
+
+SInt32 fast_unicode_compare ( const hfsp_unistr255 *ustr1,
+ const hfsp_unistr255 *ustr2)
+{
+ register UInt16 c1,c2;
+ register SInt32 diff;
+ register UInt16 temp;
+ register UInt16 length1 = ustr1->strlen;
+ register UInt16 length2 = ustr2->strlen;
+ register const UInt16* lowerCaseTable = gLowerCaseTable;
+ register const UInt16* str1 = ustr1->name;
+ register const UInt16* str2 = ustr2->name;
+
+ while (1) {
+ // Set default values for c1, c2 in case there are no more valid chars
+ c1 = c2 = 0;
+ // Find next non-ignorable char from str1, or zero if no more
+ while (length1 && c1 == 0) {
+ c1 = *(str1++);
+ --length1;
+ if ((temp = lowerCaseTable[c1>>8]) != 0) // is there a subtable
+ // for this upper byte?
+ c1 = lowerCaseTable[temp + (c1 & 0x00FF)]; // yes, so fold the char
+ }
+ // Find next non-ignorable char from str2, or zero if no more
+ while (length2 && c2 == 0) {
+ c2 = *(str2++);
+ --length2;
+ if ((temp = lowerCaseTable[c2>>8]) != 0) // is there a subtable
+ // for this upper byte?
+ c2 = lowerCaseTable[temp + (c2 & 0x00FF)]; // yes, so fold the char
+ }
+ diff = c2-c1;
+ if (diff) // found a difference, so stop looping
+ break;
+ if (c1 == 0) // did we reach the end of both strings at the same time?
+ return 0; // yes, so strings are equal
+ }
+ return diff;
+}
+
+
+/* The lower case table consists of a 256-entry high-byte table followed by
+ some number of 256-entry subtables. The high-byte table contains either an
+ offset to the subtable for characters with that high byte or zero, which
+ means that there are no case mappings or ignored characters in that block.
+ Ignored characters are mapped to zero.
+ */
+
+static const UInt16 gLowerCaseTable[] = {
+
+ // High-byte indices ( == 0 iff no case mapping and no ignorables )
+
+
+ /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00,
+
+ // Table 1 (for high byte 0x00)
+
+ /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+ /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
+ /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
+ /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
+ /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
+ /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
+ /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
+ /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+ /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7,
+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
+ /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF,
+ /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+
+ // Table 2 (for high byte 0x01)
+
+ /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
+ 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F,
+ /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117,
+ 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F,
+ /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127,
+ 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
+ /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137,
+ 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140,
+ /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
+ 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F,
+ /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157,
+ 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F,
+ /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167,
+ 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F,
+ /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177,
+ 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F,
+ /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
+ 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
+ /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
+ 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
+ /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,
+ 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF,
+ /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
+ 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
+ /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
+ 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF,
+ /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7,
+ 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF,
+ /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7,
+ 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF,
+ /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7,
+ 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF,
+
+ // Table 3 (for high byte 0x03)
+
+ /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
+ 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
+ /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
+ 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
+ /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
+ 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
+ /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
+ 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
+ /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
+ 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
+ /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
+ 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
+ /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
+ 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
+ /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
+ 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
+ /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
+ 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
+ /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
+ /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
+ 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
+ /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
+ 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
+ /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
+ 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
+ /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
+ 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
+
+ // Table 4 (for high byte 0x04)
+
+ /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407,
+ 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F,
+ /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
+ 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
+ /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
+ 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
+ /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477,
+ 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
+ /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
+ 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
+ /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
+ 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
+ /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,
+ 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
+ /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,
+ 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
+ /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,
+ 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
+ /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7,
+ 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF,
+ /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7,
+ 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF,
+ /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7,
+ 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
+
+ // Table 5 (for high byte 0x05)
+
+ /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
+ 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
+ /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
+ 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
+ /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
+ 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
+ /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+ 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+ /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+ 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+ /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,
+ 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
+ /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
+ 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
+ /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
+ 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
+ /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
+ 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
+ /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
+ 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
+ /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
+ 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
+ /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
+ 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
+ /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
+ 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
+ /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
+ 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
+ /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
+ 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
+ /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
+ 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
+
+ // Table 6 (for high byte 0x10)
+
+ /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
+ 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
+ /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
+ 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
+ /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
+ 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
+ /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037,
+ 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
+ /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
+ 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
+ /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
+ 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
+ /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067,
+ 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
+ /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077,
+ 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
+ /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
+ 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
+ /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
+ 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
+ /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
+ 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+ /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
+ 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+ /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7,
+ 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
+ /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
+ 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
+ /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
+ 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
+ /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7,
+ 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
+
+ // Table 7 (for high byte 0x20)
+
+ /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
+ 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017,
+ 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F,
+ /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027,
+ 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F,
+ /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037,
+ 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F,
+ /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047,
+ 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F,
+ /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057,
+ 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F,
+ /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067,
+ 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077,
+ 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F,
+ /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087,
+ 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F,
+ /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097,
+ 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F,
+ /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7,
+ 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF,
+ /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7,
+ 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF,
+ /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
+ 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
+ /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
+ 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF,
+ /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7,
+ 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF,
+ /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7,
+ 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF,
+
+ // Table 8 (for high byte 0x21)
+
+ /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
+ 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
+ /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
+ 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
+ /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
+ 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
+ /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
+ 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
+ /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
+ 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
+ /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
+ 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
+ /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+ 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+ /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
+ 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
+ /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
+ 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
+ /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
+ 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
+ /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
+ 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
+ /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
+ 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
+ /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
+ 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
+ /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
+ 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
+ /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
+ 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
+ /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
+ 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
+
+ // Table 9 (for high byte 0xFE)
+
+ /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07,
+ 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F,
+ /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17,
+ 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F,
+ /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27,
+ 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
+ /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37,
+ 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F,
+ /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47,
+ 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F,
+ /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57,
+ 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F,
+ /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67,
+ 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F,
+ /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77,
+ 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F,
+ /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87,
+ 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F,
+ /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97,
+ 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F,
+ /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
+ 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF,
+ /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7,
+ 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF,
+ /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7,
+ 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF,
+ /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7,
+ 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF,
+ /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7,
+ 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
+ /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7,
+ 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000,
+
+ // Table 10 (for high byte 0xFF)
+
+ /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
+ 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
+ /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
+ 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
+ /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+ 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+ /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+ 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
+ /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
+ 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
+ /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
+ 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
+ /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
+ 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
+ /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
+ 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
+ /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
+ 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
+ /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
+ 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
+ /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
+ 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
+ /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
+ 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
+ /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
+ 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
+ /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
+ 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
+ /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
+ 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
+ /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
+ 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
+};
diff --git a/roms/openbios/fs/hfsplus/hfsp_volume.c b/roms/openbios/fs/hfsplus/hfsp_volume.c
new file mode 100644
index 00000000..2d624e23
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/hfsp_volume.c
@@ -0,0 +1,323 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * Code to acces the basic volume information of a HFS+ volume.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original work by 1996-1998 Robert Leslie <rob@mars.org>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: volume.c,v 1.21 2000/10/25 05:43:04 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "volume.h"
+#include "record.h"
+#include "btree.h"
+#include "blockiter.h"
+#include "os.h"
+#include "swab.h"
+#include "hfstime.h"
+
+
+/* Fill a given buffer with the given block in volume.
+ */
+int
+volume_readinbuf(volume * vol,void* buf, long block)
+{
+ UInt16 blksize_bits;
+ ASSERT( block < vol->maxblocks);
+
+ blksize_bits = vol->blksize_bits;
+ block += vol->startblock;
+ if( os_seek(vol->os_fd, block, blksize_bits) == block)
+ if( 1 == os_read(vol->os_fd, buf, 1, blksize_bits))
+ return 0;
+ return -1;
+}
+
+/* read multiple blocks into given memory.
+ *
+ * returns given pinter or NULL on failure.
+ */
+void*
+volume_readfromfork(volume* vol, void* buf,
+ hfsp_fork_raw* f, UInt32 block,
+ UInt32 count, UInt8 forktype, UInt32 fileId)
+{
+ blockiter iter;
+ char *cbuf = buf;
+
+ blockiter_init(&iter, vol, f, forktype, fileId);
+ if( blockiter_skip(&iter, block))
+ return NULL;
+
+ while( count > 0) {
+ --count;
+ if( volume_readinbuf(vol, cbuf, blockiter_curr(&iter)))
+ return NULL;
+ cbuf += vol->blksize;
+ if( count > 0 && blockiter_next(&iter))
+ return NULL;
+ }
+ return buf;
+}
+
+
+/* Read a raw hfsp_extent_rec from memory.
+ *
+ * return pointer right after the structure.
+ */
+void*
+volume_readextent(void *p, hfsp_extent_rec er)
+{
+ int i;
+ hfsp_extent *e;
+
+ for( i=0; i < 8; i++) {
+ e = &er[i];
+ e->start_block = bswabU32_inc(p);
+ e->block_count = bswabU32_inc(p);
+ }
+ return p;
+}
+
+/* Read a raw hfsp_fork from memory.
+ *
+ * return pointer right after the structure.
+ */
+void*
+volume_readfork(void *p, hfsp_fork_raw* f)
+{
+ f->total_size = bswabU64_inc(p);
+ f->clump_size = bswabU32_inc(p);
+ f->total_blocks = bswabU32_inc(p);
+
+ return volume_readextent(p, f->extents);
+}
+
+/* Read the volume from the given buffer and swap the bytes.
+ *
+ * ToDo: add more consitency checks.
+ */
+static int
+volume_readbuf(hfsp_vh* vh, char * p)
+{
+ if( (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG)
+ HFSP_ERROR(-1, "This is not a HFS+ volume");
+
+ vh->version = bswabU16_inc(p);
+ vh->attributes = bswabU32_inc(p);
+ vh->last_mount_vers = bswabU32_inc(p);
+ vh->reserved = bswabU32_inc(p);
+ vh->create_date = bswabU32_inc(p);
+ vh->modify_date = bswabU32_inc(p);
+ vh->backup_date = bswabU32_inc(p);
+ vh->checked_date = bswabU32_inc(p);
+ vh->file_count = bswabU32_inc(p);
+ vh->folder_count = bswabU32_inc(p);
+ vh->blocksize = bswabU32_inc(p);
+ vh->total_blocks = bswabU32_inc(p);
+ vh->free_blocks = bswabU32_inc(p);
+ vh->next_alloc = bswabU32_inc(p);
+ vh->rsrc_clump_sz = bswabU32_inc(p);
+ vh->data_clump_sz = bswabU32_inc(p);
+ vh->next_cnid = bswabU32_inc(p);
+ vh->write_count = bswabU32_inc(p);
+ vh->encodings_bmp = bswabU64_inc(p);
+ memcpy(vh->finder_info, p, 32);
+ p += 32; // So finderinfo must be swapped later, ***
+ p = volume_readfork(p, &vh->alloc_file );
+ p = volume_readfork(p, &vh->ext_file );
+ p = volume_readfork(p, &vh->cat_file );
+ p = volume_readfork(p, &vh->attr_file );
+ volume_readfork(p, &vh->start_file );
+ return 0;
+ fail:
+ return -1;
+}
+
+/* Read the volume from the given block */
+static int
+volume_read(volume * vol, hfsp_vh* vh, UInt32 block)
+{
+ char buf[vol->blksize];
+
+ if( volume_readinbuf(vol, buf, block))
+ return -1;
+ return volume_readbuf(vh, buf);
+}
+
+/* Find out wether the volume is wrapped and unwrap it eventually */
+static int
+volume_read_wrapper(volume * vol, hfsp_vh* vh)
+{
+ UInt16 signature;
+ char buf[vol->blksize];
+ char *p = buf;
+ int ret;
+ UInt64 vol_size;
+
+ if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here
+ return -1;
+
+ signature = bswabU16_inc(p);
+ if( signature == HFS_VOLHEAD_SIG) { /* Wrapper */
+ UInt32 drAlBlkSiz; /* size (in bytes) of allocation blocks */
+ UInt32 sect_per_block; /* how may block build an hfs sector */
+ UInt16 drAlBlSt; /* first allocation block in volume */
+ UInt16 embeds, embedl; /* Start/lenght of embedded area in blocks */
+
+ p += 0x12; /* skip unneded HFS vol fields */
+ drAlBlkSiz = bswabU32_inc(p); /* offset 0x14 */
+ p += 0x4; /* skip unneded HFS vol fields */
+ drAlBlSt = bswabU16_inc(p); /* offset 0x1C */
+
+ p += 0x5E; /* skip unneded HFS vol fields */
+ signature = bswabU16_inc(p); /* offset 0x7C, drEmbedSigWord */
+ if( signature != HFSP_VOLHEAD_SIG)
+ HFSP_ERROR(-1, "This looks like a normal HFS volume");
+ embeds = bswabU16_inc(p);
+ embedl = bswabU16_inc(p);
+ sect_per_block = (drAlBlkSiz / HFSP_BLOCKSZ);
+ // end is absolute (not relative to HFS+ start)
+ vol->maxblocks = embedl * sect_per_block;
+ vol->startblock = drAlBlSt + embeds * sect_per_block;
+ /* Now we can try to read the embedded HFS+ volume header */
+ return volume_read(vol,vh,2);
+ }
+ else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */
+ p = buf; // Restore to begin of block
+ ret = volume_readbuf(vh, p);
+ if( !ret ) {
+ /* When reading the initial partition we must use 512 byte blocks */
+ vol_size = (uint64_t)vh->blocksize * vh->total_blocks;
+ vol->maxblocks = vol_size / HFSP_BLOCKSZ;
+ }
+
+ return ret;
+ } else
+ HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found");
+fail:
+ return -1;
+}
+
+
+/* Open the device, read and verify the volume header
+ (and its backup) */
+int
+volume_open( volume* vol, int os_fd )
+{
+ hfsp_vh backup; /* backup volume found at second to last block */
+ long sect_per_block;
+ int shift;
+
+ vol->blksize_bits = HFSP_BLOCKSZ_BITS;
+ vol->blksize = HFSP_BLOCKSZ;
+ vol->startblock = 0;
+ vol->maxblocks = 3;
+ /* this should be enough until we find the volume descriptor */
+ vol->extents = NULL; /* Thanks to Jeremias Sauceda */
+
+ btree_reset(&vol->catalog);
+ vol->os_fd = os_fd;
+
+ // vol->maxblocks = os_seek(vol->os_fd, -1, HFSP_BLOCKSZ_BITS);
+ // This wont work for /dev/... but we do not really need it
+
+ if( volume_read_wrapper(vol, &vol->vol))
+ return -1;
+ if( volume_read(vol, &backup, vol->maxblocks - 2))
+ return -1;
+
+ /* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header
+ and adjust depend values accordingly, after that a block always
+ means a HFS+ allocation size */
+
+ /* Usually 4096 / 512 == 8 */
+ sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ;
+ shift = 0;
+ if( sect_per_block > 1) {
+ shift = 1;
+ while( sect_per_block > 2) {
+ sect_per_block >>=1;
+ shift++;
+ } /* shift = 3 */
+ }
+ vol -> blksize_bits += shift;
+ vol -> blksize = 1 << vol->blksize_bits;
+ vol -> startblock >>= shift;
+ vol -> maxblocks = vol->vol.total_blocks; /* cant calculate via shift ? */
+
+ if( btree_init_cat(&vol->catalog, vol, &vol->vol.cat_file))
+ return -1;
+
+ return 0;
+}
+
+/* Write back all data eventually cached and close the device */
+int
+volume_close(volume* vol)
+{
+ btree_close(&vol->catalog);
+ if( vol->extents) {
+ btree_close(vol->extents);
+ FREE(vol->extents);
+ }
+ return 0;
+}
+
+/* internal fucntion used to create the extents btree,
+ is called by inline function when needed */
+void
+volume_create_extents_tree(volume* vol)
+{
+ btree* result = (btree*) ALLOC(btree*, sizeof(btree));
+ if( !result)
+ HFSP_ERROR(ENOMEM, "No memory for extents btree");
+ if( !btree_init_extent(result, vol, &vol->vol.ext_file)) {
+ vol->extents = result;
+ return;
+ }
+ fail:
+ vol->extents = NULL;
+}
+
+/* Determine whether the volume is a HFS-plus volume */
+int
+volume_probe(int fd, long long offset)
+{
+ UInt16 *vol;
+ int ret = 0;
+
+ vol = (UInt16 *)malloc(2 * 1 << HFSP_BLOCKSZ_BITS);
+ os_seek_offset( fd, 2 * (1 << HFSP_BLOCKSZ_BITS) + offset );
+ os_read(fd, vol, 2, HFSP_BLOCKSZ_BITS);
+
+ if (__be16_to_cpu(vol[0]) == HFS_VOLHEAD_SIG &&
+ __be16_to_cpu(vol[0x3e]) == HFSP_VOLHEAD_SIG) {
+ ret = -1;
+ } else if (__be16_to_cpu(vol[0]) == HFSP_VOLHEAD_SIG) {
+ ret = -1;
+ }
+
+ free(vol);
+ return ret;
+}
+
diff --git a/roms/openbios/fs/hfsplus/include/apple.h b/roms/openbios/fs/hfsplus/include/apple.h
new file mode 100644
index 00000000..7ba836db
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/apple.h
@@ -0,0 +1,111 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes
+ *
+ * This file contains defintions that are special for Apple.
+ * The names match the defintions found in Apple Header files.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original code 1996-1998 by Robert Leslie <rob@mars.rog>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: apple.h,v 1.2 2000/09/08 14:55:08 hasi Exp $
+ */
+
+typedef signed char Char;
+typedef unsigned char UChar;
+typedef signed char SInt8;
+typedef unsigned char UInt8;
+typedef signed short SInt16;
+typedef unsigned short UInt16;
+typedef signed long SInt32;
+typedef unsigned long UInt32;
+typedef unsigned long OSType;
+typedef unsigned long long UInt64;
+
+/* A point, normally used by Quickdraw,
+ * but found in Finderinformation, too
+ */
+typedef struct {
+ SInt16 v; /* vertical coordinate */
+ SInt16 h; /* horizontal coordinate */
+} Point;
+
+/* A rectancle, normally used by Quickdraw,
+ * but found in Finderinformation, too.
+ */
+typedef struct {
+ SInt16 top; /* top edge of rectangle */
+ SInt16 left; /* left edge */
+ SInt16 bottom; /* bottom edge */
+ SInt16 right; /* right edge */
+} Rect;
+
+/* Information about the location and size of a folder
+ * used by the Finder.
+ */
+typedef struct {
+ Rect frRect; /* folder's rectangle */
+ SInt16 frFlags; /* flags */
+ Point frLocation; /* folder's location */
+ SInt16 frView; /* folder's view */
+} DInfo;
+
+/* Extended folder information used by the Finder ...
+ */
+typedef struct {
+ Point frScroll; /* scroll position */
+ SInt32 frOpenChain; /* directory ID chain of open folders */
+ SInt16 frUnused; /* reserved */
+ SInt16 frComment; /* comment ID */
+ SInt32 frPutAway; /* directory ID */
+} DXInfo;
+
+/* Finder information for a File
+ */
+typedef struct {
+ OSType fdType; /* file type */
+ OSType fdCreator; /* file's creator */
+ SInt16 fdFlags; /* flags */
+ Point fdLocation; /* file's location */
+ SInt16 fdFldr; /* file's window */
+} FInfo;
+
+/* Extendend Finder Information for a file
+ */
+typedef struct {
+ SInt16 fdIconID; /* icon ID */
+ SInt16 fdUnused[4]; /* reserved */
+ SInt16 fdComment; /* comment ID */
+ SInt32 fdPutAway; /* home directory ID */
+} FXInfo;
+
+/* Flagvalues for FInfo and DInfo */
+# define HFS_FNDR_ISONDESK (1 << 0)
+# define HFS_FNDR_COLOR 0x0e
+# define HFS_FNDR_COLORRESERVED (1 << 4)
+# define HFS_FNDR_REQUIRESSWITCHLAUNCH (1 << 5)
+# define HFS_FNDR_ISSHARED (1 << 6)
+# define HFS_FNDR_HASNOINITS (1 << 7)
+# define HFS_FNDR_HASBEENINITED (1 << 8)
+# define HFS_FNDR_RESERVED (1 << 9)
+# define HFS_FNDR_HASCUSTOMICON (1 << 10)
+# define HFS_FNDR_ISSTATIONERY (1 << 11)
+# define HFS_FNDR_NAMELOCKED (1 << 12)
+# define HFS_FNDR_HASBUNDLE (1 << 13)
+# define HFS_FNDR_ISINVISIBLE (1 << 14)
+# define HFS_FNDR_ISALIAS (1 << 15)
diff --git a/roms/openbios/fs/hfsplus/include/blockiter.h b/roms/openbios/fs/hfsplus/include/blockiter.h
new file mode 100644
index 00000000..da3e480f
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/blockiter.h
@@ -0,0 +1,59 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * The iterator shown here iterates over the blocks of a fork.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original work by 1996-1998 Robert Leslie <rob@mars.org>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: blockiter.h,v 1.1 2000/10/10 11:14:05 hasi Exp $
+ */
+
+/* Structure of the blockiterator */
+typedef struct
+{
+ volume* vol; // volume we iterate over
+ UInt32 curr_block; // current, absolute block
+ UInt32 block; // relative block in current extent
+ UInt32 max_block; // Maximum allowed block
+ UInt32 fileId; // id of file we iterate over
+ int index; // 0 .. 7 in current extent
+ hfsp_extent* file; // original extent record from file
+ hfsp_extent* e; // current extentent under examination
+ UInt8 forktype; // type of fork we iterate over
+ UInt8 in_extent; // boolean 0 - in file extent
+ // 1 - in extents file
+ extent_record er; // record to iterate in extents file.
+} blockiter;
+
+/* Initialize iterator for a given fork */
+extern void blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f,
+ UInt8 forktype, UInt32 fileId);
+
+/* find next block of the fork iterating over */
+extern int blockiter_next(blockiter *b);
+
+/* skip the indicated number of blocks */
+extern int blockiter_skip(blockiter *b, UInt32 skip);
+
+/* return current block */
+static inline UInt32 blockiter_curr(blockiter *b)
+{
+ return b->e->start_block + b->block;
+}
diff --git a/roms/openbios/fs/hfsplus/include/btree.h b/roms/openbios/fs/hfsplus/include/btree.h
new file mode 100644
index 00000000..46ac8501
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/btree.h
@@ -0,0 +1,50 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes.
+ *
+ * The fucntions are used to handle the various forms of btrees
+ * found on HFS+ volumes.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * Additional work by Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: btree.h,v 1.10 2000/10/25 05:43:04 hasi Exp $
+ */
+
+/** Intialize catalog btree, so that btree_close can safely be called. */
+extern void btree_reset(btree* bt);
+
+/** Intialize catalog btree */
+extern int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork);
+
+/** Intialize extents btree */
+extern int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork);
+
+/** close the btree and free any resources */
+extern void btree_close(btree* bt);
+
+/* Read node at given index */
+extern node_buf* btree_node_by_index(btree* bt, UInt16 index);
+
+/* returns pointer to key given by index in current node */
+extern void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index);
+
+#ifdef DEBUG
+ /* Dump all the btree information to stdout */
+ extern void btree_print(btree* bt);
+#endif
diff --git a/roms/openbios/fs/hfsplus/include/hfs.h b/roms/openbios/fs/hfsplus/include/hfs.h
new file mode 100644
index 00000000..5b0cbb49
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/hfs.h
@@ -0,0 +1,32 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes
+ *
+ * This file includes definitions for access to old HFS structures.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original code 1996-1998 by Robert Leslie <rob@mars.rog>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: hfs.h,v 1.1.1.1 2000/07/25 10:33:40 kkaempf Exp $
+ */
+
+
+#define HFS_BLOCKSZ 512
+ /* A sector for Apple is always 512 bytes */
+#define HFS_BLOCKSZ_BITS 9 /* 1<<9 == 512 */
+#define HFS_VOLHEAD_SIG 0x4244 /* 'BD' */
diff --git a/roms/openbios/fs/hfsplus/include/hfsp.h b/roms/openbios/fs/hfsplus/include/hfsp.h
new file mode 100644
index 00000000..e916473c
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/hfsp.h
@@ -0,0 +1,305 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes
+ *
+ * This file includes definitions for the structures found on
+ * HFS+ Volumes. The structures are further wrapped by struct
+ * found in libhfsp.h. fucntions on those enhanced structures
+ * are found in files mentioned in comments below.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original code 1996-1998 by Robert Leslie <rob@mars.rog>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: hfsp.h,v 1.17 2000/10/20 06:16:52 hasi Exp $
+ */
+
+#define HFSP_BLOCKSZ 512 /* A sector for Apple is always 512 bytes */
+#define HFSP_BLOCKSZ_BITS 9 /* 1<<9 == 512 */
+#define HFSP_VOLHEAD_SIG 0x482B /* 'H+' */
+
+/* HFS+ includes POSIX permissions , although marked as reserved they will be
+ * used as such. Is ignored by MacOS 8-9 but probably not by MacOS X.
+ */
+typedef struct {
+ UInt32 owner;
+ UInt32 group;
+ UInt32 mode;
+ UInt32 dev;
+} hfsp_perm;
+
+/* A single contiguous area (fragment) of a file */
+typedef struct {
+ UInt32 start_block;
+ UInt32 block_count;
+} hfsp_extent;
+
+/* A file may contain up to 8 normale extents, all other
+ are found in some extra extent area */
+typedef hfsp_extent hfsp_extent_rec[8];
+
+/* Information for a "Fork" in a file
+ * Forks are the "usual" DATA and RSRC forks or special files
+ * (e.g. the Volume Bitmap)
+ */
+typedef struct {
+ UInt64 total_size; // logical size
+ UInt32 clump_size; // number of bytes to preallocate
+ UInt32 total_blocks;
+ hfsp_extent_rec extents; // initial (8) extents
+} hfsp_fork_raw;
+
+/* HFS+ Volume Header
+ * Always found at block 2 of the disk, a copy is stored
+ * at the second to last block of the disk.
+ */
+typedef struct hfsp_vh {
+ UInt16 signature; // must be HFSPLUS_VOLHEAD_SIG 'H+'
+ UInt16 version; // currently 4, ignored
+ UInt32 attributes; // See bit constants below
+ UInt32 last_mount_vers;
+ // Use a registered creator code here (what do we use ?)
+ // Mac OS uses '8.10' well
+ UInt32 reserved;
+
+ UInt32 create_date; // local time !
+ UInt32 modify_date; // GMT (?)
+ UInt32 backup_date; // GMT (?)
+ UInt32 checked_date; // GMT (?) fsck ?
+
+ UInt32 file_count;
+ // not including special files but including DATA and RSRC forks
+ UInt32 folder_count; // excluding the root folder
+
+ UInt32 blocksize;
+ // must be multiple of HFSPLUS_SECTOR_SIZE,
+ // should be a multiple of 4k for harddisk
+ UInt32 total_blocks;
+ UInt32 free_blocks;
+ // The total number of unused allocation blocks on the disk.
+
+ UInt32 next_alloc;
+ // hint wher to search for next allocation blocks
+ UInt32 rsrc_clump_sz;
+ // default clump size for rsrc forks
+ UInt32 data_clump_sz;
+ // default clump size for data forks
+ UInt32 next_cnid;
+ // next unused catalog id
+ UInt32 write_count;
+ // increment on every mount (and write ?)
+ UInt64 encodings_bmp;
+ // for every encoding used on the disk a bit is set
+ // ignored but eventually must be cared for
+ Char finder_info[32];
+ hfsp_fork_raw alloc_file;
+ // stores bitmap of use/free blocks
+ hfsp_fork_raw ext_file;
+ // stores oferflow extents
+ hfsp_fork_raw cat_file;
+ // This contains the root directory
+ hfsp_fork_raw attr_file;
+ hfsp_fork_raw start_file;
+ // a special startup file may be described here (used by ?)
+} hfsp_vh;
+
+/* HFS+ volume attributes */
+/* 0-6 reserved, may be used in memory only */
+#define HFSPLUS_VOL_RESERVED1 0x000000FF
+#define HFSPLUS_VOL_HARDLOCK 0x00000080 // Used in Memory by finder only
+#define HFSPLUS_VOL_UNMNT 0x00000100
+ // clear this bit when mounting, set as last step of unmounting
+ // This is checked by (slower) ROM code
+#define HFSPLUS_VOL_SPARE_BLK 0x00000200
+#define HFSPLUS_VOL_NOCACHE 0x00000400
+ // in case of RAM or ROM disk (try a HFS+ Ramdisk :)
+#define HFSPLUS_VOL_INCNSTNT 0x00000800
+ // Reverse meaning as of HFSPLUS_VOL_UNMNT
+ // This is checked by (faster) Mac OS code
+/* 12-14 reserved */
+#define HFSPLUS_VOL_RESERVED2 0x00007000
+#define HFSPLUS_VOL_SOFTLOCK 0x00008000
+#define HFSPLUS_VOL_RESERVED3 0xFFFF0000
+
+/* HFS+ Btree node descriptor */
+typedef struct {
+ UInt32 next; /* pointer to next node of this kind, or 0 */
+ UInt32 prev; /* pointer to previous node of this kind, or 0 */
+ UInt8 kind; /* see below */
+ UInt8 height; /* root node starts with 0 */
+ UInt16 num_rec; /* number of records in this node */
+ UInt16 reserved; /* fill up to 4 byte alignment */
+} btree_node_desc;
+
+/* HFS+ Btree Node types */
+#define HFSP_NODE_NDX 0x00
+#define HFSP_NODE_HEAD 0x01
+#define HFSP_NODE_MAP 0x02
+#define HFSP_NODE_LEAF 0xFF
+
+#define HFSP_CATALOG_MIN_NODE_SIZE 0x1000
+#define HFSP_ATTRMIN_DOE_SIZE 0x1000
+
+/* The record offsets are found at the end of the fork
+ * containing the Btree */
+
+typedef UInt16 btree_record_offset;
+
+typedef struct {
+ UInt16 depth;
+ // equal to height of btree_node_desc
+ UInt32 root;
+ // root node of the hierarchy
+ UInt32 leaf_count;
+ UInt32 leaf_head;
+ UInt32 leaf_tail;
+ UInt16 node_size;
+ // node size of _all_ nodes in this fork
+ UInt16 max_key_len;
+ UInt32 node_count;
+ // count of all (free and used) nodes in tree
+ UInt32 free_nodes;
+ UInt16 reserved1;
+ UInt32 clump_size;
+ // ignored my MacOS used by ?
+ UInt8 btree_type;
+ // always 0 for HFS+
+ UInt8 reserved2;
+ UInt32 attributes;
+ // see below
+ UInt32 reserved3[16];
+} btree_head;
+
+/* BTree attributes */
+#define HFSPLUS_BAD_CLOSE 0x01
+ // Btree was not properly closed and should be checked
+ // not used for HFS+ but reserved
+#define HFSPLUS_TREE_BIGKEYS 0x02
+ // always set for HFS+
+#define HFSPLUS_TREE_VAR_NDXKEY_SIZE 0x04
+ // use variable length index nodes, always set for catalog btree,
+ // always cleared for extents btree.
+
+#define HFSPLUS_TREE_UNUSED 0xFFFFFFF8
+
+/* Some special File ID numbers */
+#define HFSP_POR_CNID 1 /* Parent Of the Root */
+#define HFSP_ROOT_CNID 2 /* ROOT directory */
+#define HFSP_EXT_CNID 3 /* EXTents B-tree */
+#define HFSP_CAT_CNID 4 /* CATalog B-tree */
+#define HFSP_BAD_CNID 5 /* BAD blocks file */
+#define HFSP_ALLOC_CNID 6 /* ALLOCation file */
+#define HFSP_START_CNID 7 /* STARTup file */
+#define HFSP_ATTR_CNID 8 /* ATTRibutes file */
+#define HFSP_EXCH_CNID 15 /* ExchangeFiles temp id */
+#define HFPS_MIN_CNID 15 /* Minimum expected value */
+
+/* Unicode String */
+typedef struct {
+ UInt16 strlen;
+ UInt16 name[255]; // unicode charcters
+} hfsp_unistr255;
+
+/* HFS+ catalog entry key */
+typedef struct {
+ UInt16 key_length; /* excluding length */
+ UInt32 parent_cnid;
+ hfsp_unistr255 name;
+} hfsp_cat_key;
+
+/* HFS+ exnteds entry key */
+typedef struct {
+ UInt16 key_length; /* excluding length */
+ UInt8 fork_type; /* Seee below */
+ UInt8 filler;
+ UInt32 file_id;
+ UInt32 start_block;
+} hfsp_extent_key;
+
+#define HFSP_EXTENT_DATA 0x00
+#define HFSP_EXTENT_RSRC 0xFF
+
+/* The key is followed by a record, an index or some other data */
+
+/* The types of these records are defined as follows */
+
+#define HFSP_FOLDER 0x0001 // entry fo a Folder
+#define HFSP_FILE 0x0002 // entry for a File
+#define HFSP_FOLDER_THREAD 0x0003
+ // Like '.' in unix, identifies the folder by its id, only
+#define HFSP_FILE_THREAD 0x0004
+ // Im unsure if this is used by HFS+, too
+
+/* HFS+ folder data (part of an hfsp_cat_entry) */
+typedef struct {
+ UInt16 flags; /* no flags defined yet */
+ UInt32 valence; /* Numer of files and folders contained in folder */
+ UInt32 id;
+ UInt32 create_date; // GMT
+ UInt32 content_mod_date; // GMT
+ UInt32 attribute_mod_date; // GMT
+ UInt32 access_date; // GMT
+ UInt32 backup_date; // GMT
+ hfsp_perm permissions;
+ DInfo user_info;
+ DXInfo finder_info;
+ UInt32 text_encoding;
+ // hint fo the finder what encoding to use, unused here
+ UInt32 reserved;
+} hfsp_cat_folder;
+
+/* HFS+ file data (part of a cat_entry) */
+typedef struct {
+ UInt16 flags; /* See below */
+ UInt32 reserved1;
+ UInt32 id;
+ UInt32 create_date;
+ UInt32 content_mod_date;
+ UInt32 attribute_mod_date;
+ UInt32 access_date;
+ UInt32 backup_date;
+ hfsp_perm permissions;
+ FInfo user_info;
+ FXInfo finder_info;
+ UInt32 text_encoding;
+ UInt32 reserved2;
+
+ hfsp_fork_raw data_fork;
+ hfsp_fork_raw res_fork;
+} hfsp_cat_file;
+
+/* File attribute bits */
+#define HFSP_FILE_LOCKED 0x0001
+#define HFSP_THREAD_EXISTS 0x0002 /* Always set in HFS+ */
+
+/* HFS+ catalog thread (part of a cat_entry) */
+typedef struct {
+ UInt16 reserved;
+ UInt32 parentID;
+ hfsp_unistr255 nodeName;
+} hfsp_cat_thread;
+
+
+/* A data record in the catalog tree */
+typedef struct {
+ UInt16 type;
+ union {
+ hfsp_cat_folder folder;
+ hfsp_cat_file file;
+ hfsp_cat_thread thread;
+ } u;
+} hfsp_cat_entry;
diff --git a/roms/openbios/fs/hfsplus/include/hfstime.h b/roms/openbios/fs/hfsplus/include/hfstime.h
new file mode 100644
index 00000000..bb6bd4a6
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/hfstime.h
@@ -0,0 +1,34 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>^
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * other work 2000 from Brad Boyer (flar@pants.nu)
+ *
+ * The HFS+ dates are stored as UInt32 containing the number of seconds since
+ * midnight, January 1, 1904, GMT. This is slightly different from HFS,
+ * where the value represents local time. A notable exception is the
+ * creationdate !. Linux uses times in GMT starting at January 1, 1970
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: hfstime.h,v 1.2 2000/10/19 13:33:38 hasi Exp $
+ */
+
+ /* The number of seconds between 1.1.1904 and 1.1.1970 */
+#define HFSPTIMEDIFF 2082844800U
+
+ /* return the given apple time as UNIX time */
+extern char* get_atime(UInt32 atime);
diff --git a/roms/openbios/fs/hfsplus/include/libhfsp.h b/roms/openbios/fs/hfsplus/include/libhfsp.h
new file mode 100644
index 00000000..912cfbd0
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/libhfsp.h
@@ -0,0 +1,201 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 2000 Klaus Halfmann (khalfmann@libra.de)
+ * Original work by 1996-1998 Robert Leslie (rob@mars.org)
+ *
+ * This file defines constants,structs etc needed for this library.
+ * Everything found here is usually not related to Apple defintions.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: libhfsp.h,v 1.17 2000/10/20 06:16:52 hasi Exp $
+ */
+
+# include "apple.h"
+# include "hfs.h"
+# include "hfsp.h"
+
+/* Last error is eventually found here */
+extern const char *hfsp_error;
+
+# define HFSP_ERROR(code, str) \
+ do { hfsp_error = (str), errno = (code); goto fail; } while (0)
+
+# ifdef DEBUG
+# define ASSERT(cond) do { if (! (cond)) abort(); } while (0)
+# else
+# define ASSERT(cond) /* nothing */
+# endif
+
+# define SIZE(type, n) ((size_t) (sizeof(type) * (n)))
+# define ALLOC(type, n) ((type *) malloc(SIZE(type, n)))
+# define ALLOCX(type, n) ((n) ? ALLOC(type, n) : (type *) 0)
+# define FREE(ptr) ((ptr) ? (void) free((void *) ptr) : (void) 0)
+
+# define REALLOC(ptr, type, n) \
+ ((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n))))
+# define REALLOCX(ptr, type, n) \
+ ((n) ? REALLOC(ptr, type, n) : (FREE(ptr), (type *) 0))
+
+# define BMTST(bm, num) \
+ (((const byte *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07)))
+# define BMSET(bm, num) \
+ (((byte *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07)))
+# define BMCLR(bm, num) \
+ (((byte *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07)))
+
+# define STRINGIZE(x) #x
+# define STR(x) STRINGIZE(x)
+
+/* used by internal routines to specify the open modes */
+# define HFSP_MODE_RDONLY 0
+# define HFSP_MODE_RDWR 1
+# define HFSP_MODE_ANY 2
+
+/* Signatures registered with Apple to identify this driver */
+ /* Identifies the userland implementation */
+# define HPLS_SIGNATURE 0x482B4C58 // 'H+LX'
+ /* Identifies the kernel module by Brad Boyer (flar@pants.nu) */
+# define HPLS_SIGRES1 0x482B4C78 // 'H+Lx'
+ /* not jet in use ... */
+# define HPLS_SIGRES2 0x482B6C78 // 'H+lx'
+ /* Signature used by Apple */
+# define HPAPPLE_SIGNATURE 0x382e3130 // '8.10'
+
+/* Version used for this implementation of HFS+. This is not related
+ * to the VERSION file found at the top-level of this package,
+ * but designates the version of the low level code */
+#define HPLS_VERSION 1 /* must fit in a short */
+
+
+/* Othe Signatures may follow for informational purpos */
+
+/* prototype for key comparing functions. */
+typedef int (*hfsp_key_compare) (void* key1, void* key2);
+
+/* prototype for key reading (necessary for byte swapping) */
+typedef void* (*hfsp_key_read) (void* p, void* key);
+
+struct volume; /* foreward declaration for btree needed */
+
+/* Structures for a node cache. The cache is an array
+ * with linear search. (So making it to big may make
+ * things slower). It is searched in a round robin
+ * fashion.
+ */
+
+typedef struct
+{
+ UInt32 priority;
+ // as lower this number as higher the priority.
+ // decremetned on any sucessfull usage
+ // incremented else, intial value height*DEPTHFACTOR
+ UInt16 index; // of node in fork
+ // 0 means empty, since first node is node header
+ // contents of node in original byte order
+ UInt16 flags; // like DIRTY etc.
+} node_entry;
+
+typedef struct
+{
+ UInt32 index; // duplicate of above
+ btree_node_desc desc; // header of node
+ char node[0]; // actual node_size
+ // contents of node in original byte order
+} node_buf;
+
+typedef struct
+{
+ int size; // number of nodes in the cache
+ int currindex; // round robin index
+ int nodebufsize; // size of complete node_buf, including node
+ node_entry *entries;
+ char *buffers; // actually *node_buf
+} node_cache;
+
+typedef struct
+{
+ struct volume* vol; /* pointer to volume this tree is part of */
+ hfsp_fork_raw* fork; /* pointer to fork this tree is part of */
+ UInt32 cnid; /* (pseudo) file id for the fork */
+ hfsp_key_compare kcomp;
+ /* function used for key compare in _this_ btree */
+ hfsp_key_read kread;
+ /* fucntion used to read a key int _this_ btree */
+ btree_head head;
+
+ UInt16 blkpernode;
+ /* Number of volume blocks per node (usually 1-4) */
+ node_cache cache;
+ /* Warning all functions of btrees and records may modify
+ the following values ! */
+ // UInt16 node_index; /* index of node in fork */
+ // btree_node_desc node; /* current node under examination */
+ // char* buf; /* buf with size of a node */
+} btree;
+
+/* Function on btrees are defined in btree.h */
+
+/* A Wrapper around the raw hfs+ volume header for additional information
+ * needed by this library.
+ */
+
+typedef struct volume
+{
+ int os_fd; /* OS dependend reference to device */
+ UInt16 blksize_bits; /* blocksize of device = 1 << blksize_bits */
+ UInt16 filler;
+ UInt32 blksize; /* always 1 << blksize_bits */
+ UInt32 startblock;
+ /* Offset from physical to logical blocks,
+ eventually intodruced by HFS wrapper */
+ UInt32 maxblocks; /* maximum number of blocks in device */
+ // UInt32 currblock; /* value of current block, to cache blocks */
+ hfsp_vh vol; /* raw volume data */
+ // void* blockbuf; /* (single) buffer for fetching one block */
+ /* Buffer has double size of blksize to allow cross block reading */
+
+ btree* extents; /* is NULL by default and intialized when needed */
+ btree catalog; /* This is always neeeded */
+} volume;
+
+/* Functions on volumes are defined in volume.h */
+
+typedef struct { // may not be used as found here
+ btree* tree; // tree where this record is contained in.
+ UInt16 node_index; /* index of record in btree */
+ UInt16 keyind; /* index of current key in btree */
+ hfsp_cat_key key; /* current key */
+ UInt32 child; /* child node belonging to this key */
+} index_record;
+
+typedef struct {
+ btree* tree; // tree where this record is contained in.
+ UInt16 node_index; /* index of record in btree */
+ UInt16 keyind; /* index of current key in btree */
+ hfsp_extent_key key; /* current key */
+ hfsp_extent_rec extent; /* The payload carried around */
+} extent_record;
+
+typedef struct {
+ btree* tree; // tree where this record is contained in.
+ UInt16 node_index; /* index of record in btree */
+ UInt16 keyind; /* index of current key in btree */
+ hfsp_cat_key key; /* current key */
+ hfsp_cat_entry record; /* current record */
+} record;
+
+/* Functions on records are defined in record.h */
diff --git a/roms/openbios/fs/hfsplus/include/record.h b/roms/openbios/fs/hfsplus/include/record.h
new file mode 100644
index 00000000..6454f552
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/record.h
@@ -0,0 +1,80 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes.
+ *
+ * a record contains a key and a folder or file and is part
+ * of a btree.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ * Additional work by Brad Boyer (flar@pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: record.h,v 1.10 2000/10/01 17:08:05 hasi Exp $
+ */
+
+/* Compare two cat_keys ... */
+extern int record_key_compare(void* k1, void* k2);
+
+/* Compare two extent_keys ... */
+extern int record_extent_key_compare(void* k1, void* k2);
+
+/* read a catalog key into a given buffer */
+extern void* record_readkey(void* p, void* buf);
+
+/* read an extent key into a given buffer */
+extern void* record_extent_readkey(void* p, void* buf);
+
+/* intialize the record to the first record of the tree
+ * which is (per design) the root node.
+ */
+extern int record_init_root(record* r, btree* tree);
+
+/* intialize the record to the folder given by cnid.
+ */
+extern int record_init_cnid(record* r, btree* tree, UInt32 cnid);
+
+/* intialize the record to the first record of the parent.
+ */
+extern int record_init_parent(record* r, record* parent);
+
+/* intialize the record by searching for the given string in the given folder.
+ *
+ * parent and r may be the same.
+ */
+extern int record_init_string_parent(record* r, record* parent, char* key);
+
+/* move record up in folder hierarchy (if possible) */
+extern int record_up(record* r);
+
+/* move record foreward to next entry.
+ *
+ * In case of an error the value of *r is undefined !
+ */
+extern int record_next(record* r);
+
+/* intialize the extent_record to the extent identified by
+ * a given file */
+extern int record_init_file(extent_record* r, btree* tree,
+ UInt8 forktype, UInt32 fileId, UInt32 blockindex);
+
+/* move foreward to next entent record. */
+extern int record_next_extent(extent_record *r);
+
+#ifdef DEBUG
+ /* Dump all the record information to stdout */
+ extern void record_print(record* r);
+#endif
diff --git a/roms/openbios/fs/hfsplus/include/swab.h b/roms/openbios/fs/hfsplus/include/swab.h
new file mode 100644
index 00000000..c424008e
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/swab.h
@@ -0,0 +1,64 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * Copyright (C) 2000 Klaus Halfmann <klaus.halfmann@feri.de>
+ * Original work 1996-1998 Robert Leslie <rob@mars.org>
+ *
+ * This file defines some byte swapping function. I did not find this
+ * in any standard or linux way.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: swab.h,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
+ */
+
+#include "config.h"
+#include "libc/byteorder.h"
+
+ /* basic fuction:
+ value = swab_inc(ptr);
+ ptr is afterwards incremented by sizeof(value)
+ */
+
+#ifndef CONFIG_BIG_ENDIAN
+
+#define bswabU16(val) __bswap16(val)
+
+#define bswabU16_inc(ptr) (__extension__ ({ UInt16 v=__bswap16(*((UInt16*) (ptr))); ptr+=sizeof(UInt16);v;}))
+#define bswabU32_inc(ptr) (__extension__ ({ UInt32 v=__bswap32(*((UInt32*) (ptr))); ptr+=sizeof(UInt32);v;}))
+#define bswabU64_inc(ptr) (__extension__ ({ UInt64 v=__bswap64(*((UInt64*) (ptr))); ptr+=sizeof(UInt64);v;}))
+
+#define bstoreU16_inc(ptr, val) do {(*((UInt16*) (ptr))) = __bswap16(val); ptr+=sizeof(UInt16);} while (0)
+#define bstoreU32_inc(ptr, val) do {(*((UInt32*) (ptr))) = __bswap32(val); ptr+=sizeof(UInt32);} while (0)
+#define bstoreU64_inc(ptr, val) do {(*((UInt64*) (ptr))) = __bswap64(val); ptr+=sizeof(UInt64);} while (0)
+
+#else // BYTE_ORDER == BIG_ENDIAN
+
+#define bswabU16(val) val
+
+#define bswabU16_inc(ptr) (__extension__ ({ UInt16 v=(*((UInt16*) (ptr))); ptr+=sizeof(UInt16);v;}))
+#define bswabU32_inc(ptr) (__extension__ ({ UInt32 v=(*((UInt32*) (ptr))); ptr+=sizeof(UInt32);v;}))
+#define bswabU64_inc(ptr) (__extension__ ({ UInt64 v=(*((UInt64*) (ptr))); ptr+=sizeof(UInt64);v;}))
+
+#define bstoreU16_inc(ptr, val) do {(*((UInt16*) (ptr))) = val; ptr+=sizeof(UInt16);} while (0)
+#define bstoreU32_inc(ptr, val) do {(*((UInt32*) (ptr))) = val; ptr+=sizeof(UInt32);} while (0)
+#define bstoreU64_inc(ptr, val) do {(*((UInt64*) (ptr))) = val; ptr+=sizeof(UInt64);} while (0)
+
+#endif
+
+/* for the sake of compleetness and readability */
+#define bswabU8_inc(ptr) (__extension__ ({ UInt8 v=(*((UInt8*) (ptr))); ptr+=sizeof(UInt8);v;}))
+#define bstoreU8_inc(ptr,val) do {(*((UInt8*) (ptr))) = val; ptr+=sizeof(UInt8);} while (0)
diff --git a/roms/openbios/fs/hfsplus/include/unicode.h b/roms/openbios/fs/hfsplus/include/unicode.h
new file mode 100644
index 00000000..e7c86f78
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/unicode.h
@@ -0,0 +1,28 @@
+/*
+ * linux/fs/hfsplus/unicode.c
+ *
+ * Copyright (C) 1999-2000 Brad Boyer (flar@pants.nu)
+ * This file may be distributed under the terms of the GNU Public License.
+ *
+ * The routines found here convert hfs-unicode string into ascii Strings
+ * and vice versa. And the correct comparison between Strings.
+ */
+
+/* convert the asci string astr into a unicode string given by ustr.
+ *
+ * returns actual length of convertet string.
+ */
+
+int unicode_asc2uni(hfsp_unistr255 *ustr, const char *astr);
+
+/* Convert an unicode string ustr to a ascii string astr of given maximum len
+ *
+ * returns actual length of convertet string.
+ */
+
+int unicode_uni2asc(char *astr, const hfsp_unistr255 *ustr, int maxlen);
+
+/* similar to strcmp for unicode, pascal strings */
+
+SInt32 fast_unicode_compare (const hfsp_unistr255 *ustr1,
+ const hfsp_unistr255 *ustr2);
diff --git a/roms/openbios/fs/hfsplus/include/volume.h b/roms/openbios/fs/hfsplus/include/volume.h
new file mode 100644
index 00000000..19be0550
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/include/volume.h
@@ -0,0 +1,87 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>^
+ * Original 1996-1998 Robert Leslie <rob@mars.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: volume.h,v 1.11 2000/10/17 05:58:46 hasi Exp $
+ */
+
+#ifndef _H_VOLUME
+#define _H_VOLUME
+
+/* Open the device, read and verify the volume header
+ (and its backup) */
+extern int volume_open(volume* vol, int os_fd);
+
+/* Write back all data eventually cached and close the device. */
+extern int volume_close(volume* vol);
+
+/* read multiple blocks into given memory.
+ *
+ * returns given pointer or NULL on failure.
+ */
+extern void* volume_readfromfork(volume* vol, void* buf,
+ hfsp_fork_raw* f, UInt32 block,
+ UInt32 count, UInt8 forktype, UInt32 fileId);
+
+/* Fill a given buffer with the given block in volume.
+ */
+int volume_readinbuf(volume * vol,void* buf, long block);
+
+/* invalidat cache hold in volume, will be removed when
+ * caching strategy is clear to me. */
+/*
+extern inline void volume_invalidate_cache(volume* vol)
+{
+ vol -> currblock = (UInt32) -1;
+}
+*/
+
+/* Check in Allocation file if given block is allocated. */
+extern int volume_allocated(volume* v, UInt32 block);
+
+/* Read a raw hfsp_extent_rec from memory. */
+extern void* volume_readextent(void *p, hfsp_extent_rec er);
+
+/* Read fork information from raw memory */
+extern void* volume_readfork(void *p, hfsp_fork_raw* f);
+
+/* internal function used to create the extents btree,
+ is called by following inline fucntion when needed */
+extern void volume_create_extents_tree(volume* vol);
+
+/* accessor for entends btree, is created on demand */
+static inline btree* volume_get_extents_tree(volume* vol) {
+ if (!vol->extents)
+ volume_create_extents_tree(vol);
+ return vol->extents;
+}
+
+/* Determine whether the volume is a HFS-plus volume */
+int volume_probe(int fd, long long offset);
+
+#ifdef DEBUG
+ /* Print raw fork information to stdout */
+ void volume_print_fork(hfsp_fork_raw* f);
+ /* Dump all the volume information to stdout */
+ void volume_print(hfsp_vh* vol);
+#endif
+
+
+
+#endif /* _H_VOLUME */
diff --git a/roms/openbios/fs/hfsplus/libhfsp.c b/roms/openbios/fs/hfsplus/libhfsp.c
new file mode 100644
index 00000000..af1cde6a
--- /dev/null
+++ b/roms/openbios/fs/hfsplus/libhfsp.c
@@ -0,0 +1,29 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998 Robert Leslie
+ *
+ * Thi file contains utitlity fucntions to manage the features of
+ * the hfs+ library.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: libhfsp.c,v 1.1.1.1 2000/07/25 10:33:40 kkaempf Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+
+const char *hfsp_error = "no error"; /* static error string */
diff --git a/roms/openbios/fs/ioglue.c b/roms/openbios/fs/ioglue.c
new file mode 100644
index 00000000..1d33d8fd
--- /dev/null
+++ b/roms/openbios/fs/ioglue.c
@@ -0,0 +1,92 @@
+/*
+ * Creation Date: <2001/05/06 22:27:09 samuel>
+ * Time-stamp: <2003/12/12 02:24:56 samuel>
+ *
+ * <fs.c>
+ *
+ * I/O API used by the filesystem code
+ *
+ * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "fs/fs.h"
+#include "libc/diskio.h"
+#include "os.h"
+#include "hfs_mdb.h"
+
+/************************************************************************/
+/* functionsions used by the various filesystems */
+/************************************************************************/
+
+char *
+get_hfs_vol_name( int fd, char *buf, int size )
+{
+ char sect[512];
+ hfs_mdb_t *mdb = (hfs_mdb_t*)&sect;
+
+ seek_io( fd, 0x400 );
+ read_io( fd, sect, sizeof(sect) );
+ if( hfs_get_ushort(mdb->drSigWord) == HFS_SIGNATURE ) {
+ unsigned int n = mdb->drVN[0];
+ if( n >= size )
+ n = size - 1;
+ memcpy( buf, &mdb->drVN[1], n );
+ buf[n] = 0;
+ } else if( hfs_get_ushort(mdb->drSigWord) == HFS_PLUS_SIGNATURE ) {
+ strncpy( buf, "Unembedded HFS+", size );
+ } else {
+ strncpy( buf, "Error", size );
+ }
+ return buf;
+}
+
+unsigned long
+os_read( int fd, void *buf, unsigned long len, int blksize_bits )
+{
+ /* printk("os_read %d\n", (int)len); */
+
+ int cnt = read_io( fd, buf, len << blksize_bits );
+ return (cnt > 0)? (cnt >> blksize_bits) : cnt;
+}
+
+unsigned long
+os_seek( int fd, unsigned long blknum, int blksize_bits )
+{
+ /* printk("os_seek %d\n", blknum ); */
+ long long offs = (long long)blknum << blksize_bits;
+
+ /* offset == -1 means seek to EOF */
+ if( (int)blknum == -1 )
+ offs = -1;
+
+ if( seek_io(fd, offs) ) {
+ /* printk("os_seek failure\n"); */
+ return (unsigned long)-1;
+ }
+
+ if( (int)blknum == -1 ) {
+ if( (offs=tell(fd)) < 0 )
+ return -1;
+ blknum = offs >> blksize_bits;
+ }
+ return blknum;
+}
+
+void
+os_seek_offset( int fd, long long offset )
+{
+ seek_io(fd, offset);
+}
+
+int
+os_same( int fd1, int fd2 )
+{
+ return fd1 == fd2;
+}
diff --git a/roms/openbios/fs/iso9660/build.xml b/roms/openbios/fs/iso9660/build.xml
new file mode 100644
index 00000000..00d39021
--- /dev/null
+++ b/roms/openbios/fs/iso9660/build.xml
@@ -0,0 +1,13 @@
+<build>
+ <library name="fs" type="static" target="target">
+ <object source="iso9660_fs.c" condition="ISO9660"/>
+ <object source="iso9660_close.c" condition="ISO9660"/>
+ <object source="iso9660_closedir.c" condition="ISO9660"/>
+ <object source="iso9660_lseek.c" condition="ISO9660"/>
+ <object source="iso9660_mount.c" condition="ISO9660"/>
+ <object source="iso9660_open.c" condition="ISO9660"/>
+ <object source="iso9660_opendir.c" condition="ISO9660"/>
+ <object source="iso9660_read.c" condition="ISO9660"/>
+ <object source="iso9660_readdir.c" condition="ISO9660"/>
+ </library>
+</build>
diff --git a/roms/openbios/fs/iso9660/iso9660.h b/roms/openbios/fs/iso9660/iso9660.h
new file mode 100644
index 00000000..ac6dcf09
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#ifndef __ISO9660_H__
+#define __ISO9660_H__
+
+#include "iso9660_fs.h"
+
+typedef struct iso9660_VOLUME {
+ int ucs_level;
+ struct iso_primary_descriptor *descriptor;
+ int fd;
+} iso9660_VOLUME;
+
+typedef struct iso9660_DIR {
+ iso9660_VOLUME *volume;
+ int extent;
+ int len;
+ int index;
+ unsigned char buffer[ISOFS_BLOCK_SIZE];
+} iso9660_DIR;
+
+typedef struct iso9660_FILE {
+ iso9660_VOLUME *volume;
+ char *path;
+ int base; /* first extent of the file */
+ int size; /* size of the file */
+ int offset;
+ int current;
+ unsigned char buffer[ISOFS_BLOCK_SIZE];
+} iso9660_FILE;
+
+static inline int isonum_721(char *p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8));
+}
+
+static inline int isonum_723(char *p)
+{
+ return (isonum_721(p));
+}
+
+static inline int isonum_733(char *p)
+{
+ return ((p[0] & 0xff) | ((p[1] & 0xff) << 8) |
+ ((p[2] & 0xff) << 16) | ((p[3] & 0xff) << 24));
+}
+
+extern struct iso_directory_record *iso9660_get_root_node(iso9660_VOLUME* volume);
+extern struct iso_directory_record* iso9660_get_node(iso9660_VOLUME *volume, struct iso_directory_record *dirnode, const char *path);
+
+#endif /* __ISO9660_H__ */
diff --git a/roms/openbios/fs/iso9660/iso9660_close.c b/roms/openbios/fs/iso9660/iso9660_close.c
new file mode 100644
index 00000000..ce79c0fd
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_close.c
@@ -0,0 +1,15 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE bootloader, http://emile.sf.net
+ *
+ */
+
+#include "libiso9660.h"
+
+void iso9660_close(iso9660_FILE *file)
+{
+ free(file->path);
+ free(file);
+}
diff --git a/roms/openbios/fs/iso9660/iso9660_closedir.c b/roms/openbios/fs/iso9660/iso9660_closedir.c
new file mode 100644
index 00000000..706cc222
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_closedir.c
@@ -0,0 +1,19 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libiso9660.h"
+
+int iso9660_closedir(iso9660_DIR *dir)
+{
+ if (dir == NULL)
+ return -1;
+
+ free(dir);
+
+ return 0;
+}
diff --git a/roms/openbios/fs/iso9660/iso9660_fs.c b/roms/openbios/fs/iso9660/iso9660_fs.c
new file mode 100644
index 00000000..d6f547be
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_fs.c
@@ -0,0 +1,263 @@
+/*
+ * /packages/iso9660-files filesystem handler
+ *
+ * (c) 2009 Laurent Vivier <Laurent@vivier.eu>
+ * (c) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libiso9660.h"
+#include "fs/fs.h"
+#include "libc/vsprintf.h"
+#include "libc/diskio.h"
+
+extern void iso9660_init( void );
+
+typedef struct {
+ enum { FILE, DIR } type;
+ union {
+ iso9660_FILE *file;
+ iso9660_DIR * dir;
+ };
+} iso9660_COMMON;
+
+typedef struct {
+ iso9660_VOLUME *volume;
+ iso9660_COMMON *common;
+} iso9660_info_t;
+
+DECLARE_NODE( iso9660, 0, sizeof(iso9660_info_t), "+/packages/iso9660-files" );
+
+/* ( -- success? ) */
+static void
+iso9660_files_open( iso9660_info_t *mi )
+{
+ int fd;
+ char *path = my_args_copy();
+
+ if ( ! path )
+ RET( 0 );
+
+ fd = open_ih( my_parent() );
+ if ( fd == -1 ) {
+ free( path );
+ RET( 0 );
+ }
+
+ mi->volume = iso9660_mount( fd );
+ if ( mi->volume == NULL ) {
+ free( path );
+ close_io( fd );
+ RET( 0 );
+ }
+
+ mi->common->dir = iso9660_opendir( mi->volume, path );
+ if ( mi->common->dir == NULL ) {
+ mi->common->file = iso9660_open( mi->volume, path );
+ if (mi->common->file == NULL) {
+ iso9660_umount( mi->volume );
+ close_io( fd );
+ free( path );
+ RET( 0 );
+ }
+ mi->common->type = FILE;
+ free( path );
+ RET( -1 );
+ }
+ mi->common->type = DIR;
+ free( path );
+
+ RET( -1 );
+}
+
+/* ( -- ) */
+static void
+iso9660_files_close( iso9660_info_t *mi )
+{
+ int fd = mi->volume->fd;
+
+ if (mi->common->type == FILE )
+ iso9660_close( mi->common->file );
+ else if ( mi->common->type == DIR )
+ iso9660_closedir( mi->common->dir );
+ iso9660_umount( mi->volume );
+ close_io( fd );
+}
+
+/* ( buf len -- actlen ) */
+static void
+iso9660_files_read( iso9660_info_t *mi )
+{
+ int count = POP();
+ char *buf = (char *)cell2pointer(POP());
+ int ret;
+
+ if ( mi->common->type != FILE )
+ PUSH( 0 );
+
+ ret = iso9660_read( mi->common->file, buf, count );
+
+ PUSH( ret );
+}
+
+/* ( pos.d -- status ) */
+static void
+iso9660_files_seek( iso9660_info_t *mi )
+{
+ long long pos = DPOP();
+ cell ret;
+ int offs = (int)pos;
+ int whence = SEEK_SET;
+
+ if (mi->common->type != FILE)
+ PUSH( -1 );
+
+ if( offs == -1 ) {
+ offs = 0;
+ whence = SEEK_END;
+ }
+
+ ret = iso9660_lseek(mi->common->file, offs, whence);
+
+ PUSH( (ret < 0)? -1 : 0 );
+}
+
+/* ( -- filepos.d ) */
+static void
+iso9660_files_offset( iso9660_info_t *mi )
+{
+ if ( mi->common->type != FILE )
+ DPUSH( -1 );
+
+ DPUSH( mi->common->file->offset );
+}
+
+/* ( addr -- size ) */
+static void
+iso9660_files_load( iso9660_info_t *mi)
+{
+ char *buf = (char*)cell2pointer(POP());
+ int ret, size;
+
+ if ( mi->common->type != FILE )
+ PUSH( 0 );
+
+ size = 0;
+ while(1) {
+ ret = iso9660_read( mi->common->file, buf, 512 );
+ if (ret <= 0)
+ break;
+ buf += ret;
+ size += ret;
+ if (ret != 512)
+ break;
+ }
+ PUSH( size );
+}
+
+/* static method, ( pathstr len ihandle -- ) */
+static void
+iso9660_files_dir( iso9660_info_t *dummy )
+{
+ iso9660_VOLUME *volume;
+ iso9660_COMMON *common;
+ struct iso_directory_record *idr;
+ char name_buf[256];
+ int fd;
+
+ ihandle_t ih = POP();
+ char *path = pop_fstr_copy();
+
+ fd = open_ih( ih );
+ if ( fd == -1 ) {
+ free( path );
+ return;
+ }
+
+ volume = iso9660_mount( fd );
+ if ( volume == NULL ) {
+ free ( path );
+ close_io( fd );
+ return;
+ }
+
+ common = malloc(sizeof(iso9660_COMMON));
+ common->dir = iso9660_opendir( volume, path );
+
+ forth_printf("\n");
+ while ( (idr = iso9660_readdir(common->dir)) ) {
+
+ forth_printf("% 10d ", isonum_733(idr->size));
+ forth_printf("%d-%02d-%02d %02d:%02d:%02d ",
+ idr->date[0] + 1900, /* year */
+ idr->date[1], /* month */
+ idr->date[2], /* day */
+ idr->date[3], idr->date[4], idr->date[5]);
+ iso9660_name(common->dir->volume, idr, name_buf);
+ if (idr->flags[0] & 2)
+ forth_printf("%s\\\n", name_buf);
+ else
+ forth_printf("%s\n", name_buf);
+ }
+
+ iso9660_closedir( common->dir );
+ iso9660_umount( volume );
+
+ close_io( fd );
+
+ free( common );
+ free( path );
+}
+
+/* static method, ( pos.d ih -- flag? ) */
+static void
+iso9660_files_probe( iso9660_info_t *dummy )
+{
+ ihandle_t ih = POP_ih();
+ long long offs = DPOP();
+ int fd, ret = 0;
+
+ fd = open_ih(ih);
+ if (fd >= 0) {
+ if (iso9660_probe(fd, offs)) {
+ ret = -1;
+ }
+ close_io(fd);
+ } else {
+ ret = -1;
+ }
+
+ RET (ret);
+}
+
+static void
+iso9660_files_block_size( iso9660_info_t *dummy )
+{
+ PUSH(2048);
+}
+
+static void
+iso9660_initializer( iso9660_info_t *dummy )
+{
+ fword("register-fs-package");
+}
+
+NODE_METHODS( iso9660 ) = {
+ { "probe", iso9660_files_probe },
+ { "open", iso9660_files_open },
+ { "close", iso9660_files_close },
+ { "read", iso9660_files_read },
+ { "seek", iso9660_files_seek },
+ { "offset", iso9660_files_offset },
+ { "load", iso9660_files_load },
+ { "dir", iso9660_files_dir },
+ { "block-size", iso9660_files_block_size },
+ { NULL, iso9660_initializer },
+};
+
+void
+iso9660_init( void )
+{
+ REGISTER_NODE( iso9660 );
+}
diff --git a/roms/openbios/fs/iso9660/iso9660_fs.h b/roms/openbios/fs/iso9660/iso9660_fs.h
new file mode 100644
index 00000000..0de124da
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_fs.h
@@ -0,0 +1,161 @@
+#ifndef _ISO9660_FS_H
+#define _ISO9660_FS_H
+
+/* this file has been copied from linux 2.6.26 */
+
+/*
+ * The isofs filesystem constants/structures
+ */
+
+/* This part borrowed from the bsd386 isofs */
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_volume_descriptor {
+ char type[ISODCL(1,1)]; /* 711 */
+ char id[ISODCL(2,6)];
+ char version[ISODCL(7,7)];
+ char data[ISODCL(8,2048)];
+};
+
+/* volume descriptor types */
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_SUPPLEMENTARY 2
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+struct iso_primary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char unused1 [ISODCL ( 8, 8)];
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char unused3 [ISODCL ( 89, 120)];
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+/* Almost the same as the primary descriptor but two fields are specified */
+struct iso_supplementary_descriptor {
+ char type [ISODCL ( 1, 1)]; /* 711 */
+ char id [ISODCL ( 2, 6)];
+ char version [ISODCL ( 7, 7)]; /* 711 */
+ char flags [ISODCL ( 8, 8)]; /* 853 */
+ char system_id [ISODCL ( 9, 40)]; /* achars */
+ char volume_id [ISODCL ( 41, 72)]; /* dchars */
+ char unused2 [ISODCL ( 73, 80)];
+ char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ char escape [ISODCL ( 89, 120)]; /* 856 */
+ char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ char path_table_size [ISODCL (133, 140)]; /* 733 */
+ char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ char volume_set_id [ISODCL (191, 318)]; /* dchars */
+ char publisher_id [ISODCL (319, 446)]; /* achars */
+ char preparer_id [ISODCL (447, 574)]; /* achars */
+ char application_id [ISODCL (575, 702)]; /* achars */
+ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ char unused4 [ISODCL (883, 883)];
+ char application_data [ISODCL (884, 1395)];
+ char unused5 [ISODCL (1396, 2048)];
+};
+
+
+#define HS_STANDARD_ID "CDROM"
+
+struct hs_volume_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char data[ISODCL(16,2048)];
+};
+
+
+struct hs_primary_descriptor {
+ char foo [ISODCL ( 1, 8)]; /* 733 */
+ char type [ISODCL ( 9, 9)]; /* 711 */
+ char id [ISODCL ( 10, 14)];
+ char version [ISODCL ( 15, 15)]; /* 711 */
+ char unused1 [ISODCL ( 16, 16)]; /* 711 */
+ char system_id [ISODCL ( 17, 48)]; /* achars */
+ char volume_id [ISODCL ( 49, 80)]; /* dchars */
+ char unused2 [ISODCL ( 81, 88)]; /* 733 */
+ char volume_space_size [ISODCL ( 89, 96)]; /* 733 */
+ char unused3 [ISODCL ( 97, 128)]; /* 733 */
+ char volume_set_size [ISODCL (129, 132)]; /* 723 */
+ char volume_sequence_number [ISODCL (133, 136)]; /* 723 */
+ char logical_block_size [ISODCL (137, 140)]; /* 723 */
+ char path_table_size [ISODCL (141, 148)]; /* 733 */
+ char type_l_path_table [ISODCL (149, 152)]; /* 731 */
+ char unused4 [ISODCL (153, 180)]; /* 733 */
+ char root_directory_record [ISODCL (181, 214)]; /* 9.1 */
+};
+
+/* We use this to help us look up the parent inode numbers. */
+
+struct iso_path_table{
+ unsigned char name_len[2]; /* 721 */
+ char extent[4]; /* 731 */
+ char parent[2]; /* 721 */
+ char name[0];
+} __attribute__((packed));
+
+/* high sierra is identical to iso, except that the date is only 6 bytes, and
+ there is an extra reserved byte after the flags */
+
+struct iso_directory_record {
+ char length [ISODCL (1, 1)]; /* 711 */
+ char ext_attr_length [ISODCL (2, 2)]; /* 711 */
+ char extent [ISODCL (3, 10)]; /* 733 */
+ char size [ISODCL (11, 18)]; /* 733 */
+ char date [ISODCL (19, 25)]; /* 7 by 711 */
+ char flags [ISODCL (26, 26)];
+ char file_unit_size [ISODCL (27, 27)]; /* 711 */
+ char interleave [ISODCL (28, 28)]; /* 711 */
+ char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
+ unsigned char name_len [ISODCL (33, 33)]; /* 711 */
+ char name [0];
+} __attribute__((packed));
+
+#define ISOFS_BLOCK_BITS 11
+#define ISOFS_BLOCK_SIZE (1 << ISOFS_BLOCK_BITS)
+
+#endif /* _ISO9660_FS_H */
diff --git a/roms/openbios/fs/iso9660/iso9660_lseek.c b/roms/openbios/fs/iso9660/iso9660_lseek.c
new file mode 100644
index 00000000..62987583
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_lseek.c
@@ -0,0 +1,37 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libiso9660.h"
+
+int iso9660_lseek(iso9660_FILE *_file, long offset, int whence)
+{
+ iso9660_FILE *file = (iso9660_FILE*)_file;
+ long new_offset;
+
+ switch(whence)
+ {
+ case SEEK_SET:
+ new_offset = offset;
+ break;
+ case SEEK_CUR:
+ new_offset = file->offset + offset;
+ break;
+ case SEEK_END:
+ new_offset = file->size + offset;
+ break;
+ default:
+ return -1;
+ }
+
+ if ( (new_offset < 0) || (new_offset > file->size) )
+ return -1;
+
+ file->offset = new_offset;
+
+ return new_offset;
+}
diff --git a/roms/openbios/fs/iso9660/iso9660_mount.c b/roms/openbios/fs/iso9660/iso9660_mount.c
new file mode 100644
index 00000000..a5817040
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_mount.c
@@ -0,0 +1,210 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ * some parts from mkisofs (c) J. Schilling
+ *
+ */
+
+#include "libiso9660.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+
+void iso9660_name(iso9660_VOLUME *volume, struct iso_directory_record *idr, char *buffer)
+{
+ int j;
+ unsigned char ul, uc;
+
+ buffer[0] = 0;
+ if (idr->name_len[0] == 1 && idr->name[0] == 0)
+ strcpy(buffer, ".");
+ else if (idr->name_len[0] == 1 && idr->name[0] == 1)
+ strcpy(buffer, "..");
+ else {
+ switch (volume->ucs_level) {
+ case 3:
+ case 2:
+ case 1:
+ /*
+ * Unicode name.
+ */
+
+ for (j = 0; j < (int)idr->name_len[0] / 2; j++) {
+ ul = idr->name[j*2+1];
+
+ /*
+ * unicode convertion
+ * up = unls->unls_uni2cs[uh];
+ *
+ * if (up == NULL)
+ * uc = '\0';
+ * else
+ * uc = up[ul];
+ *
+ * we use only low byte
+ */
+
+ uc = ul;
+
+ buffer[j] = uc ? uc : '_';
+ }
+ buffer[idr->name_len[0]/2] = '\0';
+ break;
+ case 0:
+ /*
+ * Normal non-Unicode name.
+ */
+ strncpy(buffer, idr->name, idr->name_len[0]);
+ buffer[idr->name_len[0]] = 0;
+ break;
+ default:
+ /*
+ * Don't know how to do these yet. Maybe they are the same
+ * as one of the above.
+ */
+ break;
+ }
+ }
+}
+
+iso9660_VOLUME *iso9660_mount(int fd)
+{
+ iso9660_VOLUME* volume;
+ struct iso_primary_descriptor *jpd;
+ struct iso_primary_descriptor ipd;
+ int block;
+ int ucs_level = 0;
+
+ /* read filesystem descriptor */
+
+ seek_io(fd, 16 * ISOFS_BLOCK_SIZE);
+ read_io(fd, &ipd, sizeof (ipd));
+
+ /*
+ * High sierra:
+ *
+ * DESC TYPE == 1 (VD_SFS) offset 8 len 1
+ * STR ID == "CDROM" offset 9 len 5
+ * STD_VER == 1 offset 14 len 1
+ */
+
+ /* High Sierra format ? */
+
+ if ((((char *)&ipd)[8] == 1) &&
+ (strncmp(&((char *)&ipd)[9], "CDROM", 5) == 0) &&
+ (((char *)&ipd)[14] == 1)) {
+ printk("Incompatible format: High Sierra format\n");
+ return NULL;
+ }
+
+ /*
+ * ISO 9660:
+ *
+ * DESC TYPE == 1 (VD_PVD) offset 0 len 1
+ * STR ID == "CD001" offset 1 len 5
+ * STD_VER == 1 offset 6 len 1
+ */
+
+ /* NOT ISO 9660 format ? */
+
+ if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+ (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+ (ipd.version[0] != 1)) {
+ return NULL;
+ }
+
+ /* UCS info */
+
+ block = 16;
+
+ jpd = (struct iso_primary_descriptor *)
+ malloc(sizeof(struct iso_primary_descriptor));
+ if (jpd == NULL)
+ return NULL;
+
+ memcpy(jpd, &ipd, sizeof (ipd));
+ while ((uint8_t)jpd->type[0] != ISO_VD_END) {
+
+ /*
+ * If Joliet UCS escape sequence found, we may be wrong
+ */
+
+ if (jpd->unused3[0] == '%' &&
+ jpd->unused3[1] == '/' &&
+ (jpd->unused3[3] == '\0' ||
+ jpd->unused3[3] == ' ') &&
+ (jpd->unused3[2] == '@' ||
+ jpd->unused3[2] == 'C' ||
+ jpd->unused3[2] == 'E')) {
+
+ if (jpd->version[0] != 1)
+ break;
+ }
+
+ block++;
+ seek_io(fd, block * ISOFS_BLOCK_SIZE);
+ read_io(fd, jpd, sizeof (*jpd));
+ }
+
+ ucs_level = 0;
+ if (((unsigned char) jpd->type[0] == ISO_VD_END)) {
+ memcpy(jpd, &ipd, sizeof (ipd));
+ } else {
+ switch (jpd->unused3[2]) {
+ case '@':
+ ucs_level = 1;
+ break;
+ case 'C':
+ ucs_level = 2;
+ break;
+ case 'E':
+ ucs_level = 3;
+ break;
+ }
+
+ if (ucs_level && jpd->unused3[3] == ' ')
+ printk("Warning: Joliet escape sequence uses illegal space at offset 3\n");
+ }
+
+ volume = (iso9660_VOLUME*)malloc(sizeof(iso9660_VOLUME));
+ if (volume == NULL)
+ return NULL;
+
+ volume->descriptor = jpd;
+ volume->ucs_level = ucs_level;
+ volume->fd = fd;
+
+ return volume;
+}
+
+int iso9660_umount(iso9660_VOLUME* volume)
+{
+ if (volume == NULL)
+ return -1;
+ free(volume->descriptor);
+ free(volume);
+ return 0;
+}
+
+int iso9660_probe(int fd, long long offset)
+{
+ struct iso_primary_descriptor ipd;
+
+ seek_io(fd, 16 * ISOFS_BLOCK_SIZE + offset);
+ read_io(fd, &ipd, sizeof (ipd));
+
+ if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+ (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+ (ipd.version[0] != 1)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+struct iso_directory_record *iso9660_get_root_node(iso9660_VOLUME* volume)
+{
+ return (struct iso_directory_record *)volume->descriptor->root_directory_record;
+}
diff --git a/roms/openbios/fs/iso9660/iso9660_open.c b/roms/openbios/fs/iso9660/iso9660_open.c
new file mode 100644
index 00000000..77c271f0
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_open.c
@@ -0,0 +1,39 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libiso9660.h"
+
+iso9660_FILE* iso9660_open(iso9660_VOLUME *volume, const char* pathname)
+{
+ struct iso_directory_record *root;
+ struct iso_directory_record *idr;
+ iso9660_FILE *file;
+
+ root = iso9660_get_root_node(volume);
+ if (root == NULL)
+ return NULL;
+
+ idr = iso9660_get_node(volume, root, pathname);
+ if (idr == NULL)
+ return NULL;
+
+ file = (iso9660_FILE*)malloc(sizeof(iso9660_FILE));
+ if (file == NULL)
+ return NULL;
+
+ file->base = isonum_733((char *)idr->extent);
+ file->size = isonum_733((char *)idr->size);
+ file->offset = 0;
+ file->current = -1;
+ file->volume = volume;
+ file->path = strdup(pathname);
+
+ free(idr);
+
+ return file;
+}
diff --git a/roms/openbios/fs/iso9660/iso9660_opendir.c b/roms/openbios/fs/iso9660/iso9660_opendir.c
new file mode 100644
index 00000000..49eab4b4
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_opendir.c
@@ -0,0 +1,133 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libiso9660.h"
+
+static inline int iso9660_is_directory(struct iso_directory_record * idr)
+{
+ return ((idr->flags[0] & 2) != 0);
+}
+
+static iso9660_DIR* iso9660_opendir_node(iso9660_VOLUME *volume, struct iso_directory_record *node)
+{
+ iso9660_DIR *dir;
+
+ dir = (iso9660_DIR*)malloc(sizeof(iso9660_DIR));
+ if (dir == NULL)
+ return NULL;
+
+ dir->extent = isonum_733((char *)node->extent);
+ dir->len = isonum_733((char *)node->size);
+ dir->index = sizeof (dir->buffer);
+ dir->volume = volume;
+
+ return dir;
+}
+
+static struct iso_directory_record* idr_new(struct iso_directory_record* idr)
+{
+ struct iso_directory_record* result;
+ int size = sizeof(*idr) + (int)idr->name_len[0];
+
+ result = (struct iso_directory_record*)malloc(size);
+ memcpy(result, idr, size);
+
+ return result;
+}
+
+static struct iso_directory_record * seek_name(iso9660_VOLUME *volume,
+ struct iso_directory_record *idr,
+ char *name)
+{
+ struct iso_directory_record *result;
+ char name_buf[256];
+ iso9660_DIR *dir;
+
+ dir = iso9660_opendir_node(volume, idr);
+ if (dir == NULL)
+ return NULL;
+
+ while ((idr = iso9660_readdir(dir)) != NULL)
+ {
+ iso9660_name(volume, idr, name_buf);
+ if (strcasecmp(name, name_buf) == 0)
+ {
+ result = idr_new(idr);
+ iso9660_closedir(dir);
+ return result;
+ }
+ }
+ iso9660_closedir(dir);
+ return NULL;
+}
+
+struct iso_directory_record* iso9660_get_node(
+ iso9660_VOLUME *volume,
+ struct iso_directory_record *dirnode,
+ const char *path)
+{
+ struct iso_directory_record* result;
+ struct iso_directory_record* current;
+ char name[256];
+ int i;
+
+ current = idr_new(dirnode);
+ while(1)
+ {
+ /* ignore head '\' */
+
+ while (*path && *path == '\\')
+ path++;
+
+ if (*path == 0)
+ break;
+
+ /* extract first path component */
+
+ i = 0;
+ while (*path && *path != '\\')
+ name[i++] = *path++;
+ name[i] = 0;
+
+ /* seek first component in current directory */
+
+ result = seek_name(volume, current, name);
+ if (result == NULL)
+ return NULL;
+
+ free(current);
+ current = result;
+ }
+ return current;
+}
+
+iso9660_DIR* iso9660_opendir(iso9660_VOLUME *volume, const char *name)
+{
+ iso9660_DIR *dir;
+ struct iso_directory_record *node;
+
+ node = iso9660_get_root_node((iso9660_VOLUME*)volume);
+ if (node == NULL)
+ return NULL;
+
+ node = iso9660_get_node((iso9660_VOLUME*)volume, node, name);
+ if (node == NULL)
+ return NULL;
+ if (!iso9660_is_directory(node)) {
+ free(node);
+ return NULL;
+ }
+
+ dir = iso9660_opendir_node((iso9660_VOLUME*)volume, node);
+
+ free(node);
+
+ dir->volume = (iso9660_VOLUME*)volume;
+
+ return dir;
+}
diff --git a/roms/openbios/fs/iso9660/iso9660_read.c b/roms/openbios/fs/iso9660/iso9660_read.c
new file mode 100644
index 00000000..22cc463f
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_read.c
@@ -0,0 +1,74 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libiso9660.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+
+size_t iso9660_read(iso9660_FILE *_file, char *buf, size_t count)
+{
+ iso9660_FILE *file = (iso9660_FILE*)_file;
+ size_t read = 0;
+
+ if ( count > (file->size - file->offset) )
+ count = file->size - file->offset;
+
+ while (count > 0)
+ {
+ size_t part;
+ int offset_extent;
+ int offset_index;
+
+ offset_extent = file->base +
+ (file->offset / ISOFS_BLOCK_SIZE);
+ offset_index = file->offset % ISOFS_BLOCK_SIZE;
+
+ if (file->current != offset_extent)
+ {
+ if ( (offset_index == 0) &&
+ (count >= ISOFS_BLOCK_SIZE) )
+ {
+ /* direct i/o */
+
+ int extents_nb;
+
+ extents_nb = count / ISOFS_BLOCK_SIZE;
+
+ part = extents_nb * ISOFS_BLOCK_SIZE;
+
+ seek_io(file->volume->fd,
+ offset_extent * ISOFS_BLOCK_SIZE);
+ read_io(file->volume->fd, buf + read, part);
+
+ file->offset += part;
+ count -= part;
+ read += part;
+
+ continue;
+ }
+
+ file->current = offset_extent;
+ seek_io(file->volume->fd,
+ offset_extent * ISOFS_BLOCK_SIZE);
+ read_io(file->volume->fd, file->buffer,
+ ISOFS_BLOCK_SIZE);
+ }
+
+ part = ISOFS_BLOCK_SIZE - offset_index;
+ if (count < part)
+ part = count;
+
+ memcpy(buf + read, file->buffer + offset_index, part);
+
+ file->offset += part;
+ count -= part;
+ read += part;
+ }
+
+ return read;
+}
diff --git a/roms/openbios/fs/iso9660/iso9660_readdir.c b/roms/openbios/fs/iso9660/iso9660_readdir.c
new file mode 100644
index 00000000..003ffb20
--- /dev/null
+++ b/roms/openbios/fs/iso9660/iso9660_readdir.c
@@ -0,0 +1,50 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#include "libiso9660.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+
+#define offsetof(t,m) ((long)&(((t *)0)->m))
+
+static void read_extent(iso9660_DIR *dir)
+{
+ seek_io(dir->volume->fd, dir->extent * ISOFS_BLOCK_SIZE);
+ read_io(dir->volume->fd, dir->buffer, ISOFS_BLOCK_SIZE);
+
+ dir->len -= ISOFS_BLOCK_SIZE;
+ dir->extent ++;
+ dir->index = 0;
+}
+
+struct iso_directory_record *iso9660_readdir(iso9660_DIR *dir)
+{
+ struct iso_directory_record *idr;
+
+ if (dir->index >
+ ISOFS_BLOCK_SIZE - offsetof(struct iso_directory_record, name[0]))
+ {
+ if (dir->len <= 0)
+ return NULL;
+
+ read_extent(dir);
+ }
+
+ idr = (struct iso_directory_record *) &dir->buffer[dir->index];
+ if (idr->length[0] == 0) {
+ if (dir->len <= 0)
+ return NULL;
+
+ read_extent(dir);
+ idr = (struct iso_directory_record *) &dir->buffer[dir->index];
+ }
+
+ dir->index += dir->buffer[dir->index];
+
+ return idr;
+}
diff --git a/roms/openbios/fs/iso9660/libiso9660.h b/roms/openbios/fs/iso9660/libiso9660.h
new file mode 100644
index 00000000..8a5b4801
--- /dev/null
+++ b/roms/openbios/fs/iso9660/libiso9660.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ */
+
+#ifndef __LIBISO9660_H__
+#define __LIBISO9660_H__
+
+#include "config.h"
+#include "iso9660.h"
+
+extern iso9660_VOLUME* iso9660_mount(int fd);
+extern int iso9660_umount(iso9660_VOLUME *volume);
+extern int iso9660_probe(int fd, long long offs);
+extern iso9660_DIR* iso9660_opendir(iso9660_VOLUME *, const char *name);
+extern iso9660_FILE* iso9660_open(iso9660_VOLUME *, const char *pathname);
+extern int iso9660_closedir(iso9660_DIR *dir);
+extern struct iso_directory_record *iso9660_readdir(iso9660_DIR *dir);
+extern size_t iso9660_read(iso9660_FILE *file, char *buf, size_t count);
+extern void iso9660_close(iso9660_FILE *file);
+extern int iso9660_lseek(iso9660_FILE *file, long offset, int whence);
+extern void iso9660_name(iso9660_VOLUME *volume, struct iso_directory_record * idr, char *buffer);
+
+#endif /* __LIBISO9660_H__ */
diff --git a/roms/openbios/fs/os.h b/roms/openbios/fs/os.h
new file mode 100644
index 00000000..b0375f7e
--- /dev/null
+++ b/roms/openbios/fs/os.h
@@ -0,0 +1,57 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * Copyright (C) 1996-1998, 2003 Robert Leslie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: os.h,v 1.1.1.1 2000/07/25 10:33:40 kkaempf Exp $
+ */
+
+#ifndef _H_OS
+#define _H_OS
+
+/*
+ * NAME: os->same()
+ * DESCRIPTION: return 1 iff path is same as the open descriptor
+ */
+int os_same( int fd1, int fd2 );
+
+/*
+ * NAME: os->seek()
+ * DESCRIPTION: set a descriptor's seek pointer (offset in blocks)
+ */
+unsigned long os_seek( int fd, unsigned long offset, int blksize_bits);
+
+/*
+ * NAME: os->read()
+ * DESCRIPTION: read blocks from an open descriptor
+ */
+unsigned long os_read( int fd, void *buf, unsigned long len, int blksize_bits);
+
+/*
+ * NAME: os->write()
+ * DESCRIPTION: write blocks to an open descriptor
+ */
+unsigned long os_write( int fd, const void *buf, unsigned long len, int blksize_bits);
+
+/*
+ * NAME: os->seek_offset()
+ * DESCRIPTION: set a descriptor's seek pointer (offset in bytes)
+ */
+void os_seek_offset( int fd, long long offset );
+
+
+#endif /* _H_OS */
diff --git a/roms/openbios/include/arch/amd64/elf.h b/roms/openbios/include/arch/amd64/elf.h
new file mode 100644
index 00000000..e391c62b
--- /dev/null
+++ b/roms/openbios/include/arch/amd64/elf.h
@@ -0,0 +1,6 @@
+/* for now we're a 32bit architecture */
+#define ARCH_ELF_CLASS ELFCLASS32
+#define ARCH_ELF_DATA ELFDATA2LSB
+#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_386 || (x)==EM_486)
+typedef Elf32_Ehdr Elf_ehdr;
+typedef Elf32_Phdr Elf_phdr;
diff --git a/roms/openbios/include/arch/amd64/io.h b/roms/openbios/include/arch/amd64/io.h
new file mode 100644
index 00000000..9be1cb85
--- /dev/null
+++ b/roms/openbios/include/arch/amd64/io.h
@@ -0,0 +1,71 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+extern char _start, _end;
+extern unsigned long virt_offset;
+
+#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset))
+#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset)
+
+#ifndef BOOTSTRAP
+
+#define __SLOW_DOWN_IO "outb %%al,$0x80;"
+static inline void slow_down_io(void)
+{
+ __asm__ __volatile__(
+ __SLOW_DOWN_IO
+#ifdef REALLY_SLOW_IO
+ __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+ : : );
+}
+
+#define BUILDIO(bwl,bw,type) \
+static inline void out##bwl(unsigned type value, int port) { \
+ __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \
+} \
+static inline unsigned type in##bwl(int port) { \
+ unsigned type value; \
+ __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \
+ return value; \
+} \
+static inline void out##bwl##_p(unsigned type value, int port) { \
+ out##bwl(value, port); \
+ slow_down_io(); \
+} \
+static inline unsigned type in##bwl##_p(int port) { \
+ unsigned type value = in##bwl(port); \
+ slow_down_io(); \
+ return value; \
+} \
+static inline void outs##bwl(int port, const void *addr, unsigned long count) { \
+ __asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \
+} \
+static inline void ins##bwl(int port, void *addr, unsigned long count) { \
+ __asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \
+}
+
+BUILDIO(b,b,char)
+BUILDIO(w,w,short)
+BUILDIO(l,,int)
+
+#else /* BOOTSTRAP */
+#ifdef FCOMPILER
+#define inb(reg) ((u8)0xff)
+#define inw(reg) ((u16)0xffff)
+#define inl(reg) ((u32)0xffffffff)
+#define outb(reg, val) do{} while(0)
+#define outw(reg, val) do{} while(0)
+#define outl(reg, val) do{} while(0)
+#else
+extern u8 inb(u32 reg);
+extern u16 inw(u32 reg);
+extern u32 inl(u32 reg);
+extern void insw(u32 reg, void *addr, unsigned long count);
+extern void outb(u32 reg, u8 val);
+extern void outw(u32 reg, u16 val);
+extern void outl(u32 reg, u32 val);
+extern void outsw(u32 reg, const void *addr, unsigned long count);
+#endif
+#endif
+#endif
diff --git a/roms/openbios/include/arch/amd64/pci.h b/roms/openbios/include/arch/amd64/pci.h
new file mode 100644
index 00000000..3e88e150
--- /dev/null
+++ b/roms/openbios/include/arch/amd64/pci.h
@@ -0,0 +1,66 @@
+#ifndef AMD64_PCI_H
+#define AMD64_PCI_H
+
+#include "asm/io.h"
+
+#if !(defined(PCI_CONFIG_1) || defined(PCI_CONFIG_2))
+#define PCI_CONFIG_1 1 /* default */
+#endif
+
+#ifdef PCI_CONFIG_1
+
+/* PCI Configuration Mechanism #1 */
+
+/* Have pci_addr in the same format as the values written to 0xcf8
+ * so register accesses can be made easy. */
+#define PCI_ADDR(bus, dev, fn) \
+ ((pci_addr) (0x80000000u \
+ | (uint32_t) (bus) << 16 \
+ | (uint32_t) (dev) << 11 \
+ | (uint32_t) (fn) << 8))
+
+#define PCI_BUS(pcidev) ((uint8_t) ((pcidev) >> 16))
+#define PCI_DEV(pcidev) ((uint8_t) ((pcidev) >> 11) & 0x1f)
+#define PCI_FN(pcidev) ((uint8_t) ((pcidev) >> 8) & 7)
+
+static inline uint8_t pci_config_read8(pci_addr dev, uint8_t reg)
+{
+ outl(dev | (reg & ~3), 0xcf8);
+ return inb(0xcfc | (reg & 3));
+}
+
+static inline uint16_t pci_config_read16(pci_addr dev, uint8_t reg)
+{
+ outl(dev | (reg & ~3), 0xcf8);
+ return inw(0xcfc | (reg & 2));
+}
+
+static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg)
+{
+ outl(dev | reg, 0xcf8);
+ return inl(0xcfc | reg);
+}
+
+static inline void pci_config_write8(pci_addr dev, uint8_t reg, uint8_t val)
+{
+ outl(dev | (reg & ~3), 0xcf8);
+ outb(val, 0xcfc | (reg & 3));
+}
+
+static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val)
+{
+ outl(dev | (reg & ~3), 0xcf8);
+ outw(val, 0xcfc | (reg & 2));
+}
+
+static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val)
+{
+ outl(dev | reg, 0xcf8);
+ outl(val, 0xcfc);
+}
+
+#else /* !PCI_CONFIG_1 */
+#error PCI Configuration Mechanism is not specified or implemented
+#endif
+
+#endif /* AMD64_PCI_H */
diff --git a/roms/openbios/include/arch/amd64/types.h b/roms/openbios/include/arch/amd64/types.h
new file mode 100644
index 00000000..5b146cad
--- /dev/null
+++ b/roms/openbios/include/arch/amd64/types.h
@@ -0,0 +1,67 @@
+/* tag: data types for forth engine
+ *
+ * This file is autogenerated by types.sh. Do not edit!
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __TYPES_H
+#define __TYPES_H
+
+#include <inttypes.h>
+
+/* endianess */
+#include "autoconf.h"
+
+/* physical address */
+
+typedef uint64_t phys_addr_t;
+
+#define FMT_plx "%016" PRIx64
+
+/* cell based types */
+
+typedef int64_t cell;
+typedef uint64_t ucell;
+typedef __int128_t dcell;
+typedef __uint128_t ducell;
+
+#define FMT_cell "%" PRId64
+#define FMT_ucellx "%016" PRIx64
+#define FMT_ucell "%" PRIu64
+
+typedef int64_t prom_arg_t;
+typedef uint64_t prom_uarg_t;
+
+#define PRIdPROMARG PRId64
+#define PRIuPROMARG PRIu64
+#define PRIxPROMARG PRIx64
+#define FMT_prom_arg "%" PRIdPROMARG
+#define FMT_prom_uarg "%" PRIuPROMARG
+#define FMT_prom_uargx "%016" PRIxPROMARG
+
+#define FMT_elf "%#x"
+
+#define bitspercell (sizeof(cell)<<3)
+#define bitsperdcell (sizeof(dcell)<<3)
+
+#define BITS 64
+
+#define PAGE_SHIFT 12
+
+/* size named types */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long u64;
+
+typedef char s8;
+typedef short s16;
+typedef int s32;
+typedef long s64;
+
+#endif
diff --git a/roms/openbios/include/arch/common/a.out.h b/roms/openbios/include/arch/common/a.out.h
new file mode 100644
index 00000000..350babd7
--- /dev/null
+++ b/roms/openbios/include/arch/common/a.out.h
@@ -0,0 +1,271 @@
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+#include "asm/a.out.h"
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+enum machine_type {
+#if defined (M_OLDSUN2)
+ M__OLDSUN2 = M_OLDSUN2,
+#else
+ M_OLDSUN2 = 0,
+#endif
+#if defined (M_68010)
+ M__68010 = M_68010,
+#else
+ M_68010 = 1,
+#endif
+#if defined (M_68020)
+ M__68020 = M_68020,
+#else
+ M_68020 = 2,
+#endif
+#if defined (M_SPARC)
+ M__SPARC = M_SPARC,
+#else
+ M_SPARC = 3,
+#endif
+ /* skip a bunch so we don't run into any of sun's numbers */
+ M_386 = 100,
+ M_MIPS1 = 151, /* MIPS R3000/R3000 binary */
+ M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
+};
+
+#if !defined (N_MAGIC)
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#endif
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+/* Code indicating object file or impure executable. */
+#define OMAGIC 0407
+/* Code indicating pure executable. */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable. */
+#define ZMAGIC 0413
+/* This indicates a demand-paged executable with the header in the text.
+ The first page is unmapped to help trap NULL pointer references */
+#define QMAGIC 0314
+
+/* Code indicating core file. */
+#define CMAGIC 0421
+
+#if !defined (N_BADMAG)
+#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC \
+ && N_MAGIC(x) != QMAGIC)
+#endif
+
+#define _N_HDROFF(x) (1024 - sizeof (struct exec))
+
+#if !defined (N_TXTOFF)
+#define N_TXTOFF(x) \
+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
+ (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
+#endif
+
+#if !defined (N_DATOFF)
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+#endif
+
+#if !defined (N_TRELOFF)
+#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+#endif
+
+#if !defined (N_DRELOFF)
+#define N_DRELOFF(x) (N_TRELOFF(x) + N_TRSIZE(x))
+#endif
+
+#if !defined (N_SYMOFF)
+#define N_SYMOFF(x) (N_DRELOFF(x) + N_DRSIZE(x))
+#endif
+
+#if !defined (N_STROFF)
+#define N_STROFF(x) (N_SYMOFF(x) + N_SYMSIZE(x))
+#endif
+
+/* Address of text segment in memory after it is loaded. */
+#if !defined (N_TXTADDR)
+#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
+#endif
+
+/* Address of data segment in memory after it is loaded.
+ Note that it is up to you to define SEGMENT_SIZE
+ on machines not listed here. */
+#if defined(vax) || defined(hp300) || defined(pyr)
+#define SEGMENT_SIZE page_size
+#endif
+#ifdef sony
+#define SEGMENT_SIZE 0x2000
+#endif /* Sony. */
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+#if defined(m68k) && defined(PORTAR)
+#define PAGE_SIZE 0x400
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+
+#if !defined(SEGMENT_SIZE)
+#ifdef linux
+#if defined(__i386__) || defined(__mc68000__)
+#define SEGMENT_SIZE 1024
+#elif defined(__sparc__)
+#define SEGMENT_SIZE 0x2000
+#else
+#if defined(PAGE_SIZE)
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+#endif
+#endif
+#endif
+
+#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+
+#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
+ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+#endif
+
+/* Address of bss segment in memory after it is loaded. */
+#if !defined (N_BSSADDR)
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+#endif
+
+#if !defined (N_NLIST_DECLARED)
+struct nlist {
+ union {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx;
+ } n_un;
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ unsigned long n_value;
+};
+#endif /* no N_NLIST_DECLARED. */
+
+#if !defined (N_UNDF)
+#define N_UNDF 0
+#endif
+#if !defined (N_ABS)
+#define N_ABS 2
+#endif
+#if !defined (N_TEXT)
+#define N_TEXT 4
+#endif
+#if !defined (N_DATA)
+#define N_DATA 6
+#endif
+#if !defined (N_BSS)
+#define N_BSS 8
+#endif
+#if !defined (N_FN)
+#define N_FN 15
+#endif
+
+#if !defined (N_EXT)
+#define N_EXT 1
+#endif
+#if !defined (N_TYPE)
+#define N_TYPE 036
+#endif
+#if !defined (N_STAB)
+#define N_STAB 0340
+#endif
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition. */
+#define N_INDR 0xa
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ element's value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+#if !defined (N_RELOCATION_INFO_DECLARED)
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+struct relocation_info
+{
+ /* Address (within segment) to be relocated. */
+ int r_address;
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in file's the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* Four bits that aren't used, but when writing an object file
+ it is desirable to clear them. */
+#ifdef NS32K
+ unsigned r_bsr:1;
+ unsigned r_disp:1;
+ unsigned r_pad:2;
+#else
+ unsigned int r_pad:4;
+#endif
+};
+#endif /* no N_RELOCATION_INFO_DECLARED. */
+
+
+#endif /* __A_OUT_GNU_H__ */
diff --git a/roms/openbios/include/arch/common/elf.h b/roms/openbios/include/arch/common/elf.h
new file mode 100644
index 00000000..f2cca558
--- /dev/null
+++ b/roms/openbios/include/arch/common/elf.h
@@ -0,0 +1,227 @@
+#ifndef ELF_H
+#define ELF_H
+
+#define EI_NIDENT 16 /* Size of e_ident array. */
+
+/* Values for e_type. */
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+
+/* Values for e_machine (architecute). */
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386+ */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_486 6 /* Perhaps disused */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 big-endian */
+#define EM_S370 9 /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
+
+#define EM_PARISC 15 /* HPPA */
+#define EM_VPP500 17 /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+#define EM_960 19 /* Intel 80960 */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC 64-bit */
+#define EM_S390 22 /* IBM S390 */
+
+#define EM_V800 36 /* NEC V800 series */
+#define EM_FR20 37 /* Fujitsu FR20 */
+#define EM_RH32 38 /* TRW RH-32 */
+#define EM_RCE 39 /* Motorola RCE */
+#define EM_ARM 40 /* ARM */
+#define EM_FAKE_ALPHA 41 /* Digital Alpha */
+#define EM_SH 42 /* Hitachi SH */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_TRICORE 44 /* Siemens Tricore */
+#define EM_ARC 45 /* Argonaut RISC Core */
+#define EM_H8_300 46 /* Hitachi H8/300 */
+#define EM_H8_300H 47 /* Hitachi H8/300H */
+#define EM_H8S 48 /* Hitachi H8S */
+#define EM_H8_500 49 /* Hitachi H8/500 */
+#define EM_IA_64 50 /* Intel Merced */
+#define EM_MIPS_X 51 /* Stanford MIPS-X */
+#define EM_COLDFIRE 52 /* Motorola Coldfire */
+#define EM_68HC12 53 /* Motorola M68HC12 */
+#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP 55 /* Siemens PCP */
+#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor */
+#define EM_STARCORE 58 /* Motorola Start*Core processor */
+#define EM_ME16 59 /* Toyota ME16 processor */
+#define EM_ST100 60 /* STMicroelectronic ST100 processor */
+#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64 62 /* AMD x86-64 architecture */
+#define EM_PDSP 63 /* Sony DSP Processor */
+
+#define EM_FX66 66 /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
+#define EM_SVX 73 /* Silicon Graphics SVx */
+#define EM_AT19 74 /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX 75 /* Digital VAX */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY 81 /* Harvard University machine-independent object files */
+#define EM_PRISM 82 /* SiTera Prism */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30 84 /* Fujitsu FR30 */
+#define EM_D10V 85 /* Mitsubishi D10V */
+#define EM_D30V 86 /* Mitsubishi D30V */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Mitsubishi M32R */
+#define EM_MN10300 89 /* Matsushita MN10300 */
+#define EM_MN10200 90 /* Matsushita MN10200 */
+#define EM_PJ 91 /* picoJava */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_NUM 95
+
+/* Values for p_type. */
+#define PT_NULL 0 /* Unused entry. */
+#define PT_LOAD 1 /* Loadable segment. */
+#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
+#define PT_INTERP 3 /* Pathname of interpreter. */
+#define PT_NOTE 4 /* Auxiliary information. */
+#define PT_SHLIB 5 /* Reserved (not used). */
+#define PT_PHDR 6 /* Location of program header itself. */
+
+/* Values for p_flags. */
+#define PF_X 0x1 /* Executable. */
+#define PF_W 0x2 /* Writable. */
+#define PF_R 0x4 /* Readable. */
+
+
+#define ELF_PROGRAM_RETURNS_BIT 0x8000000 /* e_flags bit 31 */
+
+#define EI_MAG0 0
+#define ELFMAG0 0x7f
+
+#define EI_MAG1 1
+#define ELFMAG1 'E'
+
+#define EI_MAG2 2
+#define ELFMAG2 'L'
+
+#define EI_MAG3 3
+#define ELFMAG3 'F'
+
+#define ELFMAG "\177ELF"
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+
+#define EI_DATA 5 /* Data encodeing byte index */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement little endian */
+#define ELFDATA2MSB 2 /* 2's complement big endian */
+
+#define EI_VERSION 6 /* File version byte index */
+ /* Value must be EV_CURRENT */
+
+#define EV_NONE 0 /* Invalid ELF Version */
+#define EV_CURRENT 1 /* Current version */
+
+#define ELF32_PHDR_SIZE (8*4) /* Size of an elf program header */
+
+#ifndef __ASSEMBLY__
+#include "asm/types.h"
+/*
+ * ELF definitions common to all 32-bit architectures.
+ */
+
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Off;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Word;
+typedef uint32_t Elf32_Size;
+
+typedef uint64_t Elf64_Addr;
+typedef uint16_t Elf64_Half;
+typedef uint64_t Elf64_Off;
+typedef int32_t Elf64_Sword;
+typedef uint32_t Elf64_Word;
+typedef uint64_t Elf64_Size;
+
+/*
+ * ELF header.
+ */
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf32_Half e_type; /* File type. */
+ Elf32_Half e_machine; /* Machine architecture. */
+ Elf32_Word e_version; /* ELF format version. */
+ Elf32_Addr e_entry; /* Entry point. */
+ Elf32_Off e_phoff; /* Program header file offset. */
+ Elf32_Off e_shoff; /* Section header file offset. */
+ Elf32_Word e_flags; /* Architecture-specific flags. */
+ Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf32_Half e_phentsize; /* Size of program header entry. */
+ Elf32_Half e_phnum; /* Number of program header entries. */
+ Elf32_Half e_shentsize; /* Size of section header entry. */
+ Elf32_Half e_shnum; /* Number of section header entries. */
+ Elf32_Half e_shstrndx; /* Section name strings section. */
+} Elf32_Ehdr;
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf64_Half e_type; /* File type. */
+ Elf64_Half e_machine; /* Machine architecture. */
+ Elf64_Word e_version; /* ELF format version. */
+ Elf64_Addr e_entry; /* Entry point. */
+ Elf64_Off e_phoff; /* Program header file offset. */
+ Elf64_Off e_shoff; /* Section header file offset. */
+ Elf64_Word e_flags; /* Architecture-specific flags. */
+ Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf64_Half e_phentsize; /* Size of program header entry. */
+ Elf64_Half e_phnum; /* Number of program header entries. */
+ Elf64_Half e_shentsize; /* Size of section header entry. */
+ Elf64_Half e_shnum; /* Number of section header entries. */
+ Elf64_Half e_shstrndx; /* Section name strings section. */
+} Elf64_Ehdr;
+
+/*
+ * Program header.
+ */
+typedef struct {
+ Elf32_Word p_type; /* Entry type. */
+ Elf32_Off p_offset; /* File offset of contents. */
+ Elf32_Addr p_vaddr; /* Virtual address (not used). */
+ Elf32_Addr p_paddr; /* Physical address. */
+ Elf32_Size p_filesz; /* Size of contents in file. */
+ Elf32_Size p_memsz; /* Size of contents in memory. */
+ Elf32_Word p_flags; /* Access permission flags. */
+ Elf32_Size p_align; /* Alignment in memory and file. */
+} Elf32_Phdr;
+
+typedef struct {
+ Elf64_Word p_type; /* Entry type. */
+ Elf64_Word p_flags; /* Access permission flags. */
+ Elf64_Off p_offset; /* File offset of contents. */
+ Elf64_Addr p_vaddr; /* Virtual address (not used). */
+ Elf64_Addr p_paddr; /* Physical address. */
+ Elf64_Size p_filesz; /* Size of contents in file. */
+ Elf64_Size p_memsz; /* Size of contents in memory. */
+ Elf64_Size p_align; /* Alignment in memory and file. */
+} Elf64_Phdr;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* ELF_H */
diff --git a/roms/openbios/include/arch/common/elf_boot.h b/roms/openbios/include/arch/common/elf_boot.h
new file mode 100644
index 00000000..18487f6b
--- /dev/null
+++ b/roms/openbios/include/arch/common/elf_boot.h
@@ -0,0 +1,105 @@
+#ifndef ELF_BOOT_H
+#define ELF_BOOT_H
+
+
+/* This defines the structure of a table of parameters useful for ELF
+ * bootable images. These parameters are all passed and generated
+ * by the bootloader to the booted image. For simplicity and
+ * consistency the Elf Note format is reused.
+ *
+ * All of the information must be Position Independent Data.
+ * That is it must be safe to relocate the whole ELF boot parameter
+ * block without changing the meaning or correctnes of the data.
+ * Additionally it must be safe to permute the order of the ELF notes
+ * to any possible permutation without changing the meaning or correctness
+ * of the data.
+ *
+ */
+
+#define ELF_BHDR_MAGIC 0x0E1FB007
+
+#ifndef __ASSEMBLY__
+typedef uint16_t Elf_Half;
+typedef uint32_t Elf_Word;
+
+/*
+ * Elf boot notes...
+ */
+
+typedef struct Elf_Bhdr
+{
+ Elf_Word b_signature; /* "0x0E1FB007" */
+ Elf_Word b_size;
+ Elf_Half b_checksum;
+ Elf_Half b_records;
+} Elf_Bhdr;
+
+/*
+ * ELF Notes.
+ */
+
+typedef struct Elf_Nhdr
+{
+ Elf_Word n_namesz; /* Length of the note's name. */
+ Elf_Word n_descsz; /* Length of the note's descriptor. */
+ Elf_Word n_type; /* Type of the note. */
+} Elf_Nhdr;
+
+#endif /* __ASSEMBLY__ */
+
+/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */
+#define ELF_NOTE_BOOT "ELFBoot"
+
+#define EIN_PROGRAM_NAME 0x00000001
+/* The program in this ELF file */
+#define EIN_PROGRAM_VERSION 0x00000002
+/* The version of the program in this ELF file */
+#define EIN_PROGRAM_CHECKSUM 0x00000003
+/* ip style checksum of the memory image. */
+
+
+/* Linux image notes for booting... The name for all of these is Linux */
+
+#define LIN_COMMAND_LINE 0x00000001
+/* The command line to pass to the loaded kernel. */
+#define LIN_ROOT_DEV 0x00000002
+/* The root dev to pass to the loaded kernel. */
+#define LIN_RAMDISK_FLAGS 0x00000003
+/* Various old ramdisk flags */
+#define LIN_INITRD_START 0x00000004
+/* Start of the ramdisk in bytes */
+#define LIN_INITRD_SIZE 0x00000005
+/* Size of the ramdisk in bytes */
+
+/* Notes that are passed to a loaded image */
+/* For the standard elf boot notes n_namesz must be zero */
+#define EBN_FIRMWARE_TYPE 0x00000001
+/* ASCIZ name of the platform firmware. */
+#define EBN_BOOTLOADER_NAME 0x00000002
+/* This specifies just the ASCIZ name of the bootloader */
+#define EBN_BOOTLOADER_VERSION 0x00000003
+/* This specifies the version of the bootloader as an ASCIZ string */
+#define EBN_COMMAND_LINE 0x00000004
+/* This specifies a command line that can be set by user interaction,
+ * and is provided as a free form ASCIZ string to the loaded image.
+ */
+#define EBN_NOP 0x00000005
+/* A note nop note has no meaning, useful for inserting explicit padding */
+#define EBN_LOADED_IMAGE 0x00000006
+/* An ASCIZ string naming the loaded image */
+
+
+/* Etherboot specific notes */
+#define EB_PARAM_NOTE "Etherboot"
+#define EB_IA64_SYSTAB 0x00000001
+#define EB_IA64_MEMMAP 0x00000002
+#define EB_IA64_FPSWA 0x00000003
+#define EB_IA64_CONINFO 0x00000004
+#define EB_BOOTP_DATA 0x00000005
+#define EB_HEADER 0x00000006
+#define EB_IA64_IMAGE_HANDLE 0x00000007
+#define EB_I386_MEMMAP 0x00000008
+
+extern const struct elf_image_note elf_image_notes;
+
+#endif /* ELF_BOOT_H */
diff --git a/roms/openbios/include/arch/common/fw_cfg.h b/roms/openbios/include/arch/common/fw_cfg.h
new file mode 100644
index 00000000..df44c2e8
--- /dev/null
+++ b/roms/openbios/include/arch/common/fw_cfg.h
@@ -0,0 +1,90 @@
+#ifndef FW_CFG_H
+#define FW_CFG_H
+
+#define FW_CFG_SIGNATURE 0x00
+#define FW_CFG_ID 0x01
+#define FW_CFG_UUID 0x02
+#define FW_CFG_RAM_SIZE 0x03
+#define FW_CFG_NOGRAPHIC 0x04
+#define FW_CFG_NB_CPUS 0x05
+#define FW_CFG_MACHINE_ID 0x06
+#define FW_CFG_KERNEL_ADDR 0x07
+#define FW_CFG_KERNEL_SIZE 0x08
+#define FW_CFG_KERNEL_CMDLINE 0x09
+#define FW_CFG_INITRD_ADDR 0x0a
+#define FW_CFG_INITRD_SIZE 0x0b
+#define FW_CFG_BOOT_DEVICE 0x0c
+#define FW_CFG_NUMA 0x0d
+#define FW_CFG_BOOT_MENU 0x0e
+#define FW_CFG_MAX_CPUS 0x0f
+#define FW_CFG_KERNEL_ENTRY 0x10
+#define FW_CFG_KERNEL_DATA 0x11
+#define FW_CFG_INITRD_DATA 0x12
+#define FW_CFG_CMDLINE_ADDR 0x13
+#define FW_CFG_CMDLINE_SIZE 0x14
+#define FW_CFG_CMDLINE_DATA 0x15
+#define FW_CFG_SETUP_ADDR 0x16
+#define FW_CFG_SETUP_SIZE 0x17
+#define FW_CFG_SETUP_DATA 0x18
+#define FW_CFG_FILE_DIR 0x19
+
+#define FW_CFG_FILE_FIRST 0x20
+#define FW_CFG_FILE_SLOTS 0x10
+#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST+FW_CFG_FILE_SLOTS)
+
+#define FW_CFG_WRITE_CHANNEL 0x4000
+#define FW_CFG_ARCH_LOCAL 0x8000
+#define FW_CFG_ENTRY_MASK ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)
+
+#define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
+#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
+#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
+#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03)
+#define FW_CFG_PPC_CLOCKFREQ (FW_CFG_ARCH_LOCAL + 0x04)
+#define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05)
+#define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06)
+#define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07)
+#define FW_CFG_PPC_NVRAM_ADDR (FW_CFG_ARCH_LOCAL + 0x08)
+#define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09)
+#define FW_CFG_PPC_NVRAM_FLAT (FW_CFG_ARCH_LOCAL + 0x0a)
+
+#define FW_CFG_INVALID 0xffff
+
+#ifndef NO_QEMU_PROTOS
+typedef struct FWCfgFile {
+ uint32_t size; /* file size */
+ uint16_t select; /* write this to 0x510 to read it */
+ uint16_t reserved;
+ char name[56];
+} FWCfgFile;
+
+typedef struct FWCfgFiles {
+ uint32_t count;
+ FWCfgFile f[];
+} FWCfgFiles;
+
+typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
+
+typedef struct _FWCfgState FWCfgState;
+int fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len);
+int fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value);
+int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);
+int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value);
+int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
+ void *callback_opaque, uint8_t *data, size_t len);
+int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename,
+ uint8_t *data, uint32_t len);
+FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
+ target_phys_addr_t crl_addr, target_phys_addr_t data_addr);
+
+#endif /* NO_QEMU_PROTOS */
+
+#ifndef NO_OPENBIOS_PROTOS
+void fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes);
+uint64_t fw_cfg_read_i64(uint16_t cmd);
+uint32_t fw_cfg_read_i32(uint16_t cmd);
+uint16_t fw_cfg_read_i16(uint16_t cmd);
+void fw_cfg_init(void);
+#endif /* NO_OPENBIOS_PROTOS */
+
+#endif
diff --git a/roms/openbios/include/arch/common/nvram.h b/roms/openbios/include/arch/common/nvram.h
new file mode 100644
index 00000000..41b31ca7
--- /dev/null
+++ b/roms/openbios/include/arch/common/nvram.h
@@ -0,0 +1,24 @@
+/*
+ * Creation Date: <2003/12/20 01:04:25 samuel>
+ * Time-stamp: <2004/01/07 19:59:11 samuel>
+ *
+ * <nvram.h>
+ *
+ * arch NVRAM interface
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_NVRAM
+#define _H_NVRAM
+
+extern int arch_nvram_size( void );
+extern void arch_nvram_get( char *buf );
+extern void arch_nvram_put( char *buf );
+
+#endif /* _H_NVRAM */
diff --git a/roms/openbios/include/arch/common/xcoff.h b/roms/openbios/include/arch/common/xcoff.h
new file mode 100644
index 00000000..99106fe8
--- /dev/null
+++ b/roms/openbios/include/arch/common/xcoff.h
@@ -0,0 +1,98 @@
+#ifndef XCOFF_H
+#define XCOFF_H
+
+/* XCOFF executable loader */
+
+typedef struct COFF_filehdr_t {
+ uint16_t f_magic; /* magic number */
+ uint16_t f_nscns; /* number of sections */
+ uint32_t f_timdat; /* time & date stamp */
+ uint32_t f_symptr; /* file pointer to symtab */
+ uint32_t f_nsyms; /* number of symtab entries */
+ uint16_t f_opthdr; /* sizeof(optional hdr) */
+ uint16_t f_flags; /* flags */
+} COFF_filehdr_t;
+
+/* IBM RS/6000 */
+
+#define U802WRMAGIC 0x02DA /* writeable text segments **chh** */
+#define U802ROMAGIC 0x02DF /* readonly sharable text segments */
+#define U802TOCMAGIC 0x02E1 /* readonly text segments and TOC */
+#define U802TOMAGIC 0x01DF
+
+/*
+ * Bits for f_flags:
+ *
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (i.e. no unresolved external
+ * references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_MINMAL this is a minimal object file (".m") output of fextract
+ * F_UPDATE this is a fully bound update file, output of ogen
+ * F_SWABD this file has had its bytes swabbed (in names)
+ * F_AR16WR this file has the byte ordering of an AR16WR
+ * (e.g. 11/70) machine
+ * F_AR32WR this file has the byte ordering of an AR32WR machine
+ * (e.g. vax and iNTEL 386)
+ * F_AR32W this file has the byte ordering of an AR32W machine
+ * (e.g. 3b,maxi)
+ * F_PATCH file contains "patch" list in optional header
+ * F_NODF (minimal file only) no decision functions for
+ * replaced functions
+ */
+
+#define COFF_F_RELFLG 0000001
+#define COFF_F_EXEC 0000002
+#define COFF_F_LNNO 0000004
+#define COFF_F_LSYMS 0000010
+#define COFF_F_MINMAL 0000020
+#define COFF_F_UPDATE 0000040
+#define COFF_F_SWABD 0000100
+#define COFF_F_AR16WR 0000200
+#define COFF_F_AR32WR 0000400
+#define COFF_F_AR32W 0001000
+#define COFF_F_PATCH 0002000
+#define COFF_F_NODF 0002000
+
+typedef struct COFF_aouthdr_t {
+ uint16_t magic; /* type of file */
+ uint16_t vstamp; /* version stamp */
+ uint32_t tsize; /* text size in bytes, padded to FW bdry */
+ uint32_t dsize; /* initialized data " " */
+ uint32_t bsize; /* uninitialized data " " */
+ uint32_t entry; /* entry pt. */
+ uint32_t text_start; /* base of text used for this file */
+ uint32_t data_start; /* base of data used for this file */
+ uint32_t o_toc; /* address of TOC */
+ uint16_t o_snentry; /* section number of entry point */
+ uint16_t o_sntext; /* section number of .text section */
+ uint16_t o_sndata; /* section number of .data section */
+ uint16_t o_sntoc; /* section number of TOC */
+ uint16_t o_snloader; /* section number of .loader section */
+ uint16_t o_snbss; /* section number of .bss section */
+ uint16_t o_algntext; /* .text alignment */
+ uint16_t o_algndata; /* .data alignment */
+ uint16_t o_modtype; /* module type (??) */
+ uint16_t o_cputype; /* cpu type */
+ uint32_t o_maxstack; /* max stack size (??) */
+ uint32_t o_maxdata; /* max data size (??) */
+ char o_resv2[12]; /* reserved */
+} COFF_aouthdr_t;
+
+#define AOUT_MAGIC 0x010b
+
+typedef struct COFF_scnhdr_t {
+ char s_name[8]; /* section name */
+ uint32_t s_paddr; /* physical address, aliased s_nlib */
+ uint32_t s_vaddr; /* virtual address */
+ uint32_t s_size; /* section size */
+ uint32_t s_scnptr; /* file ptr to raw data for section */
+ uint32_t s_relptr; /* file ptr to relocation */
+ uint32_t s_lnnoptr; /* file ptr to line numbers */
+ uint16_t s_nreloc; /* number of relocation entries */
+ uint16_t s_nlnno; /* number of line number entries */
+ uint32_t s_flags; /* flags */
+} COFF_scnhdr_t;
+
+#endif /* XCOFF_H */
diff --git a/roms/openbios/include/arch/ia64/elf.h b/roms/openbios/include/arch/ia64/elf.h
new file mode 100644
index 00000000..782ddc72
--- /dev/null
+++ b/roms/openbios/include/arch/ia64/elf.h
@@ -0,0 +1,5 @@
+#define ARCH_ELF_CLASS ELFCLASS64
+#define ARCH_ELF_DATA ELFDATA2LSB
+#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_IA64)
+typedef Elf64_Ehdr Elf_ehdr;
+typedef Elf64_Phdr Elf_phdr;
diff --git a/roms/openbios/include/arch/ia64/io.h b/roms/openbios/include/arch/ia64/io.h
new file mode 100644
index 00000000..8f06dcda
--- /dev/null
+++ b/roms/openbios/include/arch/ia64/io.h
@@ -0,0 +1,59 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+extern unsigned long virt_offset;
+
+#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset))
+#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset)
+
+#define __SLOW_DOWN_IO "outb %%al,$0x80;"
+static inline void slow_down_io(void)
+{
+ __asm__ __volatile__(
+ __SLOW_DOWN_IO
+#ifdef REALLY_SLOW_IO
+ __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+ : : );
+}
+
+#define BUILDIO(bwl,bw,type) \
+static inline void out##bwl(unsigned type value, int port) { \
+ __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \
+} \
+static inline unsigned type in##bwl(int port) { \
+ unsigned type value; \
+ __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \
+ return value; \
+} \
+static inline void out##bwl##_p(unsigned type value, int port) { \
+ out##bwl(value, port); \
+ slow_down_io(); \
+} \
+static inline unsigned type in##bwl##_p(int port) { \
+ unsigned type value = in##bwl(port); \
+ slow_down_io(); \
+ return value; \
+} \
+static inline void outs##bwl(int port, const void *addr, unsigned long count) { \
+ __asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \
+} \
+static inline void ins##bwl(int port, void *addr, unsigned long count) { \
+ __asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \
+}
+
+#ifndef BOOTSTRAP
+BUILDIO(b,b,char)
+BUILDIO(w,w,short)
+BUILDIO(l,,int)
+#else
+extern u8 inb( u32 reg );
+extern u16 inw( u32 reg );
+extern u32 inl( u32 reg );
+extern void insw( u32 reg, void *addr, unsigned long count );
+extern void outb( u32 reg, u8 val );
+extern void outw( u32 reg, u16 val );
+extern void outl( u32 reg, u32 val );
+extern void outsw( u32 reg, const void *addr, unsigned long count);
+#endif
+#endif
diff --git a/roms/openbios/include/arch/ia64/types.h b/roms/openbios/include/arch/ia64/types.h
new file mode 100644
index 00000000..cb09cda5
--- /dev/null
+++ b/roms/openbios/include/arch/ia64/types.h
@@ -0,0 +1,60 @@
+/* tag: data types for forth engine
+ *
+ * This file is autogenerated by types.sh. Do not edit!
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __TYPES_H
+#define __TYPES_H
+
+#include <inttypes.h>
+
+/* endianess */
+
+#include <endian.h>
+
+/* physical address */
+
+typedef uint64_t phys_addr_t;
+
+#define FMT_plx "%016" PRIx64
+
+/* cell based types */
+
+typedef int64_t cell;
+typedef uint64_t ucell;
+typedef __int128_t dcell;
+typedef __uint128_t ducell;
+
+typedef int64_t prom_arg_t;
+typedef uint64_t prom_uarg_t;
+
+#define PRIdPROMARG PRId64
+#define PRIuPROMARG PRIu64
+#define PRIxPROMARG PRIx64
+#define FMT_prom_arg "%" PRIdPROMARG
+#define FMT_prom_uarg "%" PRIuPROMARG
+#define FMT_prom_uargx "%016" PRIxPROMARG
+
+#define bitspercell (sizeof(cell)<<3)
+#define bitsperdcell (sizeof(dcell)<<3)
+
+#define BITS 64
+
+/* size named types */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long u64;
+
+typedef char s8;
+typedef short s16;
+typedef int s32;
+typedef long s64;
+
+#endif
diff --git a/roms/openbios/include/arch/ppc/asmdefs.h b/roms/openbios/include/arch/ppc/asmdefs.h
new file mode 100644
index 00000000..3b3cad43
--- /dev/null
+++ b/roms/openbios/include/arch/ppc/asmdefs.h
@@ -0,0 +1,151 @@
+/* -*- asm -*-
+ *
+ * Creation Date: <2001/02/03 19:38:07 samuel>
+ * Time-stamp: <2003/07/08 18:55:50 samuel>
+ *
+ * <asmdefs.h>
+ *
+ * Common assembly definitions
+ *
+ * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_ASMDEFS
+#define _H_ASMDEFS
+
+/************************************************************************/
+/* High/low halfword compatibility macros */
+/************************************************************************/
+
+#ifndef __darwin__
+#define ha16( v ) (v)##@ha
+#define hi16( v ) (v)##@h
+#define lo16( v ) (v)##@l
+#endif
+#define HA(v) ha16(v)
+#define HI(v) hi16(v)
+#define LO(v) lo16(v)
+
+/* from Linux: include/asm-powerpc/ppc_asm.h */
+/*
+ * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
+ */
+
+/* General Purpose Registers (GPRs) */
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+/************************************************************************/
+/* MISC */
+/************************************************************************/
+
+#ifdef __powerpc64__
+
+#define LOAD_REG_IMMEDIATE(D, x) \
+ lis (D), (x)@highest ; \
+ ori (D), (D), (x)@higher ; \
+ sldi (D), (D), 32 ; \
+ oris (D), (D), (x)@h ; \
+ ori (D), (D), (x)@l
+
+#define LOAD_REG_FUNC(D, x) \
+ LOAD_REG_IMMEDIATE((D), (x)) ; \
+ ld (D), 0(D)
+
+#else
+
+#define LOAD_REG_IMMEDIATE(D, x) \
+ lis (D), HA(x) ; \
+ addi (D), (D), LO(x)
+
+#define LOAD_REG_FUNC(D, x) \
+ LOAD_REG_IMMEDIATE((D), (x))
+
+#endif
+
+#ifdef __powerpc64__
+#define PPC_LL ld
+#define PPC_STL std
+#define PPC_STLU stdu
+#define RFI rfid
+#define MTMSRD(r) mtmsrd r
+#define DATA_LONG(x) .quad x
+#define BRANCH_LABEL(name) . ## name
+#define PPC_LR_STKOFF 16
+#else
+#define PPC_LL lwz
+#define PPC_STL stw
+#define PPC_STLU stwu
+#define RFI rfi
+#define MTMSRD(r) mtmsr r
+#define DATA_LONG(x) .long x
+#define BRANCH_LABEL(name) name
+#define PPC_LR_STKOFF 4
+#endif
+
+#ifndef __darwin__
+#define GLOBL( name ) .globl name ; name
+#define EXTERN( name ) name
+#else
+/* an underscore is needed on Darwin */
+#define GLOBL( name ) .globl _##name ; name: ; _##name
+#define EXTERN( name ) _##name
+#endif
+
+#if defined(__powerpc64__) && !defined(__darwin__)
+#define _GLOBAL(name) \
+ .align 2 ; \
+ .section ".opd", "aw" ; \
+ .globl name ; \
+ .globl .##name ; \
+ name: \
+ .quad .##name ; \
+ .quad .TOC.@tocbase ; \
+ .quad 0 ; \
+ .previous ; \
+ .type .##name, @function ; \
+ .##name
+#else
+#define _GLOBAL(name) \
+ GLOBL(name)
+#endif
+
+#define BIT(n) (1<<(31-(n)))
+
+#endif /* _H_ASMDEFS */
diff --git a/roms/openbios/include/arch/ppc/elf.h b/roms/openbios/include/arch/ppc/elf.h
new file mode 100644
index 00000000..fd2a3f9e
--- /dev/null
+++ b/roms/openbios/include/arch/ppc/elf.h
@@ -0,0 +1,5 @@
+#define ARCH_ELF_CLASS ELFCLASS32
+#define ARCH_ELF_DATA ELFDATA2MSB
+#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_PPC)
+typedef Elf32_Ehdr Elf_ehdr;
+typedef Elf32_Phdr Elf_phdr;
diff --git a/roms/openbios/include/arch/ppc/io.h b/roms/openbios/include/arch/ppc/io.h
new file mode 100644
index 00000000..3449c5bf
--- /dev/null
+++ b/roms/openbios/include/arch/ppc/io.h
@@ -0,0 +1,208 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#include "asm/types.h"
+
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+
+extern char _start, _end;
+extern unsigned long virt_offset;
+
+#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset))
+#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset)
+
+#ifndef BOOTSTRAP
+
+extern unsigned long isa_io_base;
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ */
+static inline uint8_t in_8(volatile uint8_t *addr)
+{
+ uint8_t ret;
+
+ __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
+ return ret;
+}
+
+static inline void out_8(volatile uint8_t *addr, uint8_t val)
+{
+ __asm__ __volatile__("stb%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
+}
+
+static inline uint16_t in_le16(volatile uint16_t *addr)
+{
+ uint16_t ret;
+
+ __asm__ __volatile__("lhbrx %0,0,%1; eieio":"=r"(ret):
+ "r"(addr), "m"(*addr));
+ return ret;
+}
+
+static inline uint16_t in_be16(volatile uint16_t *addr)
+{
+ uint16_t ret;
+
+ __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
+ return ret;
+}
+
+static inline void out_le16(volatile uint16_t *addr, uint16_t val)
+{
+ __asm__ __volatile__("sthbrx %1,0,%2; eieio":"=m"(*addr):"r"(val),
+ "r"(addr));
+}
+
+static inline void out_be16(volatile uint16_t *addr, uint16_t val)
+{
+ __asm__ __volatile__("sth%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
+}
+
+static inline uint32_t in_le32(volatile uint32_t *addr)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__("lwbrx %0,0,%1; eieio":"=r"(ret):
+ "r"(addr), "m"(*addr));
+ return ret;
+}
+
+static inline uint32_t in_be32(volatile uint32_t *addr)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
+ return ret;
+}
+
+static inline void out_le32(volatile uint32_t *addr, uint32_t val)
+{
+ __asm__ __volatile__("stwbrx %1,0,%2; eieio":"=m"(*addr):"r"(val),
+ "r"(addr));
+}
+
+static inline void out_be32(volatile unsigned *addr, uint32_t val)
+{
+ __asm__ __volatile__("stw%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
+}
+
+static inline void _insw_ns(volatile uint16_t * port, void *buf, int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ *b++ = in_le16(port);
+ ns--;
+ }
+}
+
+static inline void _outsw_ns(volatile uint16_t * port, const void *buf,
+ int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ out_le16(port, *b++);
+ ns--;
+ }
+}
+
+static inline void _insw(volatile uint16_t * port, void *buf, int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ *b++ = in_be16(port);
+ ns--;
+ }
+}
+
+static inline void _outsw(volatile uint16_t * port, const void *buf,
+ int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ out_be16(port, *b++);
+ ns--;
+ }
+}
+
+
+/*
+ * The insw/outsw/insl/outsl functions don't do byte-swapping.
+ * They are only used in practice for transferring buffers which
+ * are arrays of bytes, and byte-swapping is not appropriate in
+ * that case. - paulus
+ */
+
+static inline void insw(uint16_t port, void *buf, int ns)
+{
+ _insw((uint16_t *)(port + isa_io_base), buf, ns);
+}
+
+static inline void outsw(uint16_t port, void *buf, int ns)
+{
+ _outsw((uint16_t *)(port + isa_io_base), buf, ns);
+}
+
+
+static inline uint8_t inb(uint16_t port)
+{
+ return in_8((uint8_t *)(port + isa_io_base));
+}
+
+static inline void outb(uint8_t val, uint16_t port)
+{
+ out_8((uint8_t *)(port + isa_io_base), val);
+}
+
+static inline uint16_t inw(uint16_t port)
+{
+ return in_le16((uint16_t *)(port + isa_io_base));
+}
+
+static inline void outw(uint16_t val, uint16_t port)
+{
+ out_le16((uint16_t *)(port + isa_io_base), val);
+}
+
+static inline uint32_t inl(uint16_t port)
+{
+ return in_le32((uint32_t *)(port + isa_io_base));
+}
+
+static inline void outl(uint32_t val, uint16_t port)
+{
+ out_le32((uint32_t *)(port + isa_io_base), val);
+}
+
+#else /* BOOTSTRAP */
+#ifdef FCOMPILER
+#define inb(reg) ((u8)0xff)
+#define inw(reg) ((u16)0xffff)
+#define inl(reg) ((u32)0xffffffff)
+#define outb(reg, val) do{} while(0)
+#define outw(reg, val) do{} while(0)
+#define outl(reg, val) do{} while(0)
+#else
+extern u8 inb(u32 reg);
+extern u16 inw(u32 reg);
+extern u32 inl(u32 reg);
+extern void insw(u32 reg, void *addr, unsigned long count);
+extern void outb(u32 reg, u8 val);
+extern void outw(u32 reg, u16 val);
+extern void outl(u32 reg, u32 val);
+extern void outsw(u32 reg, const void *addr, unsigned long count);
+#endif
+#endif
+
+#if defined(CONFIG_QEMU)
+#define FW_CFG_ARCH_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
+#define FW_CFG_ARCH_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
+#define FW_CFG_ARCH_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
+#endif
+
+#endif /* _ASM_IO_H */
diff --git a/roms/openbios/include/arch/ppc/pci.h b/roms/openbios/include/arch/ppc/pci.h
new file mode 100644
index 00000000..d96bd7ee
--- /dev/null
+++ b/roms/openbios/include/arch/ppc/pci.h
@@ -0,0 +1,69 @@
+#ifndef PPC_PCI_H
+#define PPC_PCI_H
+
+#include "asm/io.h"
+
+#if !(defined(PCI_CONFIG_1) || defined(PCI_CONFIG_2))
+#define PCI_CONFIG_1 1 /* default */
+#endif
+
+#ifdef PCI_CONFIG_1
+
+/* PCI Configuration Mechanism #1 */
+
+#define PCI_ADDR(bus, dev, fn) \
+ ((pci_addr) (0x80000000u \
+ | (uint32_t) (bus) << 16 \
+ | (uint32_t) (dev) << 11 \
+ | (uint32_t) (fn) << 8))
+
+#define PCI_BUS(pcidev) ((uint8_t) ((pcidev) >> 16))
+#define PCI_DEV(pcidev) ((uint8_t) ((pcidev) >> 11) & 0x1f)
+#define PCI_FN(pcidev) ((uint8_t) ((pcidev) >> 8) & 7)
+
+static inline uint8_t pci_config_read8(pci_addr dev, uint8_t reg)
+{
+ uint8_t res;
+ out_le32((unsigned *)arch->cfg_addr, dev | (reg & ~3));
+ res = in_8((unsigned char*)(arch->cfg_data + (reg & 3)));
+ return res;
+}
+
+static inline uint16_t pci_config_read16(pci_addr dev, uint8_t reg)
+{
+ uint16_t res;
+ out_le32((unsigned *)arch->cfg_addr, dev | (reg & ~3));
+ res = in_le16((unsigned short*)(arch->cfg_data + (reg & 2)));
+ return res;
+}
+
+static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg)
+{
+ uint32_t res;
+ out_le32((unsigned *)arch->cfg_addr, dev | reg);
+ res = in_le32((unsigned *)(arch->cfg_data));
+ return res;
+}
+
+static inline void pci_config_write8(pci_addr dev, uint8_t reg, uint8_t val)
+{
+ out_le32((unsigned *)arch->cfg_addr, dev | (reg & ~3));
+ out_8((unsigned char*)(arch->cfg_data + (reg & 3)), val);
+}
+
+static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val)
+{
+ out_le32((unsigned *)arch->cfg_addr, dev | (reg & ~3));
+ out_le16((unsigned short *)(arch->cfg_data + (reg & 2)), val);
+}
+
+static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val)
+{
+ out_le32((unsigned *)arch->cfg_addr, dev | reg);
+ out_le32((unsigned *)(arch->cfg_data), val);
+}
+#else /* !PCI_CONFIG_1 */
+#error PCI Configuration Mechanism is not specified or implemented
+#endif
+
+#endif /* PPC_PCI_H */
diff --git a/roms/openbios/include/arch/ppc/processor.h b/roms/openbios/include/arch/ppc/processor.h
new file mode 100644
index 00000000..bb03bb16
--- /dev/null
+++ b/roms/openbios/include/arch/ppc/processor.h
@@ -0,0 +1,467 @@
+/*
+ * Creation Date: <2000/10/29 01:43:29 samuel>
+ * Time-stamp: <2003/07/27 22:37:49 samuel>
+ *
+ * <processor.h>
+ *
+ * Extract from <asm/processor.h>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_PROCESSOR
+#define _H_PROCESSOR
+
+
+#define PTE0_VSID(s) (((s)>>7) & 0xffffff)
+#define PTE0_V BIT(0)
+#define PTE0_H BIT(25)
+#define PTE0_API 0x3f
+
+#define PTE1_R BIT(23)
+#define PTE1_C BIT(24)
+#define PTE1_W BIT(25)
+#define PTE1_I BIT(26)
+#define PTE1_M BIT(27)
+#define PTE1_G BIT(28)
+#define PTE1_WIMG (PTE1_W | PTE1_I | PTE1_M | PTE1_G)
+#define PTE1_PP 0x3
+#define PTE1_RPN (~0xfffUL)
+
+#define VSID_Ks BIT(1)
+#define VSID_Kp BIT(2)
+#define VSID_N BIT(3)
+
+
+
+#ifndef MSR_VEC
+
+#define MSR_SF (1 << 63) /* Sixty-Four Bit Mode */
+
+#define MSR_VEC (1<<25) /* 6: Enable AltiVec */
+#define MSR_POW (1<<18) /* 13: Enable Power Management */
+#define MSR_TGPR (1<<17) /* 14: TLB Update registers in use */
+#define MSR_ILE (1<<16) /* 15: Interrupt Little Endian */
+#define MSR_EE (1<<15) /* 16: External Interrupt Enable */
+#define MSR_PR (1<<14) /* 17: Privilege Level */
+#define MSR_FP (1<<13) /* 18: Floating Point enable */
+#define MSR_ME (1<<12) /* 19: Machine Check Enable */
+#define MSR_FE0 (1<<11) /* 20: Floating Exception mode 0 */
+#define MSR_SE (1<<10) /* 21: Single Step */
+#define MSR_BE (1<<9) /* 22: Branch Trace */
+#define MSR_FE1 (1<<8) /* 23: Floating Exception mode 1 */
+#define MSR_IP (1<<6) /* 25: Exception prefix 0x000/0xFFF */
+#define MSR_IR (1<<5) /* 26: Instruction Relocate */
+#define MSR_DR (1<<4) /* 27: Data Relocate */
+#define MSR_PE (1<<2) /* 29: Performance Monitor Flag */
+#define MSR_RI (1<<1) /* 30: Recoverable Exception */
+#define MSR_LE (1<<0) /* 31: Little Endian */
+
+#endif /* MSR_VEC */
+
+#ifndef S_SPRG0
+
+#define NUM_SPRS 1024
+//#define S_XER 1
+#define S_RTCU_R 4 /* 601 RTC Upper/Lower (Reading) */
+#define S_RTCL_R 5
+//#define S_LR 8
+//#define S_CTR 9
+#define S_DSISR 18 /* Source Instruction Service Register */
+#define S_DAR 19 /* Data Address Register */
+#define S_RTCU_W 20 /* 601 RTC Upper/Lower (Writing) */
+#define S_RTCL_W 21
+#define S_DEC 22 /* Decrementer Register */
+#define S_SDR1 25 /* Table Search Description Register */
+#define S_SRR0 26 /* Save and Restore Register 0 */
+#define S_SRR1 27 /* Save and Restore Register 1 */
+#define S_VRSAVE 256 /* (AltiVec) Vector Register Save Register */
+#define S_TBRL 268 /* Time base Upper/Lower (Reading) */
+#define S_TBRU 269
+#define S_SPRG0 272 /* SPR General 0-3 */
+#define S_SPRG1 273
+#define S_SPRG2 274
+#define S_SPRG3 275
+#define S_SPRG4 276 /* SPR General 4-7 (7445/7455) */
+#define S_SPRG5 277
+#define S_SPRG6 278
+#define S_SPRG7 279
+#define S_EAR 282 /* External Access Register */
+#define S_TBWL 284 /* Time base Upper/Lower (Writing) */
+#define S_TBWU 285
+#define S_PVR 287 /* Processor Version Register */
+#define S_HIOR 311 /* Hardware Interrupt Offset Register */
+#define S_IBAT0U 528
+#define S_IBAT0L 529
+#define S_IBAT1U 530
+#define S_IBAT1L 531
+#define S_IBAT2U 532
+#define S_IBAT2L 533
+#define S_IBAT3U 534
+#define S_IBAT3L 535
+#define S_DBAT0U 536
+#define S_DBAT0L 537
+#define S_DBAT1U 538
+#define S_DBAT1L 539
+#define S_DBAT2U 540
+#define S_DBAT2L 541
+#define S_DBAT3U 542
+#define S_DBAT3L 543
+#define S_UMMCR2 928
+#define S_UPMC5 929 /* User Performance Monitor Counter Register */
+#define S_UPMC6 930
+#define S_UBAMR 935
+#define S_UMMCR0 936 /* User Monitor Mode Control Register */
+#define S_UPMC1 937
+#define S_UPMC2 938
+#define S_USIAR 939 /* User Sampled Instruction Address Register */
+#define S_UMMCR1 940
+#define S_UPMC3 941
+#define S_UPMC4 942 /* User Performance Monitor Counter Register 4 */
+#define S_USDAR 943 /* User Sampled Data Address Register */
+#define S_MMCR2 944 /* Monitor Mode Control Register */
+#define S_PMC5 945
+#define S_PMC6 946
+#define S_BAMR 951 /* Breakpoint Address Mask Register (74xx) */
+#define S_MMCR0 952 /* Monitor Mode Control Register 0 */
+#define S_PMC1 953 /* Performance Counter Register */
+#define S_PMC2 954
+#define S_SIAR 955 /* Sampled Instruction Address Register */
+#define S_MMCR1 956
+#define S_PMC3 957
+#define S_PMC4 958
+#define S_SDAR 959 /* Sampled Data Address Register */
+#define S_DMISS 976 /* 603 */
+#define S_DCMP 977 /* 603 */
+#define S_HASH1 978 /* 603 */
+#define S_HASH2 979 /* 603 */
+#define S_IMISS 980 /* 603 */
+#define S_TLBMISS 980 /* 7445/7455 */
+#define S_ICMP 981 /* 603 */
+#define S_PTEHI 981 /* 7445/7455 */
+#define S_RPA 982 /* 603 */
+#define S_PTELO 982 /* 7445/7455 */
+#define S_L3PM 983 /* L3 Private Memory Address Control Register */
+#define S_L3ITCR0 984 /* ??? */
+#define S_L3OHCR 1000 /* ??? */
+#define S_L3ITCR1 1001 /* ??? */
+#define S_L3ITCR2 1002 /* ??? */
+#define S_L3ITCR3 1003 /* ??? */
+#define S_HID0 1008 /* Hardware Implementation Registers */
+#define S_HID1 1009
+#define S_HID2 1010
+#define S_IABR S_HID2 /* HID2 - Instruction Address Breakpoint Register */
+#define S_ICTRL 1011 /* HID3 - Instruction Cache & Interrupt control reg */
+#define S_HID4 1012 /* HID4 - Instruction Address Compare 1 (?) */
+#define S_HID5 1013
+#define S_DABR S_HID5 /* HID5 - Data Address Breakpoint */
+#define S_MSSCR0 1014 /* HID6 - Memory Subsystem Control Register 0 */
+#define S_MSSCR1 1015 /* HID7 - Memory Subsystem Control Register 1 */
+#define S_LDSTCR 1016 /* HID8 - Load/Store Control Register */
+#define S_L2CR 1017 /* HID9 - Level 2 Cache Control Regsiter */
+#define S_L3CR 1018 /* HID10 - Level 3 Cache Control Regsiter (7450) */
+#define S_HID11 1019
+#define S_ICTC S_HID11 /* HID11 - Instruction Cache Throttling Control Reg */
+#define S_ICCR S_HID11 /* Instruction Cache Cacheability Reigster */
+#define S_THRM1 1020 /* HID12 - Thermal Management Register 1 */
+#define S_THRM2 1021 /* HID13 - Thermal Management Register 2 */
+#define S_THRM3 1022 /* HID14 - Thermal Management Register 3 */
+#define S_HID15 1023
+#define S_PIR S_HID15 /* HID15 - Processor Identification Register */
+
+#endif /* S_SPRG0 */
+
+/* the kernel might define these too... */
+#if !defined(__KERNEL__) || defined(__ASSEMBLY__)
+
+/* Floating Point Status and Control Register (FPSCR) Fields */
+#define FPSCR_FX 0x80000000 /* FPU exception summary */
+#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */
+#define FPSCR_VX 0x20000000 /* Invalid operation summary */
+#define FPSCR_OX 0x10000000 /* Overflow exception summary */
+#define FPSCR_UX 0x08000000 /* Underflow exception summary */
+#define FPSCR_ZX 0x04000000 /* Zero-devide exception summary */
+#define FPSCR_XX 0x02000000 /* Inexact exception summary */
+#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */
+#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */
+#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */
+#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */
+#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */
+#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */
+#define FPSCR_FR 0x00040000 /* Fraction rounded */
+#define FPSCR_FI 0x00020000 /* Fraction inexact */
+#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */
+#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */
+#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */
+#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */
+#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */
+#define FPSCR_VE 0x00000080 /* Invalid op exception enable */
+#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */
+#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */
+#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */
+#define FPSCR_XE 0x00000008 /* FP inexact exception enable */
+#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */
+#define FPSCR_RN 0x00000003 /* FPU rounding control */
+
+/* SPR_HID0 */
+#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
+#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
+#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
+#define HID0_SBCLK (1<<27)
+#define HID0_EICE (1<<26)
+#define HID0_ECLK (1<<25)
+#define HID0_PAR (1<<24)
+#define HID0_DOZE (1<<23)
+#define HID0_NAP (1<<22)
+#define HID0_SLEEP (1<<21)
+#define HID0_DPM (1<<20)
+#define HID0_NHR (1<<16) /* Not Hard Reset */
+#define HID0_ICE (1<<15) /* Instruction Cache Enable */
+#define HID0_DCE (1<<14) /* Data Cache Enable */
+#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
+#define HID0_DLOCK (1<<12) /* Data Cache Lock */
+#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
+#define HID0_DCFI (1<<10) /* Data Cache Flash Invalidate */
+#define HID0_SPD (1<<9) /* Speculative disable */
+#define HID0_SGE (1<<7) /* Store Gathering Enable */
+#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
+#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache Enable */
+#define HID0_ABE (1<<3) /* Address Broadcast Enable */
+#define HID0_BHT (1<<2) /* Branch History Table Enable */
+#define HID0_BTCD (1<<1) /* Branch target cache disable */
+
+#define L2CR_L2E BIT(0) /* L2 enable */
+#define L2CR_L2PE BIT(1) /* L2 data parity generation and checking */
+#define L2CR_L2SIZ_512K BIT(2)
+#define L2CR_L2SIZ_256K BIT(3)
+#define L2CR_L2SIZ_1MB (BIT(2)|BIT(3))
+#define L2CR_L2CLK_1 BIT(6) /* L2 clock ration */
+#define L2CR_L2CLK_15 (BIT(6)*2)
+#define L2CR_L2CLK_2 (BIT(6)*4)
+#define L2CR_L2CLK_25 (BIT(6)*5)
+#define L2CR_L2CLK_3 (BIT(6)*6)
+#define L2CR_L2RAM_FT 0 /* flow-through (reg-buf) synchronous SRAM */
+#define L2CR_L2RAM_PB BIT(7) /* Piplined (reg-reg) synchronous burst SRAM */
+#define L2CR_L2RAM_PLW (BIT(7)|BIT(8)) /* Piplined (reg-reg) synchronous late-write */
+#define L2CR_L2DO BIT(9) /* L2 data-only */
+#define L2CR_L2I BIT(10) /* L2 global invalidate */
+#define L2CR_L2CTL BIT(11) /* L2 RAM control (ZZ enable, low-power mode) */
+#define L2CR_L2WT BIT(12) /* L2 write-through */
+#define L2CR_L2TS BIT(13) /* L2 test support */
+#define L2CR_L2OH_05 0 /* L2 output hold 0.5 nS */
+#define L2CR_L2OH_10 BIT(15) /* L2 output hold 1.0 nS */
+#define L2CR_L2SL BIT(16) /* L2 DLL slow (use if bus freq < 150 MHz) */
+#define L2CR_L2DF BIT(17) /* L2 differential clock */
+#define L2CR_L2BYP BIT(18) /* L2 DLL bypass */
+#define L2CR_L2IP BIT(31) /* L2 global invalidate in progress */
+
+/* SPR_THRM1 */
+#define THRM1_TIN (1 << 31)
+#define THRM1_TIV (1 << 30)
+#define THRM1_THRES(x) ((x&0x7f)<<23)
+#define THRM3_SITV(x) ((x&0x3fff)<<1)
+#define THRM1_TID (1<<2)
+#define THRM1_TIE (1<<1)
+#define THRM1_V (1<<0)
+
+/* SPR_THRM3 */
+#define THRM3_E (1<<0)
+
+/* Processor Version Numbers */
+
+#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+
+#define PVR_403GA 0x00200000
+#define PVR_403GB 0x00200100
+#define PVR_403GC 0x00200200
+#define PVR_403GCX 0x00201400
+#define PVR_405GP 0x40110000
+#define PVR_601 0x00010000
+#define PVR_602 0x00050000
+#define PVR_603 0x00030000
+#define PVR_603e 0x00060000
+#define PVR_603ev 0x00070000
+#define PVR_603r 0x00071000
+#define PVR_604 0x00040000
+#define PVR_604e 0x00090000
+#define PVR_604r 0x000A0000
+#define PVR_620 0x00140000
+#define PVR_740 0x00080000
+#define PVR_750 PVR_740
+#define PVR_740P 0x10080000
+#define PVR_750P PVR_740P
+#define PVR_821 0x00500000
+#define PVR_823 PVR_821
+#define PVR_850 PVR_821
+#define PVR_860 PVR_821
+#define PVR_7400 0x000C0000
+#define PVR_8240 0x00810100
+#define PVR_8260 PVR_8240
+
+/* Vector VSCR register */
+#define VSCR_NJ 0x10000
+#define VSCR_SAT 0x1
+
+#endif /* __KERNEL__ */
+
+
+#ifdef __ASSEMBLY__
+
+#define CTR S_CTR /* Counter Register */
+#define DAR S_DAR /* Data Address Register */
+#define DABR S_DABR /* Data Address Breakpoint Register */
+#define DBAT0L S_DBAT0L /* Data BAT 0 Lower Register */
+#define DBAT0U S_DBAT0U /* Data BAT 0 Upper Register */
+#define DBAT1L S_DBAT1L /* Data BAT 1 Lower Register */
+#define DBAT1U S_DBAT1U /* Data BAT 1 Upper Register */
+#define DBAT2L S_DBAT2L /* Data BAT 2 Lower Register */
+#define DBAT2U S_DBAT2U /* Data BAT 2 Upper Register */
+#define DBAT3L S_DBAT3L /* Data BAT 3 Lower Register */
+#define DBAT3U S_DBAT3U /* Data BAT 3 Upper Register */
+#define DCMP S_DCMP /* Data TLB Compare Register */
+#define DEC S_DEC /* Decrement Register */
+#define DMISS S_DMISS /* Data TLB Miss Register */
+#define DSISR S_DSISR /* Data Storage Interrupt Status Register */
+#define EAR S_EAR /* External Address Register */
+#define HASH1 S_HASH1 /* Primary Hash Address Register */
+#define HASH2 S_HASH2 /* Secondary Hash Address Register */
+#define HID0 S_HID0 /* Hardware Implementation Register 0 */
+#define HID1 S_HID1 /* Hardware Implementation Register 1 */
+#define IABR S_IABR /* Instruction Address Breakpoint Register */
+#define IBAT0L S_IBAT0L /* Instruction BAT 0 Lower Register */
+#define IBAT0U S_IBAT0U /* Instruction BAT 0 Upper Register */
+#define IBAT1L S_IBAT1L /* Instruction BAT 1 Lower Register */
+#define IBAT1U S_IBAT1U /* Instruction BAT 1 Upper Register */
+#define IBAT2L S_IBAT2L /* Instruction BAT 2 Lower Register */
+#define IBAT2U S_IBAT2U /* Instruction BAT 2 Upper Register */
+#define IBAT3L S_IBAT3L /* Instruction BAT 3 Lower Register */
+#define IBAT3U S_IBAT3U /* Instruction BAT 3 Upper Register */
+#define ICMP S_ICMP /* Instruction TLB Compare Register */
+#define IMISS S_IMISS /* Instruction TLB Miss Register */
+#define IMMR S_IMMR /* PPC 860/821 Internal Memory Map Register */
+#define L2CR S_L2CR /* PPC 750 L2 control register */
+#define PVR S_PVR /* Processor Version */
+#define RPA S_RPA /* Required Physical Address Register */
+#define SDR1 S_SDR1 /* MMU hash base register */
+#define SPR0 S_SPRG0 /* Supervisor Private Registers */
+#define SPR1 S_SPRG1
+#define SPR2 S_SPRG2
+#define SPR3 S_SPRG3
+#define SPRG0 S_SPRG0
+#define SPRG1 S_SPRG1
+#define SPRG2 S_SPRG2
+#define SPRG3 S_SPRG3
+#define SRR0 S_SRR0 /* Save and Restore Register 0 */
+#define SRR1 S_SRR1 /* Save and Restore Register 1 */
+#define TBRL S_STBRL /* Time Base Read Lower Register */
+#define TBRU S_TBRU /* Time Base Read Upper Register */
+#define TBWL S_TBWL /* Time Base Write Lower Register */
+#define TBWU S_TBWU /* Time Base Write Upper Register */
+#define ICTC S_ICTC
+#define THRM1 S_THRM1 /* Thermal Management Register 1 */
+#define THRM2 S_THRM2 /* Thermal Management Register 2 */
+#define THRM3 S_THRM3 /* Thermal Management Register 3 */
+#define SIAR S_SIAR
+#define SDAR S_SDAR
+#define XER 1
+
+#define SR0 0 /* Segment registers */
+#define SR1 1
+#define SR2 2
+#define SR3 3
+#define SR4 4
+#define SR5 5
+#define SR6 6
+#define SR7 7
+#define SR8 8
+#define SR9 9
+#define SR10 10
+#define SR11 11
+#define SR12 12
+#define SR13 13
+#define SR14 14
+#define SR15 15
+
+#endif /* __ASSEMBLY__ */
+
+/* opcode macros */
+
+#define OPCODE_PRIM(n) ( ((unsigned long)(n)) >> 26 )
+#define OPCODE_EXT(n) ( (((unsigned long)(n)) >> 1) & 0x3ff )
+#define OPCODE(op,op_ext) ( ((op)<<10) + op_ext )
+
+#define B1(n) ( (((unsigned long)(n)) >> 21) & 0x1f )
+#define B2(n) ( (((unsigned long)(n)) >> 16) & 0x1f )
+#define B3(n) ( (((unsigned long)(n)) >> 11) & 0x1f )
+
+#define BD(n) ((unsigned long)((n) & 0x7fff) + (((n) & 0x8000) ? (unsigned long)0xffff8000 : 0))
+
+#define SPRNUM_FLIP( v ) ( (((v)>>5) & 0x1f) | (((v)<<5) & 0x3e0) )
+
+/* C helpers */
+
+#ifndef __ASSEMBLER__
+
+#define __stringify_1(x) #x
+#define __stringify(x) __stringify_1(x)
+#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
+
+static inline unsigned long mfmsr(void)
+{
+ unsigned long msr;
+ asm volatile("mfmsr %0" : "=r" (msr));
+ return msr;
+}
+
+static inline void mtmsr(unsigned long msr)
+{
+#ifdef __powerpc64__
+ asm volatile("mtmsrd %0" :: "r" (msr));
+#else
+ asm volatile("mtmsr %0" :: "r" (msr));
+#endif
+}
+
+#ifdef __powerpc64__
+#define SDR1_HTABORG_MASK 0x3FFFFFFFFFFC0000UL
+#else
+#define SDR1_HTABORG_MASK 0xffff0000
+#endif
+
+static inline unsigned long mfsdr1(void)
+{
+ unsigned long sdr1;
+ asm volatile("mfsdr1 %0" : "=r" (sdr1));
+ return sdr1;
+}
+
+static inline void mtsdr1(unsigned long sdr1)
+{
+ asm volatile("mtsdr1 %0" :: "r" (sdr1));
+}
+
+static inline unsigned int mfpvr(void)
+{
+ unsigned int pvr;
+ asm volatile("mfspr %0, 0x11f" : "=r" (pvr) );
+ return pvr;
+}
+
+static inline void slbia(void)
+{
+ asm volatile("slbia" ::: "memory");
+}
+
+static inline void slbmte(unsigned long rs, unsigned long rb)
+{
+ asm volatile("slbmte %0,%1 ; isync" :: "r" (rs), "r" (rb) : "memory");
+}
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* _H_PROCESSOR */
diff --git a/roms/openbios/include/arch/ppc/types.h b/roms/openbios/include/arch/ppc/types.h
new file mode 100644
index 00000000..69b3db40
--- /dev/null
+++ b/roms/openbios/include/arch/ppc/types.h
@@ -0,0 +1,104 @@
+/* tag: data types for forth engine
+ *
+ * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __TYPES_H
+#define __TYPES_H
+
+#include "mconfig.h"
+
+#ifdef BOOTSTRAP
+#include <inttypes.h>
+#else
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef long long int64_t;
+typedef long intptr_t;
+
+#define PRId32 "d"
+#define PRIu32 "u"
+#define PRIx32 "x"
+#define PRIX32 "X"
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#define PRIx64 "llx"
+#define PRIX64 "llX"
+#endif
+
+/* endianess */
+#include "autoconf.h"
+
+/* physical address */
+#if defined(__powerpc64__)
+typedef uint64_t phys_addr_t;
+#define FMT_plx "%016" PRIx64
+#else
+typedef uint32_t phys_addr_t;
+#define FMT_plx "%08" PRIx32
+#endif
+
+/* cell based types */
+
+typedef int32_t cell;
+typedef uint32_t ucell;
+typedef int64_t dcell;
+typedef uint64_t ducell;
+
+#define FMT_cell "%" PRId32
+#define FMT_ucell "%" PRIu32
+#define FMT_ucellx "%08" PRIx32
+#define FMT_ucellX "%08" PRIX32
+
+typedef int32_t prom_arg_t;
+typedef uint32_t prom_uarg_t;
+
+#define PRIdPROMARG PRId32
+#define PRIuPROMARG PRIu32
+#define PRIxPROMARG PRIx32
+#define FMT_prom_arg "%" PRIdPROMARG
+#define FMT_prom_uarg "%" PRIuPROMARG
+#define FMT_prom_uargx "%08" PRIxPROMARG
+
+#define FMT_elf "%#x"
+#define FMT_sizet "%lx"
+#define FMT_aout_ehdr "%lx"
+
+#define bitspercell (sizeof(cell)<<3)
+#define bitsperdcell (sizeof(dcell)<<3)
+
+#define BITS 32
+
+#define PAGE_SHIFT 12
+
+/* size named types */
+
+typedef unsigned char u8;
+typedef unsigned char __u8;
+typedef unsigned short u16;
+typedef unsigned short __u16;
+typedef unsigned int u32;
+typedef unsigned int __u32;
+typedef unsigned long long u64;
+typedef unsigned long long __u64;
+
+typedef signed char s8;
+typedef signed char __s8;
+typedef short s16;
+typedef short __s16;
+typedef int s32;
+typedef int __s32;
+typedef long long s64;
+typedef long long __s64;
+
+#endif
diff --git a/roms/openbios/include/arch/sparc32/a.out.h b/roms/openbios/include/arch/sparc32/a.out.h
new file mode 100644
index 00000000..e4e83eb0
--- /dev/null
+++ b/roms/openbios/include/arch/sparc32/a.out.h
@@ -0,0 +1,98 @@
+/* $Id: a.out.h,v 1.13 2000/01/09 10:46:53 anton Exp $ */
+#ifndef __SPARC_A_OUT_H__
+#define __SPARC_A_OUT_H__
+
+#define SPARC_PGSIZE 0x2000 /* Thanks to the sun4 architecture... */
+#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */
+
+struct exec {
+ unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */
+ unsigned char a_toolversion:7;
+ unsigned char a_machtype;
+ unsigned short a_info;
+ unsigned long a_text; /* length of text, in bytes */
+ unsigned long a_data; /* length of data, in bytes */
+ unsigned long a_bss; /* length of bss, in bytes */
+ unsigned long a_syms; /* length of symbol table, in bytes */
+ unsigned long a_entry; /* where program begins */
+ unsigned long a_trsize;
+ unsigned long a_drsize;
+};
+
+/* Where in the file does the text information begin? */
+#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
+
+/* Where do the Symbols start? */
+#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \
+ (x).a_data + (x).a_trsize + \
+ (x).a_drsize)
+
+/* Where does text segment go in memory after being loaded? */
+#define N_TXTADDR(x) (((N_MAGIC(x) == ZMAGIC) && \
+ ((x).a_entry < SPARC_PGSIZE)) ? \
+ 0 : SPARC_PGSIZE)
+
+/* And same for the data segment.. */
+#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \
+ (N_TXTADDR(x) + (x).a_text) \
+ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+
+#define N_TRSIZE(a) ((a).a_trsize)
+#define N_DRSIZE(a) ((a).a_drsize)
+#define N_SYMSIZE(a) ((a).a_syms)
+
+/*
+ * Sparc relocation types
+ */
+enum reloc_type
+{
+ RELOC_8,
+ RELOC_16,
+ RELOC_32, /* simplest relocs */
+ RELOC_DISP8,
+ RELOC_DISP16,
+ RELOC_DISP32, /* Disp's (pc-rel) */
+ RELOC_WDISP30,
+ RELOC_WDISP22, /* SR word disp's */
+ RELOC_HI22,
+ RELOC_22, /* SR 22-bit relocs */
+ RELOC_13,
+ RELOC_LO10, /* SR 13&10-bit relocs */
+ RELOC_SFA_BASE,
+ RELOC_SFA_OFF13, /* SR S.F.A. relocs */
+ RELOC_BASE10,
+ RELOC_BASE13,
+ RELOC_BASE22, /* base_relative pic */
+ RELOC_PC10,
+ RELOC_PC22, /* special pc-rel pic */
+ RELOC_JMP_TBL, /* jmp_tbl_rel in pic */
+ RELOC_SEGOFF16, /* ShLib offset-in-seg */
+ RELOC_GLOB_DAT,
+ RELOC_JMP_SLOT,
+ RELOC_RELATIVE /* rtld relocs */
+};
+
+/*
+ * Format of a relocation datum.
+ */
+struct relocation_info /* used when header.a_machtype == M_SPARC */
+{
+ unsigned long r_address; /* relocation addr */
+ unsigned int r_index:24; /* segment index or symbol index */
+ unsigned int r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
+ int r_pad:2; /* <unused> */
+ enum reloc_type r_type:5; /* type of relocation to perform */
+ long r_addend; /* addend for relocation value */
+};
+
+#define N_RELOCATION_INFO_DECLARED 1
+
+#ifdef __KERNEL__
+
+#include <asm/page.h>
+
+#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
+
+#endif /* __KERNEL__ */
+
+#endif /* __SPARC_A_OUT_H__ */
diff --git a/roms/openbios/include/arch/sparc32/asi.h b/roms/openbios/include/arch/sparc32/asi.h
new file mode 100644
index 00000000..af3d69c1
--- /dev/null
+++ b/roms/openbios/include/arch/sparc32/asi.h
@@ -0,0 +1,111 @@
+/* $Id: asi.h,v 1.1 2002/07/12 17:06:36 zaitcev Exp $ */
+#ifndef _SPARC_ASI_H
+#define _SPARC_ASI_H
+
+/* asi.h: Address Space Identifier values for the sparc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Pioneer work for sun4m: Paul Hatchman (paul@sfe.com.au)
+ * Joint edition for sun4c+sun4m: Pete A. Zaitcev <zaitcev@ipmce.su>
+ */
+
+/* The first batch are for the sun4c. */
+
+#define ASI_NULL1 0x00
+#define ASI_NULL2 0x01
+
+/* sun4c and sun4 control registers and mmu/vac ops */
+#define ASI_CONTROL 0x02
+#define ASI_SEGMAP 0x03
+#define ASI_PTE 0x04
+#define ASI_HWFLUSHSEG 0x05
+#define ASI_HWFLUSHPAGE 0x06
+#define ASI_REGMAP 0x06
+#define ASI_HWFLUSHCONTEXT 0x07
+
+#define ASI_USERTXT 0x08
+#define ASI_KERNELTXT 0x09
+#define ASI_USERDATA 0x0a
+#define ASI_KERNELDATA 0x0b
+
+/* VAC Cache flushing on sun4c and sun4 */
+#define ASI_FLUSHSEG 0x0c
+#define ASI_FLUSHPG 0x0d
+#define ASI_FLUSHCTX 0x0e
+
+/* SPARCstation-5: only 6 bits are decoded. */
+/* wo = Write Only, rw = Read Write; */
+/* ss = Single Size, as = All Sizes; */
+#define ASI_M_RES00 0x00 /* Don't touch... */
+#define ASI_M_UNA01 0x01 /* Same here... */
+#define ASI_M_MXCC 0x02 /* Access to TI VIKING MXCC registers */
+#define ASI_M_FLUSH_PROBE 0x03 /* Reference MMU Flush/Probe; rw, ss */
+#define ASI_M_MMUREGS 0x04 /* MMU Registers; rw, ss */
+#define ASI_M_TLBDIAG 0x05 /* MMU TLB only Diagnostics */
+#define ASI_M_DIAGS 0x06 /* Reference MMU Diagnostics */
+#define ASI_M_IODIAG 0x07 /* MMU I/O TLB only Diagnostics */
+#define ASI_M_USERTXT 0x08 /* Same as ASI_USERTXT; rw, as */
+#define ASI_M_KERNELTXT 0x09 /* Same as ASI_KERNELTXT; rw, as */
+#define ASI_M_USERDATA 0x0A /* Same as ASI_USERDATA; rw, as */
+#define ASI_M_KERNELDATA 0x0B /* Same as ASI_KERNELDATA; rw, as */
+#define ASI_M_TXTC_TAG 0x0C /* Instruction Cache Tag; rw, ss */
+#define ASI_M_TXTC_DATA 0x0D /* Instruction Cache Data; rw, ss */
+#define ASI_M_DATAC_TAG 0x0E /* Data Cache Tag; rw, ss */
+#define ASI_M_DATAC_DATA 0x0F /* Data Cache Data; rw, ss */
+
+/* The following cache flushing ASIs work only with the 'sta'
+ * instruction. Results are unpredictable for 'swap' and 'ldstuba',
+ * so don't do it.
+ */
+
+/* These ASI flushes affect external caches too. */
+#define ASI_M_FLUSH_PAGE 0x10 /* Flush I&D Cache Line (page); wo, ss */
+#define ASI_M_FLUSH_SEG 0x11 /* Flush I&D Cache Line (seg); wo, ss */
+#define ASI_M_FLUSH_REGION 0x12 /* Flush I&D Cache Line (region); wo, ss */
+#define ASI_M_FLUSH_CTX 0x13 /* Flush I&D Cache Line (context); wo, ss */
+#define ASI_M_FLUSH_USER 0x14 /* Flush I&D Cache Line (user); wo, ss */
+
+/* Block-copy operations are available only on certain V8 cpus. */
+#define ASI_M_BCOPY 0x17 /* Block copy */
+
+/* These affect only the ICACHE and are Ross HyperSparc and TurboSparc specific. */
+#define ASI_M_IFLUSH_PAGE 0x18 /* Flush I Cache Line (page); wo, ss */
+#define ASI_M_IFLUSH_SEG 0x19 /* Flush I Cache Line (seg); wo, ss */
+#define ASI_M_IFLUSH_REGION 0x1A /* Flush I Cache Line (region); wo, ss */
+#define ASI_M_IFLUSH_CTX 0x1B /* Flush I Cache Line (context); wo, ss */
+#define ASI_M_IFLUSH_USER 0x1C /* Flush I Cache Line (user); wo, ss */
+
+/* Block-fill operations are available on certain V8 cpus */
+#define ASI_M_BFILL 0x1F
+
+/* This allows direct access to main memory, actually 0x20 to 0x2f are
+ * the available ASI's for physical ram pass-through, but I don't have
+ * any idea what the other ones do....
+ */
+
+#define ASI_M_BYPASS 0x20 /* Reference MMU bypass; rw, as */
+#define ASI_M_FBMEM 0x29 /* Graphics card frame buffer access */
+#define ASI_M_VMEUS 0x2A /* VME user 16-bit access */
+#define ASI_M_VMEPS 0x2B /* VME priv 16-bit access */
+#define ASI_M_VMEUT 0x2C /* VME user 32-bit access */
+#define ASI_M_VMEPT 0x2D /* VME priv 32-bit access */
+#define ASI_M_SBUS 0x2E /* Direct SBus access */
+#define ASI_M_CTL 0x2F /* Control Space (ECC and MXCC are here) */
+
+
+/* This is ROSS HyperSparc only. */
+#define ASI_M_FLUSH_IWHOLE 0x31 /* Flush entire ICACHE; wo, ss */
+
+/* Tsunami/Viking/TurboSparc i/d cache flash clear. */
+#define ASI_M_IC_FLCLEAR 0x36
+#define ASI_M_DC_FLCLEAR 0x37
+
+#define ASI_M_DCDR 0x39 /* Data Cache Diagnostics Register rw, ss */
+
+#define ASI_M_VIKING_TMP1 0x40 /* Emulation temporary 1 on Viking */
+#define ASI_M_VIKING_TMP2 0x41 /* Emulation temporary 2 on Viking */
+
+#define ASI_M_ACTION 0x4c /* Breakpoint Action Register (GNU/Viking) */
+
+#endif /* _SPARC_ASI_H */
diff --git a/roms/openbios/include/arch/sparc32/crs.h b/roms/openbios/include/arch/sparc32/crs.h
new file mode 100644
index 00000000..7b455937
--- /dev/null
+++ b/roms/openbios/include/arch/sparc32/crs.h
@@ -0,0 +1,14 @@
+/*
+ * Parts of asm-sparc/contregs.h
+ *
+ * contregs.h: Addresses of registers in the ASI_CONTROL alternate address
+ * space. These are for the mmu's context register, etc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress */
+#define AC_M_PCR 0x0000 /* shv Processor Control Reg */
+#define AC_M_CTPR 0x0100 /* shv Context Table Pointer Reg */
+#define AC_M_CXR 0x0200 /* shv Context Register */
+#define AC_M_SFSR 0x0300 /* shv Synchronous Fault Status Reg */
+#define AC_M_SFAR 0x0400 /* shv Synchronous Fault Address Reg */
diff --git a/roms/openbios/include/arch/sparc32/dma.h b/roms/openbios/include/arch/sparc32/dma.h
new file mode 100644
index 00000000..e1310557
--- /dev/null
+++ b/roms/openbios/include/arch/sparc32/dma.h
@@ -0,0 +1,213 @@
+/*
+ * Local copy of include/asm-sparc/dma.h
+ *
+ * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _ASM_SPARC_DMA_H
+#define _ASM_SPARC_DMA_H
+
+/* #include <linux/kernel.h> */
+/* #include <linux/types.h> */
+typedef unsigned int __u32;
+
+/* These are irrelevant for Sparc DMA, but we leave it in so that
+ * things can compile.
+ */
+#define MAX_DMA_CHANNELS 8
+#define MAX_DMA_ADDRESS (~0UL)
+#define DMA_MODE_READ 1
+#define DMA_MODE_WRITE 2
+
+/* Useful constants */
+#define SIZE_16MB (16*1024*1024)
+#define SIZE_64K (64*1024)
+
+/* Structure to describe the current status of DMA registers on the Sparc */
+struct sparc_dma_registers {
+ __volatile__ __u32 cond_reg; /* DMA condition register */
+ __volatile__ __u32 st_addr; /* Start address of this transfer */
+ __volatile__ __u32 cnt; /* How many bytes to transfer */
+ __volatile__ __u32 dma_test; /* DMA test register */
+};
+
+/* DVMA chip revisions */
+enum dvma_rev {
+ dvmarev0,
+ dvmaesc1,
+ dvmarev1,
+ dvmarev2,
+ dvmarev3,
+ dvmarevplus,
+ dvmahme
+};
+
+#define DMA_HASCOUNT(rev) ((rev)==dvmaesc1)
+
+#if 0
+/* Linux DMA information structure, filled during probe. */
+struct Linux_SBus_DMA {
+ struct Linux_SBus_DMA *next;
+ struct linux_sbus_device *SBus_dev;
+ struct sparc_dma_registers *regs;
+
+ /* Status, misc info */
+ int node; /* Prom node for this DMA device */
+ int running; /* Are we doing DMA now? */
+ int allocated; /* Are we "owned" by anyone yet? */
+
+ /* Transfer information. */
+ unsigned long addr; /* Start address of current transfer */
+ int nbytes; /* Size of current transfer */
+ int realbytes; /* For splitting up large transfers, etc. */
+
+ /* DMA revision */
+ enum dvma_rev revision;
+};
+
+extern struct Linux_SBus_DMA *dma_chain;
+#endif
+
+/* Broken hardware... */
+/* Have to sort this out. Does rev0 work fine on sun4[cmd] without isbroken?
+ * Or is rev0 present only on sun4 boxes? -jj */
+#define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev0 || (dma)->revision == dvmarev1)
+#define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1)
+
+/* Fields in the cond_reg register */
+/* First, the version identification bits */
+#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */
+#define DMA_VERS0 0x00000000 /* Sunray DMA version */
+#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */
+#define DMA_VERS1 0x80000000 /* DMA rev 1 */
+#define DMA_VERS2 0xa0000000 /* DMA rev 2 */
+#define DMA_VERHME 0xb0000000 /* DMA hme gate array */
+#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */
+
+#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */
+#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */
+#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */
+#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */
+#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */
+#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */
+#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */
+#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */
+#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */
+#define DMA_ST_WRITE 0x00000100 /* write from device to memory */
+#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */
+#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */
+#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */
+#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */
+#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */
+#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */
+#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */
+#define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */
+#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */
+#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */
+#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */
+#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */
+#define DMA_E_BURST8 0x00040000 /* ENET: SBUS r/w burst size */
+#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */
+#define DMA_BRST64 0x00080000 /* SCSI: 64byte bursts (HME on UltraSparc only) */
+#define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */
+#define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */
+#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */
+#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */
+#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */
+#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */
+#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */
+#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */
+#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */
+#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */
+#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */
+#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */
+#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */
+#define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */
+
+/* Values describing the burst-size property from the PROM */
+#define DMA_BURST1 0x01
+#define DMA_BURST2 0x02
+#define DMA_BURST4 0x04
+#define DMA_BURST8 0x08
+#define DMA_BURST16 0x10
+#define DMA_BURST32 0x20
+#define DMA_BURST64 0x40
+#define DMA_BURSTBITS 0x7f
+
+/* Determine highest possible final transfer address given a base */
+#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
+
+/* Yes, I hack a lot of elisp in my spare time... */
+#define DMA_ERROR_P(regs) ((((regs)->cond_reg) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs) ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
+#define DMA_WRITE_P(regs) ((((regs)->cond_reg) & DMA_ST_WRITE))
+#define DMA_OFF(regs) ((((regs)->cond_reg) &= (~DMA_ENABLE)))
+#define DMA_INTSOFF(regs) ((((regs)->cond_reg) &= (~DMA_INT_ENAB)))
+#define DMA_INTSON(regs) ((((regs)->cond_reg) |= (DMA_INT_ENAB)))
+#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV))
+#define DMA_SETSTART(regs, addr) ((((regs)->st_addr) = (char *) addr))
+#define DMA_BEGINDMA_W(regs) \
+ ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB))))
+#define DMA_BEGINDMA_R(regs) \
+ ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE)))))
+
+#if 0
+
+/* For certain DMA chips, we need to disable ints upon irq entry
+ * and turn them back on when we are done. So in any ESP interrupt
+ * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT
+ * when leaving the handler. You have been warned...
+ */
+#define DMA_IRQ_ENTRY(dma, dregs) do { \
+ if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \
+ } while (0)
+
+#define DMA_IRQ_EXIT(dma, dregs) do { \
+ if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \
+ } while(0)
+
+
+/* Pause until counter runs out or BIT isn't set in the DMA condition
+ * register.
+ */
+extern __inline__ void sparc_dma_pause(struct sparc_dma_registers *regs,
+ unsigned long bit)
+{
+ int ctr = 50000; /* Let's find some bugs ;) */
+
+ /* Busy wait until the bit is not set any more */
+ while((regs->cond_reg&bit) && (ctr>0)) {
+ ctr--;
+ __delay(5);
+ }
+
+ /* Check for bogus outcome. */
+ if(!ctr)
+ panic("DMA timeout");
+}
+
+/* Reset the friggin' thing... */
+#define DMA_RESET(dma) do { \
+ struct sparc_dma_registers *regs = dma->regs; \
+ /* Let the current FIFO drain itself */ \
+ sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN)); \
+ /* Reset the logic */ \
+ regs->cond_reg |= (DMA_RST_SCSI); /* assert */ \
+ __delay(400); /* let the bits set ;) */ \
+ regs->cond_reg &= ~(DMA_RST_SCSI); /* de-assert */ \
+ sparc_dma_enable_interrupts(regs); /* Re-enable interrupts */ \
+ /* Enable FAST transfers if available */ \
+ if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS; \
+ dma->running = 0; \
+} while(0)
+
+#define for_each_dvma(dma) \
+ for((dma) = dma_chain; (dma); (dma) = (dma)->next)
+
+extern int get_dma_list(char *);
+extern int request_dma(unsigned int, __const__ char *);
+extern void free_dma(unsigned int);
+
+#endif
+
+#endif /* !(_ASM_SPARC_DMA_H) */
diff --git a/roms/openbios/include/arch/sparc32/elf.h b/roms/openbios/include/arch/sparc32/elf.h
new file mode 100644
index 00000000..8d429d7a
--- /dev/null
+++ b/roms/openbios/include/arch/sparc32/elf.h
@@ -0,0 +1,5 @@
+#define ARCH_ELF_CLASS ELFCLASS32
+#define ARCH_ELF_DATA ELFDATA2MSB
+#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_SPARC || (x)==EM_SPARC32PLUS)
+typedef Elf32_Ehdr Elf_ehdr;
+typedef Elf32_Phdr Elf_phdr;
diff --git a/roms/openbios/include/arch/sparc32/io.h b/roms/openbios/include/arch/sparc32/io.h
new file mode 100644
index 00000000..011770ad
--- /dev/null
+++ b/roms/openbios/include/arch/sparc32/io.h
@@ -0,0 +1,201 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#include "asm/types.h"
+
+extern unsigned int va_shift; // Set in entry.S
+
+// Defined in ldscript
+extern char _start, _data, _stack, _estack, _end, _vmem, _evmem, _iomem;
+
+// XXX check use and merge
+#define phys_to_virt(phys) ((void *) ((unsigned long) (phys)))
+#define virt_to_phys(virt) ((unsigned long) (virt))
+
+#ifndef BOOTSTRAP
+
+#ifndef _IO_BASE
+#define _IO_BASE 0
+#endif
+
+/*
+ * The insw/outsw/insl/outsl macros don't do byte-swapping.
+ * They are only used in practice for transferring buffers which
+ * are arrays of bytes, and byte-swapping is not appropriate in
+ * that case. - paulus
+ */
+#define insw(port, buf, ns) _insw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns))
+#define outsw(port, buf, ns) _outsw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns))
+
+#define inb(port) in_8((uint8_t *)((port)+_IO_BASE))
+#define outb(val, port) out_8((uint8_t *)((port)+_IO_BASE), (val))
+#define inw(port) in_le16((uint16_t *)((port)+_IO_BASE))
+#define outw(val, port) out_le16((uint16_t *)((port)+_IO_BASE), (val))
+#define inl(port) in_le32((uint32_t *)((port)+_IO_BASE))
+#define outl(val, port) out_le32((uint32_t *)((port)+_IO_BASE), (val))
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ */
+static inline int in_8(volatile unsigned char *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("ldub [%1], %0\n\t"
+ "stbar\n\t"
+ :"=r"(ret):"r"(addr):"memory");
+
+ return ret;
+}
+
+static inline void out_8(volatile unsigned char *addr, int val)
+{
+ __asm__ __volatile__("stb %0, [%1]\n\t"
+ "stbar\n\t"
+ : : "r"(val), "r"(addr):"memory");
+}
+
+static inline int in_le16(volatile unsigned short *addr)
+{
+ int ret;
+
+ // XXX
+ __asm__ __volatile__("lduh [%1], %0\n\t"
+ "stbar\n\t"
+ :"=r"(ret):"r"(addr):"memory");
+
+ return ret;
+}
+
+static inline int in_be16(volatile unsigned short *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lduh [%1], %0\n\t"
+ "stbar\n\t"
+ :"=r"(ret):"r"(addr):"memory");
+
+ return ret;
+}
+
+static inline void out_le16(volatile unsigned short *addr, int val)
+{
+ // XXX
+ __asm__ __volatile__("sth %0, [%1]\n\t"
+ "stbar\n\t"
+ : : "r"(val), "r"(addr):"memory");
+}
+
+static inline void out_be16(volatile unsigned short *addr, int val)
+{
+ __asm__ __volatile__("sth %0, [%1]\n\t"
+ "stbar\n\t"
+ : : "r"(val), "r"(addr):"memory");
+}
+
+static inline unsigned in_le32(volatile unsigned *addr)
+{
+ unsigned ret;
+
+ // XXX
+ __asm__ __volatile__("ld [%1], %0\n\t"
+ "stbar\n\t"
+ :"=r"(ret):"r"(addr):"memory");
+
+ return ret;
+}
+
+static inline unsigned in_be32(volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("ld [%1], %0\n\t"
+ "stbar\n\t"
+ :"=r"(ret):"r"(addr):"memory");
+
+ return ret;
+}
+
+static inline void out_le32(volatile unsigned *addr, int val)
+{
+ // XXX
+ __asm__ __volatile__("st %0, [%1]\n\t"
+ "stbar\n\t"
+ : : "r"(val), "r"(addr):"memory");
+}
+
+static inline void out_be32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("st %0, [%1]\n\t"
+ "stbar\n\t"
+ : : "r"(val), "r"(addr):"memory");
+}
+
+static inline void _insw_ns(volatile uint16_t * port, void *buf, int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ *b++ = in_le16(port);
+ ns--;
+ }
+}
+
+static inline void _outsw_ns(volatile uint16_t * port, const void *buf,
+ int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ out_le16(port, *b++);
+ ns--;
+ }
+}
+
+static inline void _insw(volatile uint16_t * port, void *buf, int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ *b++ = in_be16(port);
+ ns--;
+ }
+}
+
+static inline void _outsw(volatile uint16_t * port, const void *buf,
+ int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ out_be16(port, *b++);
+ ns--;
+ }
+}
+#else /* BOOTSTRAP */
+#ifdef FCOMPILER
+#define inb(reg) ((u8)0xff)
+#define inw(reg) ((u16)0xffff)
+#define inl(reg) ((u32)0xffffffff)
+#define outb(reg, val) do{} while(0)
+#define outw(reg, val) do{} while(0)
+#define outl(reg, val) do{} while(0)
+#else
+extern u8 inb(u32 reg);
+extern u16 inw(u32 reg);
+extern u32 inl(u32 reg);
+extern void insw(u32 reg, void *addr, unsigned long count);
+extern void outb(u32 reg, u8 val);
+extern void outw(u32 reg, u16 val);
+extern void outl(u32 reg, u32 val);
+extern void outsw(u32 reg, const void *addr, unsigned long count);
+#endif
+#endif
+
+#if defined(CONFIG_QEMU)
+#define FW_CFG_ARCH_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
+#define FW_CFG_ARCH_WIDTH (FW_CFG_ARCH_LOCAL + 0x01)
+#define FW_CFG_ARCH_HEIGHT (FW_CFG_ARCH_LOCAL + 0x02)
+#endif
+
+#endif /* _ASM_IO_H */
diff --git a/roms/openbios/include/arch/sparc32/ofmem_sparc32.h b/roms/openbios/include/arch/sparc32/ofmem_sparc32.h
new file mode 100644
index 00000000..efc21b49
--- /dev/null
+++ b/roms/openbios/include/arch/sparc32/ofmem_sparc32.h
@@ -0,0 +1,31 @@
+/*
+ * <ofmem_sparc32.h>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999, 2002 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_OFMEM_SPARC32
+#define _H_OFMEM_SPARC32
+
+#include "libopenbios/ofmem.h"
+
+#define OF_CODE_START 0xffd00000
+#define OFMEM_VIRT_TOP 0xfe000000
+
+struct mem;
+extern struct mem cdvmem;
+
+extern unsigned long *l1;
+extern unsigned long find_pte(unsigned long va, int alloc);
+
+void mem_init(struct mem *t, char *begin, char *limit);
+void *mem_alloc(struct mem *t, int size, int align);
+
+#endif /* _H_OFMEM_SPARC32 */ \ No newline at end of file
diff --git a/roms/openbios/include/arch/sparc32/types.h b/roms/openbios/include/arch/sparc32/types.h
new file mode 100644
index 00000000..3f37d4e0
--- /dev/null
+++ b/roms/openbios/include/arch/sparc32/types.h
@@ -0,0 +1,93 @@
+/* tag: data types for forth engine
+ *
+ * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __TYPES_H
+#define __TYPES_H
+
+#include "mconfig.h"
+
+#ifdef BOOTSTRAP
+#include <inttypes.h>
+#else
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef long long int64_t;
+typedef long intptr_t;
+
+#define PRId32 "d"
+#define PRIu32 "u"
+#define PRIx32 "x"
+#define PRIX32 "X"
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#define PRIx64 "llx"
+#define PRIX64 "llX"
+#endif
+
+/* endianess */
+#include "autoconf.h"
+
+/* physical address: 36 bits */
+
+typedef uint64_t phys_addr_t;
+
+#define FMT_plx "%09" PRIx64
+
+/* cell based types */
+
+typedef int32_t cell;
+typedef uint32_t ucell;
+typedef long long dcell;
+typedef unsigned long long ducell;
+
+#define FMT_cell "%" PRId32
+#define FMT_ucell "%" PRIu32
+#define FMT_ucellx "%08" PRIx32
+#define FMT_ucellX "%08" PRIX32
+
+typedef int32_t prom_arg_t;
+typedef uint32_t prom_uarg_t;
+
+#define PRIdPROMARG PRId32
+#define PRIuPROMARG PRIu32
+#define PRIxPROMARG PRIx32
+#define FMT_prom_arg "%" PRIdPROMARG
+#define FMT_prom_uarg "%" PRIuPROMARG
+#define FMT_prom_uargx "%08" PRIxPROMARG
+
+#define FMT_elf "%#x"
+#define FMT_sizet "%lx"
+#define FMT_aout_ehdr "%lx"
+
+#define bitspercell (sizeof(cell)<<3)
+#define bitsperdcell (sizeof(dcell)<<3)
+
+#define BITS 32
+
+#define PAGE_SHIFT 12
+
+/* size named types */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+typedef signed char s8;
+typedef short s16;
+typedef int s32;
+typedef long long s64;
+
+#endif
diff --git a/roms/openbios/include/arch/sparc64/a.out.h b/roms/openbios/include/arch/sparc64/a.out.h
new file mode 100644
index 00000000..35cb5c9e
--- /dev/null
+++ b/roms/openbios/include/arch/sparc64/a.out.h
@@ -0,0 +1,108 @@
+/* $Id: a.out.h,v 1.8 2002/02/09 19:49:31 davem Exp $ */
+#ifndef __SPARC64_A_OUT_H__
+#define __SPARC64_A_OUT_H__
+
+#define SPARC_PGSIZE 0x2000 /* Thanks to the sun4 architecture... */
+#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */
+
+#ifndef __ASSEMBLY__
+
+struct exec {
+ unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */
+ unsigned char a_toolversion:7;
+ unsigned char a_machtype;
+ unsigned short a_info;
+ unsigned int a_text; /* length of text, in bytes */
+ unsigned int a_data; /* length of data, in bytes */
+ unsigned int a_bss; /* length of bss, in bytes */
+ unsigned int a_syms; /* length of symbol table, in bytes */
+ unsigned int a_entry; /* where program begins */
+ unsigned int a_trsize;
+ unsigned int a_drsize;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+/* Where in the file does the text information begin? */
+#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
+
+/* Where do the Symbols start? */
+#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \
+ (x).a_data + (x).a_trsize + \
+ (x).a_drsize)
+
+/* Where does text segment go in memory after being loaded? */
+#define N_TXTADDR(x) (unsigned long)(((N_MAGIC(x) == ZMAGIC) && \
+ ((x).a_entry < SPARC_PGSIZE)) ? \
+ 0 : SPARC_PGSIZE)
+
+/* And same for the data segment.. */
+#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \
+ (N_TXTADDR(x) + (x).a_text) \
+ : (unsigned long)(_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+
+#define N_TRSIZE(a) ((a).a_trsize)
+#define N_DRSIZE(a) ((a).a_drsize)
+#define N_SYMSIZE(a) ((a).a_syms)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Sparc relocation types
+ */
+enum reloc_type
+{
+ RELOC_8,
+ RELOC_16,
+ RELOC_32, /* simplest relocs */
+ RELOC_DISP8,
+ RELOC_DISP16,
+ RELOC_DISP32, /* Disp's (pc-rel) */
+ RELOC_WDISP30,
+ RELOC_WDISP22, /* SR word disp's */
+ RELOC_HI22,
+ RELOC_22, /* SR 22-bit relocs */
+ RELOC_13,
+ RELOC_LO10, /* SR 13&10-bit relocs */
+ RELOC_SFA_BASE,
+ RELOC_SFA_OFF13, /* SR S.F.A. relocs */
+ RELOC_BASE10,
+ RELOC_BASE13,
+ RELOC_BASE22, /* base_relative pic */
+ RELOC_PC10,
+ RELOC_PC22, /* special pc-rel pic */
+ RELOC_JMP_TBL, /* jmp_tbl_rel in pic */
+ RELOC_SEGOFF16, /* ShLib offset-in-seg */
+ RELOC_GLOB_DAT,
+ RELOC_JMP_SLOT,
+ RELOC_RELATIVE /* rtld relocs */
+};
+
+/*
+ * Format of a relocation datum.
+ */
+struct relocation_info /* used when header.a_machtype == M_SPARC */
+{
+ unsigned int r_address; /* relocation addr */
+ unsigned int r_index:24; /* segment index or symbol index */
+ unsigned int r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
+ int r_pad:2; /* <unused> */
+ enum reloc_type r_type:5; /* type of relocation to perform */
+ int r_addend; /* addend for relocation value */
+};
+
+#define N_RELOCATION_INFO_DECLARED 1
+
+#ifdef __KERNEL__
+
+#define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE)
+#define STACK_TOP64 (0x0000080000000000UL - (1UL << 32UL))
+
+#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+ STACK_TOP32 : STACK_TOP64)
+
+#endif
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_A_OUT_H__) */
diff --git a/roms/openbios/include/arch/sparc64/asi.h b/roms/openbios/include/arch/sparc64/asi.h
new file mode 100644
index 00000000..53485566
--- /dev/null
+++ b/roms/openbios/include/arch/sparc64/asi.h
@@ -0,0 +1,145 @@
+/* $Id: asi.h,v 1.5 2001/03/29 11:47:47 davem Exp $ */
+#ifndef _SPARC64_ASI_H
+#define _SPARC64_ASI_H
+
+/* asi.h: Address Space Identifier values for the V9.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* V9 Architecture mandary ASIs. */
+#define ASI_N 0x04 /* Nucleus */
+#define ASI_NL 0x0c /* Nucleus, little endian */
+#define ASI_AIUP 0x10 /* Primary, user */
+#define ASI_AIUS 0x11 /* Secondary, user */
+#define ASI_AIUPL 0x18 /* Primary, user, little endian */
+#define ASI_AIUSL 0x19 /* Secondary, user, little endian */
+#define ASI_P 0x80 /* Primary, implicit */
+#define ASI_S 0x81 /* Secondary, implicit */
+#define ASI_PNF 0x82 /* Primary, no fault */
+#define ASI_SNF 0x83 /* Secondary, no fault */
+#define ASI_PL 0x88 /* Primary, implicit, l-endian */
+#define ASI_SL 0x89 /* Secondary, implicit, l-endian */
+#define ASI_PNFL 0x8a /* Primary, no fault, l-endian */
+#define ASI_SNFL 0x8b /* Secondary, no fault, l-endian */
+
+/* SpitFire and later extended ASIs. The "(III)" marker designates
+ * UltraSparc-III and later specific ASIs. The "(CMT)" marker designates
+ * Chip Multi Threading specific ASIs.
+ */
+#define ASI_PHYS_USE_EC 0x14 /* PADDR, E-cachable */
+#define ASI_PHYS_BYPASS_EC_E 0x15 /* PADDR, E-bit */
+#define ASI_PHYS_USE_EC_L 0x1c /* PADDR, E-cachable, little endian*/
+#define ASI_PHYS_BYPASS_EC_E_L 0x1d /* PADDR, E-bit, little endian */
+#define ASI_NUCLEUS_QUAD_LDD 0x24 /* Cachable, qword load */
+#define ASI_NUCLEUS_QUAD_LDD_L 0x2c /* Cachable, qword load, l-endian */
+#define ASI_PCACHE_DATA_STATUS 0x30 /* (III) PCache data stat RAM diag */
+#define ASI_PCACHE_DATA 0x31 /* (III) PCache data RAM diag */
+#define ASI_PCACHE_TAG 0x32 /* (III) PCache tag RAM diag */
+#define ASI_PCACHE_SNOOP_TAG 0x33 /* (III) PCache snoop tag RAM diag */
+#define ASI_QUAD_LDD_PHYS 0x34 /* (III+) PADDR, qword load */
+#define ASI_WCACHE_VALID_BITS 0x38 /* (III) WCache Valid Bits diag */
+#define ASI_WCACHE_DATA 0x39 /* (III) WCache data RAM diag */
+#define ASI_WCACHE_TAG 0x3a /* (III) WCache tag RAM diag */
+#define ASI_WCACHE_SNOOP_TAG 0x3b /* (III) WCache snoop tag RAM diag */
+#define ASI_QUAD_LDD_PHYS_L 0x3c /* (III+) PADDR, qw-load, l-endian */
+#define ASI_SRAM_FAST_INIT 0x40 /* (III+) Fast SRAM init */
+#define ASI_CORE_AVAILABLE 0x41 /* (CMT) LP Available */
+#define ASI_CORE_ENABLE_STAT 0x41 /* (CMT) LP Enable Status */
+#define ASI_CORE_ENABLE 0x41 /* (CMT) LP Enable RW */
+#define ASI_XIR_STEERING 0x41 /* (CMT) XIR Steering RW */
+#define ASI_CORE_RUNNING_RW 0x41 /* (CMT) LP Running RW */
+#define ASI_CORE_RUNNING_W1S 0x41 /* (CMT) LP Running Write-One Set */
+#define ASI_CORE_RUNNING_W1C 0x41 /* (CMT) LP Running Write-One Clr */
+#define ASI_CORE_RUNNING_STAT 0x41 /* (CMT) LP Running Status */
+#define ASI_CMT_ERROR_STEERING 0x41 /* (CMT) Error Steering RW */
+#define ASI_DCACHE_INVALIDATE 0x42 /* (III) DCache Invalidate diag */
+#define ASI_DCACHE_UTAG 0x43 /* (III) DCache uTag diag */
+#define ASI_DCACHE_SNOOP_TAG 0x44 /* (III) DCache snoop tag RAM diag */
+#define ASI_LSU_CONTROL 0x45 /* Load-store control unit */
+#define ASI_DCU_CONTROL_REG 0x45 /* (III) DCache Unit Control reg */
+#define ASI_DCACHE_DATA 0x46 /* DCache data-ram diag access */
+#define ASI_DCACHE_TAG 0x47 /* Dcache tag/valid ram diag access*/
+#define ASI_INTR_DISPATCH_STAT 0x48 /* IRQ vector dispatch status */
+#define ASI_INTR_RECEIVE 0x49 /* IRQ vector receive status */
+#define ASI_UPA_CONFIG 0x4a /* UPA config space */
+#define ASI_JBUS_CONFIG 0x4a /* (IIIi) JBUS Config Register */
+#define ASI_SAFARI_CONFIG 0x4a /* (III) Safari Config Register */
+#define ASI_SAFARI_ADDRESS 0x4a /* (III) Safari Address Register */
+#define ASI_ESTATE_ERROR_EN 0x4b /* E-cache error enable space */
+#define ASI_AFSR 0x4c /* Async fault status register */
+#define ASI_AFAR 0x4d /* Async fault address register */
+#define ASI_EC_TAG_DATA 0x4e /* E-cache tag/valid ram diag acc */
+#define ASI_IMMU 0x50 /* Insn-MMU main register space */
+#define ASI_IMMU_TSB_8KB_PTR 0x51 /* Insn-MMU 8KB TSB pointer reg */
+#define ASI_IMMU_TSB_64KB_PTR 0x52 /* Insn-MMU 64KB TSB pointer reg */
+#define ASI_ITLB_DATA_IN 0x54 /* Insn-MMU TLB data in reg */
+#define ASI_ITLB_DATA_ACCESS 0x55 /* Insn-MMU TLB data access reg */
+#define ASI_ITLB_TAG_READ 0x56 /* Insn-MMU TLB tag read reg */
+#define ASI_IMMU_DEMAP 0x57 /* Insn-MMU TLB demap */
+#define ASI_DMMU 0x58 /* Data-MMU main register space */
+#define ASI_DMMU_TSB_8KB_PTR 0x59 /* Data-MMU 8KB TSB pointer reg */
+#define ASI_DMMU_TSB_64KB_PTR 0x5a /* Data-MMU 16KB TSB pointer reg */
+#define ASI_DMMU_TSB_DIRECT_PTR 0x5b /* Data-MMU TSB direct pointer reg */
+#define ASI_DTLB_DATA_IN 0x5c /* Data-MMU TLB data in reg */
+#define ASI_DTLB_DATA_ACCESS 0x5d /* Data-MMU TLB data access reg */
+#define ASI_DTLB_TAG_READ 0x5e /* Data-MMU TLB tag read reg */
+#define ASI_DMMU_DEMAP 0x5f /* Data-MMU TLB demap */
+#define ASI_IIU_INST_TRAP 0x60 /* (III) Instruction Breakpoint */
+#define ASI_INTR_ID 0x63 /* (CMT) Interrupt ID register */
+#define ASI_CORE_ID 0x63 /* (CMT) LP ID register */
+#define ASI_CESR_ID 0x63 /* (CMT) CESR ID register */
+#define ASI_IC_INSTR 0x66 /* Insn cache instrucion ram diag */
+#define ASI_IC_TAG 0x67 /* Insn cache tag/valid ram diag */
+#define ASI_IC_STAG 0x68 /* (III) Insn cache snoop tag ram */
+#define ASI_IC_PRE_DECODE 0x6e /* Insn cache pre-decode ram diag */
+#define ASI_IC_NEXT_FIELD 0x6f /* Insn cache next-field ram diag */
+#define ASI_BRPRED_ARRAY 0x6f /* (III) Branch Prediction RAM diag*/
+#define ASI_BLK_AIUP 0x70 /* Primary, user, block load/store */
+#define ASI_BLK_AIUS 0x71 /* Secondary, user, block ld/st */
+#define ASI_MCU_CTRL_REG 0x72 /* (III) Memory controller regs */
+#define ASI_EC_DATA 0x74 /* (III) E-cache data staging reg */
+#define ASI_EC_CTRL 0x75 /* (III) E-cache control reg */
+#define ASI_EC_W 0x76 /* E-cache diag write access */
+#define ASI_UDB_ERROR_W 0x77 /* External UDB error regs W */
+#define ASI_UDB_CONTROL_W 0x77 /* External UDB control regs W */
+#define ASI_INTR_W 0x77 /* IRQ vector dispatch write */
+#define ASI_INTR_DATAN_W 0x77 /* (III) Out irq vector data reg N */
+#define ASI_INTR_DISPATCH_W 0x77 /* (III) Interrupt vector dispatch */
+#define ASI_BLK_AIUPL 0x78 /* Primary, user, little, blk ld/st*/
+#define ASI_BLK_AIUSL 0x79 /* Secondary, user, little, blk ld/st*/
+#define ASI_EC_R 0x7e /* E-cache diag read access */
+#define ASI_UDBH_ERROR_R 0x7f /* External UDB error regs rd hi */
+#define ASI_UDBL_ERROR_R 0x7f /* External UDB error regs rd low */
+#define ASI_UDBH_CONTROL_R 0x7f /* External UDB control regs rd hi */
+#define ASI_UDBL_CONTROL_R 0x7f /* External UDB control regs rd low*/
+#define ASI_INTR_R 0x7f /* IRQ vector dispatch read */
+#define ASI_INTR_DATAN_R 0x7f /* (III) In irq vector data reg N */
+#define ASI_PST8_P 0xc0 /* Primary, 8 8-bit, partial */
+#define ASI_PST8_S 0xc1 /* Secondary, 8 8-bit, partial */
+#define ASI_PST16_P 0xc2 /* Primary, 4 16-bit, partial */
+#define ASI_PST16_S 0xc3 /* Secondary, 4 16-bit, partial */
+#define ASI_PST32_P 0xc4 /* Primary, 2 32-bit, partial */
+#define ASI_PST32_S 0xc5 /* Secondary, 2 32-bit, partial */
+#define ASI_PST8_PL 0xc8 /* Primary, 8 8-bit, partial, L */
+#define ASI_PST8_SL 0xc9 /* Secondary, 8 8-bit, partial, L */
+#define ASI_PST16_PL 0xca /* Primary, 4 16-bit, partial, L */
+#define ASI_PST16_SL 0xcb /* Secondary, 4 16-bit, partial, L */
+#define ASI_PST32_PL 0xcc /* Primary, 2 32-bit, partial, L */
+#define ASI_PST32_SL 0xcd /* Secondary, 2 32-bit, partial, L */
+#define ASI_FL8_P 0xd0 /* Primary, 1 8-bit, fpu ld/st */
+#define ASI_FL8_S 0xd1 /* Secondary, 1 8-bit, fpu ld/st */
+#define ASI_FL16_P 0xd2 /* Primary, 1 16-bit, fpu ld/st */
+#define ASI_FL16_S 0xd3 /* Secondary, 1 16-bit, fpu ld/st */
+#define ASI_FL8_PL 0xd8 /* Primary, 1 8-bit, fpu ld/st, L */
+#define ASI_FL8_SL 0xd9 /* Secondary, 1 8-bit, fpu ld/st, L*/
+#define ASI_FL16_PL 0xda /* Primary, 1 16-bit, fpu ld/st, L */
+#define ASI_FL16_SL 0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/
+#define ASI_BLK_COMMIT_P 0xe0 /* Primary, blk store commit */
+#define ASI_BLK_COMMIT_S 0xe1 /* Secondary, blk store commit */
+#define ASI_BLK_P 0xf0 /* Primary, blk ld/st */
+#define ASI_BLK_S 0xf1 /* Secondary, blk ld/st */
+#define ASI_BLK_PL 0xf8 /* Primary, blk ld/st, little */
+#define ASI_BLK_SL 0xf9 /* Secondary, blk ld/st, little */
+
+#endif /* _SPARC64_ASI_H */
diff --git a/roms/openbios/include/arch/sparc64/elf.h b/roms/openbios/include/arch/sparc64/elf.h
new file mode 100644
index 00000000..8acad1a4
--- /dev/null
+++ b/roms/openbios/include/arch/sparc64/elf.h
@@ -0,0 +1,5 @@
+#define ARCH_ELF_CLASS ELFCLASS64
+#define ARCH_ELF_DATA ELFDATA2MSB
+#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_SPARCV9)
+typedef Elf64_Ehdr Elf_ehdr;
+typedef Elf64_Phdr Elf_phdr;
diff --git a/roms/openbios/include/arch/sparc64/io.h b/roms/openbios/include/arch/sparc64/io.h
new file mode 100644
index 00000000..2e4dfa37
--- /dev/null
+++ b/roms/openbios/include/arch/sparc64/io.h
@@ -0,0 +1,209 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#include "asm/types.h"
+#include "asi.h"
+
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+
+extern unsigned long va_shift; // Set in entry.S
+// Defined in ldscript
+extern char _start, _data, _stack, _estack, _end, _iomem;
+
+// XXX check use and merge
+#define phys_to_virt(phys) ((void *) ((unsigned long) (phys)))
+#define virt_to_phys(virt) ((unsigned long) (virt))
+
+#ifndef BOOTSTRAP
+
+extern unsigned long isa_io_base;
+
+/*
+ * The insw/outsw/insl/outsl macros don't do byte-swapping.
+ * They are only used in practice for transferring buffers which
+ * are arrays of bytes, and byte-swapping is not appropriate in
+ * that case. - paulus
+ */
+#define insw(port, buf, ns) _insw_ns((uint16_t *)((port)+isa_io_base), (buf), (ns))
+#define outsw(port, buf, ns) _outsw_ns((uint16_t *)((port)+isa_io_base), (buf), (ns))
+
+#define inb(port) in_8((uint8_t *)((port)+isa_io_base))
+#define outb(val, port) out_8((uint8_t *)((port)+isa_io_base), (val))
+#define inw(port) in_be16((uint16_t *)((port)+isa_io_base))
+#define outw(val, port) out_be16((uint16_t *)((port)+isa_io_base), (val))
+#define inl(port) in_be32((uint32_t *)((port)+isa_io_base))
+#define outl(val, port) out_be32((uint32_t *)((port)+isa_io_base), (val))
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ * On Sparc64, BE versions must swap bytes using LE access ASI.
+ */
+static inline int in_8(volatile unsigned char *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lduba [%1] %2, %0\n\t"
+ : "=r"(ret)
+ : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+
+ return ret;
+}
+
+static inline void out_8(volatile unsigned char *addr, int val)
+{
+ __asm__ __volatile__("stba %0, [%1] %2\n\t"
+ :
+ : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+}
+
+static inline int in_le16(volatile unsigned short *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lduha [%1] %2, %0\n\t"
+ : "=r"(ret)
+ : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+
+ return ret;
+}
+
+static inline int in_be16(volatile unsigned short *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lduha [%1] %2, %0\n\t"
+ : "=r"(ret)
+ : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+static inline void out_le16(volatile unsigned short *addr, int val)
+{
+
+ __asm__ __volatile__("stha %0, [%1] %2\n\t"
+ :
+ : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+}
+
+static inline void out_be16(volatile unsigned short *addr, int val)
+{
+ __asm__ __volatile__("stha %0, [%1] %2\n\t"
+ :
+ : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+static inline unsigned in_le32(volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lduwa [%1] %2, %0\n\t"
+ : "=r"(ret)
+ : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+
+ return ret;
+}
+
+static inline unsigned in_be32(volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lduwa [%1] %2, %0\n\t"
+ : "=r"(ret)
+ : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ return ret;
+}
+
+static inline void out_le32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stwa %0, [%1] %2\n\t"
+ :
+ : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E)
+ : "memory");
+}
+
+static inline void out_be32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stwa %0, [%1] %2\n\t"
+ :
+ : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+static inline void _insw_ns(volatile uint16_t * port, void *buf, int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ *b++ = in_le16(port);
+ ns--;
+ }
+}
+
+static inline void _outsw_ns(volatile uint16_t * port, const void *buf,
+ int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ out_le16(port, *b++);
+ ns--;
+ }
+}
+
+static inline void _insw(volatile uint16_t * port, void *buf, int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ *b++ = in_be16(port);
+ ns--;
+ }
+}
+
+static inline void _outsw(volatile uint16_t * port, const void *buf,
+ int ns)
+{
+ uint16_t *b = (uint16_t *) buf;
+
+ while (ns > 0) {
+ out_be16(port, *b++);
+ ns--;
+ }
+}
+#else /* BOOTSTRAP */
+#ifdef FCOMPILER
+#define inb(reg) ((u8)0xff)
+#define inw(reg) ((u16)0xffff)
+#define inl(reg) ((u32)0xffffffff)
+#define outb(reg, val) do{} while(0)
+#define outw(reg, val) do{} while(0)
+#define outl(reg, val) do{} while(0)
+#else
+extern u8 inb(u32 reg);
+extern u16 inw(u32 reg);
+extern u32 inl(u32 reg);
+extern void insw(u32 reg, void *addr, unsigned long count);
+extern void outb(u32 reg, u8 val);
+extern void outw(u32 reg, u16 val);
+extern void outl(u32 reg, u32 val);
+extern void outsw(u32 reg, const void *addr, unsigned long count);
+#endif
+#endif
+
+#if defined(CONFIG_QEMU)
+#define FW_CFG_ARCH_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
+#define FW_CFG_ARCH_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
+#define FW_CFG_ARCH_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
+#endif
+
+#endif /* _ASM_IO_H */
diff --git a/roms/openbios/include/arch/sparc64/ofmem_sparc64.h b/roms/openbios/include/arch/sparc64/ofmem_sparc64.h
new file mode 100644
index 00000000..7ff24ae3
--- /dev/null
+++ b/roms/openbios/include/arch/sparc64/ofmem_sparc64.h
@@ -0,0 +1,50 @@
+/*
+ * <ofmem_sparc64.h>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999, 2002 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_OFMEM_SPARC64
+#define _H_OFMEM_SPARC64
+
+#include "libopenbios/ofmem.h"
+
+#define PAGE_SIZE_4M (4 * 1024 * 1024)
+#define PAGE_SIZE_512K (512 * 1024)
+#define PAGE_SIZE_64K (64 * 1024)
+#define PAGE_SIZE_8K (8 * 1024)
+#define PAGE_MASK_4M (4 * 1024 * 1024 - 1)
+#define PAGE_MASK_512K (512 * 1024 - 1)
+#define PAGE_MASK_64K (64 * 1024 - 1)
+#define PAGE_MASK_8K (8 * 1024 - 1)
+
+extern ucell *va2ttedata;
+extern unsigned long find_tte(unsigned long va);
+
+void itlb_load2(unsigned long vaddr, unsigned long tte_data);
+void itlb_load3(unsigned long vaddr, unsigned long tte_data, unsigned long tte_index);
+unsigned long itlb_faultva(void);
+void itlb_demap(unsigned long vaddr);
+void dtlb_load2(unsigned long vaddr, unsigned long tte_data);
+void dtlb_load3(unsigned long vaddr, unsigned long tte_data, unsigned long tte_index);
+unsigned long dtlb_faultva(void);
+void dtlb_demap(unsigned long vaddr);
+
+typedef int (*translation_entry_cb)(ucell phys, ucell virt, ucell size, ucell mode);
+
+extern void ofmem_walk_boot_map(translation_entry_cb cb);
+
+extern translation_t **g_ofmem_translations;
+
+extern void dtlb_miss_handler(void);
+extern void itlb_miss_handler(void);
+extern void bug(void);
+
+#endif /* _H_OFMEM_SPARC64 */
diff --git a/roms/openbios/include/arch/sparc64/pci.h b/roms/openbios/include/arch/sparc64/pci.h
new file mode 100644
index 00000000..c7509afe
--- /dev/null
+++ b/roms/openbios/include/arch/sparc64/pci.h
@@ -0,0 +1,67 @@
+#ifndef SPARC64_PCI_H
+#define SPARC64_PCI_H
+
+#include "asm/io.h"
+
+#if !(defined(PCI_CONFIG_1) || defined(PCI_CONFIG_2))
+#define PCI_CONFIG_1 1 /* default */
+#endif
+
+#ifdef PCI_CONFIG_1
+
+/* PCI Configuration Mechanism #1 */
+
+#define PCI_ADDR(bus, dev, fn) \
+ (((pci_addr) (uint32_t) (bus) << 16 \
+ | (uint32_t) (dev) << 11 \
+ | (uint32_t) (fn) << 8))
+
+#define PCI_BUS(pcidev) ((uint8_t) ((pcidev) >> 16) & 0xff)
+#define PCI_DEV(pcidev) ((uint8_t) ((pcidev) >> 11) & 0x1f)
+#define PCI_FN(pcidev) ((uint8_t) ((pcidev) >> 8) & 7)
+
+#define PCI_CONFIG(dev) (arch->cfg_addr \
+ + (unsigned long)PCI_ADDR(PCI_BUS(dev), \
+ PCI_DEV(dev), \
+ PCI_FN(dev)))
+
+static inline uint8_t pci_config_read8(pci_addr dev, uint8_t reg)
+{
+ uint8_t res;
+ res = in_8((unsigned char*)(PCI_CONFIG(dev) + reg));
+ return res;
+}
+
+static inline uint16_t pci_config_read16(pci_addr dev, uint8_t reg)
+{
+ uint16_t res;
+ res = in_be16((uint16_t *)(PCI_CONFIG(dev) + reg));
+ return res;
+}
+
+static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg)
+{
+ uint32_t res;
+ res = in_be32((uint32_t *)(PCI_CONFIG(dev) + reg));
+ return res;
+}
+
+static inline void pci_config_write8(pci_addr dev, uint8_t reg, uint8_t val)
+{
+ out_8((unsigned char*)(PCI_CONFIG(dev) + reg), val);
+}
+
+static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val)
+{
+ out_be16((uint16_t *)(PCI_CONFIG(dev) + reg), val);
+}
+
+static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val)
+{
+ out_be32((uint32_t *)(PCI_CONFIG(dev) + reg), val);
+}
+#else /* !PCI_CONFIG_1 */
+#error PCI Configuration Mechanism is not specified or implemented
+#endif
+
+#endif /* SPARC64_PCI_H */
diff --git a/roms/openbios/include/arch/sparc64/types.h b/roms/openbios/include/arch/sparc64/types.h
new file mode 100644
index 00000000..a26fccb2
--- /dev/null
+++ b/roms/openbios/include/arch/sparc64/types.h
@@ -0,0 +1,102 @@
+/* tag: data types for forth engine
+ *
+ * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __TYPES_H
+#define __TYPES_H
+
+#include "mconfig.h"
+
+#ifdef BOOTSTRAP
+#include <inttypes.h>
+#else
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef long long int64_t;
+typedef long intptr_t;
+
+#define PRId32 "d"
+#define PRIu32 "u"
+#define PRIx32 "x"
+#define PRIX32 "X"
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#define PRIx64 "llx"
+#define PRIX64 "llX"
+#endif
+
+/* endianess */
+#include "autoconf.h"
+
+/* physical address */
+typedef uint64_t phys_addr_t;
+
+#define FMT_plx "%016" PRIx64
+
+/* cell based types */
+typedef int64_t cell;
+typedef uint64_t ucell;
+
+#define FMT_cell "%" PRId64
+#define FMT_ucell "%" PRIu64
+#define FMT_ucellx "%016" PRIx64
+#define FMT_ucellX "%016" PRIX64
+
+typedef int64_t prom_arg_t;
+typedef uint64_t prom_uarg_t;
+
+#define PRIdPROMARG PRId64
+#define PRIuPROMARG PRIu64
+#define PRIxPROMARG PRIx64
+#define FMT_prom_arg "%" PRIdPROMARG
+#define FMT_prom_uarg "%" PRIuPROMARG
+#define FMT_prom_uargx "%016" PRIxPROMARG
+
+#define FMT_elf "%#llx"
+#define FMT_sizet "%lx"
+#define FMT_aout_ehdr "%x"
+
+#ifdef NEED_FAKE_INT128_T
+typedef struct {
+ uint64_t hi;
+ uint64_t lo;
+} blob_128_t;
+
+typedef blob_128_t dcell;
+typedef blob_128_t ducell;
+#else
+typedef __int128_t dcell;
+typedef __uint128_t ducell;
+#endif
+
+#define bitspercell (sizeof(cell)<<3)
+#define bitsperdcell (sizeof(dcell)<<3)
+
+#define BITS 64
+
+#define PAGE_SHIFT 13
+
+/* size named types */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+typedef signed char s8;
+typedef short s16;
+typedef int s32;
+typedef long long s64;
+
+#endif
diff --git a/roms/openbios/include/arch/unix/plugin_pci.h b/roms/openbios/include/arch/unix/plugin_pci.h
new file mode 100644
index 00000000..513db633
--- /dev/null
+++ b/roms/openbios/include/arch/unix/plugin_pci.h
@@ -0,0 +1,25 @@
+/* tag: openbios pci plugin headers
+ *
+ * Copyright (C) 2003 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __PLUGINS_PCI_H
+#define __PLUGINS_PCI_H
+
+typedef struct pci_dev pci_dev_t;
+
+struct pci_dev {
+ unsigned bus;
+ unsigned dev;
+ unsigned fn;
+
+ u8 *config;
+ pci_dev_t *next;
+};
+
+int pci_register_device(unsigned bus, unsigned dev, unsigned fn, u8 *config);
+
+#endif
diff --git a/roms/openbios/include/arch/unix/plugins.h b/roms/openbios/include/arch/unix/plugins.h
new file mode 100644
index 00000000..305b3da9
--- /dev/null
+++ b/roms/openbios/include/arch/unix/plugins.h
@@ -0,0 +1,31 @@
+
+#ifndef __PLUGINS_H
+#define __PLUGINS_H
+
+#include "asm/types.h"
+
+struct io_ops {
+ u8 (*inb)(u32 reg);
+ u16 (*inw)(u32 reg);
+ u32 (*inl)(u32 reg);
+ void (*outb)(u32 reg, u8 val);
+ void (*outw)(u32 reg, u16 val);
+ void (*outl)(u32 reg, u32 val);
+};
+typedef struct io_ops io_ops_t;
+
+extern unsigned char *plugindir;
+
+#define PLUGIN_DEPENDENCIES(x...) const char *plugin_deps[]={ x, NULL };
+#define PLUGIN_AUTHOR(author) const char *plugin_author=author;
+#define PLUGIN_LICENSE(license) const char *plugin_license=license;
+#define PLUGIN_DESCRIPTION(desc) const char *plugin_description=desc;
+
+int register_iorange(const char *name, io_ops_t *ops,
+ unsigned int rstart, unsigned int rend);
+io_ops_t *find_iorange(u32 reg);
+
+int load_plugin(const char *plugin_name);
+int is_loaded(const char *plugin_name);
+
+#endif
diff --git a/roms/openbios/include/arch/x86/elf.h b/roms/openbios/include/arch/x86/elf.h
new file mode 100644
index 00000000..86c67250
--- /dev/null
+++ b/roms/openbios/include/arch/x86/elf.h
@@ -0,0 +1,5 @@
+#define ARCH_ELF_CLASS ELFCLASS32
+#define ARCH_ELF_DATA ELFDATA2LSB
+#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_386 || (x)==EM_486)
+typedef Elf32_Ehdr Elf_ehdr;
+typedef Elf32_Phdr Elf_phdr;
diff --git a/roms/openbios/include/arch/x86/io.h b/roms/openbios/include/arch/x86/io.h
new file mode 100644
index 00000000..76fa4f23
--- /dev/null
+++ b/roms/openbios/include/arch/x86/io.h
@@ -0,0 +1,74 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#include "asm/types.h"
+
+extern char _start, _end;
+extern unsigned long virt_offset;
+
+#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset))
+#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset)
+
+#ifndef BOOTSTRAP
+#define __SLOW_DOWN_IO "outb %%al,$0x80;"
+static inline void slow_down_io(void)
+{
+ __asm__ __volatile__(
+ __SLOW_DOWN_IO
+#ifdef REALLY_SLOW_IO
+ __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+ : : );
+}
+
+#define BUILDIO(bwl,bw,type) \
+static inline void out##bwl(unsigned type value, int port) { \
+ __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \
+} \
+static inline unsigned type in##bwl(int port) { \
+ unsigned type value; \
+ __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \
+ return value; \
+} \
+static inline void out##bwl##_p(unsigned type value, int port) { \
+ out##bwl(value, port); \
+ slow_down_io(); \
+} \
+static inline unsigned type in##bwl##_p(int port) { \
+ unsigned type value = in##bwl(port); \
+ slow_down_io(); \
+ return value; \
+} \
+static inline void outs##bwl(int port, const void *addr, unsigned long count) { \
+ __asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \
+} \
+static inline void ins##bwl(int port, void *addr, unsigned long count) { \
+ __asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \
+}
+
+#ifndef BOOTSTRAP
+BUILDIO(b,b,char)
+BUILDIO(w,w,short)
+BUILDIO(l,,int)
+#endif
+
+#else /* BOOTSTRAP */
+#ifdef FCOMPILER
+#define inb(reg) ((u8)0xff)
+#define inw(reg) ((u16)0xffff)
+#define inl(reg) ((u32)0xffffffff)
+#define outb(reg, val) do{} while(0)
+#define outw(reg, val) do{} while(0)
+#define outl(reg, val) do{} while(0)
+#else
+extern u8 inb(u32 reg);
+extern u16 inw(u32 reg);
+extern u32 inl(u32 reg);
+extern void insw(u32 reg, void *addr, unsigned long count);
+extern void outb(u32 reg, u8 val);
+extern void outw(u32 reg, u16 val);
+extern void outl(u32 reg, u32 val);
+extern void outsw(u32 reg, const void *addr, unsigned long count);
+#endif
+#endif
+#endif
diff --git a/roms/openbios/include/arch/x86/pci.h b/roms/openbios/include/arch/x86/pci.h
new file mode 100644
index 00000000..49247d97
--- /dev/null
+++ b/roms/openbios/include/arch/x86/pci.h
@@ -0,0 +1,66 @@
+#ifndef i386_PCI_H
+#define i386_PCI_H
+
+#include "asm/io.h"
+
+#if !(defined(PCI_CONFIG_1) || defined(PCI_CONFIG_2))
+#define PCI_CONFIG_1 1 /* default */
+#endif
+
+#ifdef PCI_CONFIG_1
+
+/* PCI Configuration Mechanism #1 */
+
+/* Have pci_addr in the same format as the values written to 0xcf8
+ * so register accesses can be made easy. */
+#define PCI_ADDR(bus, dev, fn) \
+ ((pci_addr) (0x80000000u \
+ | (uint32_t) (bus) << 16 \
+ | (uint32_t) (dev) << 11 \
+ | (uint32_t) (fn) << 8))
+
+#define PCI_BUS(pcidev) ((uint8_t) ((pcidev) >> 16))
+#define PCI_DEV(pcidev) ((uint8_t) ((pcidev) >> 11) & 0x1f)
+#define PCI_FN(pcidev) ((uint8_t) ((pcidev) >> 8) & 7)
+
+static inline uint8_t pci_config_read8(pci_addr dev, uint8_t reg)
+{
+ outl(dev | (reg & ~3), 0xcf8);
+ return inb(0xcfc | (reg & 3));
+}
+
+static inline uint16_t pci_config_read16(pci_addr dev, uint8_t reg)
+{
+ outl(dev | (reg & ~3), 0xcf8);
+ return inw(0xcfc | (reg & 2));
+}
+
+static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg)
+{
+ outl(dev | reg, 0xcf8);
+ return inl(0xcfc | reg);
+}
+
+static inline void pci_config_write8(pci_addr dev, uint8_t reg, uint8_t val)
+{
+ outl(dev | (reg & ~3), 0xcf8);
+ outb(val, 0xcfc | (reg & 3));
+}
+
+static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val)
+{
+ outl(dev | (reg & ~3), 0xcf8);
+ outw(val, 0xcfc | (reg & 2));
+}
+
+static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val)
+{
+ outl(dev | reg, 0xcf8);
+ outl(val, 0xcfc);
+}
+
+#else /* !PCI_CONFIG_1 */
+#error PCI Configuration Mechanism is not specified or implemented
+#endif
+
+#endif /* i386_PCI_H */
diff --git a/roms/openbios/include/arch/x86/types.h b/roms/openbios/include/arch/x86/types.h
new file mode 100644
index 00000000..d7261f2a
--- /dev/null
+++ b/roms/openbios/include/arch/x86/types.h
@@ -0,0 +1,69 @@
+/* tag: data types for forth engine
+ *
+ * This file is autogenerated by types.sh. Do not edit!
+ *
+ * Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __TYPES_H
+#define __TYPES_H
+
+#include <inttypes.h>
+
+/* endianess */
+
+#include "autoconf.h"
+
+/* physical address: XXX theoretically 36 bits for PAE */
+
+typedef uint32_t phys_addr_t;
+
+#define FMT_plx "%08" PRIx32
+
+/* cell based types */
+
+typedef int32_t cell;
+typedef uint32_t ucell;
+typedef int64_t dcell;
+typedef uint64_t ducell;
+
+#define FMT_cell "%" PRId32
+#define FMT_ucell "%" PRIu32
+#define FMT_ucellx "%08" PRIx32
+#define FMT_ucellX "%08" PRIX32
+
+typedef int32_t prom_arg_t;
+typedef uint32_t prom_uarg_t;
+
+#define PRIdPROMARG PRId32
+#define PRIuPROMARG PRIu32
+#define PRIxPROMARG PRIx32
+#define FMT_prom_arg "%" PRIdPROMARG
+#define FMT_prom_uarg "%" PRIuPROMARG
+#define FMT_prom_uargx "%08" PRIxPROMARG
+
+#define FMT_elf "%#x"
+
+#define bitspercell (sizeof(cell)<<3)
+#define bitsperdcell (sizeof(dcell)<<3)
+
+#define BITS 32
+
+#define PAGE_SHIFT 12
+
+/* size named types */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+typedef char s8;
+typedef short s16;
+typedef int s32;
+typedef long long s64;
+
+#endif
diff --git a/roms/openbios/include/config.h b/roms/openbios/include/config.h
new file mode 100644
index 00000000..d5a1e200
--- /dev/null
+++ b/roms/openbios/include/config.h
@@ -0,0 +1,68 @@
+/*
+ * Creation Date: <2003/12/20 00:07:16 samuel>
+ * Time-stamp: <2004/01/19 17:40:26 stepan>
+ *
+ * <config.h>
+ *
+ *
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_CONFIG
+#define _H_CONFIG
+
+#include "autoconf.h"
+#include "mconfig.h"
+#include "asm/types.h"
+
+#define PROGRAM_NAME "OpenBIOS"
+
+#ifndef BOOTSTRAP
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+typedef unsigned int size_t;
+typedef unsigned int usize_t;
+typedef signed int ssize_t;
+typedef signed int off_t;
+
+typedef unsigned int time_t;
+
+#define UINT_MAX ((unsigned int)-1)
+
+#define ENOMEM 1
+#define EIO 2
+#define EINVAL 3
+#define ENOENT 4
+#define ENOTDIR 5
+#define EISDIR 6
+#define ENAMETOOLONG 7
+
+#define SEEK_CUR 1
+#define SEEK_SET 2
+#define SEEK_END 3
+
+#endif /* BOOTSTRAP */
+
+#include "sysinclude.h"
+
+#ifndef MIN
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+#endif
+
+/* errno is a macro on some systems, which might cause nasty problems.
+ * We try to cope with this here.
+ */
+#undef errno
+#define errno errno_int
+
+#endif /* _H_CONFIG */
diff --git a/roms/openbios/include/drivers/drivers.h b/roms/openbios/include/drivers/drivers.h
new file mode 100644
index 00000000..3b83b12d
--- /dev/null
+++ b/roms/openbios/include/drivers/drivers.h
@@ -0,0 +1,132 @@
+/*
+ * OpenBIOS driver prototypes
+ *
+ * (C) 2004 Stefan Reinauer <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+#ifndef OPENBIOS_DRIVERS_H
+#define OPENBIOS_DRIVERS_H
+
+#include "config.h"
+
+#ifdef CONFIG_DRIVER_PCI
+/* drivers/pci.c */
+int ob_pci_init(void);
+#endif
+
+#if defined(CONFIG_DRIVER_PCI) || defined(CONFIG_DRIVER_ESCC)
+#ifdef CONFIG_PPC
+extern int is_apple(void);
+extern int is_oldworld(void);
+extern int is_newworld(void);
+#else
+static inline int is_apple(void)
+{
+ return 0;
+}
+static inline int is_oldworld(void)
+{
+ return 0;
+}
+static inline int is_newworld(void)
+{
+ return 0;
+}
+#endif
+#define AAPL(_cmd) do { if (is_apple()) _cmd; } while(0)
+#define OLDWORLD(_cmd) do { if (is_oldworld()) _cmd; } while(0)
+#define NEWWORLD(_cmd) do { if (is_newworld()) _cmd; } while(0)
+#endif
+#ifdef CONFIG_DRIVER_SBUS
+/* drivers/sbus.c */
+int ob_sbus_init(uint64_t base, int machine_id);
+
+/* arch/sparc32/console.c */
+void kbd_init(uint64_t base);
+#endif
+#ifdef CONFIG_DRIVER_IDE
+/* drivers/ide.c */
+int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0,
+ uint32_t io_port1, uint32_t ctl_port1);
+int macio_ide_init(const char *path, uint32_t addr, int nb_channels);
+#endif
+#ifdef CONFIG_DRIVER_ESP
+/* drivers/esp.c */
+int ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset,
+ unsigned long dmaoffset);
+#endif
+#ifdef CONFIG_DRIVER_OBIO
+/* drivers/obio.c */
+int ob_obio_init(uint64_t slavio_base, unsigned long fd_offset,
+ unsigned long counter_offset, unsigned long intr_offset,
+ int intr_ncpu, unsigned long aux1_offset, unsigned long aux2_offset,
+ unsigned long mem_size);
+int start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context,
+ int cpu);
+void ob_eccmemctl_init(uint64_t base);
+void ss5_init(uint64_t base);
+
+/* drivers/iommu.c */
+void ob_init_iommu(uint64_t base);
+void *dvma_alloc(int size, unsigned int *pphys);
+
+/* drivers/sbus.c */
+extern uint16_t graphic_depth;
+
+/* drivers/obio.c */
+extern volatile unsigned char *power_reg;
+extern volatile unsigned int *reset_reg;
+extern volatile struct sun4m_timer_regs *counter_regs;
+
+void ob_new_obio_device(const char *name, const char *type);
+unsigned long ob_reg(uint64_t base, uint64_t offset, unsigned long size, int map);
+void ob_intr(int intr);
+
+/* arch/sparc32/boot.c */
+extern uint32_t kernel_image;
+extern uint32_t kernel_size;
+extern uint32_t qemu_cmdline;
+extern uint32_t cmdline_size;
+extern char boot_device;
+#endif
+#ifdef CONFIG_DRIVER_FLOPPY
+int ob_floppy_init(const char *path, const char *dev_name,
+ unsigned long io_base, unsigned long mmio_base);
+#endif
+#ifdef CONFIG_DRIVER_PC_KBD
+void ob_pc_kbd_init(const char *path, const char *dev_name, uint64_t base,
+ uint64_t offset, int intr);
+int pc_kbd_dataready(void);
+unsigned char pc_kbd_readdata(void);
+#endif
+#ifdef CONFIG_DRIVER_PC_SERIAL
+void ob_pc_serial_init(const char *path, const char *dev_name, uint64_t base,
+ uint64_t offset, int intr);
+int uart_init(int port, unsigned long speed);
+int uart_charav(int port);
+char uart_getchar(int port);
+void uart_putchar(int c);
+#endif
+#ifdef CONFIG_DRIVER_ESCC
+int escc_uart_init(phys_addr_t port, unsigned long speed);
+int escc_uart_charav(uintptr_t port);
+char escc_uart_getchar(uintptr_t port);
+void escc_uart_putchar(int c);
+void serial_cls(void);
+#ifdef CONFIG_DRIVER_ESCC_SUN
+int keyboard_dataready(void);
+unsigned char keyboard_readdata(void);
+#endif
+#endif
+int macio_get_nvram_size(void);
+void macio_nvram_put(char *buf);
+void macio_nvram_get(char *buf);
+
+/* drivers/timer.c */
+void setup_timers(void);
+
+#endif /* OPENBIOS_DRIVERS_H */
diff --git a/roms/openbios/include/drivers/pci.h b/roms/openbios/include/drivers/pci.h
new file mode 100644
index 00000000..2eb5685d
--- /dev/null
+++ b/roms/openbios/include/drivers/pci.h
@@ -0,0 +1,217 @@
+#ifndef _H_PCI
+#define _H_PCI
+
+typedef uint32_t pci_addr;
+
+typedef struct pci_arch_t pci_arch_t;
+
+struct pci_arch_t {
+ const char * name;
+ uint16_t vendor_id;
+ uint16_t device_id;
+ unsigned long cfg_addr;
+ unsigned long cfg_data;
+ unsigned long cfg_base;
+ unsigned long cfg_len;
+ unsigned long host_pci_base; /* offset of PCI memory space within host memory space */
+ unsigned long pci_mem_base; /* in PCI memory space */
+ unsigned long mem_len;
+ unsigned long io_base;
+ unsigned long io_len;
+ unsigned long rbase;
+ unsigned long rlen;
+ uint8_t irqs[4];
+};
+
+extern const pci_arch_t *arch;
+
+/* Device tree offsets */
+
+#define PCI_INT_MAP_PCI0 0
+#define PCI_INT_MAP_PCI1 1
+#define PCI_INT_MAP_PCI2 2
+#define PCI_INT_MAP_PCI_INT 3
+#define PCI_INT_MAP_PIC_HANDLE 4
+#define PCI_INT_MAP_PIC_INT 5
+#define PCI_INT_MAP_PIC_POL 6
+
+/* Device classes and subclasses */
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_SUBCLASS_STORAGE_SCSI 0x00
+#define PCI_SUBCLASS_STORAGE_IDE 0x01
+#define PCI_SUBCLASS_STORAGE_FLOPPY 0x02
+#define PCI_SUBCLASS_STORAGE_IPI 0x03
+#define PCI_SUBCLASS_STORAGE_RAID 0x04
+#define PCI_SUBCLASS_STORAGE_ATA 0x05
+#define PCI_SUBCLASS_STORAGE_SAS 0x07
+#define PCI_SUBCLASS_STORAGE_OTHER 0x80
+
+#define PCI_BASE_CLASS_NETWORK 0x02
+#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00
+#define PCI_SUBCLASS_NETWORK_TOKEN_RING 0x01
+#define PCI_SUBCLASS_NETWORK_FDDI 0x02
+#define PCI_SUBCLASS_NETWORK_ATM 0x03
+#define PCI_SUBCLASS_NETWORK_ISDN 0x04
+#define PCI_SUBCLASS_NETWORK_WORDFIP 0x05
+#define PCI_SUBCLASS_NETWORK_PICMG214 0x06
+#define PCI_SUBCLASS_NETWORK_OTHER 0x80
+
+#define PCI_BASE_CLASS_DISPLAY 0x03
+#define PCI_SUBCLASS_DISPLAY_VGA 0x00
+#define PCI_SUBCLASS_DISPLAY_XGA 0x01
+#define PCI_SUBCLASS_DISPLAY_3D 0x02
+#define PCI_SUBCLASS_DISPLAY_OTHER 0x80
+
+#define PCI_BASE_CLASS_MULTIMEDIA 0x04
+#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00
+#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x01
+#define PCI_SUBCLASS_MULTIMEDIA_PHONE 0x02
+#define PCI_SUBCLASS_MULTIMEDIA_OTHER 0x80
+
+#define PCI_BASE_CLASS_MEMORY 0x05
+#define PCI_SUBCLASS_MEMORY_RAM 0x00
+#define PCI_SUBCLASS_MEMORY_FLASH 0x01
+
+#define PCI_BASE_CLASS_BRIDGE 0x06
+#define PCI_SUBCLASS_BRIDGE_HOST 0x00
+#define PCI_SUBCLASS_BRIDGE_ISA 0x01
+#define PCI_SUBCLASS_BRIDGE_EISA 0x02
+#define PCI_SUBCLASS_BRIDGE_MC 0x03
+#define PCI_SUBCLASS_BRIDGE_PCI 0x04
+#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x05
+#define PCI_SUBCLASS_BRIDGE_NUBUS 0x06
+#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x07
+#define PCI_SUBCLASS_BRIDGE_RACEWAY 0x08
+#define PCI_SUBCLASS_BRIDGE_PCI_SEMITP 0x09
+#define PCI_SUBCLASS_BRIDGE_IB_PCI 0x0a
+#define PCI_SUBCLASS_BRIDGE_OTHER 0x80
+
+#define PCI_BASE_CLASS_COMMUNICATION 0x07
+#define PCI_SUBCLASS_COMMUNICATION_SERIAL 0x00
+#define PCI_SUBCLASS_COMMUNICATION_PARALLEL 0x01
+#define PCI_SUBCLASS_COMMUNICATION_MULTISERIAL 0x02
+#define PCI_SUBCLASS_COMMUNICATION_MODEM 0x03
+#define PCI_SUBCLASS_COMMUNICATION_GPIB 0x04
+#define PCI_SUBCLASS_COMMUNICATION_SC 0x05
+#define PCI_SUBCLASS_COMMUNICATION_OTHER 0x80
+
+#define PCI_BASE_CLASS_SYSTEM 0x08
+#define PCI_SUBCLASS_SYSTEM_PIC 0x00
+#define PCI_SUBCLASS_SYSTEM_DMA 0x01
+#define PCI_SUBCLASS_SYSTEM_TIMER 0x02
+#define PCI_SUBCLASS_SYSTEM_RTC 0x03
+#define PCI_SUBCLASS_SYSTEM_PCI_HOTPLUG 0x04
+#define PCI_SUBCLASS_SYSTEM_OTHER 0x80
+
+#define PCI_BASE_CLASS_INPUT 0x09
+#define PCI_SUBCLASS_INPUT_KEYBOARD 0x00
+#define PCI_SUBCLASS_INPUT_PEN 0x01
+#define PCI_SUBCLASS_INPUT_MOUSE 0x02
+#define PCI_SUBCLASS_INPUT_SCANNER 0x03
+#define PCI_SUBCLASS_INPUT_GAMEPORT 0x04
+#define PCI_SUBCLASS_INPUT_OTHER 0x80
+
+#define PCI_BASE_CLASS_DOCKING 0x0a
+#define PCI_SUBCLASS_DOCKING_GENERIC 0x00
+#define PCI_SUBCLASS_DOCKING_OTHER 0x80
+
+#define PCI_BASE_CLASS_PROCESSOR 0x0b
+#define PCI_SUBCLASS_PROCESSOR_386 0x00
+#define PCI_SUBCLASS_PROCESSOR_486 0x01
+#define PCI_SUBCLASS_PROCESSOR_PENTIUM 0x02
+#define PCI_SUBCLASS_PROCESSOR_ALPHA 0x10
+#define PCI_SUBCLASS_PROCESSOR_POWERPC 0x20
+#define PCI_SUBCLASS_PROCESSOR_MIPS 0x30
+#define PCI_SUBCLASS_PROCESSOR_CO 0x40
+
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_SUBCLASS_SERIAL_FIREWIRE 0x00
+#define PCI_SUBCLASS_SERIAL_ACCESS 0x01
+#define PCI_SUBCLASS_SERIAL_SSA 0x02
+#define PCI_SUBCLASS_SERIAL_USB 0x03
+#define PCI_SUBCLASS_SERIAL_FIBER 0x04
+#define PCI_SUBCLASS_SERIAL_SMBUS 0x05
+#define PCI_SUBCLASS_SERIAL_IB 0x06
+#define PCI_SUBCLASS_SERIAL_IPMI 0x07
+#define PCI_SUBCLASS_SERIAL_SERCOS 0x08
+#define PCI_SUBCLASS_SERIAL_CANBUS 0x09
+
+#define PCI_BASE_CLASS_WIRELESS 0x0d
+#define PCI_SUBCLASS_WIRELESS_IRDA 0x00
+#define PCI_SUBCLASS_WIRELESS_CIR 0x01
+#define PCI_SUBCLASS_WIRELESS_RF_CONTROLLER 0x10
+#define PCI_SUBCLASS_WIRELESS_BLUETOOTH 0x11
+#define PCI_SUBCLASS_WIRELESS_BROADBAND 0x12
+#define PCI_SUBCLASS_WIRELESS_OTHER 0x80
+
+#define PCI_BASE_CLASS_SATELLITE 0x0f
+#define PCI_SUBCLASS_SATELLITE_TV 0x00
+#define PCI_SUBCLASS_SATELLITE_AUDIO 0x01
+#define PCI_SUBCLASS_SATELLITE_VOICE 0x03
+#define PCI_SUBCLASS_SATELLITE_DATA 0x04
+
+#define PCI_BASE_CLASS_CRYPT 0x10
+#define PCI_SUBCLASS_CRYPT_NETWORK 0x00
+#define PCI_SUBCLASS_CRYPT_ENTERTAINMENT 0x01
+#define PCI_SUBCLASS_CRYPT_OTHER 0x80
+
+#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11
+#define PCI_SUBCLASS_SP_DPIO 0x00
+#define PCI_SUBCLASS_SP_PERF 0x01
+#define PCI_SUBCLASS_SP_SYNCH 0x10
+#define PCI_SUBCLASS_SP_MANAGEMENT 0x20
+#define PCI_SUBCLASS_SP_OTHER 0x80
+
+#define PCI_CLASS_OTHERS 0xff
+
+/* Vendors and devices. */
+
+#define PCI_VENDOR_ID_ATI 0x1002
+#define PCI_DEVICE_ID_ATI_RAGE128_PF 0x5046
+
+#define PCI_VENDOR_ID_DEC 0x1011
+#define PCI_DEVICE_ID_DEC_21154 0x0026
+
+#define PCI_VENDOR_ID_IBM 0x1014
+#define PCI_DEVICE_ID_IBM_OPENPIC 0x0002
+#define PCI_DEVICE_ID_IBM_OPENPIC2 0xffff
+
+#define PCI_VENDOR_ID_MOTOROLA 0x1057
+#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002
+#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801
+
+#define PCI_VENDOR_ID_APPLE 0x106b
+#define PCI_DEVICE_ID_APPLE_343S1201 0x0010
+#define PCI_DEVICE_ID_APPLE_343S1211 0x0017
+#define PCI_DEVICE_ID_APPLE_UNI_N_I_PCI 0x001e
+#define PCI_DEVICE_ID_APPLE_UNI_N_PCI 0x001f
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020
+#define PCI_DEVICE_ID_APPLE_UNI_N_KEYL 0x0022
+#define PCI_DEVICE_ID_APPLE_KEYL_USB 0x003f
+#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b
+
+#define PCI_VENDOR_ID_SUN 0x108e
+#define PCI_DEVICE_ID_SUN_EBUS 0x1000
+#define PCI_DEVICE_ID_SUN_SIMBA 0x5000
+#define PCI_DEVICE_ID_SUN_PBM 0x8000
+#define PCI_DEVICE_ID_SUN_SABRE 0xa000
+
+#define PCI_VENDOR_ID_CMD 0x1095
+#define PCI_DEVICE_ID_CMD_646 0x0646
+
+#define PCI_VENDOR_ID_REALTEK 0x10ec
+#define PCI_DEVICE_ID_REALTEK_RTL8029 0x8029
+
+#define PCI_VENDOR_ID_QEMU 0x1234
+#define PCI_DEVICE_ID_QEMU_VGA 0x1111
+
+#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4
+#define PCI_DEVICE_ID_VIRTIO_NET 0x1000
+#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_DEVICE_ID_INTEL_82378 0x0484
+#define PCI_DEVICE_ID_INTEL_82441 0x1237
+
+#endif /* _H_PCI */
diff --git a/roms/openbios/include/drivers/usb.h b/roms/openbios/include/drivers/usb.h
new file mode 100644
index 00000000..143ed27b
--- /dev/null
+++ b/roms/openbios/include/drivers/usb.h
@@ -0,0 +1,8 @@
+#ifndef USB_H
+#define USB_H
+
+int ob_usb_ohci_init(const char *path, uint32_t addr);
+void ob_usb_hid_add_keyboard(const char *path);
+int usb_exit(void);
+
+#endif /* USB_H */
diff --git a/roms/openbios/include/drivers/vga.h b/roms/openbios/include/drivers/vga.h
new file mode 100644
index 00000000..a4951f87
--- /dev/null
+++ b/roms/openbios/include/drivers/vga.h
@@ -0,0 +1,20 @@
+#ifndef VIDEO_VGA_H
+#define VIDEO_VGA_H
+
+/* drivers/vga_load_regs.c */
+void vga_load_regs(void);
+
+/* drivers/vga_set_mode.c */
+void vga_set_gmode (void);
+void vga_set_amode (void);
+void vga_font_load(unsigned char *vidmem, const unsigned char *font, int height, int num_chars);
+
+/* drivers/vga_vbe.c */
+void vga_set_color(int i, unsigned int r, unsigned int g, unsigned int b);
+void vga_vbe_set_mode(int width, int height, int depth);
+void vga_vbe_init(const char *path, unsigned long fb, uint32_t fb_size,
+ unsigned long rom, uint32_t rom_size);
+
+extern volatile uint32_t *dac;
+
+#endif /* VIDEO_VGA_H */
diff --git a/roms/openbios/include/fs/fs.h b/roms/openbios/include/fs/fs.h
new file mode 100644
index 00000000..0a22fa27
--- /dev/null
+++ b/roms/openbios/include/fs/fs.h
@@ -0,0 +1,100 @@
+/*
+ * Creation Date: <2001/05/06 17:12:45 samuel>
+ * Time-stamp: <2003/10/22 11:43:45 samuel>
+ *
+ * <fs_loader.h>
+ *
+ * Generic file system access
+ *
+ * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_FS
+#define _H_FS
+
+
+typedef struct fs_ops fs_ops_t;
+typedef struct opaque_struct file_desc_t;
+
+#define fs_open_path( fs, path ) (fs)->open_path( fs, path )
+#define fs_search_rom( fs ) (fs)->search_rom( fs )
+#define fs_search_file( fs, name ) (fs)->search_file( fs, name )
+#define fs_vol_name( fs, buf, size ) (fs)->vol_name( fs, buf, size )
+
+struct fs_ops {
+ void *fs_data;
+ int fd; /* owner block device */
+ int type;
+
+ void (*close_fs)( fs_ops_t *fs );
+ file_desc_t *(*open_path)( fs_ops_t *fs, const char *path );
+ file_desc_t *(*search_rom)( fs_ops_t *fs );
+ file_desc_t *(*search_file)( fs_ops_t *fs, const char *name );
+ char *(*vol_name)( fs_ops_t *fs, char *buf, int size );
+
+ /* file ops */
+ void (*close)( file_desc_t *file );
+ int (*read)( file_desc_t *file, void *buf, size_t count );
+ int (*lseek)( file_desc_t *file, off_t offset, int whence );
+ char *(*get_path)( file_desc_t *file, char *buf, int len );
+ void (*dir)( file_desc_t *file );
+
+ const char *(*get_fstype)( fs_ops_t *fs );
+};
+
+extern fs_ops_t *fs_open( int fs_type, int fd );
+extern void fs_close( fs_ops_t *fs );
+const char *fs_get_name( fs_ops_t *fs );
+
+#ifdef CONFIG_HFSP
+extern int fs_hfsp_open( int fd, fs_ops_t *fs );
+extern int fs_hfsp_probe( int fd, long long offs );
+#else
+static inline int fs_hfsp_open( int fd, fs_ops_t *fs ) { return -1; }
+static inline int fs_hfsp_probe( int fd, long long offs ) { return -1; }
+#endif
+
+#ifdef CONFIG_HFS
+extern int fs_hfs_open( int fd, fs_ops_t *fs );
+extern int fs_hfs_probe( int fd, long long offs );
+#else
+static inline int fs_hfs_open( int fd, fs_ops_t *fs ) { return -1; }
+static inline int fs_hfs_probe( int fd, long long offs ) { return -1; }
+#endif
+
+#ifdef CONFIG_ISO9660
+extern int fs_iso9660_open( int fd, fs_ops_t *fs );
+extern int fs_iso9660_probe( int fd, long long offs );
+#else
+static inline int fs_iso9660_open( int fd, fs_ops_t *fs ) { return -1; }
+static inline int fs_iso9660_probe( int fd, long long offs ) { return -1; }
+#endif
+
+#ifdef CONFIG_EXT2
+extern int fs_ext2_open( int fd, fs_ops_t *fs );
+extern int fs_ext2_probe( int fd, long long offs );
+#else
+static inline int fs_ext2_open( int fd, fs_ops_t *fs ) { return -1; }
+static inline int fs_ext2_probe( int fd, long long offs ) { return -1; }
+#endif
+
+#ifdef CONFIG_GRUBFS
+extern int fs_grubfs_open( int fd, fs_ops_t *fs );
+extern int fs_grubfs_probe( int fd, long long offs );
+#else
+static inline int fs_grubfs_open( int fd, fs_ops_t *fs ) { return -1; }
+static inline int fs_grubfs_probe( int fd, long long offs ) { return -1; }
+#endif
+
+
+
+/* misc */
+extern char *get_hfs_vol_name( int fd, char *buf, int size );
+
+
+#endif /* _H_FS */
diff --git a/roms/openbios/include/kernel/kernel.h b/roms/openbios/include/kernel/kernel.h
new file mode 100644
index 00000000..c887e24b
--- /dev/null
+++ b/roms/openbios/include/kernel/kernel.h
@@ -0,0 +1,58 @@
+/*
+ * Creation Date: <2003/12/19 00:20:11 samuel>
+ * Time-stamp: <2004/01/07 19:19:14 samuel>
+ *
+ * <kernel.h>
+ *
+ *
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ * Stefan Reinauer (stepan@openbios.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_KERNEL
+#define _H_KERNEL
+
+#include "kernel/stack.h"
+#include "asm/io.h"
+
+/* Interrupt status */
+#define FORTH_INTSTAT_CLR 0x0
+#define FORTH_INTSTAT_STOP 0x1
+#define FORTH_INTSTAT_DBG 0x2
+
+extern volatile int interruptforth;
+extern int enterforth( xt_t xt );
+extern void panic(const char *error) __attribute__ ((noreturn));
+
+extern xt_t findword(const char *s1);
+extern void modules_init( void );
+extern void init_trampoline(ucell *t);
+extern void forth_init(void);
+
+/* arch kernel hooks */
+extern void exception(cell no);
+
+#ifdef FCOMPILER
+extern void include_file( const char *str );
+extern void encode_file( const char *str );
+extern int get_inputbyte( void );
+extern void put_outputbyte( int c );
+#endif
+
+#ifndef BOOTSTRAP
+#undef putchar
+#undef getchar
+
+extern int putchar( int ch );
+extern int getchar( void );
+#endif
+
+extern int availchar( void );
+
+#endif /* _H_KERNEL */
diff --git a/roms/openbios/include/kernel/stack.h b/roms/openbios/include/kernel/stack.h
new file mode 100644
index 00000000..5edfc5cf
--- /dev/null
+++ b/roms/openbios/include/kernel/stack.h
@@ -0,0 +1,117 @@
+/* stack.h
+ * tag: stack and stack access functions
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __STACK_H
+#define __STACK_H
+
+#define dstacksize 512
+extern int dstackcnt;
+extern cell dstack[dstacksize];
+
+#define rstacksize 512
+extern int rstackcnt;
+extern cell rstack[rstacksize];
+
+extern int dbgrstackcnt;
+
+//typedef struct opaque_xt *xt_t;
+//typedef struct opaque_ihandle *ihandle_t;
+//typedef struct opaque_phandle *phandle_t;
+
+typedef ucell xt_t;
+typedef ucell ihandle_t;
+typedef ucell phandle_t;
+
+
+
+#ifdef NATIVE_BITWIDTH_EQUALS_HOST_BITWIDTH
+
+static inline ucell pointer2cell(const void* x)
+{
+ return (ucell)(uintptr_t)x;
+}
+
+static inline void* cell2pointer(ucell x)
+{
+ return (void*)(uintptr_t)x;
+}
+
+#endif
+
+static inline void PUSH(ucell value) {
+ dstack[++dstackcnt] = (value);
+}
+static inline void PUSH_xt( xt_t xt ) { PUSH( (ucell)xt ); }
+static inline void PUSH_ih( ihandle_t ih ) { PUSH( (ucell)ih ); }
+static inline void PUSH_ph( phandle_t ph ) { PUSH( (ucell)ph ); }
+
+static inline ucell POP(void) {
+ return (ucell) dstack[dstackcnt--];
+}
+static inline xt_t POP_xt( void ) { return (xt_t)POP(); }
+static inline ihandle_t POP_ih( void ) { return (ihandle_t)POP(); }
+static inline phandle_t POP_ph( void ) { return (phandle_t)POP(); }
+
+static inline void DROP(void) {
+ dstackcnt--;
+}
+
+static inline void DDROP(void) {
+ dstackcnt -= 2;
+}
+
+static inline void DPUSH(ducell value) {
+#ifdef NEED_FAKE_INT128_T
+ dstack[++dstackcnt] = (cell) value.lo;
+ dstack[++dstackcnt] = (cell) value.hi;
+#else
+ dstack[++dstackcnt] = (cell) value;
+ dstack[++dstackcnt] = (cell) (value >> bitspercell);
+#endif
+}
+
+static inline ducell DPOP(void) {
+#ifdef NEED_FAKE_INT128_T
+ ducell du;
+ du.hi = (ucell) dstack[dstackcnt--];
+ du.lo = (ucell) dstack[dstackcnt--];
+ return du;
+#else
+ ducell du;
+ du = ((ducell)(ucell) dstack[dstackcnt--]) << bitspercell;
+ du |= (ucell) dstack[dstackcnt--];
+ return du;
+#endif
+}
+
+static inline ucell GETTOS(void) {
+ return dstack[dstackcnt];
+}
+
+#define GETITEM(number) (dstack[dstackcnt - number])
+static inline void PUSHR(ucell value) {
+ rstack[++rstackcnt] = (value);
+}
+
+static inline ucell POPR(void) {
+ return (ucell) rstack[rstackcnt--];
+}
+static inline ucell GETTORS(void) {
+ return rstack[rstackcnt];
+}
+
+
+#if defined(DEBUG_DSTACK) || defined(FCOMPILER)
+void printdstack(void);
+#endif
+#if defined(DEBUG_RSTACK) || defined(FCOMPILER)
+void printrstack(void);
+#endif
+
+#endif
diff --git a/roms/openbios/include/libc/byteorder.h b/roms/openbios/include/libc/byteorder.h
new file mode 100644
index 00000000..4ac9562f
--- /dev/null
+++ b/roms/openbios/include/libc/byteorder.h
@@ -0,0 +1,61 @@
+/* tag: byteorder prototypes
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * see the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+#ifndef __BYTEORDER_H
+#define __BYTEORDER_H
+
+#define __bswap32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+
+#define __bswap16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
+
+#define __bswap64(x) ( (__bswap32( (x) >> 32)) | \
+ (__bswap32((x) & 0xffffffff) << 32) )
+
+#ifdef CONFIG_LITTLE_ENDIAN
+#define __cpu_to_le64(x) ((u64) (x))
+#define __le64_to_cpu(x) ((u64) (x))
+#define __cpu_to_le32(x) ((u32) (x))
+#define __le32_to_cpu(x) ((u32) (x))
+#define __cpu_to_le16(x) ((u16) (x))
+#define __le16_to_cpu(x) ((u16) (x))
+#define __cpu_to_be64(x) (__bswap64((u64) (x)))
+#define __be64_to_cpu(x) (__bswap64((u64) (x)))
+#define __cpu_to_be32(x) (__bswap32((u32) (x)))
+#define __be32_to_cpu(x) (__bswap32((u32) (x)))
+#define __cpu_to_be16(x) (__bswap16((u16) (x)))
+#define __be16_to_cpu(x) (__bswap16((u16) (x)))
+#endif
+#ifdef CONFIG_BIG_ENDIAN
+#define __cpu_to_le64(x) (__bswap64((u64) (x)))
+#define __le64_to_cpu(x) (__bswap64((u64) (x)))
+#define __cpu_to_le32(x) (__bswap32((u32) (x)))
+#define __le32_to_cpu(x) (__bswap32((u32) (x)))
+#define __cpu_to_le16(x) (__bswap16((u16) (x)))
+#define __le16_to_cpu(x) (__bswap16((u16) (x)))
+#define __cpu_to_be64(x) ((u64) (x))
+#define __be64_to_cpu(x) ((u64) (x))
+#define __cpu_to_be32(x) ((u32) (x))
+#define __be32_to_cpu(x) ((u32) (x))
+#define __cpu_to_be16(x) ((u16) (x))
+#define __be16_to_cpu(x) ((u16) (x))
+#endif
+
+#if BITS==32
+#define __becell_to_cpu(x) (__be32_to_cpu(x))
+#define __lecell_to_cpu(x) (__le32_to_cpu(x))
+#define __cpu_to_becell(x) (__cpu_to_be32(x))
+#define __cpu_to_lecell(x) (__cpu_to_le32(x))
+#else
+#define __becell_to_cpu(x) (__be64_to_cpu(x))
+#define __lecell_to_cpu(x) (__le64_to_cpu(x))
+#define __cpu_to_becell(x) (__cpu_to_be64(x))
+#define __cpu_to_lecell(x) (__cpu_to_le64(x))
+#endif
+
+#endif
diff --git a/roms/openbios/include/libc/diskio.h b/roms/openbios/include/libc/diskio.h
new file mode 100644
index 00000000..3a5abb65
--- /dev/null
+++ b/roms/openbios/include/libc/diskio.h
@@ -0,0 +1,33 @@
+/*
+ * Creation Date: <2003/12/20 00:57:01 samuel>
+ * Time-stamp: <2004/01/07 19:32:29 samuel>
+ *
+ * <diskio.h>
+ *
+ *
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_DISKIO
+#define _H_DISKIO
+
+extern int open_ih( ihandle_t ih );
+extern int open_io( const char *spec );
+extern int close_io( int fd );
+extern int read_io( int fd, void *buf, size_t cnt );
+extern int seek_io( int fd, long long offs );
+extern long long tell( int fd );
+extern int reopen( int fd, const char *filename );
+extern int reopen_nwrom( int fd );
+extern ihandle_t get_ih_from_fd( int fd );
+const char *get_file_path( int fd );
+const char *get_fstype( int fd );
+const char *get_volume_name( int fd );
+
+#endif /* _H_DISKIO */
diff --git a/roms/openbios/include/libc/stdlib.h b/roms/openbios/include/libc/stdlib.h
new file mode 100644
index 00000000..ef08838d
--- /dev/null
+++ b/roms/openbios/include/libc/stdlib.h
@@ -0,0 +1,26 @@
+/*
+ * Creation Date: <2003/12/19 18:52:20 samuel>
+ * Time-stamp: <2003/12/19 18:52:21 samuel>
+ *
+ * <stdlib.h>
+ *
+ *
+ * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_STDLIB
+#define _H_STDLIB
+
+extern void *malloc( int size );
+extern void free( void *ptr );
+extern void *realloc( void *ptr, size_t size );
+
+/* should perhaps go somewhere else... */
+extern void qsort( void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
+
+#endif /* _H_STDLIB */
diff --git a/roms/openbios/include/libc/string.h b/roms/openbios/include/libc/string.h
new file mode 100644
index 00000000..0e72f8d7
--- /dev/null
+++ b/roms/openbios/include/libc/string.h
@@ -0,0 +1,105 @@
+/*
+ * Creation Date: <2002/10/12 20:41:57 samuel>
+ * Time-stamp: <2003/10/25 12:51:22 samuel>
+ *
+ * <string.h>
+ *
+ * string library functions
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_STRING
+#define _H_STRING
+
+#include "config.h"
+
+#define bzero(s,n) memset( s, 0, n )
+#define atol(nptr) strtol(nptr, NULL, 10 )
+
+extern long strtol( const char *nptr, char **endptr, int base );
+extern long long int strtoll( const char *nptr, char **endptr, int base );
+
+
+extern int strnicmp(const char *s1, const char *s2, size_t len);
+extern char *strcpy(char * dest,const char *src);
+extern char *strncpy(char * dest,const char *src,size_t count);
+extern char *strcat(char * dest, const char * src);
+extern char *strncat(char *dest, const char *src, size_t count);
+extern int strcmp(const char * cs,const char * ct);
+extern int strncmp(const char * cs,const char * ct,size_t count);
+extern char *strchr(const char * s, int c);
+extern char *strrchr(const char * s, int c);
+extern size_t strlen(const char * s);
+extern size_t strnlen(const char * s, size_t count);
+extern char *strpbrk(const char * cs,const char * ct);
+extern char *strsep(char **s, const char *ct);
+extern void *memset(void * s,int c,size_t count);
+extern void *memcpy(void * dest,const void *src,size_t count);
+extern void *memmove(void * dest,const void *src,size_t count);
+extern int memcmp(const void * cs,const void * ct,size_t count);
+
+extern char *strdup( const char *str );
+extern int strcasecmp( const char *cs, const char *ct );
+extern int strncasecmp( const char *cs, const char *ct, size_t count );
+
+extern char *strncpy_nopad( char *dest, const char *src, size_t n );
+
+#define _U 0x01 /* upper */
+#define _L 0x02 /* lower */
+#define _D 0x04 /* digit */
+#define _C 0x08 /* cntrl */
+#define _P 0x10 /* punct */
+#define _S 0x20 /* white space (space/lf/tab) */
+#define _X 0x40 /* hex digit */
+#define _SP 0x80 /* hard space (0x20) */
+
+extern const unsigned char _ctype[];
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
+#define isdigit(c) ((__ismask(c)&(_D)) != 0)
+#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c) ((__ismask(c)&(_L)) != 0)
+#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c) ((__ismask(c)&(_P)) != 0)
+#define isspace(c) ((__ismask(c)&(_S)) != 0)
+#define isupper(c) ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+
+static inline unsigned char __tolower(unsigned char c) {
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static inline unsigned char __toupper(unsigned char c) {
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+extern int errno_int;
+
+// Propolice support
+extern long __guard[8];
+
+void __stack_smash_handler(const char *func, int damaged);
+void __stack_chk_fail(void);
+
+#endif /* _H_STRING */
diff --git a/roms/openbios/include/libc/vsprintf.h b/roms/openbios/include/libc/vsprintf.h
new file mode 100644
index 00000000..4852274f
--- /dev/null
+++ b/roms/openbios/include/libc/vsprintf.h
@@ -0,0 +1,35 @@
+/*
+ * Creation Date: <2003/12/20 01:51:22 samuel>
+ * Time-stamp: <2004/01/07 19:02:17 samuel>
+ *
+ * <vsprintf.h>
+ *
+ *
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_VSPRINTF
+#define _H_VSPRINTF
+
+#include <stdarg.h>
+#include "config.h"
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+ __attribute__((__format__(__printf__, 2, 0)));
+int sprintf(char * buf, const char *fmt, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+ __attribute__((__format__(__printf__, 3, 0)));
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+ __attribute__((__format__(__printf__, 3, 4)));
+
+int forth_printf(const char *fmt, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+
+#endif /* _H_VSPRINTF */
diff --git a/roms/openbios/include/libopenbios/aout_load.h b/roms/openbios/include/libopenbios/aout_load.h
new file mode 100644
index 00000000..b462e1c8
--- /dev/null
+++ b/roms/openbios/include/libopenbios/aout_load.h
@@ -0,0 +1,27 @@
+/*
+ * Creation Date: <2010/03/22 18:00:00 mcayland>
+ * Time-stamp: <2010/03/22 18:00:00 mcayland>
+ *
+ * <aout_load.h>
+ *
+ * a.out loader
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_AOUTLOAD
+#define _H_AOUTLOAD
+
+#include "arch/common/a.out.h"
+#include "libopenbios/sys_info.h"
+
+extern int is_aout(struct exec *ehdr);
+extern int aout_load(struct sys_info *info, ihandle_t dev);
+extern void aout_init_program(void);
+
+#endif /* _H_AOUTLOAD */
diff --git a/roms/openbios/include/libopenbios/bindings.h b/roms/openbios/include/libopenbios/bindings.h
new file mode 100644
index 00000000..de9c7752
--- /dev/null
+++ b/roms/openbios/include/libopenbios/bindings.h
@@ -0,0 +1,156 @@
+/*
+ * Creation Date: <2003/12/19 23:09:56 samuel>
+ * Time-stamp: <2004/01/07 19:36:42 samuel>
+ *
+ * <bindings.h>
+ *
+ * Forth bindings
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_BINDINGS
+#define _H_BINDINGS
+
+#include "kernel/stack.h"
+#include "kernel/kernel.h"
+
+#define PUSH3(a,b,c) do { PUSH((a)); PUSH((b)); PUSH((c)); } while(0)
+#define PUSH2(a,b) do { PUSH((a)); PUSH((b)); } while(0)
+#define RET( v ) do { PUSH(v); return; } while(0)
+
+/* initialization */
+extern int initialize_forth( void );
+
+/* panic */
+extern int forth_segv_handler( char *segv_addr );
+
+/* active package */
+extern phandle_t find_dev( const char *path );
+extern phandle_t get_cur_dev( void );
+extern phandle_t activate_device( const char *str );
+extern void device_end( void );
+extern void activate_dev( phandle_t ph );
+
+
+/* ihandle related */
+extern phandle_t ih_to_phandle( ihandle_t ih );
+extern ihandle_t my_parent( void );
+extern ihandle_t my_self( void );
+extern char *my_args_copy( void );
+
+extern xt_t find_package_method( const char *meth, phandle_t ph );
+extern xt_t find_ih_method( const char *method, ihandle_t ih );
+extern xt_t find_parent_method( const char *method );
+extern void call_package( xt_t xt, ihandle_t ihandle );
+extern void call_parent( xt_t xt );
+extern void call_parent_method( const char *method );
+
+/* package */
+extern ihandle_t open_package( const char *argstr, phandle_t ph );
+extern ihandle_t open_dev( const char *spec );
+extern void close_package( ihandle_t ih );
+extern void close_dev( ihandle_t ih );
+
+/* property access */
+extern void set_property( phandle_t ph, const char *name,
+ const char *buf, int len );
+extern void set_int_property( phandle_t ph, const char *name,
+ u32 val );
+extern u32 get_int_property( phandle_t ph, const char *name,
+ int *retlen );
+extern char *get_property( phandle_t ph, const char *name,
+ int *retlen );
+
+/* device tree iteration */
+extern phandle_t dt_iter_begin( void );
+extern phandle_t dt_iterate( phandle_t last_tree );
+extern phandle_t dt_iterate_type( phandle_t last_tree,
+ const char *type );
+static inline phandle_t dt_find_type( const char *type ) {
+ return dt_iterate_type( 0, type );
+}
+
+/* forth bindings */
+extern cell feval( const char *str );
+extern void bind_xtfunc( const char *name, xt_t xt,
+ ucell arg, void (*func)(void) );
+extern void bind_func( const char *name, void (*func)(void) );
+extern xt_t bind_noname_func( void (*func)(void) );
+extern void push_str( const char *str );
+extern char *pop_fstr_copy( void );
+
+extern int _fword( const char *word, xt_t *cache_xt );
+extern cell _eword( const char *word, xt_t *cache_xt, int nargs );
+extern int _selfword( const char *method, xt_t *cache_xt );
+extern int _parword( const char *method, xt_t *cache_xt );
+
+#define fword(w) ({ static xt_t cache_xt = 0; _fword(w, &cache_xt); })
+#define eword(w, nargs) ({ static xt_t cache_xt = 0; _eword(w, &cache_xt, nargs); })
+#define selfword(w) ({ static xt_t cache_xt = 0; _selfword(w, &cache_xt); })
+#define parword(w) ({ static xt_t cache_xt = 0; _parword(w, &cache_xt); })
+
+extern void throw( int error );
+
+
+/* node bindings */
+extern void make_openable( int only_parents );
+
+
+typedef struct {
+ const char *name;
+ void *func;
+} method_t;
+
+#define REGISTER_NAMED_NODE( name, path ) do { \
+ bind_new_node( name##_flags_, name##_size_, \
+ path, name##_m, sizeof(name##_m)/sizeof(method_t)); \
+ } while(0)
+
+#define REGISTER_NAMED_NODE_PHANDLE( name, path, phandle ) do { \
+ phandle = \
+ bind_new_node( name##_flags_, name##_size_, \
+ path, name##_m, sizeof(name##_m)/sizeof(method_t)); \
+ } while(0)
+
+#define REGISTER_NODE_METHODS( name, path ) do { \
+ const char *paths[1]; \
+ \
+ paths[0] = path; \
+ bind_node( name##_flags_, name##_size_, \
+ paths, 1, name##_m, sizeof(name##_m)/sizeof(method_t)); \
+ } while(0)
+
+#define DECLARE_UNNAMED_NODE( name, flags, size ) \
+static const int name##_flags_ = flags; \
+static const int name##_size_ = size;
+
+#define DECLARE_NODE( name, flags, size, paths... ) \
+static const char * const name##_p[] = { paths }; \
+DECLARE_UNNAMED_NODE(name, flags, size)
+
+#define NODE_METHODS( name ) \
+static const method_t name##_m[]
+
+#define REGISTER_NODE( name ) do { \
+ bind_node( name##_flags_, name##_size_, \
+ name##_p, sizeof(name##_p)/sizeof(char*), \
+ name##_m, sizeof(name##_m)/sizeof(method_t) ); \
+ } while(0)
+
+extern void bind_node( int flags, int size, const char * const *paths, int npaths,
+ const method_t *methods, int nmethods );
+
+extern phandle_t bind_new_node( int flags, int size, const char *name,
+ const method_t *methods, int nmethods );
+
+#define INSTALL_OPEN 1 /* install trivial open and close methods */
+
+
+
+#endif /* _H_BINDINGS */
diff --git a/roms/openbios/include/libopenbios/bootcode_load.h b/roms/openbios/include/libopenbios/bootcode_load.h
new file mode 100644
index 00000000..147783ae
--- /dev/null
+++ b/roms/openbios/include/libopenbios/bootcode_load.h
@@ -0,0 +1,22 @@
+/*
+ * Creation Date: <2010/03/22 18:00:00 mcayland>
+ * Time-stamp: <2010/03/22 18:00:00 mcayland>
+ *
+ * <bootcode_load.h>
+ *
+ * Raw bootcode (%BOOT) loader
+ *
+ * Copyright (C) 2013 Mark Cave-Ayland (mark.cave-ayland@ilande.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_BOOTCODELOAD
+#define _H_BOOTCODELOAD
+
+extern int bootcode_load(ihandle_t dev);
+
+#endif /* _H__H_BOOTCODELOAD */
diff --git a/roms/openbios/include/libopenbios/bootinfo_load.h b/roms/openbios/include/libopenbios/bootinfo_load.h
new file mode 100644
index 00000000..1905a5e9
--- /dev/null
+++ b/roms/openbios/include/libopenbios/bootinfo_load.h
@@ -0,0 +1,26 @@
+/*
+ * Creation Date: <2010/03/22 18:00:00 mcayland>
+ * Time-stamp: <2010/03/22 18:00:00 mcayland>
+ *
+ * <bootinfo_load.h>
+ *
+ * CHRP boot info loader
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_BOOTINFOLOAD
+#define _H_BOOTINFOLOAD
+
+#include "libopenbios/sys_info.h"
+
+extern int is_bootinfo(char *bootinfo);
+extern int bootinfo_load(struct sys_info *info, const char *filename);
+extern void bootinfo_init_program(void);
+
+#endif /* _H_BOOTINFOLOAD */
diff --git a/roms/openbios/include/libopenbios/console.h b/roms/openbios/include/libopenbios/console.h
new file mode 100644
index 00000000..899dab83
--- /dev/null
+++ b/roms/openbios/include/libopenbios/console.h
@@ -0,0 +1,25 @@
+/*
+ * <console.h>
+ *
+ * Shared console routines
+ *
+ * Copyright (C) 2013 Mark Cave-Ayland (mark.cave-ayland@ilande.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_CONSOLE
+#define _H_CONSOLE
+
+struct _console_ops {
+ int (*putchar)(int c);
+ int (*availchar)(void);
+ int (*getchar)(void);
+};
+
+void init_console(struct _console_ops ops);
+
+#endif /* _H_CONSOLE */
diff --git a/roms/openbios/include/libopenbios/elf_load.h b/roms/openbios/include/libopenbios/elf_load.h
new file mode 100644
index 00000000..d3876241
--- /dev/null
+++ b/roms/openbios/include/libopenbios/elf_load.h
@@ -0,0 +1,31 @@
+/*
+ * Creation Date: <2001/05/05 16:44:17 samuel>
+ * Time-stamp: <2003/10/22 23:18:42 samuel>
+ *
+ * <elfload.h>
+ *
+ * Elf loader
+ *
+ * Copyright (C) 2001, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_ELFLOAD
+#define _H_ELFLOAD
+
+#include "arch/common/elf.h"
+#include "asm/elf.h"
+#include "libopenbios/sys_info.h"
+
+extern int elf_load(struct sys_info *info, ihandle_t dev, const char *cmdline, void **boot_notes);
+extern void elf_init_program(void);
+extern int is_elf(Elf_ehdr *ehdr);
+extern int find_elf(Elf_ehdr *ehdr);
+
+extern Elf_phdr * elf_readhdrs(int offset, Elf_ehdr *ehdr);
+
+#endif /* _H_ELFLOAD */
diff --git a/roms/openbios/include/libopenbios/fcode_load.h b/roms/openbios/include/libopenbios/fcode_load.h
new file mode 100644
index 00000000..a84ac982
--- /dev/null
+++ b/roms/openbios/include/libopenbios/fcode_load.h
@@ -0,0 +1,24 @@
+/*
+ * Creation Date: <2010/03/22 18:00:00 mcayland>
+ * Time-stamp: <2010/03/22 18:00:00 mcayland>
+ *
+ * <fcode_load.h>
+ *
+ * Fcode loader
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_FCODELOAD
+#define _H_FCODELOAD
+
+extern int is_fcode(unsigned char *fcode);
+extern int fcode_load(ihandle_t dev);
+extern void fcode_init_program(void);
+
+#endif /* _H_FCODELOAD */
diff --git a/roms/openbios/include/libopenbios/fontdata.h b/roms/openbios/include/libopenbios/fontdata.h
new file mode 100644
index 00000000..1f8f0de3
--- /dev/null
+++ b/roms/openbios/include/libopenbios/fontdata.h
@@ -0,0 +1,28 @@
+/* Font definitions */
+
+#ifndef OPENBIOS_FONTDATA_H
+#define OPENBIOS_FONTDATA_H
+
+#define FONTDATAMAX_8X8 2048
+#define FONT_WIDTH_8X8 8
+#define FONT_HEIGHT_8X8 8
+
+extern const unsigned char fontdata_8x8[FONTDATAMAX_8X8];
+
+#define FONTDATAMAX_8X16 4096
+#define FONT_WIDTH_8X16 8
+#define FONT_HEIGHT_8X16 16
+
+extern const unsigned char fontdata_8x16[FONTDATAMAX_8X16];
+
+#if defined(CONFIG_FONT_8X8)
+#define fontdata fontdata_8x8
+#define FONT_HEIGHT FONT_HEIGHT_8X8
+#define FONT_WIDTH FONT_WIDTH_8X8
+#elif defined(CONFIG_FONT_8X16)
+#define fontdata fontdata_8x16
+#define FONT_HEIGHT FONT_HEIGHT_8X16
+#define FONT_WIDTH FONT_WIDTH_8X16
+#endif
+
+#endif /* OPENBIOS_FONTDATA_H */
diff --git a/roms/openbios/include/libopenbios/forth_load.h b/roms/openbios/include/libopenbios/forth_load.h
new file mode 100644
index 00000000..a39d414c
--- /dev/null
+++ b/roms/openbios/include/libopenbios/forth_load.h
@@ -0,0 +1,24 @@
+/*
+ * Creation Date: <2010/03/22 18:00:00 mcayland>
+ * Time-stamp: <2010/03/22 18:00:00 mcayland>
+ *
+ * <forth_load.h>
+ *
+ * Forth loader
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_FORTHLOAD
+#define _H_FORTHLOAD
+
+extern int is_forth(char *forth);
+extern int forth_load(ihandle_t dev);
+extern void forth_init_program(void);
+
+#endif /* _H_FORTHLOAD */
diff --git a/roms/openbios/include/libopenbios/initprogram.h b/roms/openbios/include/libopenbios/initprogram.h
new file mode 100644
index 00000000..1684f5d9
--- /dev/null
+++ b/roms/openbios/include/libopenbios/initprogram.h
@@ -0,0 +1,22 @@
+/*
+ * Creation Date: <2010/04/02 13:00:00 mcayland>
+ * Time-stamp: <2010/04/02 13:00:00 mcayland>
+ *
+ * <initprogram.h>
+ *
+ * C implementation of (init-program) word
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_INITPROGRAM
+#define _H_INITPROGRAM
+
+extern void init_program(void);
+
+#endif /* _H_INITPROGRAM */
diff --git a/roms/openbios/include/libopenbios/ipchecksum.h b/roms/openbios/include/libopenbios/ipchecksum.h
new file mode 100644
index 00000000..24cc1d74
--- /dev/null
+++ b/roms/openbios/include/libopenbios/ipchecksum.h
@@ -0,0 +1,7 @@
+#ifndef IPCHECKSUM_H
+#define IPCHECKSUM_H
+
+unsigned short ipchksum(const void *data, unsigned long length);
+unsigned short add_ipchksums(unsigned long offset, unsigned short sum, unsigned short new);
+
+#endif /* IPCHECKSUM_H */
diff --git a/roms/openbios/include/libopenbios/load.h b/roms/openbios/include/libopenbios/load.h
new file mode 100644
index 00000000..2a4d97f3
--- /dev/null
+++ b/roms/openbios/include/libopenbios/load.h
@@ -0,0 +1,22 @@
+/*
+ * Creation Date: <2010/06/25 20:00:00 mcayland>
+ * Time-stamp: <2010/06/25 20:00:00 mcayland>
+ *
+ * <load.h>
+ *
+ * C implementation of load
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_LOAD
+#define _H_LOAD
+
+extern void load(ihandle_t dev);
+
+#endif /* _H_LOAD */
diff --git a/roms/openbios/include/libopenbios/of.h b/roms/openbios/include/libopenbios/of.h
new file mode 100644
index 00000000..64cf6d08
--- /dev/null
+++ b/roms/openbios/include/libopenbios/of.h
@@ -0,0 +1,22 @@
+/*
+ * Creation Date: <2004/01/07 19:19:18 samuel>
+ * Time-stamp: <2004/01/07 19:19:48 samuel>
+ *
+ * <of.h>
+ *
+ * OpenFirmware related defines
+ *
+ * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_OF
+#define _H_OF
+
+extern int of_client_interface( int *params );
+
+#endif /* _H_OF */
diff --git a/roms/openbios/include/libopenbios/ofmem.h b/roms/openbios/include/libopenbios/ofmem.h
new file mode 100644
index 00000000..0b19db1c
--- /dev/null
+++ b/roms/openbios/include/libopenbios/ofmem.h
@@ -0,0 +1,145 @@
+/*
+ * Creation Date: <1999/11/16 00:47:06 samuel>
+ * Time-stamp: <2003/10/18 13:28:14 samuel>
+ *
+ * <ofmem.h>
+ *
+ *
+ *
+ * Copyright (C) 1999, 2002 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_OFMEM
+#define _H_OFMEM
+
+#include "kernel/stack.h"
+
+typedef struct alloc_desc {
+ struct alloc_desc *next;
+ ucell size; /* size (including) this struct */
+} alloc_desc_t;
+
+typedef struct mem_range {
+ struct mem_range *next;
+ phys_addr_t start; /* sizeof(phys) >= sizeof(virt), e.g SPARC32 */
+ ucell size;
+} range_t;
+
+typedef struct trans {
+ struct trans *next;
+ ucell virt; /* chain is sorted by virt */
+ ucell size;
+ phys_addr_t phys;
+ ucell mode;
+} translation_t;
+
+/* ofmem private data */
+typedef struct {
+ ucell ramsize;
+ char *next_malloc;
+ alloc_desc_t *mfree; /* list of free malloc blocks */
+
+ range_t *phys_range;
+ range_t *virt_range;
+ range_t *io_range;
+
+ translation_t *trans; /* this is really a translation_t */
+} ofmem_t;
+
+/* structure for retained data */
+typedef struct {
+ ucell magic;
+ ucell numentries;
+ range_t retain_phys_range[8]; /* physical memory that should survive a warm reset */
+} retain_t;
+
+/* TODO: temporary migration interface */
+extern ofmem_t* ofmem_arch_get_private(void);
+extern void* ofmem_arch_get_malloc_base(void);
+extern ucell ofmem_arch_get_heap_top(void);
+extern ucell ofmem_arch_get_virt_top(void);
+extern ucell ofmem_arch_get_iomem_base(void);
+extern ucell ofmem_arch_get_iomem_top(void);
+extern retain_t* ofmem_arch_get_retained(void);
+extern int ofmem_arch_get_physaddr_cellsize(void);
+extern int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value);
+extern int ofmem_arch_get_available_entry_size(phandle_t ph);
+extern void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size);
+extern int ofmem_arch_get_translation_entry_size(void);
+extern void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t);
+extern ucell ofmem_arch_default_translation_mode( phys_addr_t phys );
+extern ucell ofmem_arch_io_translation_mode( phys_addr_t phys );
+extern void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size,
+ ucell mode);
+extern void ofmem_arch_unmap_pages(ucell virt, ucell size);
+/* sparc64 uses this method */
+extern int ofmem_map_page_range( phys_addr_t phys, ucell virt, ucell size,
+ ucell mode );
+
+/* Private functions for mapping between physical/virtual addresses */
+extern phys_addr_t va2pa(unsigned long va);
+extern unsigned long pa2va(phys_addr_t pa);
+
+/* malloc interface */
+extern int ofmem_posix_memalign( void **memptr, size_t alignment, size_t size );
+extern void* ofmem_malloc( size_t size );
+extern void ofmem_free( void *ptr );
+extern void* ofmem_realloc( void *ptr, size_t size );
+
+/* ofmem_common.c */
+
+extern void ofmem_cleanup( void );
+extern void ofmem_init( void );
+
+/*
+ * register /memory and /virtual-memory handles
+ * ofmem module will update "available" and "translations" properties
+ * using these handles
+ *
+ * to disable updating /memory properties pass zero memory handle
+ */
+extern void ofmem_register( phandle_t ph_memory, phandle_t ph_mmu );
+
+extern ucell ofmem_claim( ucell addr, ucell size, ucell align );
+extern phys_addr_t ofmem_claim_phys( phys_addr_t mphys, ucell size, ucell align );
+extern ucell ofmem_claim_virt( ucell mvirt, ucell size, ucell align );
+extern ucell ofmem_claim_io( ucell virt, ucell size, ucell align );
+
+extern phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align );
+
+extern int ofmem_map( phys_addr_t phys, ucell virt, ucell size, ucell mode );
+extern int ofmem_unmap( ucell virt, ucell size );
+extern ucell ofmem_map_io( phys_addr_t phys, ucell size );
+
+extern void ofmem_release( ucell virt, ucell size );
+extern void ofmem_release_phys( phys_addr_t phys, ucell size );
+extern void ofmem_release_virt( ucell virt, ucell size );
+extern void ofmem_release_io( ucell virt, ucell size );
+extern phys_addr_t ofmem_translate( ucell virt, ucell *ret_mode );
+
+/* memory and virtual-memory nodes */
+extern phandle_t s_phandle_memory;
+extern phandle_t s_phandle_mmu;
+
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE - 1))
+#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
+
+#if defined(CONFIG_DEBUG_OFMEM)
+ #define DEBUG_OFMEM 1
+#else
+ #define DEBUG_OFMEM 0
+#endif
+
+#define OFMEM_TRACE(fmt, ...) do { \
+ if (DEBUG_OFMEM) { \
+ printk("OFMEM: " fmt, ## __VA_ARGS__); \
+ } \
+} while (0);
+
+#endif /* _H_OFMEM */
diff --git a/roms/openbios/include/libopenbios/openbios.h b/roms/openbios/include/libopenbios/openbios.h
new file mode 100644
index 00000000..394ed448
--- /dev/null
+++ b/roms/openbios/include/libopenbios/openbios.h
@@ -0,0 +1,22 @@
+/*
+ * Creation Date: <2010/04/02 12:00:00 mcayland>
+ * Time-stamp: <2010/04/02 12:00:00 mcayland>
+ *
+ * <openbios.h>
+ *
+ * General OpenBIOS initialization
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_LIBOPENBIOS
+#define _H_LIBOPENBIOS
+
+extern void openbios_init( void );
+
+#endif /* _H_LIBOPENBIOS */
diff --git a/roms/openbios/include/libopenbios/sys_info.h b/roms/openbios/include/libopenbios/sys_info.h
new file mode 100644
index 00000000..a8b3cce3
--- /dev/null
+++ b/roms/openbios/include/libopenbios/sys_info.h
@@ -0,0 +1,38 @@
+#ifndef SYS_INFO_H
+#define SYS_INFO_H
+
+/* Information collected from firmware/bootloader */
+
+struct sys_info {
+ /* Values passed by bootloader */
+ unsigned long boot_type;
+ unsigned long boot_data;
+ unsigned long boot_arg;
+
+ const char *firmware; /* "PCBIOS", "LinuxBIOS", etc. */
+ const char *command_line; /* command line given to us */
+
+ /* memory map */
+ int n_memranges;
+ struct memrange {
+ unsigned long long base;
+ unsigned long long size;
+ } *memrange;
+ unsigned long *dict_start;
+ unsigned long *dict_end;
+ cell dict_limit;
+ ucell *dict_last;
+};
+
+extern void *elf_boot_notes;
+extern struct sys_info sys_info;
+
+void collect_elfboot_info(struct sys_info *info);
+void collect_linuxbios_info(struct sys_info *info);
+
+/* Our name and version. I want to see single instance of these in the image */
+extern const char *program_name, *program_version;
+
+#define LOADER_NOT_SUPPORT 0xbadf11e
+
+#endif /* SYS_INFO_H */
diff --git a/roms/openbios/include/libopenbios/video.h b/roms/openbios/include/libopenbios/video.h
new file mode 100644
index 00000000..44d74564
--- /dev/null
+++ b/roms/openbios/include/libopenbios/video.h
@@ -0,0 +1,36 @@
+
+#ifdef CONFIG_VGA_WIDTH
+#define VGA_DEFAULT_WIDTH CONFIG_VGA_WIDTH
+#else
+#define VGA_DEFAULT_WIDTH 800
+#endif
+
+#ifdef CONFIG_VGA_HEIGHT
+#define VGA_DEFAULT_HEIGHT CONFIG_VGA_HEIGHT
+#else
+#define VGA_DEFAULT_HEIGHT 600
+#endif
+
+#ifdef CONFIG_VGA_DEPTH
+#define VGA_DEFAULT_DEPTH CONFIG_VGA_DEPTH
+#else
+#define VGA_DEFAULT_DEPTH 8
+#endif
+
+#define VGA_DEFAULT_LINEBYTES (VGA_DEFAULT_WIDTH*((VGA_DEFAULT_DEPTH+7)/8))
+
+void setup_video(void);
+unsigned long video_get_color(int col_ind);
+void video_mask_blit(void);
+void video_invert_rect(void);
+void video_fill_rect(void);
+
+extern struct video_info {
+ volatile ihandle_t *ih;
+ volatile ucell *mvirt;
+ volatile ucell *rb, *w, *h, *depth;
+
+ volatile ucell *pal; /* 256 elements */
+} video;
+
+#define VIDEO_DICT_VALUE(x) (*(ucell *)(x))
diff --git a/roms/openbios/include/libopenbios/xcoff_load.h b/roms/openbios/include/libopenbios/xcoff_load.h
new file mode 100644
index 00000000..2ec693d6
--- /dev/null
+++ b/roms/openbios/include/libopenbios/xcoff_load.h
@@ -0,0 +1,27 @@
+/*
+ * Creation Date: <2010/03/22 18:00:00 mcayland>
+ * Time-stamp: <2010/03/22 18:00:00 mcayland>
+ *
+ * <xcoff_load.h>
+ *
+ * XCOFF loader
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_XCOFFLOAD
+#define _H_XCOFFLOAD
+
+#include "arch/common/xcoff.h"
+#include "libopenbios/sys_info.h"
+
+extern int is_xcoff(COFF_filehdr_t *fhdr);
+extern int xcoff_load(struct sys_info *info, const char *filename);
+extern void xcoff_init_program(void);
+
+#endif /* _H_XCOFFLOAD */
diff --git a/roms/openbios/include/mconfig.h b/roms/openbios/include/mconfig.h
new file mode 100644
index 00000000..0a4decfb
--- /dev/null
+++ b/roms/openbios/include/mconfig.h
@@ -0,0 +1,70 @@
+/*
+ * We got rid of configure for now, and I hope it stays like this.
+ * This file may have to be changed/reworked completely
+ *
+ *
+ */
+
+/* mconfig.h. Generated by configure. */
+/* mconfig.h.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the <endian.h> header file. */
+#define HAVE_ENDIAN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <machine/endian.h> header file. */
+/* #undef HAVE_MACHINE_ENDIAN_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#define YYTEXT_POINTER 1
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
diff --git a/roms/openbios/include/packages/nvram.h b/roms/openbios/include/packages/nvram.h
new file mode 100644
index 00000000..ba1b38b9
--- /dev/null
+++ b/roms/openbios/include/packages/nvram.h
@@ -0,0 +1,24 @@
+/*
+ * Creation Date: <2003/12/20 01:04:25 samuel>
+ * Time-stamp: <2004/01/07 19:59:11 samuel>
+ *
+ * <nvram.h>
+ *
+ * arch NVRAM interface
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_NVRAM_PACKAGE
+#define _H_NVRAM_PACKAGE
+
+extern void nvconf_init( void );
+extern void nvram_init( const char *path );
+extern void update_nvram( void );
+
+#endif /* _H_NVRAM_PACKAGE */
diff --git a/roms/openbios/include/packages/video.h b/roms/openbios/include/packages/video.h
new file mode 100644
index 00000000..2b7f4124
--- /dev/null
+++ b/roms/openbios/include/packages/video.h
@@ -0,0 +1,7 @@
+#ifndef VIDEO_SUBR_H
+#define VIDEO_SUBR_H
+
+/* packages/video.c */
+void molvideo_init(void);
+
+#endif /* VIDEO_SUBR_H */
diff --git a/roms/openbios/include/sysinclude.h b/roms/openbios/include/sysinclude.h
new file mode 100644
index 00000000..a8b828b4
--- /dev/null
+++ b/roms/openbios/include/sysinclude.h
@@ -0,0 +1,20 @@
+#ifndef __SYSINCLUDE_H
+#define __SYSINCLUDE_H
+
+#ifdef BOOTSTRAP
+#include "asm/types.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#else /* BOOTSTRAP */
+#include "libc/stdlib.h"
+#include "libc/string.h"
+#endif /* BOOTSTRAP */
+
+extern int printk( const char *fmt, ... ) \
+ __attribute__ ((format (printf, 1, 2)));
+#ifdef BOOTSTRAP
+#define printk printf
+#endif
+
+#endif /* __SYSINCLUDE_H */
diff --git a/roms/openbios/kernel/Kconfig b/roms/openbios/kernel/Kconfig
new file mode 100644
index 00000000..32831f73
--- /dev/null
+++ b/roms/openbios/kernel/Kconfig
@@ -0,0 +1,88 @@
+menu "Kernel Debugging"
+
+config DEBUG
+ bool "Kernel Debugging"
+ default y
+ help
+ Kernel Debugging
+
+config DEBUG_BOOT
+ bool "Boot messages"
+ depends on DEBUG
+ default y
+ help
+ early boot code (multiboot parsing etc)
+
+config DEBUG_DSTACK
+ bool "dstack messages"
+ depends on DEBUG
+ default n
+ help
+ stack debugging. warning: heavy output!
+
+config DEBUG_RSTACK
+ bool "rstack messages"
+ depends on DEBUG
+ default n
+ help
+ stack debugging. warning: heavy output!
+
+config DEBUG_DICTIONARY
+ bool "Dictionary loading/dumping"
+ depends on DEBUG
+ default n
+ help
+ print few additional information on dictionary loading/dumping
+
+config DEBUG_INTERNAL
+ bool "Prime Words"
+ depends on DEBUG
+ default n
+ help
+ print additional information for some prime words, like branches
+
+config DEBUG_INTERPRETER
+ bool "Interpreter"
+ depends on DEBUG
+ default n
+ help
+ additional information about the unix.c builtin C interpreter
+ and some other places where it actually does not belong.
+
+config DEBUG_CONSOLE
+ bool "Console"
+ default y
+ help
+ use builtin C console code for user interaction. There is no
+ real alternative to this until someone writes a display/kbd or
+ serial driver in forth.
+
+config DEBUG_CONSOLE_SERIAL
+ bool "Serial Console"
+ depends on DEBUG_CONSOLE
+ default y
+ help
+ use serial console.
+
+config SERIAL_PORT
+ int "Serial Port"
+ depends on DEBUG_CONSOLE_SERIAL
+ default "1"
+ help
+ 0 for none, 1 for ttyS0, 2 for ttyS1
+
+config SERIAL_SPEED
+ int "Serial line speed"
+ depends on DEBUG_CONSOLE_SERIAL
+ default "115200"
+ help
+ supported speeds are: 115200, 57600, 38400, 19200, 9600
+
+config DEBUG_CONSOLE_VGA
+ bool "VGA Console"
+ depends on DEBUG_CONSOLE
+ default y
+ help
+ use vga textmode and keyboard console
+
+endmenu
diff --git a/roms/openbios/kernel/README b/roms/openbios/kernel/README
new file mode 100644
index 00000000..c84879b8
--- /dev/null
+++ b/roms/openbios/kernel/README
@@ -0,0 +1,93 @@
+
+Welcome to the OpenBIOS forth core "begin again".
+
+Find more information about OpenBIOS at http://www.openbios.org/
+
+This program was written by Patrick Mauritz and Stefan Reinauer in 2003
+For license details on this piece of software, check Documentation/COPYING.
+
+How OpenBIOS works
+------------------
+
+ The OpenBIOS forth core is split into a forth kernel written in C
+ and a forth dictionary which operated on by the kernel.
+
+ When building the forth core, you get different versions of
+ the forth kernel:
+
+ * a "hosted" unix binary. This binary can be used on a unix system
+
+ - to execute a forth dictionary from a file. This can be used for
+ testing openbios code in a development environment on a unix host.
+
+ - to create a dictionary file. Such a dictionary file sets up
+ all of the forth language. Primitives are indexed to save relocations.
+
+ The default is to create a forth dictionary forth.dict from
+ forth/start.fs. This file includes all of the basic forth language
+ constructs from forth/bootstrap.fs and starts the interpreter.
+
+ To achieve this, the hosted unix version contains a basic set of
+ forth words coded in C that allow creating a full dictionary.
+
+ * a varying number of target specific binaries. On x86 you can start
+ openbios for example from GRUB or LinuxBIOS. They are all based on
+ the same forth engine consisting of a dictionary scheduler, primitive
+ words needed to build the forth environment, 2 stacks and a simple
+ set of console functions. These binaries can not be started directly
+ in the unix host environment.
+
+Requirements
+------------
+ * gcc
+ * grub or any other multiboot loader to run the standalone
+ binary "openbios.multiboot"
+
+Building & Usage
+----------------
+
+ * make
+
+ this builds "openbios.multiboot", the standalone image and "unix",
+ the hosted image. Additionally it creates a forth dictionary
+ file from forth/start.fs. All generated files are written to
+ the absolute directory held by the variable BUILDDIR, which defaults
+ to obj-[platform]. Some compile time parameters can be tweaked in
+ include/config.h
+
+ * use "unix" to create a forth dictionary on your own:
+ $ ./unix -Iforth start.fs
+ creates the file forth.dict from forth source forth/start.fs.
+
+ * use "unix" to run a created dictionary:
+ $ ./unix forth.dict
+ This is useful for testing
+
+ * booting openbios
+ You can boot openbios i.e. in grub. Add the following lines to
+ your menu.lst:
+
+ title openbios
+ kernel (hd0,2)/boot/openbios.multiboot
+ module (hd0,2)/boot/openfirmware.dict
+
+ Note: change (hd0,2) to the partition you copied openbios and
+ forth.dict to.
+
+ To boot OpenBIOS from LinuxBIOS/etherboot, you can either use
+ "openbios" or "openbios.full":
+
+ - openbios is the pure kernel that loads the dictionary from a
+ hardcoded address in flash memory (0xfffe0000)
+
+ - openbios.full also includes the dictionary directly so that it
+ can be easily used from etherboot or the LinuxBIOS builtin ELF
+ loader without taking care of the dictionary
+
+
+Comments are welcome.
+
+ OpenBIOS team
+
+------------------------------------------------------------------------
+tag: README for openbios forth core
diff --git a/roms/openbios/kernel/bootstrap.c b/roms/openbios/kernel/bootstrap.c
new file mode 100644
index 00000000..520d7b48
--- /dev/null
+++ b/roms/openbios/kernel/bootstrap.c
@@ -0,0 +1,1322 @@
+/* tag: forth bootstrap environment
+ *
+ * Copyright (C) 2003-2006 Stefan Reinauer, Patrick Mauritz
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "sysinclude.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/stat.h>
+
+#ifdef __GLIBC__
+#define _GNU_SOURCE
+#include <getopt.h>
+#endif
+
+#include "config.h"
+#include "kernel/stack.h"
+#include "sysinclude.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+#include "cross.h"
+#include "openbios-version.h"
+
+#define MAX_PATH_LEN 256
+
+#define MEMORY_SIZE (1024*1024) /* 1M ram for hosted system */
+#define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */
+#define TRAMPOLINE_SIZE (4*sizeof(cell)) /* 4 cells for the trampoline */
+
+/* state variables */
+static ucell *latest, *state, *base;
+static ucell *memory;
+ucell *trampoline;
+
+/* local variables */
+static int errors = 0;
+static int segfault = 0;
+static int verbose = 0;
+
+#define MAX_SRC_FILES 128
+
+static FILE *srcfiles[MAX_SRC_FILES];
+static char *srcfilenames[MAX_SRC_FILES];
+static int srclines[MAX_SRC_FILES];
+static unsigned int cursrc = 0;
+
+static char *srcbasedict;
+
+/* console variables */
+static FILE *console;
+
+#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
+unsigned long base_address;
+#endif
+
+/* include path handling */
+typedef struct include_path include;
+struct include_path {
+ const char *path;
+ include *next;
+};
+
+static include includes = { ".", NULL };
+static FILE *depfile;
+
+static ucell * relocation_address=NULL;
+static int relocation_length=0;
+
+/* the word names are used to generate the prim words in the
+ * dictionary. This is done by the C written interpreter.
+ */
+static const char *wordnames[] = {
+ "(semis)", "", "(lit)", "", "", "", "", "(do)", "(?do)", "(loop)",
+ "(+loop)", "", "", "", "dup", "2dup", "?dup", "over", "2over", "pick", "drop",
+ "2drop", "nip", "roll", "rot", "-rot", "swap", "2swap", ">r", "r>",
+ "r@", "depth", "depth!", "rdepth", "rdepth!", "+", "-", "*", "u*",
+ "mu/mod", "abs", "negate", "max", "min", "lshift", "rshift", ">>a",
+ "and", "or", "xor", "invert", "d+", "d-", "m*", "um*", "@", "c@",
+ "w@", "l@", "!", "+!", "c!", "w!", "l!", "=", ">", "<", "u>", "u<",
+ "sp@", "move", "fill", "(emit)", "(key?)", "(key)", "execute",
+ "here", "here!", "dobranch", "do?branch", "unaligned-w@",
+ "unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@",
+ "iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug",
+ "$include", "$encode-file", "(debug", "(debug-off)"
+};
+
+/*
+ * dictionary related functions.
+ */
+
+/*
+ * Compare two dictionaries constructed at different addresses. When
+ * the cells don't match, a need for relocation is detected and the
+ * corresponding bit in reloc_table bitmap is set.
+ */
+static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length)
+{
+ ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two;
+ ucell *reloc_table;
+ int pos, bit;
+ int l=(length+(sizeof(cell)-1))/sizeof(ucell), i;
+
+ /* prepare relocation table */
+ relocation_length=(length+BITS-1)/BITS;
+ reloc_table = malloc(relocation_length*sizeof(cell));
+ memset(reloc_table,0,relocation_length*sizeof(cell));
+
+ for (i=0; i<l; i++) {
+
+ pos=i/BITS;
+ bit=i&~(-BITS);
+
+ if(d1[i]==d2[i]) {
+ reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit));
+
+ // This check might bring false positives in data.
+ //if(d1[i] >= pointer2cell(dict_one) &&
+ // d1[i] <= pointer2cell(dict_one+length))
+ // printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]);
+ } else {
+ /* This is a pointer, it needs relocation, d2==dict */
+ reloc_table[pos] |= target_ucell((ucell)1ULL << bit);
+ d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2));
+ }
+ }
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict);
+ for (i=0; i< relocation_length ; i++)
+ printk("reloc %d %lx\n",i+1, reloc_table[i]);
+#endif
+ relocation_address=reloc_table;
+}
+
+static void write_dictionary(const char *filename)
+{
+ FILE *f;
+ unsigned char *write_data, *walk_data;
+ int write_len;
+ dictionary_header_t *header;
+ u32 checksum=0;
+
+ /*
+ * get memory for dictionary
+ */
+
+ write_len = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell);
+ write_data = malloc(write_len);
+ if(!write_data) {
+ printk("panic: can't allocate memory for output dictionary (%d"
+ " bytes\n", write_len);
+ exit(1);
+ }
+ memset(write_data, 0, write_len);
+
+ /*
+ * prepare dictionary header
+ */
+
+ header = (dictionary_header_t *)write_data;
+ *header = (dictionary_header_t){
+ .signature = DICTID,
+ .version = 2,
+ .cellsize = sizeof(ucell),
+#ifdef CONFIG_BIG_ENDIAN
+ .endianess = -1,
+#else
+ .endianess = 0,
+#endif
+ .checksum = 0,
+ .compression = 0,
+ .relocation = -1,
+ .length = target_ulong((uint32_t)dicthead),
+ .last = target_ucell((ucell)((unsigned long)last
+ - (unsigned long)dict)),
+ };
+
+ /*
+ * prepare dictionary data
+ */
+
+ walk_data=write_data+sizeof(dictionary_header_t);
+ memcpy (walk_data, dict, dicthead);
+
+ /*
+ * prepare relocation data.
+ * relocation_address is zero when writing a dictionary core.
+ */
+
+ if (relocation_address) {
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("writing %d reloc cells \n",relocation_length);
+#endif
+ walk_data += dicthead;
+ memcpy(walk_data, relocation_address,
+ relocation_length*sizeof(cell));
+ /* free relocation information */
+ free(relocation_address);
+ relocation_address=NULL;
+ } else {
+ header->relocation=0;
+ }
+
+ /*
+ * Calculate Checksum
+ */
+
+ walk_data=write_data;
+ while (walk_data<write_data+write_len) {
+ checksum+=read_long(walk_data);
+ walk_data+=sizeof(u32);
+ }
+ checksum=(u32)-checksum;
+
+ header->checksum=target_long(checksum);
+
+ if (verbose) {
+ dump_header(header);
+ }
+
+ f = fopen(filename, "w");
+ if (!f) {
+ printk("panic: can't write to dictionary '%s'.\n", filename);
+ exit(1);
+ }
+
+ fwrite(write_data, write_len, 1, f);
+
+ free(write_data);
+ fclose(f);
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("wrote dictionary to file %s.\n", filename);
+#endif
+}
+
+/*
+ * Write dictionary as a list of ucell hex values to filename. Array
+ * header and end lines are not generated.
+ *
+ * Cells with relocations are output using the expression
+ * DICTIONARY_BASE + value.
+ *
+ * Define some helpful constants.
+ */
+static void write_dictionary_hex(const char *filename)
+{
+ FILE *f;
+ ucell *walk;
+
+ f = fopen(filename, "w");
+ if (!f) {
+ printk("panic: can't write to dictionary '%s'.\n", filename);
+ exit(1);
+ }
+
+ for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) {
+ int pos, bit, l;
+ ucell val;
+
+ l = (walk - (ucell *)dict);
+ pos = l / BITS;
+ bit = l & ~(-BITS);
+
+ val = read_ucell(walk);
+ if (relocation_address[pos] & target_ucell((ucell)1ULL << bit)) {
+ fprintf(f, "DICTIONARY_BASE + 0x%" FMT_CELL_x
+ ",\n", val);
+ } else {
+ fprintf(f, "0x%" FMT_CELL_x",\n", val);
+ }
+ }
+
+ fprintf(f, "#define FORTH_DICTIONARY_LAST 0x%" FMT_CELL_x"\n",
+ (ucell)((unsigned long)last - (unsigned long)dict));
+ fprintf(f, "#define FORTH_DICTIONARY_END 0x%" FMT_CELL_x"\n",
+ (ucell)dicthead);
+ fclose(f);
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("wrote dictionary to file %s.\n", filename);
+#endif
+}
+
+static ucell read_dictionary(char *fil)
+{
+ int ilen;
+ ucell ret;
+ char *mem;
+ FILE *f;
+ struct stat finfo;
+
+ if (stat(fil, &finfo))
+ return 0;
+
+ ilen = finfo.st_size;
+
+ if ((mem = malloc(ilen)) == NULL) {
+ printk("panic: not enough memory.\n");
+ exit(1);
+ }
+
+ f = fopen(fil, "r");
+ if (!f) {
+ printk("panic: can't open dictionary.\n");
+ exit(1);
+ }
+
+ if (fread(mem, ilen, 1, f) != 1) {
+ printk("panic: can't read dictionary.\n");
+ fclose(f);
+ exit(1);
+ }
+ fclose(f);
+
+ ret = load_dictionary(mem, ilen);
+
+ free(mem);
+ return ret;
+}
+
+
+/*
+ * C Parser related functions
+ */
+
+/*
+ * skipws skips all whitespaces (space, tab, newline) from the input file
+ */
+
+static void skipws(FILE * f)
+{
+ int c;
+ while (!feof(f)) {
+ c = getc(f);
+
+ if (c == ' ' || c == '\t')
+ continue;
+
+ if (c == '\n') {
+ srclines[cursrc - 1]++;
+ continue;
+ }
+
+ ungetc(c, f);
+ break;
+ }
+}
+
+/*
+ * parse gets the next word from the input stream, delimited by
+ * delim. If delim is 0, any word delimiter will end the stream
+ * word delimiters are space, tab and newline. The resulting word
+ * will be put zero delimited to the char array line.
+ */
+
+static int parse(FILE * f, char *line, char delim)
+{
+ int cnt = 0, c = 0;
+
+ while (!feof(f)) {
+ c = getc(f);
+
+ if (delim && c == delim)
+ break;
+
+ if ((!delim) && (c == ' ' || c == '\t' || c == '\n'))
+ break;
+
+ line[cnt++] = c;
+ }
+
+ /* Update current line number */
+ if (c == '\n') {
+ srclines[cursrc - 1]++;
+ }
+
+ line[cnt] = 0;
+
+ return cnt;
+}
+
+/*
+ * parse_word is a small helper that skips whitespaces before a word.
+ * it's behaviour is similar to the forth version parse-word.
+ */
+
+static void parse_word(FILE * f, char *line)
+{
+ skipws(f);
+ parse(f, line, 0);
+}
+
+
+static void writestring(const char *str)
+{
+ unsigned int i;
+ for (i = 0; i < strlen(str); i++) {
+ dict[dicthead + i] = str[i];
+ }
+ dicthead += i + 1;
+ dict[dicthead - 1] = (char) strlen(str) + 128;
+}
+
+#define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;}
+#define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);}
+
+/*
+ * reveal a word, ie. make it visible.
+ */
+
+static void reveal(void)
+{
+ *last = *latest;
+}
+
+/*
+ * dictionary padding
+ */
+
+static void paddict(ucell align)
+{
+ while (dicthead % align != 0)
+ writebyte(0);
+}
+
+/*
+ * generic forth word creator function.
+ */
+
+static void fcreate(const char *word, ucell cfaval)
+{
+ if (strlen(word) == 0) {
+ printk("WARNING: tried to create unnamed word.\n");
+ return;
+ }
+
+ writestring(word);
+ /* get us at least 1 byte for flags */
+ writebyte(0);
+ paddict(sizeof(cell));
+ /* set flags high bit. */
+ dict[dicthead - 1] = 128;
+ /* lfa and cfa */
+ writecell(read_ucell(latest));
+ *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell));
+ writecell(cfaval);
+}
+
+
+static ucell *buildvariable(const char *name, cell defval)
+{
+ fcreate(name, DOVAR); /* see dict.h for DOVAR and other CFA ids */
+ writecell(defval);
+ return (ucell *) (dict + dicthead - sizeof(cell));
+}
+
+static void buildconstant(const char *name, cell defval)
+{
+ fcreate(name, DOCON); /* see dict.h for DOCON and other CFA ids */
+ writecell(defval);
+}
+
+static void builddefer(const char *name)
+{
+ fcreate(name, DODFR); /* see dict.h for DODFR and other CFA ids */
+ writecell((ucell)0);
+ writecell((ucell)findword("(semis)"));
+}
+
+/*
+ * Include file handling
+ */
+
+static void add_includepath(char *path)
+{
+ include *incl = &includes;
+ include *newpath;
+
+ while (incl->next)
+ incl = incl->next;
+
+ newpath = malloc(sizeof(include));
+ if (!newpath) {
+ printk("panic: not enough memory for include path.\n");
+ exit(1);
+ }
+
+ incl->next = newpath;
+ newpath->path = path;
+ newpath->next = NULL;
+}
+
+
+static FILE *fopen_include(const char *fil)
+{
+ char fullpath[MAX_PATH_LEN];
+ FILE *ret;
+ include *incl = &includes;
+
+ while (incl) {
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil);
+
+ ret = fopen(fullpath, "r");
+ if (ret != NULL) {
+
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("Including '%s'\n", fil);
+#endif
+ srcfilenames[cursrc] = strdup(fil);
+ srclines[cursrc] = 1;
+ srcfiles[cursrc++] = ret;
+
+ if (depfile) {
+ fprintf(depfile, " %s", fullpath);
+ }
+
+ return ret;
+ }
+
+ incl = incl->next;
+ }
+ return NULL;
+}
+
+
+/*
+ * Forth exception handler
+ */
+
+void exception(cell no)
+{
+ printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]);
+
+ /* See also forth/bootstrap/interpreter.fs */
+ switch (no) {
+ case -1:
+ case -2:
+ printk("Aborted.\n");
+ break;
+ case -3:
+ printk("Stack Overflow.\n");
+ break;
+ case -4:
+ printk("Stack Underflow.\n");
+ break;
+ case -5:
+ printk("Return Stack Overflow.\n");
+ break;
+ case -6:
+ printk("Return Stack Underflow.\n");
+ break;
+ case -19:
+ printk("undefined word.\n");
+ break;
+ case -21:
+ printk("out of memory.\n");
+ break;
+ case -33:
+ printk("undefined method.\n");
+ break;
+ case -34:
+ printk("no such device.\n");
+ break;
+ default:
+ printk("error %" FMT_CELL_d " occured.\n", no);
+ }
+ exit(1);
+}
+
+
+/*
+ * This is the C version of the forth interpreter
+ */
+
+static int interpret_source(char *fil)
+{
+ FILE *f;
+ char tib[160];
+ cell num;
+ char *test;
+
+ const ucell SEMIS = (ucell)findword("(semis)");
+ const ucell LIT = (ucell)findword("(lit)");
+ const ucell DOBRANCH = (ucell)findword("dobranch");
+
+ if ((f = fopen_include(fil)) == NULL) {
+ printk("error while loading source file '%s'\n", fil);
+ errors++;
+ exit(1);
+ }
+
+ /* FIXME: We should read this file at
+ * once. No need to get it char by char
+ */
+
+ while (!feof(f)) {
+ xt_t res;
+ parse_word(f, tib);
+
+ /* if there is actually no word, we continue right away */
+ if (strlen(tib) == 0) {
+ continue;
+ }
+
+ /* Checking for builtin words that are needed to
+ * bootstrap the forth base dictionary.
+ */
+
+ if (!strcmp(tib, "(")) {
+ parse(f, tib, ')');
+ continue;
+ }
+
+ if (!strcmp(tib, "\\")) {
+ parse(f, tib, '\n');
+ continue;
+ }
+
+ if (!strcmp(tib, ":")) {
+ parse_word(f, tib);
+
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("create colon word %s\n\n", tib);
+#endif
+ fcreate(tib, DOCOL); /* see dict.h for DOCOL and other CFA ids */
+ *state = (ucell) (-1);
+ continue;
+ }
+
+ if (!strcmp(tib, ";")) {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("finish colon definition\n\n");
+#endif
+ writecell((cell)SEMIS);
+ *state = (ucell) 0;
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "variable")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("defining variable %s\n\n", tib);
+#endif
+ buildvariable(tib, 0);
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "constant")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("defining constant %s\n\n", tib);
+#endif
+ buildconstant(tib, POP());
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "value")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("defining value %s\n\n", tib);
+#endif
+ buildconstant(tib, POP());
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "defer")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("defining defer word %s\n\n", tib);
+#endif
+ builddefer(tib);
+ reveal();
+ continue;
+ }
+
+ if (!strcasecmp(tib, "include")) {
+ parse_word(f, tib);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("including file %s\n\n", tib);
+#endif
+ interpret_source(tib);
+ continue;
+ }
+
+ if (!strcmp(tib, "[']")) {
+ xt_t xt;
+ parse_word(f, tib);
+ xt = findword(tib);
+ if (*state == 0) {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk
+ ("writing address of %s to stack\n\n",
+ tib);
+#endif
+ PUSH_xt(xt);
+ } else {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("writing lit, addr(%s) to dict\n\n",
+ tib);
+#endif
+ writecell(LIT); /* lit */
+ writecell((cell)xt);
+ }
+ continue;
+ /* we have no error detection here */
+ }
+
+ if (!strcasecmp(tib, "s\"")) {
+ int cnt;
+ cell loco;
+
+ cnt = parse(f, tib, '"');
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("compiling string %s\n", tib);
+#endif
+ loco = dicthead + (6 * sizeof(cell));
+ writecell(LIT);
+ writecell(pointer2cell(dict) + loco);
+ writecell(LIT);
+ writecell((ucell)cnt);
+ writecell(DOBRANCH);
+ loco = cnt + sizeof(cell) - 1;
+ loco &= ~(sizeof(cell) - 1);
+ writecell(loco);
+ memcpy(dict + dicthead, tib, cnt);
+ dicthead += cnt;
+ paddict(sizeof(cell));
+ continue;
+ }
+
+ /* look if tib is in dictionary. */
+ /* should the dictionary be searched before the builtins ? */
+ res = findword(tib);
+ if (res) {
+ u8 flags = read_byte((u8*)cell2pointer(res) -
+ sizeof(cell) - 1);
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("%s is 0x%" FMT_CELL_x "\n", tib, (ucell) res);
+#endif
+ if (!(*state) || (flags & 3)) {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("executing %s, %" FMT_CELL_d
+ " (flags: %s %s)\n",
+ tib, res,
+ (flags & 1) ? "immediate" : "",
+ (flags & 2) ? "compile-only" : "");
+#endif
+ PC = (ucell)res;
+ enterforth(res);
+ } else {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("writing %s to dict\n\n", tib);
+#endif
+ writecell((cell)res);
+ }
+ continue;
+ }
+
+ /* if not look if it's a number */
+ if (tib[0] == '-')
+ num = strtoll(tib, &test, read_ucell(base));
+ else
+ num = strtoull(tib, &test, read_ucell(base));
+
+
+ if (*test != 0) {
+ /* what is it?? */
+ printk("%s:%d: %s is not defined.\n\n", srcfilenames[cursrc - 1], srclines[cursrc - 1], tib);
+ errors++;
+#ifdef CONFIG_DEBUG_INTERPRETER
+ continue;
+#else
+ return -1;
+#endif
+ }
+
+ if (*state == 0) {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("pushed %" FMT_CELL_x " to stack\n\n", num);
+#endif
+ PUSH(num);
+ } else {
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("writing lit, %" FMT_CELL_x " to dict\n\n", num);
+#endif
+ writecell(LIT); /* lit */
+ writecell(num);
+ }
+ }
+
+ fclose(f);
+ cursrc--;
+
+ return 0;
+}
+
+static int build_dictionary(void)
+{
+ ucell lfa = 0;
+ unsigned int i;
+
+ /* we need a temporary place for latest outside the dictionary */
+ latest = &lfa;
+
+ /* starting a new dictionary: clear dicthead */
+ dicthead = 0;
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("building dictionary, %d primitives.\nbuilt words:",
+ sizeof(wordnames) / sizeof(void *));
+#endif
+
+ for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) {
+ if (strlen(wordnames[i]) != 0) {
+ fcreate((char *) wordnames[i], i);
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk(" %s", wordnames[i]);
+#endif
+ }
+ }
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk(".\n");
+#endif
+
+ /* get last/latest and state */
+ state = buildvariable("state", 0);
+ last = buildvariable("forth-last", 0);
+ latest = buildvariable("latest", 0);
+
+ *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell));
+
+ base=buildvariable("base", 10);
+
+ buildconstant("/c", sizeof(u8));
+ buildconstant("/w", sizeof(u16));
+ buildconstant("/l", sizeof(u32));
+ buildconstant("/n", sizeof(ucell));
+ buildconstant("/x", sizeof(u64));
+
+ reveal();
+ if (verbose) {
+ printk("Dictionary initialization finished.\n");
+ }
+ return 0;
+}
+
+/*
+ * functions used by primitives
+ */
+
+int availchar(void)
+{
+ int tmp;
+ if( cursrc < 1 ) {
+ interruptforth |= FORTH_INTSTAT_STOP;
+ /* return -1 in order to exit the loop in key() */
+ return -1;
+ }
+
+ tmp = getc( srcfiles[cursrc-1] );
+ if (tmp != EOF) {
+ ungetc(tmp, srcfiles[cursrc-1]);
+ return -1;
+ }
+
+ fclose(srcfiles[--cursrc]);
+
+ return availchar();
+}
+
+int get_inputbyte( void )
+{
+ int tmp;
+
+ if( cursrc < 1 ) {
+ interruptforth |= FORTH_INTSTAT_STOP;
+ return 0;
+ }
+
+ tmp = getc( srcfiles[cursrc-1] );
+
+ /* Update current line number */
+ if (tmp == '\n') {
+ srclines[cursrc - 1]++;
+ }
+
+ if (tmp != EOF) {
+ return tmp;
+ }
+
+ fclose(srcfiles[--cursrc]);
+
+ return get_inputbyte();
+}
+
+void put_outputbyte( int c )
+{
+ if (console)
+ fputc(c, console);
+}
+
+/*
+ * segmentation fault handler. linux specific?
+ */
+
+static void
+segv_handler(int signo __attribute__ ((unused)),
+ siginfo_t * si, void *context __attribute__ ((unused)))
+{
+ static int count = 0;
+ ucell addr = 0xdeadbeef;
+
+ if (count) {
+ printk("Died while dumping forth dictionary core.\n");
+ goto out;
+ }
+
+ count++;
+
+ if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead)
+ addr = read_cell(cell2pointer(PC));
+
+ printk("panic: segmentation violation at %p\n", (char *)si->si_addr);
+ printk("dict=%p here=%p(dict+0x%" FMT_CELL_x ") pc=0x%" FMT_CELL_x "(dict+0x%" FMT_CELL_x ")\n",
+ dict, dict + dicthead, dicthead, PC, PC - pointer2cell(dict));
+ printk("dstackcnt=%d rstackcnt=%d instruction=%" FMT_CELL_x "\n",
+ dstackcnt, rstackcnt, addr);
+
+ printdstack();
+ printrstack();
+
+ printk("Writing dictionary core file\n");
+ write_dictionary("forth.dict.core");
+
+ out:
+ exit(1);
+}
+
+/*
+ * allocate memory and prepare engine for memory management.
+ */
+
+static void init_memory(void)
+{
+ memset(memory, 0, MEMORY_SIZE);
+
+ /* we push start and end of memory to the stack
+ * so that it can be used by the forth word QUIT
+ * to initialize the memory allocator.
+ * Add a cell to the start address so we don't end
+ * up with a start address of zero during bootstrap
+ */
+
+ PUSH(pointer2cell(memory)+sizeof(cell));
+ PUSH(pointer2cell(memory) + MEMORY_SIZE-1);
+}
+
+
+void
+include_file( const char *name )
+{
+ FILE *file;
+
+ if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) {
+ printk("\npanic: Maximum include depth reached!\n");
+ exit(1);
+ }
+
+ file = fopen_include( name );
+ if( !file ) {
+ printk("\npanic: Failed opening file '%s'\n", name );
+ exit(1);
+ }
+}
+
+
+void
+encode_file( const char *name )
+{
+ FILE *file = fopen_include(name);
+ int size;
+
+ if( !file ) {
+ printk("\npanic: Can't open '%s'\n", name );
+ exit(1);
+ }
+ fseek( file, 0, SEEK_END );
+ size = ftell( file );
+ fseek( file, 0, SEEK_SET );
+
+ if (verbose) {
+ printk("\nEncoding %s [%d bytes]\n", name, size );
+ }
+ fread( dict + dicthead, size, 1, file );
+ PUSH( pointer2cell(dict + dicthead) );
+ PUSH( size );
+ dicthead += size;
+ paddict(sizeof(cell));
+}
+
+
+static void run_dictionary(char *basedict, char *confile)
+{
+ if(!basedict)
+ return;
+
+ read_dictionary(basedict);
+ PC = (ucell)findword("initialize");
+
+ if (!PC) {
+ if (verbose) {
+ printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict);
+ }
+ return;
+ }
+
+ if(!srcfiles[0]) {
+ cursrc = 1;
+ srcfiles[cursrc-1] = stdin;
+ }
+
+ dstackcnt=0;
+ rstackcnt=0;
+
+ init_memory();
+ if (verbose)
+ printk("Jumping to dictionary %s...\n", basedict);
+
+ /* If a console file has been specified, open it */
+ if (confile)
+ console = fopen(confile, "w");
+
+ srcbasedict = basedict;
+
+ enterforth((xt_t)PC);
+
+ /* Close the console file */
+ if (console)
+ fclose(console);
+}
+
+static void new_dictionary(const char *source)
+{
+ build_dictionary();
+
+ interpret_source((char *)source);
+
+ if (verbose || errors > 0) {
+ printk("interpretion finished. %d errors occured.\n",
+ errors);
+ }
+}
+
+/*
+ * main loop
+ */
+
+#define BANNER "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\
+ "This software comes with absolutely no warranty. "\
+ "All rights reserved.\n\n"
+
+#ifdef __GLIBC__
+#define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
+ " -h|--help show this help\n" \
+ " -V|--version print version and exit\n" \
+ " -v|--verbose print debugging information\n" \
+ " -I|--include dir add dir to include path\n" \
+ " -d|--source-dictionary bootstrap.dict\n" \
+ " use this dictionary as base\n" \
+ " -D|--target-dictionary output.dict\n" \
+ " write to output.dict\n" \
+ " -c|--console output.log\n" \
+ " write kernel console output to log file\n" \
+ " -s|--segfault install segfault handler\n" \
+ " -M|--dependency-dump file\n" \
+ " dump dependencies in Makefile format\n\n" \
+ " -x|--hexdump output format is C language hex dump\n"
+#else
+#define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
+ " -h show this help\n" \
+ " -V print version and exit\n" \
+ " -v print debugging information\n" \
+ " -I add dir to include path\n" \
+ " -d bootstrap.dict\n" \
+ " use this dictionary as base\n" \
+ " -D output.dict\n" \
+ " write to output.dict\n" \
+ " -c output.log\n" \
+ " write kernel console output to log file\n" \
+ " -s install segfault handler\n\n" \
+ " -M file dump dependencies in Makefile format\n\n" \
+ " -x output format is C language hex dump\n"
+#endif
+
+int main(int argc, char *argv[])
+{
+ struct sigaction sa;
+
+ unsigned char *ressources=NULL; /* All memory used by us */
+ const char *dictname = NULL;
+ char *basedict = NULL;
+ char *consolefile = NULL;
+ char *depfilename = NULL;
+
+ unsigned char *bootstrapdict[2];
+ int c, cnt, hexdump = 0;
+
+ const char *optstring = "VvhsI:d:D:c:M:x?";
+
+ while (1) {
+#ifdef __GLIBC__
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"version", 0, NULL, 'V'},
+ {"verbose", 0, NULL, 'v'},
+ {"help", 0, NULL, 'h'},
+ {"segfault", 0, NULL, 's'},
+ {"include", 1, NULL, 'I'},
+ {"source-dictionary", 1, NULL, 'd'},
+ {"target-dictionary", 1, NULL, 'D'},
+ {"console", 1, NULL, 'c'},
+ {"dependency-dump", 1, NULL, 'M'},
+ {"hexdump", 0, NULL, 'x'},
+ };
+
+ /*
+ * option handling
+ */
+
+ c = getopt_long(argc, argv, optstring, long_options,
+ &option_index);
+#else
+ c = getopt(argc, argv, optstring);
+#endif
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'V':
+ printk("Version " OPENBIOS_VERSION_STR "\n");
+ return 0;
+ case 'h':
+ case '?':
+ printk("Version " OPENBIOS_VERSION_STR "\n" USAGE,
+ argv[0]);
+ return 0;
+ case 'v':
+ verbose = 1;
+ break;
+ case 's':
+ segfault = 1;
+ break;
+ case 'I':
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printk("adding '%s' to include path\n", optarg);
+#endif
+ add_includepath(optarg);
+ break;
+ case 'd':
+ if (!basedict) {
+ basedict = optarg;
+ }
+ break;
+ case 'D':
+ if(!dictname) {
+ dictname = optarg;
+ }
+ break;
+ case 'c':
+ if (!consolefile) {
+ consolefile = optarg;
+ }
+ break;
+ case 'M':
+ if (!depfilename) {
+ depfilename = optarg;
+ }
+ break;
+ case 'x':
+ hexdump = 1;
+ break;
+ default:
+ return 1;
+ }
+ }
+
+ if (!dictname) {
+ dictname = "bootstrap.dict";
+ }
+ if (verbose) {
+ printk(BANNER);
+ printk("Using source dictionary '%s'\n", basedict);
+ printk("Dumping final dictionary to '%s'\n", dictname);
+ printk("Dumping dependencies to '%s'\n", depfilename);
+ }
+
+ if (argc < optind) {
+ printk(USAGE, argv[0]);
+ return 1;
+ }
+
+ if (depfilename) {
+ depfile = fopen(depfilename, "w");
+ if (!depfile) {
+ printk("panic: can't write to dependency file '%s'.\n",
+ depfilename);
+ exit(1);
+ }
+ fprintf(depfile, "%s:", dictname);
+ }
+
+ /*
+ * Get all required resources
+ */
+
+
+ ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE);
+ if (!ressources) {
+ printk("panic: not enough memory on host system.\n");
+ return 1;
+ }
+
+#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
+ base_address=(unsigned long)ressources;
+#endif
+
+ memory = (ucell *)ressources;
+
+ bootstrapdict[0] = ressources + MEMORY_SIZE;
+ bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE;
+ trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE);
+
+#ifdef CONFIG_DEBUG_INTERPRETER
+ printf("memory: %p\n",memory);
+ printf("dict1: %p\n",bootstrapdict[0]);
+ printf("dict2: %p\n",bootstrapdict[1]);
+ printf("trampoline: %p\n",trampoline);
+ printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 *
+ DICTIONARY_SIZE) + TRAMPOLINE_SIZE,
+ TRAMPOLINE_SIZE);
+#endif
+
+ if (trampoline == NULL) {
+ /* We're using side effects which is to some extent nasty */
+ printf("WARNING: no trampoline!\n");
+ } else {
+ init_trampoline(trampoline);
+ }
+
+ if (!segfault) {
+ if (verbose)
+ printk("Installing SIGSEGV handler...");
+
+ sa.sa_sigaction = segv_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sigaction(SIGSEGV, &sa, NULL);
+
+ if (verbose)
+ printk("done.\n");
+ }
+
+ /*
+ * Now do the real work
+ */
+
+ for (cnt=0; cnt<2; cnt++) {
+ if (verbose) {
+ printk("Compiling dictionary %d/%d\n", cnt+1, 2);
+ }
+ dict=bootstrapdict[cnt];
+ if(!basedict) {
+ new_dictionary(argv[optind]);
+ } else {
+ for (c=argc-1; c>=optind; c--)
+ include_file(argv[c]);
+
+ run_dictionary(basedict, consolefile);
+ }
+ if (depfile) {
+ fprintf(depfile, "\n");
+ fclose(depfile);
+ depfile = NULL;
+ }
+ if(errors)
+ break;
+ }
+
+#ifndef CONFIG_DEBUG_INTERPRETER
+ if (errors)
+ printk("dictionary not dumped to file.\n");
+ else
+#endif
+ {
+ relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead);
+ if (hexdump) {
+ write_dictionary_hex(dictname);
+ } else {
+ write_dictionary(dictname);
+ }
+ }
+
+ free(ressources);
+
+ if (errors)
+ return 1;
+ else
+ return 0;
+}
diff --git a/roms/openbios/kernel/build.xml b/roms/openbios/kernel/build.xml
new file mode 100644
index 00000000..1090cd62
--- /dev/null
+++ b/roms/openbios/kernel/build.xml
@@ -0,0 +1,16 @@
+<build>
+
+ <executable name="forthstrap" target="host">
+ <object source="dict.c"/>
+ <object source="bootstrap.c"/>
+ <object source="forth.c"/>
+ <object source="stack.c"/>
+ </executable>
+
+ <library name="bootstrap" type="static" target="target">
+ <object source="dict.c"/>
+ <object source="forth.c"/>
+ <object source="stack.c"/>
+ </library>
+
+</build>
diff --git a/roms/openbios/kernel/cross.h b/roms/openbios/kernel/cross.h
new file mode 100644
index 00000000..9dd656f8
--- /dev/null
+++ b/roms/openbios/kernel/cross.h
@@ -0,0 +1,124 @@
+/* memory access abstraction layer for forth kernel
+ *
+ * Copyright (C) 2005 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __CROSS_H
+#define __CROSS_H 1
+
+/* The forthstrap compiler has to abstract the underlying dictionary
+ * type: big/little endian, 32/64bit. All other binaries shall use
+ * unchanged memory access for performance.
+ */
+
+/* byte swapping */
+
+#ifndef SWAP_ENDIANNESS
+
+/* trivial case - we don't have to change anything */
+#define read_ucell(addr) (*(ucell *)(addr))
+#define read_cell(addr) (*(cell *)(addr))
+#define read_long(addr) (*(u32 *)(addr))
+#define read_word(addr) (*(u16 *)(addr))
+#define read_byte(addr) (*(u8 *)(addr))
+
+#define write_ucell(addr, value) {*(ucell *)(addr)=(value);}
+#define write_cell(addr, value) {*(cell *)(addr)=(value);}
+#define write_long(addr, value) {*(u32 *)(addr)=(value);}
+#define write_word(addr, value) {*(u16 *)(addr)=(value);}
+#define write_byte(addr, value) {*(u8 *)(addr)=(value);}
+
+#define target_ucell(x) (x)
+#define target_cell(x) (x)
+#define target_long(x) (x)
+#define target_ulong(x) (x)
+
+#else /* SWAP_ENDIANNESS */
+
+#define target_word(value) ( (((value)>>8)&0xff) | (((value)&0xff)<<8) )
+#define target_long(value) ( (((value)&0xff000000)>>24)|(((value)&0x00ff0000)>>8)|(((value)&0xff00)<<8)|(((value)&0xff)<<24) )
+#define target_ulong(value) (target_long(value))
+
+#if BITS==32
+#define target_ucell(value) ((ucell)target_long(value))
+#define target_cell(value) ((cell)target_long(value))
+#elif BITS==64
+#define target_ucell(value) \
+ ((((ucell)target_long((value) & 0xffffffff)) << 32) | \
+ ((ucell)target_long((value) >> 32)))
+#define target_cell(value) \
+ ((((cell)target_long((value) & 0xffffffff)) << 32) | \
+ ((cell)target_long((value) >> 32)))
+#else
+#error "Endianness not supported. Please report."
+#endif
+
+#define read_ucell(addr) target_ucell(*(ucell *)(addr))
+#define read_cell(addr) target_cell(*(cell *)(addr))
+#define read_long(addr) target_long(*(u32 *)(addr))
+#define read_word(addr) target_word(*(u16 *)(addr))
+#define read_byte(addr) (*(u8 *)(addr))
+
+#define write_ucell(addr, value) {*(ucell *)(addr)=target_ucell(value);}
+#define write_cell(addr, value) {*(cell *)(addr)=target_cell(value);}
+#define write_long(addr, value) {*(u32 *)(addr)=target_long(value);}
+#define write_word(addr, value) {*(u16 *)(addr)=target_word(value);}
+#define write_byte(addr, value) {*(u8 *)(addr)=(value);}
+#endif
+
+#ifdef CONFIG_LITTLE_ENDIAN
+#define unaligned_read_word(addr) \
+ (read_byte(addr)|(read_byte((u8 *)addr+1)<<8))
+
+#define unaligned_read_long(addr) \
+ (unaligned_read_word(addr)|(unaligned_read_word((u8 *)addr+2)<<16))
+
+#define unaligned_write_word(addr, value) \
+ write_byte(addr, (value & 0xff)); write_byte((u8 *)(addr+1), (value>>8))
+
+#define unaligned_write_long(addr, value) \
+ unaligned_write_word(addr, (value & 0xffff)); \
+ unaligned_write_word((addr + 2), (value >> 16))
+
+#endif
+
+#ifdef CONFIG_BIG_ENDIAN
+#define unaligned_read_word(addr) \
+ ((read_byte(addr)<<8)|read_byte((u8 *)addr+1))
+
+#define unaligned_read_long(addr) \
+ ((unaligned_read_word(addr)<<16)|unaligned_read_word((u8 *)addr+2))
+
+#define unaligned_write_word(addr, value) \
+ write_byte(addr, (value >> 8)); write_byte((u8 *)(addr+1), (value & 0xff))
+
+#define unaligned_write_long(addr, value) \
+ unaligned_write_word(addr, (value >> 16)); \
+ unaligned_write_word((addr + 2), (value & 0xffff))
+#endif
+
+/* bit width handling */
+
+#if BITS==32
+#define FMT_CELL_x PRIx32
+#define FMT_CELL_d PRId32
+#else
+#define FMT_CELL_x PRIx64
+#define FMT_CELL_d PRId64
+#endif
+
+#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
+extern unsigned long base_address;
+#define pointer2cell(x) ((ucell)(((unsigned long)(x))-base_address))
+#define cell2pointer(x) ((u8 *)(((unsigned long)(x))+base_address))
+#endif
+
+#ifdef NATIVE_BITWIDTH_LARGER_THAN_HOST_BITWIDTH
+#define pointer2cell(x) ((ucell)(unsigned long)(x))
+#define cell2pointer(x) ((u8 *)((unsigned long)(x)&0xFFFFFFFFUL))
+#endif
+
+#endif
diff --git a/roms/openbios/kernel/dict.c b/roms/openbios/kernel/dict.c
new file mode 100644
index 00000000..0986cb14
--- /dev/null
+++ b/roms/openbios/kernel/dict.c
@@ -0,0 +1,320 @@
+/*
+ * tag: dict management
+ *
+ * Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+#ifdef BOOTSTRAP
+#include <string.h>
+#else
+#include "libc/string.h"
+#endif
+#include "cross.h"
+
+
+unsigned char *dict = NULL;
+ucell *last;
+cell dicthead = 0;
+cell dictlimit = 0;
+
+/* lfa2nfa
+ * converts a link field address to a name field address,
+ * i.e find pointer to a given words name
+ */
+
+ucell lfa2nfa(ucell ilfa)
+{
+ /* get offset from dictionary start */
+ ilfa = ilfa - (ucell)pointer2cell(dict);
+ ilfa--; /* skip status */
+ while (dict[--ilfa] == 0); /* skip all pad bytes */
+ ilfa -= (dict[ilfa] - 128);
+ return ilfa + (ucell)pointer2cell(dict);
+}
+
+/* lfa2cfa
+ * converts a link field address to a code field address.
+ * in this forth implementation this is just a fixed offset
+ */
+
+static xt_t lfa2cfa(ucell ilfa)
+{
+ return (xt_t)(ilfa + sizeof(cell));
+}
+
+
+/* fstrlen - returns length of a forth string. */
+
+ucell fstrlen(ucell fstr)
+{
+ fstr -= pointer2cell(dict)+1;
+ //fstr -= pointer2cell(dict); FIXME
+ while (dict[++fstr] < 128)
+ ;
+ return dict[fstr] - 128;
+}
+
+/* to_lower - convert a character to lowecase */
+
+static int to_lower(int c)
+{
+ return ((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a') : c;
+}
+
+/* fstrcmp - compare null terminated string with forth string. */
+
+static int fstrcmp(const char *s1, ucell fstr)
+{
+ char *s2 = (char*)cell2pointer(fstr);
+ while (*s1) {
+ if ( to_lower(*(s1++)) != to_lower(*(s2++)) )
+ return -1;
+ }
+ return 0;
+}
+
+/* fstrncpy - copy a forth string to a destination (with NULL termination) */
+
+void fstrncpy(char *dest, ucell src, unsigned int maxlen)
+{
+ int len = fstrlen(src);
+
+ if (fstrlen(src) >= maxlen) len = maxlen - 1;
+ memcpy(dest, cell2pointer(src), len);
+ *(dest + len) = '\0';
+}
+
+
+/* findword
+ * looks up a given word in the dictionary. This function
+ * is used by the c based interpreter and to find the "initialize"
+ * word.
+ */
+
+xt_t findword(const char *s1)
+{
+ ucell tmplfa, len;
+
+ if (!last)
+ return 0;
+
+ tmplfa = read_ucell(last);
+
+ len = strlen(s1);
+
+ while (tmplfa) {
+ ucell nfa = lfa2nfa(tmplfa);
+
+ if (len == fstrlen(nfa) && !fstrcmp(s1, nfa)) {
+ return lfa2cfa(tmplfa);
+ }
+
+ tmplfa = read_ucell(cell2pointer(tmplfa));
+ }
+
+ return 0;
+}
+
+
+/* findsemis_wordlist
+ * Given a DOCOL xt and a wordlist, find the address of the semis
+ * word at the end of the word definition. We do this by finding
+ * the word before this in the dictionary, then counting back one
+ * from the NFA.
+ */
+
+static ucell findsemis_wordlist(ucell xt, ucell wordlist)
+{
+ ucell tmplfa, nextlfa, nextcfa;
+
+ if (!wordlist)
+ return 0;
+
+ tmplfa = read_ucell(cell2pointer(wordlist));
+ nextcfa = lfa2cfa(tmplfa);
+
+ /* Catch the special case where the lfa of the word we
+ * want is the last word in the dictionary; in that case
+ * the end of the word is given by "here" - 1 */
+ if (nextcfa == xt)
+ return pointer2cell(dict) + dicthead - sizeof(cell);
+
+ while (tmplfa) {
+
+ /* Peek ahead and see if the next CFA in the list is the
+ * one we are searching for */
+ nextlfa = read_ucell(cell2pointer(tmplfa));
+ nextcfa = lfa2cfa(nextlfa);
+
+ /* If so, count back 1 cell from the current NFA */
+ if (nextcfa == xt)
+ return lfa2nfa(tmplfa) - sizeof(cell);
+
+ tmplfa = nextlfa;
+ }
+
+ return 0;
+}
+
+
+/* findsemis
+ * Given a DOCOL xt, find the address of the semis word at the end
+ * of the word definition by searching all vocabularies */
+
+ucell findsemis(ucell xt)
+{
+ ucell usesvocab = findword("vocabularies?") + sizeof(cell);
+ unsigned int i;
+
+ if (read_ucell(cell2pointer(usesvocab))) {
+ /* Vocabularies are in use, so search each one in turn */
+ ucell numvocabs = findword("#order") + sizeof(cell);
+
+ for (i = 0; i < read_ucell(cell2pointer(numvocabs)); i++) {
+ ucell vocabs = findword("vocabularies") + 2 * sizeof(cell);
+ ucell semis = findsemis_wordlist(xt, read_cell(cell2pointer(vocabs + (i * sizeof(cell)))));
+
+ /* If we get a non-zero result, we found the xt in this vocab */
+ if (semis)
+ return semis;
+ }
+ } else {
+ /* Vocabularies not in use */
+ return findsemis_wordlist(xt, read_ucell(last));
+ }
+
+ return 0;
+}
+
+
+/* findxtfromcell_wordlist
+ * Given a cell and a wordlist, determine the CFA of the word containing
+ * the cell or 0 if we are unable to return a suitable CFA
+ */
+
+ucell findxtfromcell_wordlist(ucell incell, ucell wordlist)
+{
+ ucell tmplfa;
+
+ if (!wordlist)
+ return 0;
+
+ tmplfa = read_ucell(cell2pointer(wordlist));
+ while (tmplfa) {
+ if (tmplfa < incell)
+ return lfa2cfa(tmplfa);
+
+ tmplfa = read_ucell(cell2pointer(tmplfa));
+ }
+
+ return 0;
+}
+
+
+/* findxtfromcell
+ * Given a cell, determine the CFA of the word containing
+ * the cell by searching all vocabularies
+ */
+
+ucell findxtfromcell(ucell incell)
+{
+ ucell usesvocab = findword("vocabularies?") + sizeof(cell);
+ unsigned int i;
+
+ if (read_ucell(cell2pointer(usesvocab))) {
+ /* Vocabularies are in use, so search each one in turn */
+ ucell numvocabs = findword("#order") + sizeof(cell);
+
+ for (i = 0; i < read_ucell(cell2pointer(numvocabs)); i++) {
+ ucell vocabs = findword("vocabularies") + 2 * sizeof(cell);
+ ucell semis = findxtfromcell_wordlist(incell, read_cell(cell2pointer(vocabs + (i * sizeof(cell)))));
+
+ /* If we get a non-zero result, we found the xt in this vocab */
+ if (semis)
+ return semis;
+ }
+ } else {
+ /* Vocabularies not in use */
+ return findxtfromcell_wordlist(incell, read_ucell(last));
+ }
+
+ return 0;
+}
+
+void dump_header(dictionary_header_t *header)
+{
+ printk("OpenBIOS dictionary:\n");
+ printk(" version: %d\n", header->version);
+ printk(" cellsize: %d\n", header->cellsize);
+ printk(" endianess: %s\n", header->endianess?"big":"little");
+ printk(" compression: %s\n", header->compression?"yes":"no");
+ printk(" relocation: %s\n", header->relocation?"yes":"no");
+ printk(" checksum: %08x\n", target_long(header->checksum));
+ printk(" length: %08x\n", target_long(header->length));
+ printk(" last: %0" FMT_CELL_x "\n", target_cell(header->last));
+}
+
+ucell load_dictionary(const char *data, ucell len)
+{
+ u32 checksum=0;
+ const char *checksum_walk;
+ ucell *walk, *reloc_table;
+ dictionary_header_t *header=(dictionary_header_t *)data;
+
+ /* assertions */
+ if (len <= (sizeof(dictionary_header_t)) || strncmp(DICTID, data, 8))
+ return 0;
+#ifdef CONFIG_DEBUG_DICTIONARY
+ dump_header(header);
+#endif
+
+ checksum_walk=data;
+ while (checksum_walk<data+len) {
+ checksum+=read_long(checksum_walk);
+ checksum_walk+=sizeof(u32);
+ }
+
+ if(checksum) {
+ printk("Checksum invalid (%08x)!\n", checksum);
+ return 0;
+ }
+
+ data += sizeof(dictionary_header_t);
+
+ dicthead = target_long(header->length);
+
+ memcpy(dict, data, dicthead);
+ reloc_table=(ucell *)(data+dicthead);
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk("\nmoving dictionary (%x bytes) to %x\n",
+ (ucell)dicthead, (ucell)dict);
+ printk("\ndynamic relocation...");
+#endif
+
+ for (walk = (ucell *) dict; walk < (ucell *) (dict + dicthead);
+ walk++) {
+ int pos, bit, l;
+ l=(walk-(ucell *)dict);
+ pos=l/BITS;
+ bit=l&~(-BITS);
+ if (reloc_table[pos] & target_ucell((ucell)1ULL << bit)) {
+ // printk("%lx, pos %x, bit %d\n",*walk, pos, bit);
+ write_ucell(walk, read_ucell(walk)+pointer2cell(dict));
+ }
+ }
+
+#ifdef CONFIG_DEBUG_DICTIONARY
+ printk(" done.\n");
+#endif
+
+ last = (ucell *)(dict + target_ucell(header->last));
+
+ return -1;
+}
diff --git a/roms/openbios/kernel/forth.c b/roms/openbios/kernel/forth.c
new file mode 100644
index 00000000..61dd70d3
--- /dev/null
+++ b/roms/openbios/kernel/forth.c
@@ -0,0 +1,1966 @@
+/* tag: C implementation of all forth primitives,
+ * internal words, inner interpreter and such
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "sysinclude.h"
+#include "kernel/stack.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+
+/*
+ * cross platform abstraction
+ */
+
+#include "cross.h"
+
+#ifndef FCOMPILER
+#include "libc/vsprintf.h"
+#else
+#include <stdarg.h>
+#endif
+
+/*
+ * execution works as follows:
+ * - PC is pushed on return stack
+ * - PC is set to new CFA
+ * - address pointed by CFA is executed by CPU
+ */
+
+typedef void forth_word(void);
+
+static forth_word * const words[];
+ucell PC;
+volatile int interruptforth = 0;
+
+#define DEBUG_MODE_NONE 0
+#define DEBUG_MODE_STEP 1
+#define DEBUG_MODE_TRACE 2
+#define DEBUG_MODE_STEPUP 3
+
+#define DEBUG_BANNER "\nStepper keys: <space>/<enter> Up Down Trace Rstack Forth\n"
+
+/* Empty linked list of debug xts */
+struct debug_xt {
+ ucell xt_docol;
+ ucell xt_semis;
+ int mode;
+ struct debug_xt *next;
+};
+
+static struct debug_xt debug_xt_eol = { (ucell)0, (ucell)0, 0, NULL};
+static struct debug_xt *debug_xt_list = &debug_xt_eol;
+
+/* Static buffer for xt name */
+char xtname[MAXNFALEN];
+
+#ifndef FCOMPILER
+/* instead of pointing to an explicit 0 variable we
+ * point behind the pointer.
+ */
+static ucell t[] = { 0, 0, 0, 0 };
+static ucell *trampoline = t;
+
+/*
+ * Code Field Address (CFA) definitions (DOCOL and the like)
+ */
+
+void forth_init(void)
+{
+ init_trampoline(trampoline);
+}
+#endif
+
+#ifndef CONFIG_DEBUG_INTERPRETER
+#define dbg_interp_printk( a... ) do { } while(0)
+#else
+#define dbg_interp_printk( a... ) printk( a )
+#endif
+
+#ifndef CONFIG_DEBUG_INTERNAL
+#define dbg_internal_printk( a... ) do { } while(0)
+#else
+#define dbg_internal_printk( a... ) printk( a )
+#endif
+
+
+void init_trampoline(ucell *tramp)
+{
+ tramp[0] = DOCOL;
+ tramp[1] = 0;
+ tramp[2] = target_ucell(pointer2cell(tramp) + 3 * sizeof(ucell));
+ tramp[3] = 0;
+}
+
+static inline void processxt(ucell xt)
+{
+ void (*tokenp) (void);
+
+ dbg_interp_printk("processxt: pc=%x, xt=%x\n", PC, xt);
+ tokenp = words[xt];
+ tokenp();
+}
+
+static void docol(void)
+{ /* DOCOL */
+ PUSHR(PC);
+ PC = read_ucell(cell2pointer(PC));
+
+ dbg_interp_printk("docol: %s\n", cell2pointer( lfa2nfa(PC - sizeof(cell)) ));
+}
+
+static void semis(void)
+{
+ PC = POPR();
+}
+
+static inline void next(void)
+{
+ PC += sizeof(ucell);
+
+ dbg_interp_printk("next: PC is now %x\n", PC);
+ processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))));
+}
+
+static inline void next_dbg(void);
+
+int enterforth(xt_t xt)
+{
+ ucell *_cfa = (ucell*)cell2pointer(xt);
+ cell tmp;
+
+ if (read_ucell(_cfa) != DOCOL) {
+ trampoline[1] = target_ucell(xt);
+ _cfa = trampoline;
+ }
+
+ if (rstackcnt < 0) {
+ rstackcnt = 0;
+ }
+
+ tmp = rstackcnt;
+ interruptforth = FORTH_INTSTAT_CLR;
+
+ PUSHR(PC);
+ PC = pointer2cell(_cfa);
+
+ while (rstackcnt > tmp && !(interruptforth & FORTH_INTSTAT_STOP)) {
+ if (debug_xt_list->next == NULL) {
+ while (rstackcnt > tmp && !interruptforth) {
+ dbg_interp_printk("enterforth: NEXT\n");
+ next();
+ }
+ } else {
+ while (rstackcnt > tmp && !interruptforth) {
+ dbg_interp_printk("enterforth: NEXT_DBG\n");
+ next_dbg();
+ }
+ }
+
+ /* Always clear the debug mode change flag */
+ interruptforth = interruptforth & (~FORTH_INTSTAT_DBG);
+ }
+
+#if 0
+ /* return true if we took an exception. The caller should normally
+ * handle exceptions by returning immediately since the throw
+ * is supposed to abort the execution of this C-code too.
+ */
+
+ if (rstackcnt != tmp) {
+ printk("EXCEPTION DETECTED!\n");
+ }
+#endif
+ return rstackcnt != tmp;
+}
+
+/* called inline thus a slightly different behaviour */
+static void lit(void)
+{ /* LIT */
+ PC += sizeof(cell);
+ PUSH(read_ucell(cell2pointer(PC)));
+ dbg_interp_printk("lit: %x\n", read_ucell(cell2pointer(PC)));
+}
+
+static void docon(void)
+{ /* DOCON */
+ ucell tmp = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell)));
+ PUSH(tmp);
+ dbg_interp_printk("docon: PC=%x, value=%x\n", PC, tmp);
+}
+
+static void dovar(void)
+{ /* DOVAR */
+ ucell tmp = read_ucell(cell2pointer(PC)) + sizeof(ucell);
+ PUSH(tmp); /* returns address to variable */
+ dbg_interp_printk("dovar: PC: %x, %x\n", PC, tmp);
+}
+
+static void dobranch(void)
+{ /* unconditional branch */
+ PC += sizeof(cell);
+ PC += read_cell(cell2pointer(PC));
+}
+
+static void docbranch(void)
+{ /* conditional branch */
+ PC += sizeof(cell);
+ if (POP()) {
+ dbg_internal_printk(" ?branch: end loop\n");
+ } else {
+ dbg_internal_printk(" ?branch: follow branch\n");
+ PC += read_cell(cell2pointer(PC));
+ }
+}
+
+
+static void execute(void)
+{ /* EXECUTE */
+ ucell address = POP();
+ dbg_interp_printk("execute: %x\n", address);
+
+ PUSHR(PC);
+ trampoline[1] = target_ucell(address);
+ PC = pointer2cell(trampoline);
+}
+
+/*
+ * call ( ... function-ptr -- ??? )
+ */
+static void call(void)
+{
+#ifdef FCOMPILER
+ printk("Sorry. Usage of Forth2C binding is forbidden during bootstrap.\n");
+ exit(1);
+#else
+ void (*funcptr) (void);
+ funcptr=(void *)cell2pointer(POP());
+ dbg_interp_printk("call: %x", funcptr);
+ funcptr();
+#endif
+}
+
+/*
+ * sys-debug ( errno -- )
+ */
+
+static void sysdebug(void)
+{
+#ifdef FCOMPILER
+ cell errorno=POP();
+ exception(errorno);
+#else
+ (void) POP();
+#endif
+}
+
+static void dodoes(void)
+{ /* DODOES */
+ ucell data = read_ucell(cell2pointer(PC)) + (2 * sizeof(ucell));
+ ucell word = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell)));
+
+ dbg_interp_printk("DODOES data=%x word=%x\n", data, word);
+
+ PUSH(data);
+ PUSH(word);
+
+ execute();
+}
+
+static void dodefer(void)
+{
+ docol();
+}
+
+static void dodo(void)
+{
+ cell startval, endval;
+ startval = POP();
+ endval = POP();
+
+ PUSHR(endval);
+ PUSHR(startval);
+}
+
+static void doisdo(void)
+{
+ cell startval, endval, offset;
+
+ startval = POP();
+ endval = POP();
+
+ PC += sizeof(cell);
+
+ if (startval == endval) {
+ offset = read_cell(cell2pointer(PC));
+ PC += offset;
+ } else {
+ PUSHR(endval);
+ PUSHR(startval);
+ }
+}
+
+static void doloop(void)
+{
+ cell offset, startval, endval;
+
+ startval = POPR() + 1;
+ endval = POPR();
+
+ PC += sizeof(cell);
+
+ if (startval < endval) {
+ offset = read_cell(cell2pointer(PC));
+ PC += offset;
+ PUSHR(endval);
+ PUSHR(startval);
+ }
+
+}
+
+static void doplusloop(void)
+{
+ ucell high, low;
+ cell increment, startval, endval, offset;
+
+ increment = POP();
+
+ startval = POPR();
+ endval = POPR();
+
+ low = (ucell) startval;
+ startval += increment;
+
+ PC += sizeof(cell);
+
+ if (increment >= 0) {
+ high = (ucell) startval;
+ } else {
+ high = low;
+ low = (ucell) startval;
+ }
+
+ if (endval - (low + 1) >= high - low) {
+ offset = read_cell(cell2pointer(PC));
+ PC += offset;
+
+ PUSHR(endval);
+ PUSHR(startval);
+ }
+}
+
+/*
+ * instance handling CFAs
+ */
+#ifndef FCOMPILER
+static ucell get_myself(void)
+{
+ static ucell *myselfptr = NULL;
+ if (myselfptr == NULL) {
+ myselfptr = (ucell*)cell2pointer(findword("my-self")) + 1;
+ }
+ ucell *myself = (ucell*)cell2pointer(*myselfptr);
+ return (myself != NULL) ? *myself : 0;
+}
+
+static void doivar(void)
+{
+ ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+ ucell ibase = get_myself();
+
+ dbg_interp_printk("ivar, offset: %d size: %d (ibase %d)\n", p[0], p[1], ibase );
+
+ r = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+ PUSH( r );
+}
+
+static void doival(void)
+{
+ ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+ ucell ibase = get_myself();
+
+ dbg_interp_printk("ivar, offset: %d size: %d\n", p[0], p[1] );
+
+ r = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+ PUSH( *(ucell *)cell2pointer(r) );
+}
+
+static void doidefer(void)
+{
+ ucell *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell));
+ ucell ibase = get_myself();
+
+ dbg_interp_printk("doidefer, offset: %d size: %d\n", p[0], p[1] );
+
+ PUSHR(PC);
+ PC = ibase ? ibase + p[0] : pointer2cell(&p[2]);
+ PC -= sizeof(ucell);
+}
+#else
+static void noinstances(void)
+{
+ printk("Opening devices is not supported during bootstrap. Sorry.\n");
+ exit(1);
+}
+#define doivar noinstances
+#define doival noinstances
+#define doidefer noinstances
+#endif
+
+/*
+ * $include / $encode-file
+ */
+#ifdef FCOMPILER
+static void
+string_relay(void (*func)(const char *))
+{
+ int len = POP();
+ char *name, *p = (char*)cell2pointer(POP());
+ name = malloc(len + 1);
+ memcpy(name, p, len);
+ name[len] = 0;
+ (*func)(name);
+ free(name);
+}
+#else
+#define string_relay(dummy) do { DROP(); DROP(); } while(0)
+#endif
+
+static void
+do_include(void)
+{
+ string_relay(&include_file);
+}
+
+static void
+do_encode_file( void )
+{
+ string_relay(&encode_file);
+}
+
+/*
+ * Debug support functions
+ */
+
+static
+int printf_console(const char *fmt, ...)
+{
+ cell tmp;
+
+ char buf[512];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ /* Push to the Forth interpreter for console output */
+ tmp = rstackcnt;
+
+ PUSH(pointer2cell(buf));
+ PUSH((int)strlen(buf));
+ trampoline[1] = findword("type");
+
+ PUSHR(PC);
+ PC = pointer2cell(trampoline);
+
+ while (rstackcnt > tmp) {
+ dbg_interp_printk("printf_console: NEXT\n");
+ next();
+ }
+
+ return i;
+}
+
+static
+int getchar_console(void)
+{
+ cell tmp;
+
+ /* Push to the Forth interpreter for console output */
+ tmp = rstackcnt;
+
+ trampoline[1] = findword("key");
+
+ PUSHR(PC);
+ PC = pointer2cell(trampoline);
+
+ while (rstackcnt > tmp) {
+ dbg_interp_printk("getchar_console: NEXT\n");
+ next();
+ }
+
+ return POP();
+}
+
+static void
+display_dbg_dstack(void)
+{
+ /* Display dstack contents between parentheses */
+ int i;
+
+ if (dstackcnt == 0) {
+ printf_console(" ( Empty ) ");
+ return;
+ } else {
+ printf_console(" ( ");
+ for (i = 1; i <= dstackcnt; i++) {
+ if (i != 1) {
+ printf_console(" ");
+ }
+ printf_console("%" FMT_CELL_x, dstack[i]);
+ }
+ printf_console(" ) ");
+ }
+}
+
+static void
+display_dbg_rstack(void)
+{
+ /* Display rstack contents between parentheses */
+ int i;
+
+ if (rstackcnt == 0) {
+ printf_console(" ( Empty ) ");
+ return;
+ } else {
+ printf_console("\nR: ( ");
+ for (i = 1; i <= rstackcnt; i++) {
+ if (i != 1) {
+ printf_console(" ");
+ }
+ printf_console("%" FMT_CELL_x, rstack[i]);
+ }
+ printf_console(" ) \n");
+ }
+}
+
+static int
+add_debug_xt(ucell xt)
+{
+ struct debug_xt *debug_xt_item;
+
+ /* If the xt CFA isn't DOCOL then issue a warning and do nothing */
+ if (read_ucell(cell2pointer(xt)) != DOCOL) {
+ printf_console("\nprimitive words cannot be debugged\n");
+ return 0;
+ }
+
+ /* If this xt is already in the list, do nothing but indicate success */
+ for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL;
+ debug_xt_item = debug_xt_item->next)
+ if (debug_xt_item->xt_docol == xt) {
+ return 1;
+ }
+
+ /* We already have the CFA (PC) indicating the starting cell of
+ the word, however we also need the ending cell too (we cannot
+ rely on the rstack as it can be arbitrarily changed by a forth
+ word). Hence the use of findsemis() */
+
+ /* Otherwise add to the head of the linked list */
+ debug_xt_item = malloc(sizeof(struct debug_xt));
+ debug_xt_item->xt_docol = xt;
+ debug_xt_item->xt_semis = findsemis(xt);
+ debug_xt_item->mode = DEBUG_MODE_NONE;
+ debug_xt_item->next = debug_xt_list;
+ debug_xt_list = debug_xt_item;
+
+ /* Indicate debug mode change */
+ interruptforth |= FORTH_INTSTAT_DBG;
+
+ /* Success */
+ return 1;
+}
+
+static void
+del_debug_xt(ucell xt)
+{
+ struct debug_xt *debug_xt_item, *tmp_xt_item;
+
+ /* Handle the case where the xt is at the head of the list */
+ if (debug_xt_list->xt_docol == xt) {
+ tmp_xt_item = debug_xt_list;
+ debug_xt_list = debug_xt_list->next;
+ free(tmp_xt_item);
+
+ return;
+ }
+
+ /* Otherwise find this xt in the linked list and remove it */
+ for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL;
+ debug_xt_item = debug_xt_item->next) {
+ if (debug_xt_item->next->xt_docol == xt) {
+ tmp_xt_item = debug_xt_item->next;
+ debug_xt_item->next = debug_xt_item->next->next;
+ free(tmp_xt_item);
+ }
+ }
+
+ /* If the list is now empty, indicate debug mode change */
+ if (debug_xt_list->next == NULL) {
+ interruptforth |= FORTH_INTSTAT_DBG;
+ }
+}
+
+static void
+do_source_dbg(struct debug_xt *debug_xt_item)
+{
+ /* Forth source debugger implementation */
+ char k, done = 0;
+
+ /* Display current dstack */
+ display_dbg_dstack();
+ printf_console("\n");
+
+ fstrncpy(xtname, lfa2nfa(read_ucell(cell2pointer(PC)) - sizeof(cell)), MAXNFALEN);
+ printf_console("%p: %s ", cell2pointer(PC), xtname);
+
+ /* If in trace mode, we just carry on */
+ if (debug_xt_item->mode == DEBUG_MODE_TRACE) {
+ return;
+ }
+
+ /* Otherwise in step mode, prompt for a keypress */
+ k = getchar_console();
+
+ /* Only proceed if done is true */
+ while (!done) {
+ switch (k) {
+
+ case ' ':
+ case '\n':
+ /* Perform a single step */
+ done = 1;
+ break;
+
+ case 'u':
+ case 'U':
+ /* Up - unmark current word for debug, mark its caller for
+ * debugging and finish executing current word */
+
+ /* Since this word could alter the rstack during its execution,
+ * we only know the caller when (semis) is called for this xt.
+ * Hence we mark the xt as a special DEBUG_MODE_STEPUP which
+ * means we run as normal, but schedule the xt for deletion
+ * at its corresponding (semis) word when we know the rstack
+ * will be set to its final parent value */
+ debug_xt_item->mode = DEBUG_MODE_STEPUP;
+ done = 1;
+ break;
+
+ case 'd':
+ case 'D':
+ /* Down - mark current word for debug and step into it */
+ done = add_debug_xt(read_ucell(cell2pointer(PC)));
+ if (!done) {
+ k = getchar_console();
+ }
+ break;
+
+ case 't':
+ case 'T':
+ /* Trace mode */
+ debug_xt_item->mode = DEBUG_MODE_TRACE;
+ done = 1;
+ break;
+
+ case 'r':
+ case 'R':
+ /* Display rstack */
+ display_dbg_rstack();
+ done = 0;
+ k = getchar_console();
+ break;
+
+ case 'f':
+ case 'F':
+ /* Start subordinate Forth interpreter */
+ PUSHR(PC - sizeof(cell));
+ PC = findword("outer-interpreter") + sizeof(ucell);
+
+ /* Save rstack position for when we return */
+ dbgrstackcnt = rstackcnt;
+ done = 1;
+ break;
+
+ default:
+ /* Display debug banner */
+ printf_console(DEBUG_BANNER);
+ k = getchar_console();
+ }
+ }
+}
+
+static void docol_dbg(void)
+{ /* DOCOL */
+ struct debug_xt *debug_xt_item;
+
+ PUSHR(PC);
+ PC = read_ucell(cell2pointer(PC));
+
+ /* If current xt is in our debug xt list, display word name */
+ debug_xt_item = debug_xt_list;
+ while (debug_xt_item->next) {
+ if (debug_xt_item->xt_docol == PC) {
+ fstrncpy(xtname, lfa2nfa(PC - sizeof(cell)), MAXNFALEN);
+ printf_console("\n: %s ", xtname);
+
+ /* Step mode is the default */
+ debug_xt_item->mode = DEBUG_MODE_STEP;
+ }
+
+ debug_xt_item = debug_xt_item->next;
+ }
+
+ dbg_interp_printk("docol_dbg: %s\n", cell2pointer(lfa2nfa(PC - sizeof(cell))));
+}
+
+static void semis_dbg(void)
+{
+ struct debug_xt *debug_xt_item, *debug_xt_up = NULL;
+
+ /* If current semis is in our debug xt list, disable debug mode */
+ debug_xt_item = debug_xt_list;
+ while (debug_xt_item->next) {
+ if (debug_xt_item->xt_semis == PC) {
+ if (debug_xt_item->mode != DEBUG_MODE_STEPUP) {
+ /* Handle the normal case */
+ fstrncpy(xtname, lfa2nfa(debug_xt_item->xt_docol - sizeof(cell)), MAXNFALEN);
+ printf_console("\n[ Finished %s ] ", xtname);
+
+ /* Reset to step mode in case we were in trace mode */
+ debug_xt_item->mode = DEBUG_MODE_STEP;
+ } else {
+ /* This word requires execution of the debugger "Up"
+ * semantics. However we can't do this here since we
+ * are iterating through the debug list, and we need
+ * to change it. So we do it afterwards.
+ */
+ debug_xt_up = debug_xt_item;
+ }
+ }
+
+ debug_xt_item = debug_xt_item->next;
+ }
+
+ /* Execute debugger "Up" semantics if required */
+ if (debug_xt_up) {
+ /* Only add the parent word if it is not within the trampoline */
+ if (rstack[rstackcnt] != (cell)pointer2cell(&trampoline[1])) {
+ del_debug_xt(debug_xt_up->xt_docol);
+ add_debug_xt(findxtfromcell(rstack[rstackcnt]));
+
+ fstrncpy(xtname, lfa2nfa(findxtfromcell(rstack[rstackcnt]) - sizeof(cell)), MAXNFALEN);
+ printf_console("\n[ Up to %s ] ", xtname);
+ } else {
+ fstrncpy(xtname, lfa2nfa(findxtfromcell(debug_xt_up->xt_docol) - sizeof(cell)), MAXNFALEN);
+ printf_console("\n[ Finished %s (Unable to go up, hit trampoline) ] ", xtname);
+
+ del_debug_xt(debug_xt_up->xt_docol);
+ }
+
+ debug_xt_up = NULL;
+ }
+
+ PC = POPR();
+}
+
+static inline void next_dbg(void)
+{
+ struct debug_xt *debug_xt_item;
+ void (*tokenp) (void);
+
+ PC += sizeof(ucell);
+
+ /* If the PC lies within a debug range, run the source debugger */
+ debug_xt_item = debug_xt_list;
+ while (debug_xt_item->next) {
+ if (PC >= debug_xt_item->xt_docol && PC <= debug_xt_item->xt_semis &&
+ debug_xt_item->mode != DEBUG_MODE_STEPUP) {
+ do_source_dbg(debug_xt_item);
+ }
+
+ debug_xt_item = debug_xt_item->next;
+ }
+
+ dbg_interp_printk("next_dbg: PC is now %x\n", PC);
+
+ /* Intercept DOCOL and SEMIS and redirect to debug versions */
+ if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOCOL) {
+ tokenp = docol_dbg;
+ tokenp();
+ } else if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOSEMIS) {
+ tokenp = semis_dbg;
+ tokenp();
+ } else {
+ /* Otherwise process as normal */
+ processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))));
+ }
+}
+
+static void
+do_debug_xt(void)
+{
+ ucell xt = POP();
+
+ /* Add to the debug list */
+ if (add_debug_xt(xt)) {
+ /* Display debug banner */
+ printf_console(DEBUG_BANNER);
+
+ /* Indicate change to debug mode */
+ interruptforth |= FORTH_INTSTAT_DBG;
+ }
+}
+
+static void
+do_debug_off(void)
+{
+ /* Empty the debug xt linked list */
+ while (debug_xt_list->next != NULL) {
+ del_debug_xt(debug_xt_list->xt_docol);
+ }
+}
+
+/*
+ * Forth primitives needed to set up
+ * all the words described in IEEE1275-1994.
+ */
+
+/*
+ * dup ( x -- x x )
+ */
+
+static void fdup(void)
+{
+ const cell tmp = GETTOS();
+ PUSH(tmp);
+}
+
+
+/*
+ * 2dup ( x1 x2 -- x1 x2 x1 x2 )
+ */
+
+static void twodup(void)
+{
+ cell tmp = GETITEM(1);
+ PUSH(tmp);
+ tmp = GETITEM(1);
+ PUSH(tmp);
+}
+
+
+/*
+ * ?dup ( x -- 0 | x x )
+ */
+
+static void isdup(void)
+{
+ const cell tmp = GETTOS();
+ if (tmp)
+ PUSH(tmp);
+}
+
+
+/*
+ * over ( x y -- x y x )
+ */
+
+static void over(void)
+{
+ const cell tmp = GETITEM(1);
+ PUSH(tmp);
+}
+
+
+/*
+ * 2over ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )
+ */
+
+static void twoover(void)
+{
+ const cell tmp = GETITEM(3);
+ const cell tmp2 = GETITEM(2);
+ PUSH(tmp);
+ PUSH(tmp2);
+}
+
+/*
+ * pick ( xu ... x1 x0 u -- xu ... x1 x0 xu )
+ */
+
+static void pick(void)
+{
+ const cell u = POP();
+ if (dstackcnt >= u) {
+ ucell tmp = dstack[dstackcnt - u];
+ PUSH(tmp);
+ } else {
+ /* underrun */
+ }
+}
+
+
+/*
+ * drop ( x -- )
+ */
+
+static void drop(void)
+{
+ POP();
+}
+
+/*
+ * 2drop ( x1 x2 -- )
+ */
+
+static void twodrop(void)
+{
+ POP();
+ POP();
+}
+
+
+/*
+ * nip ( x1 x2 -- x2 )
+ */
+
+static void nip(void)
+{
+ const cell tmp = POP();
+ POP();
+ PUSH(tmp);
+}
+
+
+/*
+ * roll ( xu ... x1 x0 u -- xu-1... x1 x0 xu )
+ */
+
+static void roll(void)
+{
+ const cell u = POP();
+ if (dstackcnt >= u) {
+ int i;
+ const cell xu = dstack[dstackcnt - u];
+ for (i = dstackcnt - u; i < dstackcnt; i++) {
+ dstack[i] = dstack[i + 1];
+ }
+ dstack[dstackcnt] = xu;
+ } else {
+ /* Stack underrun */
+ }
+}
+
+
+/*
+ * rot ( x1 x2 x3 -- x2 x3 x1 )
+ */
+
+static void rot(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ const cell tmp3 = POP();
+ PUSH(tmp2);
+ PUSH(tmp);
+ PUSH(tmp3);
+}
+
+
+/*
+ * -rot ( x1 x2 x3 -- x3 x1 x2 )
+ */
+
+static void minusrot(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ const cell tmp3 = POP();
+ PUSH(tmp);
+ PUSH(tmp3);
+ PUSH(tmp2);
+}
+
+
+/*
+ * swap ( x1 x2 -- x2 x1 )
+ */
+
+static void swap(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ PUSH(tmp);
+ PUSH(tmp2);
+}
+
+
+/*
+ * 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
+ */
+
+static void twoswap(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ const cell tmp3 = POP();
+ const cell tmp4 = POP();
+ PUSH(tmp2);
+ PUSH(tmp);
+ PUSH(tmp4);
+ PUSH(tmp3);
+}
+
+
+/*
+ * >r ( x -- ) (R: -- x )
+ */
+
+static void tor(void)
+{
+ ucell tmp = POP();
+#ifdef CONFIG_DEBUG_RSTACK
+ printk(" >R: %x\n", tmp);
+#endif
+ PUSHR(tmp);
+}
+
+
+/*
+ * r> ( -- x ) (R: x -- )
+ */
+
+static void rto(void)
+{
+ ucell tmp = POPR();
+#ifdef CONFIG_DEBUG_RSTACK
+ printk(" R>: %x\n", tmp);
+#endif
+ PUSH(tmp);
+}
+
+
+/*
+ * r@ ( -- x ) (R: x -- x )
+ */
+
+static void rfetch(void)
+{
+ PUSH(GETTORS());
+}
+
+
+/*
+ * depth ( -- u )
+ */
+
+static void depth(void)
+{
+ const cell tmp = dstackcnt;
+ PUSH(tmp);
+}
+
+
+/*
+ * depth! ( ... u -- x1 x2 .. xu )
+ */
+
+static void depthwrite(void)
+{
+ ucell tmp = POP();
+ dstackcnt = tmp;
+}
+
+
+/*
+ * rdepth ( -- u )
+ */
+
+static void rdepth(void)
+{
+ const cell tmp = rstackcnt;
+ PUSH(tmp);
+}
+
+
+/*
+ * rdepth! ( u -- ) ( R: ... -- x1 x2 .. xu )
+ */
+
+static void rdepthwrite(void)
+{
+ ucell tmp = POP();
+ rstackcnt = tmp;
+}
+
+
+/*
+ * + ( nu1 nu2 -- sum )
+ */
+
+static void plus(void)
+{
+ cell tmp = POP() + POP();
+ PUSH(tmp);
+}
+
+
+/*
+ * - ( nu1 nu2 -- diff )
+ */
+
+static void minus(void)
+{
+ const cell nu2 = POP();
+ const cell nu1 = POP();
+ PUSH(nu1 - nu2);
+}
+
+
+/*
+ * * ( nu1 nu2 -- prod )
+ */
+
+static void mult(void)
+{
+ const cell nu2 = POP();
+ const cell nu1 = POP();
+ PUSH(nu1 * nu2);
+}
+
+
+/*
+ * u* ( u1 u2 -- prod )
+ */
+
+static void umult(void)
+{
+ const ucell tmp = (ucell) POP() * (ucell) POP();
+ PUSH(tmp);
+}
+
+
+/*
+ * mu/mod ( n1 n2 -- rem quot.l quot.h )
+ */
+
+static void mudivmod(void)
+{
+ const ucell b = POP();
+ const ducell a = DPOP();
+#ifdef NEED_FAKE_INT128_T
+ if (a.hi != 0) {
+ fprintf(stderr, "mudivmod called (0x%016llx %016llx / 0x%016llx)\n",
+ a.hi, a.lo, b);
+ exit(-1);
+ } else {
+ ducell c;
+
+ PUSH(a.lo % b);
+ c.hi = 0;
+ c.lo = a.lo / b;
+ DPUSH(c);
+ }
+#else
+ PUSH(a % b);
+ DPUSH(a / b);
+#endif
+}
+
+
+/*
+ * abs ( n -- u )
+ */
+
+static void forthabs(void)
+{
+ const cell tmp = GETTOS();
+ if (tmp < 0) {
+ POP();
+ PUSH(-tmp);
+ }
+}
+
+
+/*
+ * negate ( n1 -- n2 )
+ */
+
+static void negate(void)
+{
+ const cell tmp = POP();
+ PUSH(-tmp);
+}
+
+
+/*
+ * max ( n1 n2 -- n1|n2 )
+ */
+
+static void max(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ PUSH((tmp > tmp2) ? tmp : tmp2);
+}
+
+
+/*
+ * min ( n1 n2 -- n1|n2 )
+ */
+
+static void min(void)
+{
+ const cell tmp = POP();
+ const cell tmp2 = POP();
+ PUSH((tmp < tmp2) ? tmp : tmp2);
+}
+
+
+/*
+ * lshift ( x1 u -- x2 )
+ */
+
+static void lshift(void)
+{
+ const ucell u = POP();
+ const ucell x1 = POP();
+ PUSH(x1 << u);
+}
+
+
+/*
+ * rshift ( x1 u -- x2 )
+ */
+
+static void rshift(void)
+{
+ const ucell u = POP();
+ const ucell x1 = POP();
+ PUSH(x1 >> u);
+}
+
+
+/*
+ * >>a ( x1 u -- x2 ) ??
+ */
+
+static void rshifta(void)
+{
+ const cell u = POP();
+ const cell x1 = POP();
+ PUSH(x1 >> u);
+}
+
+
+/*
+ * and ( x1 x2 -- x3 )
+ */
+
+static void and(void)
+{
+ const cell x1 = POP();
+ const cell x2 = POP();
+ PUSH(x1 & x2);
+}
+
+
+/*
+ * or ( x1 x2 -- x3 )
+ */
+
+static void or(void)
+{
+ const cell x1 = POP();
+ const cell x2 = POP();
+ PUSH(x1 | x2);
+}
+
+
+/*
+ * xor ( x1 x2 -- x3 )
+ */
+
+static void xor(void)
+{
+ const cell x1 = POP();
+ const cell x2 = POP();
+ PUSH(x1 ^ x2);
+}
+
+
+/*
+ * invert ( x1 -- x2 )
+ */
+
+static void invert(void)
+{
+ const cell x1 = POP();
+ PUSH(x1 ^ -1);
+}
+
+
+/*
+ * d+ ( d1 d2 -- d.sum )
+ */
+
+static void dplus(void)
+{
+ const dcell d2 = DPOP();
+ const dcell d1 = DPOP();
+#ifdef NEED_FAKE_INT128_T
+ ducell c;
+
+ if (d1.hi != 0 || d2.hi != 0) {
+ fprintf(stderr, "dplus called (0x%016llx %016llx + 0x%016llx %016llx)\n",
+ d1.hi, d1.lo, d2.hi, d2.lo);
+ exit(-1);
+ }
+ c.hi = 0;
+ c.lo = d1.lo + d2.lo;
+ DPUSH(c);
+#else
+ DPUSH(d1 + d2);
+#endif
+}
+
+
+/*
+ * d- ( d1 d2 -- d.diff )
+ */
+
+static void dminus(void)
+{
+ const dcell d2 = DPOP();
+ const dcell d1 = DPOP();
+#ifdef NEED_FAKE_INT128_T
+ ducell c;
+
+ if (d1.hi != 0 || d2.hi != 0) {
+ fprintf(stderr, "dminus called (0x%016llx %016llx + 0x%016llx %016llx)\n",
+ d1.hi, d1.lo, d2.hi, d2.lo);
+ exit(-1);
+ }
+ c.hi = 0;
+ c.lo = d1.lo - d2.lo;
+ DPUSH(c);
+#else
+ DPUSH(d1 - d2);
+#endif
+}
+
+
+/*
+ * m* ( ?? -- )
+ */
+
+static void mmult(void)
+{
+ const cell u2 = POP();
+ const cell u1 = POP();
+#ifdef NEED_FAKE_INT128_T
+ ducell c;
+
+ if (0) { // XXX How to detect overflow?
+ fprintf(stderr, "mmult called (%016llx * 0x%016llx)\n", u1, u2);
+ exit(-1);
+ }
+ c.hi = 0;
+ c.lo = u1 * u2;
+ DPUSH(c);
+#else
+ DPUSH((dcell) u1 * u2);
+#endif
+}
+
+
+/*
+ * um* ( u1 u2 -- d.prod )
+ */
+
+static void ummult(void)
+{
+ const ucell u2 = POP();
+ const ucell u1 = POP();
+#ifdef NEED_FAKE_INT128_T
+ ducell c;
+
+ if (0) { // XXX How to detect overflow?
+ fprintf(stderr, "ummult called (%016llx * 0x%016llx)\n", u1, u2);
+ exit(-1);
+ }
+ c.hi = 0;
+ c.lo = u1 * u2;
+ DPUSH(c);
+#else
+ DPUSH((ducell) u1 * u2);
+#endif
+}
+
+
+/*
+ * @ ( a-addr -- x )
+ */
+
+static void fetch(void)
+{
+ const ucell *aaddr = (ucell *)cell2pointer(POP());
+ PUSH(read_ucell(aaddr));
+}
+
+
+/*
+ * c@ ( addr -- byte )
+ */
+
+static void cfetch(void)
+{
+ const u8 *aaddr = (u8 *)cell2pointer(POP());
+ PUSH(read_byte(aaddr));
+}
+
+
+/*
+ * w@ ( waddr -- w )
+ */
+
+static void wfetch(void)
+{
+ const u16 *aaddr = (u16 *)cell2pointer(POP());
+ PUSH(read_word(aaddr));
+}
+
+
+/*
+ * l@ ( qaddr -- quad )
+ */
+
+static void lfetch(void)
+{
+ const u32 *aaddr = (u32 *)cell2pointer(POP());
+ PUSH(read_long(aaddr));
+}
+
+
+/*
+ * ! ( x a-addr -- )
+ */
+
+static void store(void)
+{
+ const ucell *aaddr = (ucell *)cell2pointer(POP());
+ const ucell x = POP();
+#ifdef CONFIG_DEBUG_INTERNAL
+ printk("!: %lx : %lx -> %lx\n", aaddr, read_ucell(aaddr), x);
+#endif
+ write_ucell(aaddr,x);
+}
+
+
+/*
+ * +! ( nu a-addr -- )
+ */
+
+static void plusstore(void)
+{
+ const ucell *aaddr = (ucell *)cell2pointer(POP());
+ const cell nu = POP();
+ write_cell(aaddr,read_cell(aaddr)+nu);
+}
+
+
+/*
+ * c! ( byte addr -- )
+ */
+
+static void cstore(void)
+{
+ const u8 *aaddr = (u8 *)cell2pointer(POP());
+ const ucell byte = POP();
+#ifdef CONFIG_DEBUG_INTERNAL
+ printk("c!: %x = %x\n", aaddr, byte);
+#endif
+ write_byte(aaddr, byte);
+}
+
+
+/*
+ * w! ( w waddr -- )
+ */
+
+static void wstore(void)
+{
+ const u16 *aaddr = (u16 *)cell2pointer(POP());
+ const u16 word = POP();
+ write_word(aaddr, word);
+}
+
+
+/*
+ * l! ( quad qaddr -- )
+ */
+
+static void lstore(void)
+{
+ const u32 *aaddr = (u32 *)cell2pointer(POP());
+ const u32 longval = POP();
+ write_long(aaddr, longval);
+}
+
+
+/*
+ * = ( x1 x2 -- equal? )
+ */
+
+static void equals(void)
+{
+ cell tmp = (POP() == POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * > ( n1 n2 -- greater? )
+ */
+
+static void greater(void)
+{
+ cell tmp = ((cell) POP() < (cell) POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * < ( n1 n2 -- less? )
+ */
+
+static void less(void)
+{
+ cell tmp = ((cell) POP() > (cell) POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * u> ( u1 u2 -- unsigned-greater? )
+ */
+
+static void ugreater(void)
+{
+ cell tmp = ((ucell) POP() < (ucell) POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * u< ( u1 u2 -- unsigned-less? )
+ */
+
+static void uless(void)
+{
+ cell tmp = ((ucell) POP() > (ucell) POP());
+ PUSH(-tmp);
+}
+
+
+/*
+ * sp@ ( -- stack-pointer )
+ */
+
+static void spfetch(void)
+{
+ // FIXME this can only work if the stack pointer
+ // is within range.
+ ucell tmp = pointer2cell(&(dstack[dstackcnt]));
+ PUSH(tmp);
+}
+
+
+/*
+ * move ( src-addr dest-addr len -- )
+ */
+
+static void fmove(void)
+{
+ ucell count = POP();
+ void *dest = (void *)cell2pointer(POP());
+ const void *src = (const void *)cell2pointer(POP());
+ memmove(dest, src, count);
+}
+
+
+/*
+ * fill ( addr len byte -- )
+ */
+
+static void ffill(void)
+{
+ ucell value = POP();
+ ucell count = POP();
+ void *src = (void *)cell2pointer(POP());
+ memset(src, value, count);
+}
+
+
+/*
+ * unaligned-w@ ( addr -- w )
+ */
+
+static void unalignedwordread(void)
+{
+ const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
+ PUSH(unaligned_read_word(addr));
+}
+
+
+/*
+ * unaligned-w! ( w addr -- )
+ */
+
+static void unalignedwordwrite(void)
+{
+ const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
+ u16 w = POP();
+ unaligned_write_word(addr, w);
+}
+
+
+/*
+ * unaligned-l@ ( addr -- quad )
+ */
+
+static void unalignedlongread(void)
+{
+ const unsigned char *addr = (const unsigned char *) cell2pointer(POP());
+ PUSH(unaligned_read_long(addr));
+}
+
+
+/*
+ * unaligned-l! ( quad addr -- )
+ */
+
+static void unalignedlongwrite(void)
+{
+ unsigned char *addr = (unsigned char *) cell2pointer(POP());
+ u32 l = POP();
+ unaligned_write_long(addr, l);
+}
+
+/*
+ * here ( -- dictionary-pointer )
+ */
+
+static void here(void)
+{
+ PUSH(pointer2cell(dict) + dicthead);
+#ifdef CONFIG_DEBUG_INTERNAL
+ printk("here: %x\n", pointer2cell(dict) + dicthead);
+#endif
+}
+
+/*
+ * here! ( new-dict-pointer -- )
+ */
+
+static void herewrite(void)
+{
+ ucell tmp = POP(); /* converted pointer */
+ dicthead = tmp - pointer2cell(dict);
+#ifdef CONFIG_DEBUG_INTERNAL
+ printk("here!: new value: %x\n", tmp);
+#endif
+
+ if (dictlimit && dicthead >= dictlimit) {
+ printk("Dictionary space overflow:"
+ " dicthead=" FMT_ucellx
+ " dictlimit=" FMT_ucellx
+ "\n",
+ dicthead, dictlimit);
+ }
+}
+
+
+/*
+ * emit ( char -- )
+ */
+
+static void emit(void)
+{
+ cell tmp = POP();
+#ifndef FCOMPILER
+ putchar(tmp);
+#else
+ put_outputbyte(tmp);
+#endif
+}
+
+
+/*
+ * key? ( -- pressed? )
+ */
+
+static void iskey(void)
+{
+ PUSH((cell) availchar());
+}
+
+
+/*
+ * key ( -- char )
+ */
+
+static void key(void)
+{
+ while (!availchar());
+#ifdef FCOMPILER
+ PUSH(get_inputbyte());
+#else
+ PUSH(getchar());
+#endif
+}
+
+
+/*
+ * ioc@ ( reg -- val )
+ */
+
+static void iocfetch(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ PUSH(inb(reg));
+#else
+ (void)POP();
+ PUSH(0);
+#endif
+}
+
+
+/*
+ * iow@ ( reg -- val )
+ */
+
+static void iowfetch(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ PUSH(inw(reg));
+#else
+ (void)POP();
+ PUSH(0);
+#endif
+}
+
+/*
+ * iol@ ( reg -- val )
+ */
+
+static void iolfetch(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ PUSH(inl(reg));
+#else
+ (void)POP();
+ PUSH(0);
+#endif
+}
+
+
+/*
+ * ioc! ( val reg -- )
+ */
+
+static void iocstore(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ cell val = POP();
+
+ outb(val, reg);
+#else
+ (void)POP();
+ (void)POP();
+#endif
+}
+
+
+/*
+ * iow! ( val reg -- )
+ */
+
+static void iowstore(void)
+{
+#ifndef FCOMPILER
+ cell reg = POP();
+ cell val = POP();
+
+ outw(val, reg);
+#else
+ (void)POP();
+ (void)POP();
+#endif
+}
+
+
+/*
+ * iol! ( val reg -- )
+ */
+
+static void iolstore(void)
+{
+#ifndef FCOMPILER
+ ucell reg = POP();
+ ucell val = POP();
+
+ outl(val, reg);
+#else
+ (void)POP();
+ (void)POP();
+#endif
+}
+
+/*
+ * i ( -- i )
+ */
+
+static void loop_i(void)
+{
+ PUSH(rstack[rstackcnt]);
+}
+
+/*
+ * j ( -- i )
+ */
+
+static void loop_j(void)
+{
+ PUSH(rstack[rstackcnt - 2]);
+}
+
+/* words[] is a function array of all native code functions used by
+ * the dictionary, i.e. CFAs and primitives.
+ * Any change here needs a matching change in the primitive word's
+ * name list that is kept for bootstrapping in kernel/bootstrap.c
+ *
+ * NOTE: THIS LIST SHALL NOT CHANGE (EXCEPT MANDATORY ADDITIONS AT
+ * THE END). ANY OTHER CHANGE WILL BREAK COMPATIBILITY TO OLDER
+ * BINARY DICTIONARIES.
+ */
+static forth_word * const words[] = {
+ /*
+ * CFAs and special words
+ */
+ semis,
+ docol,
+ lit,
+ docon,
+ dovar,
+ dodefer,
+ dodoes,
+ dodo,
+ doisdo,
+ doloop,
+ doplusloop,
+ doival,
+ doivar,
+ doidefer,
+
+ /*
+ * primitives
+ */
+ fdup, /* dup */
+ twodup, /* 2dup */
+ isdup, /* ?dup */
+ over, /* over */
+ twoover, /* 2over */
+ pick, /* pick */
+ drop, /* drop */
+ twodrop, /* 2drop */
+ nip, /* nip */
+ roll, /* roll */
+ rot, /* rot */
+ minusrot, /* -rot */
+ swap, /* swap */
+ twoswap, /* 2swap */
+ tor, /* >r */
+ rto, /* r> */
+ rfetch, /* r@ */
+ depth, /* depth */
+ depthwrite, /* depth! */
+ rdepth, /* rdepth */
+ rdepthwrite, /* rdepth! */
+ plus, /* + */
+ minus, /* - */
+ mult, /* * */
+ umult, /* u* */
+ mudivmod, /* mu/mod */
+ forthabs, /* abs */
+ negate, /* negate */
+ max, /* max */
+ min, /* min */
+ lshift, /* lshift */
+ rshift, /* rshift */
+ rshifta, /* >>a */
+ and, /* and */
+ or, /* or */
+ xor, /* xor */
+ invert, /* invert */
+ dplus, /* d+ */
+ dminus, /* d- */
+ mmult, /* m* */
+ ummult, /* um* */
+ fetch, /* @ */
+ cfetch, /* c@ */
+ wfetch, /* w@ */
+ lfetch, /* l@ */
+ store, /* ! */
+ plusstore, /* +! */
+ cstore, /* c! */
+ wstore, /* w! */
+ lstore, /* l! */
+ equals, /* = */
+ greater, /* > */
+ less, /* < */
+ ugreater, /* u> */
+ uless, /* u< */
+ spfetch, /* sp@ */
+ fmove, /* move */
+ ffill, /* fill */
+ emit, /* emit */
+ iskey, /* key? */
+ key, /* key */
+ execute, /* execute */
+ here, /* here */
+ herewrite, /* here! */
+ dobranch, /* dobranch */
+ docbranch, /* do?branch */
+ unalignedwordread, /* unaligned-w@ */
+ unalignedwordwrite, /* unaligned-w! */
+ unalignedlongread, /* unaligned-l@ */
+ unalignedlongwrite, /* unaligned-l! */
+ iocfetch, /* ioc@ */
+ iowfetch, /* iow@ */
+ iolfetch, /* iol@ */
+ iocstore, /* ioc! */
+ iowstore, /* iow! */
+ iolstore, /* iol! */
+ loop_i, /* i */
+ loop_j, /* j */
+ call, /* call */
+ sysdebug, /* sys-debug */
+ do_include, /* $include */
+ do_encode_file, /* $encode-file */
+ do_debug_xt, /* (debug */
+ do_debug_off, /* (debug-off) */
+};
diff --git a/roms/openbios/kernel/include/dict.h b/roms/openbios/kernel/include/dict.h
new file mode 100644
index 00000000..749fd6fb
--- /dev/null
+++ b/roms/openbios/kernel/include/dict.h
@@ -0,0 +1,59 @@
+/* tag: dict management headers
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#ifndef __DICT_H
+#define __DICT_H
+
+#define DICTID "OpenBIOS"
+
+#define DOSEMIS 0
+#define DOCOL 1
+#define DOLIT 2
+#define DOCON 3
+#define DOVAR 4
+#define DODFR 5
+#define DODOES 6
+
+#define MAXNFALEN 128
+
+/* The header is 28/32 bytes on 32/64bit platforms */
+
+typedef struct dictionary_header {
+ char signature[8];
+ u8 version;
+ u8 cellsize;
+ u8 endianess;
+ u8 compression;
+ u8 relocation;
+ u8 reserved[3];
+ u32 checksum;
+ u32 length;
+ ucell last;
+} __attribute__((packed)) dictionary_header_t;
+
+ucell lfa2nfa(ucell ilfa);
+ucell load_dictionary(const char *data, ucell len);
+void dump_header(dictionary_header_t *header);
+ucell fstrlen(ucell fstr);
+void fstrncpy(char *dest, ucell src, unsigned int maxlen);
+ucell findsemis(ucell xt);
+ucell findxtfromcell_wordlist(ucell incell, ucell wordlist);
+ucell findxtfromcell(ucell incell);
+
+/* program counter */
+extern ucell PC;
+
+extern unsigned char *dict;
+extern cell dicthead;
+extern cell dictlimit;
+extern ucell *last;
+#ifdef FCOMPILER
+extern ucell *trampoline;
+#endif
+
+#endif
diff --git a/roms/openbios/kernel/stack.c b/roms/openbios/kernel/stack.c
new file mode 100644
index 00000000..f6715d1c
--- /dev/null
+++ b/roms/openbios/kernel/stack.c
@@ -0,0 +1,46 @@
+/* tag: defines the stacks, program counter and ways to access those
+ *
+ * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+
+#include "config.h"
+#include "kernel/stack.h"
+#include "cross.h"
+
+#define dstacksize 512
+int dstackcnt = 0;
+cell dstack[dstacksize];
+
+#define rstacksize 512
+int rstackcnt = 0;
+cell rstack[rstacksize];
+
+/* Rstack value saved before entering forth interpreter in debugger */
+int dbgrstackcnt = 0;
+
+#if defined(CONFIG_DEBUG_DSTACK) || defined(FCOMPILER)
+void printdstack(void)
+{
+ int i;
+ printk("dstack:");
+ for (i = 0; i <= dstackcnt; i++) {
+ printk(" 0x%" FMT_CELL_x , dstack[i]);
+ }
+ printk("\n");
+}
+#endif
+#if defined(CONFIG_DEBUG_RSTACK) || defined(FCOMPILER)
+void printrstack(void)
+{
+ int i;
+ printk("rstack:");
+ for (i = 0; i <= rstackcnt; i++) {
+ printk(" 0x%" FMT_CELL_x , rstack[i]);
+ }
+ printk("\n");
+}
+#endif
diff --git a/roms/openbios/libc/build.xml b/roms/openbios/libc/build.xml
new file mode 100644
index 00000000..cb2b560d
--- /dev/null
+++ b/roms/openbios/libc/build.xml
@@ -0,0 +1,12 @@
+<build>
+
+ <library name="libc" type="static" target="target">
+ <object source="ctype.c"/>
+ <object source="diskio.c"/>
+ <object source="extra.c"/>
+ <object source="misc.c"/>
+ <object source="string.c"/>
+ <object source="vsprintf.c"/>
+ </library>
+
+</build>
diff --git a/roms/openbios/libc/ctype.c b/roms/openbios/libc/ctype.c
new file mode 100644
index 00000000..c433f6c6
--- /dev/null
+++ b/roms/openbios/libc/ctype.c
@@ -0,0 +1,34 @@
+/*
+ * linux/lib/ctype.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include "config.h"
+#include "libc/string.h"
+
+const unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
diff --git a/roms/openbios/libc/diskio.c b/roms/openbios/libc/diskio.c
new file mode 100644
index 00000000..23f38ebb
--- /dev/null
+++ b/roms/openbios/libc/diskio.c
@@ -0,0 +1,248 @@
+/*
+ * Creation Date: <2003/12/07 19:36:00 samuel>
+ * Time-stamp: <2004/01/07 19:28:43 samuel>
+ *
+ * <diskio.c>
+ *
+ * I/O wrappers
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+
+//#define CONFIG_DEBUG_DISKIO
+#ifdef CONFIG_DEBUG_DISKIO
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+typedef struct {
+ ihandle_t ih;
+ int do_close;
+ xt_t read_xt;
+ xt_t seek_xt;
+
+ xt_t reopen_xt;
+ xt_t tell_xt;
+ xt_t get_path_xt;
+ xt_t get_fstype_xt;
+ xt_t open_nwrom_xt;
+ xt_t volume_name_xt;
+} priv_fd_t;
+
+#define MAX_FD 32
+static priv_fd_t *file_descriptors[MAX_FD];
+
+static int
+lookup_xt( ihandle_t ih, const char *method, xt_t *xt )
+{
+ if( *xt )
+ return 0;
+ *xt = find_ih_method( method, ih );
+ return (*xt) ? 0:1;
+}
+
+int
+open_ih( ihandle_t ih )
+{
+ xt_t read_xt=0, seek_xt=0;
+ priv_fd_t *fdp;
+ int fd;
+
+ if( !ih || lookup_xt(ih, "read", &read_xt) )
+ return -1;
+ if( lookup_xt(ih, "seek", &seek_xt) )
+ return -1;
+
+ for (fd=0; fd<MAX_FD; fd++)
+ if(file_descriptors[fd]==NULL)
+ break;
+ if(fd==MAX_FD)
+ return -1;
+
+ fdp = malloc( sizeof(*fdp) );
+ /* Better clear the fd, as it
+ * contains valuable information
+ */
+ memset(fdp, 0, sizeof(*fdp));
+ fdp->ih = ih;
+ fdp->read_xt = read_xt;
+ fdp->seek_xt = seek_xt;
+ fdp->do_close = 0;
+
+ file_descriptors[fd]=fdp;
+ DPRINTF("%s(0x%lx) = %d\n", __func__, (unsigned long)ih, fd);
+ return fd;
+}
+
+int
+open_io( const char *spec )
+{
+ int fd;
+ ihandle_t ih = open_dev( spec );
+ priv_fd_t *fdp;
+
+ DPRINTF("%s(%s)\n", __func__, spec);
+ if( !ih )
+ return -1;
+
+ if( (fd=open_ih(ih)) == -1 ) {
+ close_dev( ih );
+ return -1;
+ }
+
+ fdp = file_descriptors[fd];
+ fdp->do_close = 1;
+
+ return fd;
+}
+
+int
+reopen( int fd, const char *filename )
+{
+ priv_fd_t *fdp = file_descriptors[fd];
+ int ret;
+
+ if( lookup_xt(fdp->ih, "reopen", &fdp->reopen_xt) )
+ return -1;
+
+ push_str( filename );
+ call_package( fdp->reopen_xt, fdp->ih );
+ ret = (POP() == (ucell)-1)? 0 : -1;
+
+ DPRINTF("%s(%d, %s) = %d\n", __func__, fd, filename, ret);
+ return ret;
+}
+
+int
+reopen_nwrom( int fd )
+{
+ priv_fd_t *fdp = file_descriptors[fd];
+
+ DPRINTF("%s(%d)\n", __func__, fd);
+ if( lookup_xt(fdp->ih, "open-nwrom", &fdp->open_nwrom_xt) )
+ return -1;
+ call_package( fdp->open_nwrom_xt, fdp->ih );
+ return (POP() == (ucell)-1)? 0 : -1;
+}
+
+ihandle_t
+get_ih_from_fd( int fd )
+{
+ priv_fd_t *fdp = file_descriptors[fd];
+ return fdp->ih;
+}
+
+const char *
+get_file_path( int fd )
+{
+ priv_fd_t *fdp = file_descriptors[fd];
+ if( lookup_xt(fdp->ih, "get-path", &fdp->get_path_xt) )
+ return NULL;
+ call_package( fdp->get_path_xt, fdp->ih );
+ return (char*)cell2pointer(POP());
+}
+
+const char *
+get_volume_name( int fd )
+{
+ priv_fd_t *fdp = file_descriptors[fd];
+ if( lookup_xt(fdp->ih, "volume-name", &fdp->volume_name_xt) )
+ return NULL;
+ call_package( fdp->volume_name_xt, fdp->ih );
+ return (char*)cell2pointer(POP());
+}
+
+const char *
+get_fstype( int fd )
+{
+ priv_fd_t *fdp = file_descriptors[fd];
+ if( lookup_xt(fdp->ih, "get-fstype", &fdp->get_fstype_xt) )
+ return NULL;
+ call_package( fdp->get_fstype_xt, fdp->ih );
+ return (char*)cell2pointer(POP());
+}
+
+int
+read_io( int fd, void *buf, size_t cnt )
+{
+ priv_fd_t *fdp;
+ ucell ret;
+
+ DPRINTF("%s(%d, %p, %u)\n", __func__, fd, buf, cnt);
+ if (fd != -1) {
+ fdp = file_descriptors[fd];
+
+ PUSH( pointer2cell(buf) );
+ PUSH( cnt );
+ call_package( fdp->read_xt, fdp->ih );
+ ret = POP();
+
+ if( !ret && cnt )
+ ret = -1;
+ } else {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int
+seek_io( int fd, long long offs )
+{
+ priv_fd_t *fdp;
+
+ DPRINTF("%s(%d, %lld)\n", __func__, fd, offs);
+ if (fd != -1) {
+ fdp = file_descriptors[fd];
+
+ DPUSH( offs );
+ call_package( fdp->seek_xt, fdp->ih );
+ return ((((cell)POP()) >= 0)? 0 : -1);
+ } else {
+ return -1;
+ }
+}
+
+long long
+tell( int fd )
+{
+ priv_fd_t *fdp = file_descriptors[fd];
+ long long offs;
+
+ if( lookup_xt(fdp->ih, "tell", &fdp->tell_xt) )
+ return -1;
+ call_package( fdp->tell_xt, fdp->ih );
+ offs = DPOP();
+ DPRINTF("%s(%d) = %lld\n", __func__, fd, offs);
+ return offs;
+}
+
+int
+close_io( int fd )
+{
+ priv_fd_t *fdp;
+
+ DPRINTF("%s(%d)\n", __func__, fd);
+ if (fd != -1) {
+ fdp = file_descriptors[fd];
+
+ if( fdp->do_close )
+ close_dev( fdp->ih );
+ free( fdp );
+
+ file_descriptors[fd]=NULL;
+ }
+
+ return 0;
+}
diff --git a/roms/openbios/libc/extra.c b/roms/openbios/libc/extra.c
new file mode 100644
index 00000000..85731ade
--- /dev/null
+++ b/roms/openbios/libc/extra.c
@@ -0,0 +1,49 @@
+/*
+ * Creation Date: <2003/10/18 13:52:32 samuel>
+ * Time-stamp: <2003/10/18 13:54:24 samuel>
+ *
+ * <extra.c>
+ *
+ * Libc extras
+ *
+ * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libc/string.h"
+#include "libc/vsprintf.h"
+#include "libopenbios/bindings.h"
+
+/* strncpy without 0-pad */
+char *
+strncpy_nopad( char *dest, const char *src, size_t n )
+{
+ int len = MIN( n, strlen(src)+1 );
+ return memcpy( dest, src, len );
+}
+
+/* printf */
+
+int forth_printf( const char *fmt, ... )
+{
+ char buf[512];
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ PUSH(pointer2cell(buf));
+ PUSH(i);
+ fword("type");
+
+ return i;
+}
+
+
diff --git a/roms/openbios/libc/misc.c b/roms/openbios/libc/misc.c
new file mode 100644
index 00000000..e7cf4f40
--- /dev/null
+++ b/roms/openbios/libc/misc.c
@@ -0,0 +1,144 @@
+/*
+ * Creation Date: <2002/10/19 21:05:07 samuel>
+ * Time-stamp: <2002/10/22 22:29:18 samuel>
+ *
+ * <misc.c>
+ *
+ * Miscellaneous
+ *
+ * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libc/string.h"
+
+int errno_int;
+
+void
+qsort( void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void*) )
+{
+ unsigned int worked, i, j;
+
+ /* even more inefficient than the glibc variant :-) */
+ do {
+ char *p = base;
+ worked = 0;
+ for( i=0; i<nmemb-1; i++, p+= size ) {
+ if( compar( p, p + size ) > 0 ) {
+ worked = 1;
+ for( j=0; j<size; j++ ) {
+ char ch = p[j];
+ p[j] = p[j+size];
+ p[j+size] = ch;
+ }
+ }
+ }
+ } while( worked );
+}
+
+
+long int
+strtol( const char *nptr, char **endptr, int base )
+{
+ int sum, n, sign=1;
+ while( isspace(*nptr) )
+ nptr++;
+
+ if( *nptr == '-' || *nptr == '+' )
+ sign = (*nptr++ == '-') ? -1 : 1;
+
+ if( base == 16 || base == 0) {
+ if( !base )
+ base = (nptr[0] == '0')? 8 : 10;
+ if( nptr[0] == '0' && nptr[1] == 'x' ) {
+ nptr += 2;
+ base = 16;
+ }
+ }
+ for( sum=0 ;; nptr++ ) {
+ char ch = *nptr;
+ if( !isalnum(ch) )
+ break;
+ n = isdigit(ch) ? ch - '0' : toupper(ch) - 'A' + 10;
+ if( n >= base || n < 0 )
+ break;
+ sum *= base;
+ sum += n;
+ }
+ if( endptr )
+ *endptr = (char*)nptr;
+
+ return sum * sign;
+}
+
+long long int
+strtoll( const char *nptr, char **endptr, int base )
+{
+ long long int sum;
+ int n, sign=1;
+ while( isspace(*nptr) )
+ nptr++;
+
+ if( *nptr == '-' || *nptr == '+' )
+ sign = (*nptr++ == '-') ? -1 : 1;
+
+ if( base == 16 || base == 0) {
+ if( !base )
+ base = (nptr[0] == '0')? 8 : 10;
+ if( nptr[0] == '0' && nptr[1] == 'x' ) {
+ nptr += 2;
+ base = 16;
+ }
+ }
+ for( sum=0 ;; nptr++ ) {
+ char ch = *nptr;
+ if( !isalnum(ch) )
+ break;
+ n = isdigit(ch) ? ch - '0' : toupper(ch) - 'A' + 10;
+ if( n >= base || n < 0 )
+ break;
+ sum *= base;
+ sum += n;
+ }
+ if( endptr )
+ *endptr = (char*)nptr;
+
+ return sum * sign;
+}
+
+// Propolice support
+long __guard[8] = {
+#ifdef CONFIG_BIG_ENDIAN
+ (0 << 24) | (0 << 16) | ('\n' << 8) | 255,
+#else
+ (255 << 24) | ('\n' << 16) | (0 << 8) | 0,
+#endif
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static void freeze(void)
+{
+ // Freeze
+ // XXX: Disable interrupts?
+ for(;;)
+ ;
+}
+
+void __stack_smash_handler(const char *func, int damaged)
+{
+ printk("Propolice detected a stack smashing attack %x at function %s,"
+ " freezing\n", damaged, func);
+ freeze();
+}
+
+void __stack_chk_fail(void)
+{
+ printk("Propolice detected a stack smashing attack, freezing\n");
+
+ freeze();
+}
diff --git a/roms/openbios/libc/string.c b/roms/openbios/libc/string.c
new file mode 100644
index 00000000..8f62bd7b
--- /dev/null
+++ b/roms/openbios/libc/string.c
@@ -0,0 +1,387 @@
+/*
+ * linux/lib/string.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
+ * - Added strsep() which will replace strtok() soon (because strsep() is
+ * reentrant and should be faster). Use only strsep() in new code, please.
+ */
+
+#include "config.h"
+#include "libc/string.h"
+#include "libc/stdlib.h"
+
+/**
+ * strnicmp - Case insensitive, length-limited string comparison
+ * @s1: One string
+ * @s2: The other string
+ * @len: the maximum number of characters to compare
+ */
+int strnicmp(const char *s1, const char *s2, size_t len)
+{
+ /* Yes, Virginia, it had better be unsigned */
+ unsigned char c1, c2;
+
+ c1 = 0; c2 = 0;
+ if (len) {
+ do {
+ c1 = *s1; c2 = *s2;
+ s1++; s2++;
+ if (!c1)
+ break;
+ if (!c2)
+ break;
+ if (c1 == c2)
+ continue;
+ c1 = tolower(c1);
+ c2 = tolower(c2);
+ if (c1 != c2)
+ break;
+ } while (--len);
+ }
+ return (int)c1 - (int)c2;
+}
+
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char * strcpy(char * dest,const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0')
+ /* nothing */;
+ return tmp;
+}
+
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * strncpy(char * dest,const char *src,size_t count)
+{
+ char *tmp = dest;
+
+ while (count-- && (*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+
+/**
+ * strcat - Append one %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ */
+char * strcat(char * dest, const char * src)
+{
+ char *tmp = dest;
+
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++) != '\0')
+ ;
+
+ return tmp;
+}
+
+/**
+ * strncat - Append a length-limited, %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ * @count: The maximum numbers of bytes to copy
+ *
+ * Note that in contrast to strncpy, strncat ensures the result is
+ * terminated.
+ */
+char * strncat(char *dest, const char *src, size_t count)
+{
+ char *tmp = dest;
+
+ if (count) {
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++)) {
+ if (--count == 0) {
+ *dest = '\0';
+ break;
+ }
+ }
+ }
+
+ return tmp;
+}
+
+/**
+ * strcmp - Compare two strings
+ * @cs: One string
+ * @ct: Another string
+ */
+int strcmp(const char * cs,const char * ct)
+{
+ register signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+
+ return __res;
+}
+
+/**
+ * strncmp - Compare two length-limited strings
+ * @cs: One string
+ * @ct: Another string
+ * @count: The maximum number of bytes to compare
+ */
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+ register signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+
+ return __res;
+}
+
+
+/**
+ * strchr - Find the first occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strchr(const char * s, int c)
+{
+ for(; *s != (char) c; ++s)
+ if (*s == '\0')
+ return NULL;
+ return (char *) s;
+}
+
+/**
+ * strrchr - Find the last occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char * strrchr(const char * s, int c)
+{
+ const char *p = s + strlen(s);
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+/**
+ * strpbrk - Find the first occurrence of a set of characters
+ * @cs: The string to be searched
+ * @ct: The characters to search for
+ */
+char * strpbrk(const char * cs,const char * ct)
+{
+ const char *sc1,*sc2;
+
+ for( sc1 = cs; *sc1 != '\0'; ++sc1) {
+ for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+ if (*sc1 == *sc2)
+ return (char *) sc1;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * strsep - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * strsep() updates @s to point after the token, ready for the next call.
+ *
+ * It returns empty tokens, too, behaving exactly like the libc function
+ * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
+ * Same semantics, slimmer shape. ;)
+ */
+char * strsep(char **s, const char *ct)
+{
+ char *sbegin = *s, *end;
+
+ if (sbegin == NULL)
+ return NULL;
+
+ end = strpbrk(sbegin, ct);
+ if (end)
+ *end++ = '\0';
+ *s = end;
+
+ return sbegin;
+}
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void * memset(void * s,int c,size_t count)
+{
+ char *xs = (char *) s;
+
+ while (count--)
+ *xs++ = c;
+
+ return s;
+}
+
+/**
+ * memcpy - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * You should not use this function to access IO space, use memcpy_toio()
+ * or memcpy_fromio() instead.
+ */
+void * memcpy(void * dest,const void *src,size_t count)
+{
+ char *tmp = (char *) dest, *s = (char *) src;
+
+ while (count--)
+ *tmp++ = *s++;
+
+ return dest;
+}
+
+/**
+ * memmove - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * Unlike memcpy(), memmove() copes with overlapping areas.
+ */
+void * memmove(void * dest,const void *src,size_t count)
+{
+ char *tmp, *s;
+
+ if (dest <= src) {
+ tmp = (char *) dest;
+ s = (char *) src;
+ while (count--)
+ *tmp++ = *s++;
+ }
+ else {
+ tmp = (char *) dest + count;
+ s = (char *) src + count;
+ while (count--)
+ *--tmp = *--s;
+ }
+
+ return dest;
+}
+
+/**
+ * memcmp - Compare two areas of memory
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ */
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+
+char *
+strdup( const char *str )
+{
+ char *p;
+ if( !str )
+ return NULL;
+ p = malloc( strlen(str) + 1 );
+ strcpy( p, str );
+ return p;
+}
+
+int
+strcasecmp( const char *cs, const char *ct )
+{
+ register signed char __res;
+
+ while (1) {
+ char ch1 = toupper(*cs), ch2 = toupper(*ct);
+ ct++;
+ if ((__res = ch1 - ch2) != 0 || !*cs++)
+ break;
+ }
+ return __res;
+}
+
+int
+strncasecmp( const char *cs, const char *ct, size_t count )
+{
+ register signed char __res = 0;
+
+ while (count--) {
+ char ch1 = toupper(*cs), ch2 = toupper(*ct);
+ ct++;
+ if ((__res = ch1 - ch2) != 0 || !*cs++)
+ break;
+ }
+ return __res;
+}
+
diff --git a/roms/openbios/libc/vsprintf.c b/roms/openbios/libc/vsprintf.c
new file mode 100644
index 00000000..29ec7b96
--- /dev/null
+++ b/roms/openbios/libc/vsprintf.c
@@ -0,0 +1,448 @@
+/*
+ * String functions for logger.
+ */
+
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+/*
+ * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
+ * - changed to provide snprintf and vsnprintf functions
+ */
+
+#include "config.h"
+#include "libc/string.h"
+#include "libc/vsprintf.h"
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long long) n) % (unsigned) base; \
+n = ((unsigned long long) n) / (unsigned) base; \
+__res; })
+
+static int mstrlen( const char *str );
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
+{
+ char c,sign,tmp[66];
+ const char *digits;
+ static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ digits = (type & LARGE) ? large_digits : small_digits;
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return NULL;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf <= end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & SPECIAL) {
+ if (base==8) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ } else if (base==16) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ if (buf <= end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf <= end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
+}
+
+/**
+* vsnprintf - Format a string and place it in a buffer
+* @buf: The buffer to place the result into
+* @size: The size of the buffer, including the trailing null space
+* @fmt: The format string to use
+* @args: Arguments for the format string
+*
+* Call this function if you are already dealing with a va_list.
+* You probably want snprintf instead.
+ */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long long num;
+ int i, base;
+ char *str, *end, c;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+ /* 'z' support added 23/7/1999 S.H. */
+ /* 'z' changed to 'Z' --davidm 1/25/99 */
+
+ str = buf;
+ end = buf + size - 1;
+
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ size = end - buf + 1;
+ }
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+ *fmt =='Z' || *fmt == 'z') {
+ qualifier = *fmt;
+ ++fmt;
+ if (qualifier == 'l' && *fmt == 'l') {
+ qualifier = 'L';
+ ++fmt;
+ }
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT)) {
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ c = (unsigned char) va_arg(args, int);
+ if (str <= end)
+ *str = c;
+ ++str;
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if ((unsigned long)s < PAGE_SIZE)
+ s = "<NULL>";
+
+#if 0
+ len = strnlen(s, precision);
+#else
+ len = mstrlen(s);
+ if( precision > len )
+ len = precision;
+#endif
+ if (!(flags & LEFT)) {
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *s;
+ ++str; ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str, end,
+ (unsigned long) va_arg(args, void *),
+ 16, field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ /* FIXME:
+ * What does C99 say about the overflow case here? */
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else if (qualifier == 'Z' || qualifier == 'z') {
+ size_t * ip = va_arg(args, size_t *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ if (str <= end)
+ *str = '%';
+ ++str;
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ if (str <= end)
+ *str = '%';
+ ++str;
+ if (*fmt) {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ } else {
+ --fmt;
+ }
+ continue;
+ }
+ if (qualifier == 'L')
+ num = va_arg(args, long long);
+ else if (qualifier == 'l') {
+ num = va_arg(args, unsigned long);
+ if (flags & SIGN)
+ num = (signed long) num;
+ } else if (qualifier == 'Z' || qualifier == 'z') {
+ num = va_arg(args, size_t);
+ } else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (signed short) num;
+ } else {
+ num = va_arg(args, unsigned int);
+ if (flags & SIGN)
+ num = (signed int) num;
+ }
+ str = number(str, end, num, base,
+ field_width, precision, flags);
+ }
+ if (str <= end)
+ *str = '\0';
+ else if (size > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = '\0';
+ /* the trailing null byte doesn't count towards the total
+ * ++str;
+ */
+ return str-buf;
+}
+
+/**
+ * snprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ return vsnprintf(buf, (~0U)>>1, fmt, args);
+}
+
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+static int mstrlen( const char *str )
+{
+ int i=0;
+ if( str == NULL )
+ return 0;
+ while( *str++ )
+ i++;
+ return i;
+}
diff --git a/roms/openbios/libgcc/__divdi3.c b/roms/openbios/libgcc/__divdi3.c
new file mode 100644
index 00000000..a6b29b9a
--- /dev/null
+++ b/roms/openbios/libgcc/__divdi3.c
@@ -0,0 +1,26 @@
+/*
+ * arch/i386/libgcc/__divdi3.c
+ */
+
+#include "libgcc.h"
+
+int64_t __divdi3(int64_t num, int64_t den)
+{
+ int minus = 0;
+ int64_t v;
+
+ if ( num < 0 ) {
+ num = -num;
+ minus = 1;
+ }
+ if ( den < 0 ) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ v = __udivmoddi4(num, den, NULL);
+ if ( minus )
+ v = -v;
+
+ return v;
+}
diff --git a/roms/openbios/libgcc/__divti3.c b/roms/openbios/libgcc/__divti3.c
new file mode 100644
index 00000000..501c14f6
--- /dev/null
+++ b/roms/openbios/libgcc/__divti3.c
@@ -0,0 +1,26 @@
+/*
+ * arch/i386/libgcc/__divti3.c
+ */
+
+#include "libgcc.h"
+
+__int128_t __divti3(__int128_t num, __int128_t den)
+{
+ int minus = 0;
+ __int128_t v;
+
+ if ( num < 0 ) {
+ num = -num;
+ minus = 1;
+ }
+ if ( den < 0 ) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ v = __udivmodti4(num, den, NULL);
+ if ( minus )
+ v = -v;
+
+ return v;
+}
diff --git a/roms/openbios/libgcc/__lshrdi3.c b/roms/openbios/libgcc/__lshrdi3.c
new file mode 100644
index 00000000..4c1a38cd
--- /dev/null
+++ b/roms/openbios/libgcc/__lshrdi3.c
@@ -0,0 +1,59 @@
+/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin St, Fifth Floor, Boston,
+MA 02110-1301, USA. */
+
+#include "libgcc.h"
+
+#define BITS_PER_UNIT 8
+
+struct DIstruct {SItype high, low;};
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
+DItype
+__lshrdi3 (DItype u, word_type b)
+{
+ DIunion w;
+ word_type bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+ if (bm <= 0)
+ {
+ w.s.high = 0;
+ w.s.low = (USItype)uu.s.high >> -bm;
+ }
+ else
+ {
+ USItype carries = (USItype)uu.s.high << bm;
+ w.s.high = (USItype)uu.s.high >> b;
+ w.s.low = ((USItype)uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
diff --git a/roms/openbios/libgcc/__negti2.c b/roms/openbios/libgcc/__negti2.c
new file mode 100644
index 00000000..e97cd122
--- /dev/null
+++ b/roms/openbios/libgcc/__negti2.c
@@ -0,0 +1,53 @@
+/* Extracted from gcc-3.4.1/gcc/config/mips/_tilibi.c */
+/* A few TImode functions needed for TFmode emulated arithmetic.
+ Copyright 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "libgcc.h"
+
+#if defined(__sparc__) || defined(__ppc__)
+#define LIBGCC2_WORDS_BIG_ENDIAN
+#endif
+
+typedef union
+{
+ struct TIstruct {
+#if defined(LIBGCC2_WORDS_BIG_ENDIAN)
+ DItype high, low;
+#else
+ DItype low, high;
+#endif
+ } s;
+ TItype ll;
+} TIunion;
+
+TItype
+__negti2 (TItype u)
+{
+ TIunion w;
+ TIunion uu;
+
+ uu.ll = u;
+
+ w.s.low = -uu.s.low;
+ w.s.high = -uu.s.high - ((UDItype) w.s.low > 0);
+
+ return w.ll;
+}
diff --git a/roms/openbios/libgcc/__udivdi3.c b/roms/openbios/libgcc/__udivdi3.c
new file mode 100644
index 00000000..2bfe9139
--- /dev/null
+++ b/roms/openbios/libgcc/__udivdi3.c
@@ -0,0 +1,10 @@
+/*
+ * arch/i386/libgcc/__divdi3.c
+ */
+
+#include "libgcc.h"
+
+uint64_t __udivdi3(uint64_t num, uint64_t den)
+{
+ return __udivmoddi4(num, den, NULL);
+}
diff --git a/roms/openbios/libgcc/__udivmoddi4.c b/roms/openbios/libgcc/__udivmoddi4.c
new file mode 100644
index 00000000..bed70e12
--- /dev/null
+++ b/roms/openbios/libgcc/__udivmoddi4.c
@@ -0,0 +1,31 @@
+#include "libgcc.h"
+
+uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem_p)
+{
+ uint64_t quot = 0, qbit = 1;
+
+ if ( den == 0 ) {
+ __divide_error();
+ return 0; /* If trap returns... */
+ }
+
+ /* Left-justify denominator and count shift */
+ while ( (int64_t)den >= 0 ) {
+ den <<= 1;
+ qbit <<= 1;
+ }
+
+ while ( qbit ) {
+ if ( den <= num ) {
+ num -= den;
+ quot += qbit;
+ }
+ den >>= 1;
+ qbit >>= 1;
+ }
+
+ if ( rem_p )
+ *rem_p = num;
+
+ return quot;
+}
diff --git a/roms/openbios/libgcc/__udivmodti4.c b/roms/openbios/libgcc/__udivmodti4.c
new file mode 100644
index 00000000..e373c59e
--- /dev/null
+++ b/roms/openbios/libgcc/__udivmodti4.c
@@ -0,0 +1,31 @@
+#include "libgcc.h"
+
+__uint128_t __udivmodti4(__uint128_t num, __uint128_t den, __uint128_t *rem_p)
+{
+ __uint128_t quot = 0, qbit = 1;
+
+ if ( den == 0 ) {
+ __divide_error();
+ return 0; /* If trap returns... */
+ }
+
+ /* Left-justify denominator and count shift */
+ while ( (__int128_t)den >= 0 ) {
+ den <<= 1;
+ qbit <<= 1;
+ }
+
+ while ( qbit ) {
+ if ( den <= num ) {
+ num -= den;
+ quot += qbit;
+ }
+ den >>= 1;
+ qbit >>= 1;
+ }
+
+ if ( rem_p )
+ *rem_p = num;
+
+ return quot;
+}
diff --git a/roms/openbios/libgcc/__udivti3.c b/roms/openbios/libgcc/__udivti3.c
new file mode 100644
index 00000000..6be015bb
--- /dev/null
+++ b/roms/openbios/libgcc/__udivti3.c
@@ -0,0 +1,10 @@
+/*
+ * arch/i386/libgcc/__divdi3.c
+ */
+
+#include "libgcc.h"
+
+__uint128_t __udivti3(__uint128_t num, __uint128_t den)
+{
+ return __udivmodti4(num, den, NULL);
+}
diff --git a/roms/openbios/libgcc/__umoddi3.c b/roms/openbios/libgcc/__umoddi3.c
new file mode 100644
index 00000000..1c7b1cd7
--- /dev/null
+++ b/roms/openbios/libgcc/__umoddi3.c
@@ -0,0 +1,13 @@
+/*
+ * arch/i386/libgcc/__umoddi3.c
+ */
+
+#include "libgcc.h"
+
+uint64_t __umoddi3(uint64_t num, uint64_t den)
+{
+ uint64_t v;
+
+ (void) __udivmoddi4(num, den, &v);
+ return v;
+}
diff --git a/roms/openbios/libgcc/__umodti3.c b/roms/openbios/libgcc/__umodti3.c
new file mode 100644
index 00000000..196c7bf7
--- /dev/null
+++ b/roms/openbios/libgcc/__umodti3.c
@@ -0,0 +1,13 @@
+/*
+ * arch/i386/libgcc/__umoddi3.c
+ */
+
+#include "libgcc.h"
+
+__uint128_t __umodti3(__uint128_t num, __uint128_t den)
+{
+ __uint128_t v;
+
+ (void) __udivmodti4(num, den, &v);
+ return v;
+}
diff --git a/roms/openbios/libgcc/ashldi3.c b/roms/openbios/libgcc/ashldi3.c
new file mode 100644
index 00000000..6feb063e
--- /dev/null
+++ b/roms/openbios/libgcc/ashldi3.c
@@ -0,0 +1,59 @@
+/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin St, Fifth Floor, Boston,
+MA 02110-1301, USA. */
+
+#include "libgcc.h"
+
+#define BITS_PER_UNIT 8
+
+struct DIstruct {SItype high, low;};
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
+DItype
+__ashldi3 (DItype u, word_type b)
+{
+ DIunion w;
+ word_type bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+ if (bm <= 0)
+ {
+ w.s.low = 0;
+ w.s.high = (USItype)uu.s.low << -bm;
+ }
+ else
+ {
+ USItype carries = (USItype)uu.s.low >> bm;
+ w.s.low = (USItype)uu.s.low << b;
+ w.s.high = ((USItype)uu.s.high << b) | carries;
+ }
+
+ return w.ll;
+}
diff --git a/roms/openbios/libgcc/ashrdi3.c b/roms/openbios/libgcc/ashrdi3.c
new file mode 100644
index 00000000..8594d5ee
--- /dev/null
+++ b/roms/openbios/libgcc/ashrdi3.c
@@ -0,0 +1,60 @@
+/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin St, Fifth Floor, Boston,
+MA 02110-1301, USA. */
+
+#include "libgcc.h"
+
+#define BITS_PER_UNIT 8
+
+struct DIstruct {SItype high, low;};
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
+DItype
+__ashrdi3 (DItype u, word_type b)
+{
+ DIunion w;
+ word_type bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+ if (bm <= 0)
+ {
+ /* w.s.high = 1..1 or 0..0 */
+ w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
+ w.s.low = uu.s.high >> -bm;
+ }
+ else
+ {
+ USItype carries = (USItype)uu.s.high << bm;
+ w.s.high = uu.s.high >> b;
+ w.s.low = ((USItype)uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
diff --git a/roms/openbios/libgcc/build.xml b/roms/openbios/libgcc/build.xml
new file mode 100644
index 00000000..1b7724c5
--- /dev/null
+++ b/roms/openbios/libgcc/build.xml
@@ -0,0 +1,24 @@
+<build>
+
+ <library name="gcc" type="static" target="target">
+ <object source="ashldi3.c"/>
+ <object source="ashrdi3.c"/>
+ <object source="__lshrdi3.c"/>
+
+ <object source="__divdi3.c"/>
+ <object source="__udivdi3.c"/>
+ <object source="__udivmoddi4.c"/>
+ <object source="__umoddi3.c"/>
+
+ <object source="crtsavres.S" condition="PPC"/>
+
+ <!-- CONDITION="CONFIG_64BITS" -->
+ <object source="__divti3.c" condition="SPARC64"/>
+ <object source="__udivti3.c" condition="SPARC64"/>
+ <object source="__udivmodti4.c" condition="SPARC64"/>
+ <object source="__umodti3.c" condition="SPARC64"/>
+ <object source="multi3.c" condition="SPARC64"/>
+ <object source="__negti2.c" condition="SPARC64"/>
+ </library>
+
+</build>
diff --git a/roms/openbios/libgcc/crtsavres.S b/roms/openbios/libgcc/crtsavres.S
new file mode 100644
index 00000000..40bd7365
--- /dev/null
+++ b/roms/openbios/libgcc/crtsavres.S
@@ -0,0 +1,401 @@
+/*
+ * Special support for eabi and SVR4
+ *
+ * Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ * Written By Michael Meissner
+ *
+ * Based on gcc/config/rs6000/crtsavres.asm from gcc
+ * 64 bit additions from reading the PPC elf64abi document.
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * In addition to the permissions in the GNU General Public License, the
+ * Free Software Foundation gives you unlimited permission to link the
+ * compiled version of this file with other programs, and to distribute
+ * those programs without any restriction coming from the use of this
+ * file. (The General Public License restrictions do apply in other
+ * respects; for example, they cover modification of the file, and
+ * distribution when not linked into another program.)
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * As a special exception, if you link this library with files
+ * compiled with GCC to produce an executable, this does not cause
+ * the resulting executable to be covered by the GNU General Public License.
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ */
+
+/* taken from Linux arch/powerpc/lib/crtsavres.S */
+
+/* arch/powerpc/include/asm/ppc_asm.h */
+#ifdef CONFIG_PPC64
+
+#define XGLUE(a,b) a##b
+#define GLUE(a,b) XGLUE(a,b)
+
+#define _GLOBAL(name) \
+ .section ".text"; \
+ .align 2 ; \
+ .globl name; \
+ .globl GLUE(.,name); \
+ .section ".opd","aw"; \
+name: \
+ .quad GLUE(.,name); \
+ .quad .TOC.@tocbase; \
+ .quad 0; \
+ .previous; \
+ .type GLUE(.,name),@function; \
+GLUE(.,name):
+
+#else /* 32-bit */
+
+/* include/linux/stringify.h */
+
+/* Indirect stringification. Doing two levels allows the parameter to be a
+ * macro itself. For example, compile with -DFOO=bar, __stringify(FOO)
+ * converts to "bar".
+ */
+
+#define __stringify_1(x...) #x
+#define __stringify(x...) __stringify_1(x)
+
+/* arch/powerpc/include/asm/ppc_asm.h continues */
+
+#define _GLOBAL(n) \
+ .text; \
+ .stabs __stringify(n:F-1),N_FUN,0,0,n;\
+ .globl n; \
+n:
+
+/* some stab codes */
+#define N_FUN 36
+
+#endif
+
+/* arch/powerpc/lib/crtsavres.S continues */
+
+ .file "crtsavres.S"
+ .section ".text"
+
+#ifndef CONFIG_PPC64
+
+/* Routines for saving integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer save area. */
+
+_GLOBAL(_savegpr_14)
+_GLOBAL(_save32gpr_14)
+ stw 14,-72(11) /* save gp registers */
+_GLOBAL(_savegpr_15)
+_GLOBAL(_save32gpr_15)
+ stw 15,-68(11)
+_GLOBAL(_savegpr_16)
+_GLOBAL(_save32gpr_16)
+ stw 16,-64(11)
+_GLOBAL(_savegpr_17)
+_GLOBAL(_save32gpr_17)
+ stw 17,-60(11)
+_GLOBAL(_savegpr_18)
+_GLOBAL(_save32gpr_18)
+ stw 18,-56(11)
+_GLOBAL(_savegpr_19)
+_GLOBAL(_save32gpr_19)
+ stw 19,-52(11)
+_GLOBAL(_savegpr_20)
+_GLOBAL(_save32gpr_20)
+ stw 20,-48(11)
+_GLOBAL(_savegpr_21)
+_GLOBAL(_save32gpr_21)
+ stw 21,-44(11)
+_GLOBAL(_savegpr_22)
+_GLOBAL(_save32gpr_22)
+ stw 22,-40(11)
+_GLOBAL(_savegpr_23)
+_GLOBAL(_save32gpr_23)
+ stw 23,-36(11)
+_GLOBAL(_savegpr_24)
+_GLOBAL(_save32gpr_24)
+ stw 24,-32(11)
+_GLOBAL(_savegpr_25)
+_GLOBAL(_save32gpr_25)
+ stw 25,-28(11)
+_GLOBAL(_savegpr_26)
+_GLOBAL(_save32gpr_26)
+ stw 26,-24(11)
+_GLOBAL(_savegpr_27)
+_GLOBAL(_save32gpr_27)
+ stw 27,-20(11)
+_GLOBAL(_savegpr_28)
+_GLOBAL(_save32gpr_28)
+ stw 28,-16(11)
+_GLOBAL(_savegpr_29)
+_GLOBAL(_save32gpr_29)
+ stw 29,-12(11)
+_GLOBAL(_savegpr_30)
+_GLOBAL(_save32gpr_30)
+ stw 30,-8(11)
+_GLOBAL(_savegpr_31)
+_GLOBAL(_save32gpr_31)
+ stw 31,-4(11)
+ blr
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+_GLOBAL(_restgpr_14)
+_GLOBAL(_rest32gpr_14)
+ lwz 14,-72(11) /* restore gp registers */
+_GLOBAL(_restgpr_15)
+_GLOBAL(_rest32gpr_15)
+ lwz 15,-68(11)
+_GLOBAL(_restgpr_16)
+_GLOBAL(_rest32gpr_16)
+ lwz 16,-64(11)
+_GLOBAL(_restgpr_17)
+_GLOBAL(_rest32gpr_17)
+ lwz 17,-60(11)
+_GLOBAL(_restgpr_18)
+_GLOBAL(_rest32gpr_18)
+ lwz 18,-56(11)
+_GLOBAL(_restgpr_19)
+_GLOBAL(_rest32gpr_19)
+ lwz 19,-52(11)
+_GLOBAL(_restgpr_20)
+_GLOBAL(_rest32gpr_20)
+ lwz 20,-48(11)
+_GLOBAL(_restgpr_21)
+_GLOBAL(_rest32gpr_21)
+ lwz 21,-44(11)
+_GLOBAL(_restgpr_22)
+_GLOBAL(_rest32gpr_22)
+ lwz 22,-40(11)
+_GLOBAL(_restgpr_23)
+_GLOBAL(_rest32gpr_23)
+ lwz 23,-36(11)
+_GLOBAL(_restgpr_24)
+_GLOBAL(_rest32gpr_24)
+ lwz 24,-32(11)
+_GLOBAL(_restgpr_25)
+_GLOBAL(_rest32gpr_25)
+ lwz 25,-28(11)
+_GLOBAL(_restgpr_26)
+_GLOBAL(_rest32gpr_26)
+ lwz 26,-24(11)
+_GLOBAL(_restgpr_27)
+_GLOBAL(_rest32gpr_27)
+ lwz 27,-20(11)
+_GLOBAL(_restgpr_28)
+_GLOBAL(_rest32gpr_28)
+ lwz 28,-16(11)
+_GLOBAL(_restgpr_29)
+_GLOBAL(_rest32gpr_29)
+ lwz 29,-12(11)
+_GLOBAL(_restgpr_30)
+_GLOBAL(_rest32gpr_30)
+ lwz 30,-8(11)
+_GLOBAL(_restgpr_31)
+_GLOBAL(_rest32gpr_31)
+ lwz 31,-4(11)
+ blr
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+_GLOBAL(_restgpr_14_x)
+_GLOBAL(_rest32gpr_14_x)
+ lwz 14,-72(11) /* restore gp registers */
+_GLOBAL(_restgpr_15_x)
+_GLOBAL(_rest32gpr_15_x)
+ lwz 15,-68(11)
+_GLOBAL(_restgpr_16_x)
+_GLOBAL(_rest32gpr_16_x)
+ lwz 16,-64(11)
+_GLOBAL(_restgpr_17_x)
+_GLOBAL(_rest32gpr_17_x)
+ lwz 17,-60(11)
+_GLOBAL(_restgpr_18_x)
+_GLOBAL(_rest32gpr_18_x)
+ lwz 18,-56(11)
+_GLOBAL(_restgpr_19_x)
+_GLOBAL(_rest32gpr_19_x)
+ lwz 19,-52(11)
+_GLOBAL(_restgpr_20_x)
+_GLOBAL(_rest32gpr_20_x)
+ lwz 20,-48(11)
+_GLOBAL(_restgpr_21_x)
+_GLOBAL(_rest32gpr_21_x)
+ lwz 21,-44(11)
+_GLOBAL(_restgpr_22_x)
+_GLOBAL(_rest32gpr_22_x)
+ lwz 22,-40(11)
+_GLOBAL(_restgpr_23_x)
+_GLOBAL(_rest32gpr_23_x)
+ lwz 23,-36(11)
+_GLOBAL(_restgpr_24_x)
+_GLOBAL(_rest32gpr_24_x)
+ lwz 24,-32(11)
+_GLOBAL(_restgpr_25_x)
+_GLOBAL(_rest32gpr_25_x)
+ lwz 25,-28(11)
+_GLOBAL(_restgpr_26_x)
+_GLOBAL(_rest32gpr_26_x)
+ lwz 26,-24(11)
+_GLOBAL(_restgpr_27_x)
+_GLOBAL(_rest32gpr_27_x)
+ lwz 27,-20(11)
+_GLOBAL(_restgpr_28_x)
+_GLOBAL(_rest32gpr_28_x)
+ lwz 28,-16(11)
+_GLOBAL(_restgpr_29_x)
+_GLOBAL(_rest32gpr_29_x)
+ lwz 29,-12(11)
+_GLOBAL(_restgpr_30_x)
+_GLOBAL(_rest32gpr_30_x)
+ lwz 30,-8(11)
+_GLOBAL(_restgpr_31_x)
+_GLOBAL(_rest32gpr_31_x)
+ lwz 0,4(11)
+ lwz 31,-4(11)
+ mtlr 0
+ mr 1,11
+ blr
+
+#else /* CONFIG_PPC64 */
+
+.globl _savegpr0_14
+_savegpr0_14:
+ std r14,-144(r1)
+.globl _savegpr0_15
+_savegpr0_15:
+ std r15,-136(r1)
+.globl _savegpr0_16
+_savegpr0_16:
+ std r16,-128(r1)
+.globl _savegpr0_17
+_savegpr0_17:
+ std r17,-120(r1)
+.globl _savegpr0_18
+_savegpr0_18:
+ std r18,-112(r1)
+.globl _savegpr0_19
+_savegpr0_19:
+ std r19,-104(r1)
+.globl _savegpr0_20
+_savegpr0_20:
+ std r20,-96(r1)
+.globl _savegpr0_21
+_savegpr0_21:
+ std r21,-88(r1)
+.globl _savegpr0_22
+_savegpr0_22:
+ std r22,-80(r1)
+.globl _savegpr0_23
+_savegpr0_23:
+ std r23,-72(r1)
+.globl _savegpr0_24
+_savegpr0_24:
+ std r24,-64(r1)
+.globl _savegpr0_25
+_savegpr0_25:
+ std r25,-56(r1)
+.globl _savegpr0_26
+_savegpr0_26:
+ std r26,-48(r1)
+.globl _savegpr0_27
+_savegpr0_27:
+ std r27,-40(r1)
+.globl _savegpr0_28
+_savegpr0_28:
+ std r28,-32(r1)
+.globl _savegpr0_29
+_savegpr0_29:
+ std r29,-24(r1)
+.globl _savegpr0_30
+_savegpr0_30:
+ std r30,-16(r1)
+.globl _savegpr0_31
+_savegpr0_31:
+ std r31,-8(r1)
+ std r0,16(r1)
+ blr
+
+.globl _restgpr0_14
+_restgpr0_14:
+ ld r14,-144(r1)
+.globl _restgpr0_15
+_restgpr0_15:
+ ld r15,-136(r1)
+.globl _restgpr0_16
+_restgpr0_16:
+ ld r16,-128(r1)
+.globl _restgpr0_17
+_restgpr0_17:
+ ld r17,-120(r1)
+.globl _restgpr0_18
+_restgpr0_18:
+ ld r18,-112(r1)
+.globl _restgpr0_19
+_restgpr0_19:
+ ld r19,-104(r1)
+.globl _restgpr0_20
+_restgpr0_20:
+ ld r20,-96(r1)
+.globl _restgpr0_21
+_restgpr0_21:
+ ld r21,-88(r1)
+.globl _restgpr0_22
+_restgpr0_22:
+ ld r22,-80(r1)
+.globl _restgpr0_23
+_restgpr0_23:
+ ld r23,-72(r1)
+.globl _restgpr0_24
+_restgpr0_24:
+ ld r24,-64(r1)
+.globl _restgpr0_25
+_restgpr0_25:
+ ld r25,-56(r1)
+.globl _restgpr0_26
+_restgpr0_26:
+ ld r26,-48(r1)
+.globl _restgpr0_27
+_restgpr0_27:
+ ld r27,-40(r1)
+.globl _restgpr0_28
+_restgpr0_28:
+ ld r28,-32(r1)
+.globl _restgpr0_29
+_restgpr0_29:
+ ld r0,16(r1)
+ ld r29,-24(r1)
+ mtlr r0
+ ld r30,-16(r1)
+ ld r31,-8(r1)
+ blr
+
+.globl _restgpr0_30
+_restgpr0_30:
+ ld r30,-16(r1)
+.globl _restgpr0_31
+_restgpr0_31:
+ ld r0,16(r1)
+ ld r31,-8(r1)
+ mtlr r0
+ blr
+
+#endif /* CONFIG_PPC64 */
diff --git a/roms/openbios/libgcc/libgcc.h b/roms/openbios/libgcc/libgcc.h
new file mode 100644
index 00000000..fc82397d
--- /dev/null
+++ b/roms/openbios/libgcc/libgcc.h
@@ -0,0 +1,45 @@
+#ifndef _LIBGCC_H
+#define _LIBGCC_H
+
+#include "asm/types.h"
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+typedef int word_type __attribute__ ((mode (__word__)));
+
+uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem);
+
+int64_t __divdi3(int64_t num, int64_t den);
+uint64_t __udivdi3(uint64_t num, uint64_t den);
+
+uint64_t __umoddi3(uint64_t num, uint64_t den);
+
+DItype __ashldi3 (DItype u, word_type b);
+DItype __lshrdi3 (DItype u, word_type b);
+DItype __ashrdi3 (DItype u, word_type b);
+
+// Must be implemented outside:
+void __divide_error(void);
+
+#if defined(__arch64__) || defined(__LP64__)
+typedef int TItype __attribute__ ((mode (TI)));
+
+__uint128_t __udivmodti4(__uint128_t num, __uint128_t den, __uint128_t *rem);
+
+__int128_t __divti3(__int128_t num, __int128_t den);
+__uint128_t __udivti3(__uint128_t num, __uint128_t den);
+
+__uint128_t __umodti3(__uint128_t num, __uint128_t den);
+
+TItype __multi3 (TItype u, TItype v);
+TItype __negti2 (TItype u);
+
+#endif
+
+#endif /* _LIBGCC_H */
diff --git a/roms/openbios/libgcc/multi3.c b/roms/openbios/libgcc/multi3.c
new file mode 100644
index 00000000..e7186be2
--- /dev/null
+++ b/roms/openbios/libgcc/multi3.c
@@ -0,0 +1,83 @@
+/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
+ gcc-2.7.2.3/longlong.h which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin St, Fifth Floor, Boston,
+MA 02110-1301, USA. */
+
+#include "libgcc.h"
+
+#define BITS_PER_UNIT 8
+#define DI_TYPE_SIZE 64
+
+#define __BITS4 (DI_TYPE_SIZE / 4)
+#define __ll_B (1L << (DI_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UDItype) (t) % __ll_B)
+#define __ll_highpart(t) ((UDItype) (t) / __ll_B)
+
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UDItype __x0, __x1, __x2, __x3; \
+ UDItype __ul, __vl, __uh, __vh; \
+ \
+ __ul = __ll_lowpart (u); \
+ __uh = __ll_highpart (u); \
+ __vl = __ll_lowpart (v); \
+ __vh = __ll_highpart (v); \
+ \
+ __x0 = (UDItype) __ul * __vl; \
+ __x1 = (UDItype) __ul * __vh; \
+ __x2 = (UDItype) __uh * __vl; \
+ __x3 = (UDItype) __uh * __vh; \
+ \
+ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + __ll_highpart (__x1); \
+ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
+ } while (0)
+
+#define __umulsidi3(u, v) \
+ ({TIunion __w; \
+ umul_ppmm (__w.s.high, __w.s.low, u, v); \
+ __w.ll; })
+
+struct TIstruct {DItype high, low;};
+
+typedef union
+{
+ struct TIstruct s;
+ TItype ll;
+} TIunion;
+
+TItype
+__multi3 (TItype u, TItype v)
+{
+ TIunion w;
+ TIunion uu, vv;
+
+ uu.ll = u,
+ vv.ll = v;
+
+ w.ll = __umulsidi3 (uu.s.low, vv.s.low);
+ w.s.high += ((UDItype) uu.s.low * (UDItype) vv.s.high
+ + (UDItype) uu.s.high * (UDItype) vv.s.low);
+
+ return w.ll;
+}
diff --git a/roms/openbios/libopenbios/Kconfig b/roms/openbios/libopenbios/Kconfig
new file mode 100644
index 00000000..1b36f192
--- /dev/null
+++ b/roms/openbios/libopenbios/Kconfig
@@ -0,0 +1,97 @@
+
+
+menu "Module Configuration"
+
+
+config CMDLINE
+ bool "Command Line Editing"
+ default y
+ help
+ Improved openfirmware prompt
+
+config DEBLOCKER
+ bool "Deblocker"
+ default y
+ help
+ Deblocker implementation
+
+endmenu
+
+menu "Filesystem Configuration"
+
+config DISK_LABEL
+ bool "Disk-Label"
+ default y
+ help
+ Disk-label package implementation
+
+config PART_SUPPORT
+ depends on DISK_LABEL
+ bool "Partition support"
+ default y
+ help
+ Support for partition tables
+
+config MAC_PARTS
+ depends on PART_SUPPORT && BIG_ENDIAN
+ bool "Mac partition support"
+ default y
+ help
+ Support for Macintosh partition tables
+
+config PC_PARTS
+ depends on PART_SUPPORT
+ bool "PC style partition support"
+ default y
+ help
+ Support for PC style partition tables
+
+config FS
+ depends on DISK_LABEL
+ bool "Filesystem Support"
+ default y
+ help
+ Include filesystem support
+
+config HFS
+ depends on FS && BIG_ENDIAN
+ bool "HFS support"
+ default y
+ help
+ Include HFS support
+
+config HFSP
+ depends on FS && BIG_ENDIAN
+ bool "HFS+ support"
+ default y
+ help
+ Include HFS+ support
+
+config GRUBFS
+ depends on FS
+ bool "Additional Filesystems (from GRUB)"
+ default y
+ help
+ Grub provides a lot of filesystem drivers.
+
+source "fs/grubfs/Kconfig"
+
+config DEBUG_FS
+ depends on FS
+ bool "Debugging output for Filesystem code"
+ default y
+ help
+ Say Y here if you want to debug the filesystem layer
+
+endmenu
+
+menu "Miscellaneous"
+
+config LINUXBIOS
+ bool "Support reading LinuxBIOS table"
+ default y
+ help
+ If you want to boot OpenBIOS as a LinuxBIOS payload,
+ you should say Y here.
+
+endmenu
diff --git a/roms/openbios/libopenbios/aout_load.c b/roms/openbios/libopenbios/aout_load.c
new file mode 100644
index 00000000..e9d20025
--- /dev/null
+++ b/roms/openbios/libopenbios/aout_load.c
@@ -0,0 +1,176 @@
+/* a.out boot loader
+ * As we have seek, this implementation can be straightforward.
+ * 2003-07 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+
+#ifdef CONFIG_SPARC64
+#define CONFIG_SPARC64_PAGE_SIZE_8KB
+#endif
+
+/* NextStep bootloader on SPARC32 expects the a.out header directly
+ below load-base (0x4000) */
+#ifdef CONFIG_SPARC32
+#define AOUT_HEADER_COPY
+#endif
+
+#include "libopenbios/sys_info.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/aout_load.h"
+#include "libc/diskio.h"
+#define printf printk
+#define debug printk
+
+#define addr_fixup(addr) ((addr) & 0x00ffffff)
+
+static char *image_name, *image_version;
+static int fd;
+
+static int
+check_mem_ranges(struct sys_info *info,
+ unsigned long start,
+ unsigned long size)
+{
+ int j;
+ unsigned long end;
+ unsigned long prog_start, prog_end;
+ struct memrange *mem;
+
+ prog_start = virt_to_phys(&_start);
+ prog_end = virt_to_phys(&_end);
+
+ end = start + size;
+
+ if (start < prog_start && end > prog_start)
+ goto conflict;
+ if (start < prog_end && end > prog_end)
+ goto conflict;
+ mem = info->memrange;
+ for (j = 0; j < info->n_memranges; j++) {
+ if (mem[j].base <= start && mem[j].base + mem[j].size >= end)
+ break;
+ }
+ if (j >= info->n_memranges)
+ goto badseg;
+ return 1;
+
+ conflict:
+ printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end);
+
+ badseg:
+ printf("A.out file [%#lx-%#lx] doesn't fit into memory\n", start, end - 1);
+ return 0;
+}
+
+int
+is_aout(struct exec *ehdr)
+{
+ return ((ehdr->a_info & 0xffff) == OMAGIC
+ || (ehdr->a_info & 0xffff) == NMAGIC
+ || (ehdr->a_info & 0xffff) == ZMAGIC
+ || (ehdr->a_info & 0xffff) == QMAGIC);
+}
+
+int
+aout_load(struct sys_info *info, ihandle_t dev)
+{
+ int retval = -1;
+ struct exec ehdr;
+ unsigned long start, size;
+ unsigned int offset;
+
+ image_name = image_version = NULL;
+
+ /* Mark the saved-program-state as invalid */
+ feval("0 state-valid !");
+
+ fd = open_ih(dev);
+ if (fd == -1) {
+ goto out;
+ }
+
+ for (offset = 0; offset < 16 * 512; offset += 512) {
+ seek_io(fd, offset);
+ if (read_io(fd, &ehdr, sizeof ehdr) != sizeof ehdr) {
+ debug("Can't read a.out header\n");
+ retval = LOADER_NOT_SUPPORT;
+ goto out;
+ }
+ if (is_aout(&ehdr))
+ break;
+ }
+
+ if (!is_aout(&ehdr)) {
+ debug("Not a bootable a.out image\n");
+ retval = LOADER_NOT_SUPPORT;
+ goto out;
+ }
+
+ if (ehdr.a_text == 0x30800007)
+ ehdr.a_text=64*1024;
+
+ if (N_MAGIC(ehdr) == NMAGIC) {
+ size = addr_fixup(N_DATADDR(ehdr)) + addr_fixup(ehdr.a_data);
+ } else {
+ size = addr_fixup(ehdr.a_text) + addr_fixup(ehdr.a_data);
+ }
+
+ if (size < 7680)
+ size = 7680;
+
+ fword("load-base");
+ start = POP(); // N_TXTADDR(ehdr);
+
+ if (!check_mem_ranges(info, start, size))
+ goto out;
+
+ printf("Loading a.out %s...\n", image_name ? image_name : "image");
+
+ seek_io(fd, offset + N_TXTOFF(ehdr));
+
+ if (N_MAGIC(ehdr) == NMAGIC) {
+ if ((size_t)read_io(fd, (void *)start, ehdr.a_text) != ehdr.a_text) {
+ printf("Can't read program text segment (size 0x" FMT_aout_ehdr ")\n", ehdr.a_text);
+ goto out;
+ }
+ if ((size_t)read_io(fd, (void *)(start + N_DATADDR(ehdr)), ehdr.a_data) != ehdr.a_data) {
+ printf("Can't read program data segment (size 0x" FMT_aout_ehdr ")\n", ehdr.a_data);
+ goto out;
+ }
+ } else {
+ if ((size_t)read_io(fd, (void *)start, size) != size) {
+ printf("Can't read program (size 0x" FMT_sizet ")\n", size);
+ goto out;
+ }
+ }
+
+ debug("Loaded %lu bytes\n", size);
+ debug("entry point is %#lx\n", start);
+
+#ifdef AOUT_HEADER_COPY
+ // Copy the a.out header just before start
+ memcpy((char *)(start - 0x20), &ehdr, 0x20);
+#endif
+
+ // Initialise saved-program-state
+ PUSH(addr_fixup(start));
+ feval("saved-program-state >sps.entry !");
+ PUSH(size);
+ feval("saved-program-state >sps.file-size !");
+ feval("aout saved-program-state >sps.file-type !");
+
+ feval("-1 state-valid !");
+
+out:
+ close_io(fd);
+ return retval;
+}
+
+void
+aout_init_program(void)
+{
+ // Currently not implemented
+ feval("0 state-valid !");
+}
diff --git a/roms/openbios/libopenbios/bindings.c b/roms/openbios/libopenbios/bindings.c
new file mode 100644
index 00000000..5323421f
--- /dev/null
+++ b/roms/openbios/libopenbios/bindings.c
@@ -0,0 +1,524 @@
+/*
+ * Creation Date: <2003/11/24 12:30:18 samuel>
+ * Time-stamp: <2004/01/07 19:37:38 samuel>
+ *
+ * <bindings.c>
+ *
+ * Forth bindings
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "libc/stdlib.h"
+#include "libc/byteorder.h"
+
+
+/************************************************************************/
+/* forth interface glue */
+/************************************************************************/
+
+void
+push_str( const char *str )
+{
+ PUSH( pointer2cell(str) );
+ PUSH( str ? strlen(str) : 0 );
+}
+
+/* WARNING: sloooow - AVOID */
+cell
+feval( const char *str )
+{
+ push_str( str );
+ return eword("evaluate", 2);
+}
+
+cell
+_eword( const char *word, xt_t *cache_xt, int nargs )
+{
+ static xt_t catch_xt = 0;
+ cell ret = -1;
+
+ if( !catch_xt )
+ catch_xt = findword("catch");
+ if( !*cache_xt )
+ *cache_xt = findword( (char*)word );
+
+ if( *cache_xt ) {
+ PUSH_xt( *cache_xt );
+ enterforth( catch_xt );
+ if( (ret=POP()) )
+ dstackcnt -= nargs;
+ }
+ return ret;
+}
+
+/* note: only the built-in dictionary is searched */
+int
+_fword( const char *word, xt_t *cache_xt )
+{
+ if( !*cache_xt )
+ *cache_xt = findword( (char*)word );
+
+ if( *cache_xt ) {
+ enterforth( *cache_xt );
+ return 0;
+ }
+ return -1;
+}
+
+int
+_selfword( const char *method, xt_t *cache_xt )
+{
+ if( !*cache_xt )
+ *cache_xt = find_ih_method( method, my_self() );
+ if( *cache_xt ) {
+ enterforth( *cache_xt );
+ return 0;
+ }
+ return -1;
+}
+
+int
+_parword( const char *method, xt_t *cache_xt )
+{
+ if( !*cache_xt )
+ *cache_xt = find_ih_method( method, my_parent() );
+ if( *cache_xt ) {
+ enterforth( *cache_xt );
+ return 0;
+ }
+ return -1;
+}
+
+void
+bind_func( const char *name, void (*func)(void) )
+{
+ PUSH( pointer2cell(func) );
+ push_str( name );
+ fword("is-cfunc");
+}
+
+void
+bind_xtfunc( const char *name, xt_t xt, ucell arg, void (*func)(void) )
+{
+ PUSH_xt( xt );
+ PUSH( arg );
+ PUSH( pointer2cell(func) );
+ push_str( name );
+ fword("is-xt-cfunc");
+}
+
+xt_t
+bind_noname_func( void (*func)(void) )
+{
+ PUSH( pointer2cell(func) );
+ fword("is-noname-cfunc");
+ return POP_xt();
+}
+
+void
+throw( int error )
+{
+ PUSH( error );
+ fword("throw");
+}
+
+
+/************************************************************************/
+/* ihandle related */
+/************************************************************************/
+
+phandle_t
+ih_to_phandle( ihandle_t ih )
+{
+ PUSH_ih( ih );
+ fword("ihandle>phandle");
+ return POP_ph();
+}
+
+ihandle_t
+my_parent( void )
+{
+ fword("my-parent");
+ return POP_ih();
+}
+
+ihandle_t
+my_self( void )
+{
+ fword("my-self");
+ return POP_ih();
+}
+
+xt_t
+find_package_method( const char *method, phandle_t ph )
+{
+ push_str( method );
+ PUSH_ph( ph );
+ fword("find-method");
+ if( POP() )
+ return POP_xt();
+ return 0;
+}
+
+xt_t
+find_ih_method( const char *method, ihandle_t ih )
+{
+ return find_package_method( method, ih_to_phandle(ih) );
+}
+
+
+xt_t
+find_parent_method( const char *method )
+{
+ return find_ih_method( method, my_parent() );
+}
+
+void
+call_package( xt_t xt, ihandle_t ihandle )
+{
+ PUSH_xt( xt );
+ PUSH_ih( ihandle );
+ fword("call-package");
+}
+
+void
+call_parent( xt_t xt )
+{
+ PUSH_xt( xt );
+ fword("call-parent");
+}
+
+void
+call_parent_method( const char *method )
+{
+ push_str( method );
+ fword("$call-parent");
+}
+
+
+/************************************************************************/
+/* open/close package/dev */
+/************************************************************************/
+
+ihandle_t
+open_dev( const char *spec )
+{
+ push_str( spec );
+ fword("open-dev");
+ return POP_ih();
+}
+
+void
+close_dev( ihandle_t ih )
+{
+ PUSH_ih( ih );
+ fword("close-dev");
+}
+
+ihandle_t
+open_package( const char *argstr, phandle_t ph )
+{
+ push_str( argstr );
+ PUSH_ph( ph );
+ fword("open-package");
+ return POP_ih();
+}
+
+void
+close_package( ihandle_t ih )
+{
+ PUSH_ih( ih );
+ fword("close-package");
+}
+
+
+/************************************************************************/
+/* ihandle arguments */
+/************************************************************************/
+
+char *
+pop_fstr_copy( void )
+{
+ int len = POP();
+ char *str, *p = (char*)cell2pointer(POP());
+ if( !len )
+ return NULL;
+ str = malloc( len + 1 );
+ if( !str )
+ return NULL;
+ memcpy( str, p, len );
+ str[len] = 0;
+ return str;
+}
+
+char *
+my_args_copy( void )
+{
+ fword("my-args");
+ return pop_fstr_copy();
+}
+
+
+/************************************************************************/
+/* properties */
+/************************************************************************/
+
+void
+set_property( phandle_t ph, const char *name, const char *buf, int len )
+{
+ if( !ph ) {
+ printk("set_property: NULL phandle\n");
+ return;
+ }
+ PUSH(pointer2cell(buf));
+ PUSH(len);
+ push_str( name );
+ PUSH_ph(ph);
+ fword("set-property");
+}
+
+void
+set_int_property( phandle_t ph, const char *name, u32 val )
+{
+ u32 swapped=__cpu_to_be32(val);
+ set_property( ph, name, (char*)&swapped, sizeof(swapped) );
+}
+
+char *
+get_property( phandle_t ph, const char *name, int *retlen )
+{
+ int len;
+
+ if( retlen )
+ *retlen = -1;
+
+ push_str( name );
+ PUSH_ph( ph );
+ fword("get-package-property");
+ if( POP() )
+ return NULL;
+ len = POP();
+ if( retlen )
+ *retlen = len;
+ return (char*)cell2pointer(POP());
+}
+
+u32
+get_int_property( phandle_t ph, const char *name, int *retlen )
+{
+ u32 *p;
+
+ if( !(p=(u32 *)get_property(ph, name, retlen)) )
+ return 0;
+ return __be32_to_cpu(*p);
+}
+
+
+/************************************************************************/
+/* device selection / iteration */
+/************************************************************************/
+
+void
+activate_dev( phandle_t ph )
+{
+ PUSH_ph( ph );
+ fword("active-package!");
+}
+
+phandle_t
+activate_device( const char *str )
+{
+ phandle_t ph = find_dev( str );
+ activate_dev( ph );
+ return ph;
+}
+
+void
+device_end( void )
+{
+ fword("device-end");
+}
+
+phandle_t
+get_cur_dev( void )
+{
+ fword("active-package");
+ return POP_ph();
+}
+
+phandle_t
+find_dev( const char *path )
+{
+ phandle_t ret = 0;
+ push_str( path );
+ fword("(find-dev)");
+ if( POP() )
+ return POP_ph();
+ return ret;
+}
+
+phandle_t
+dt_iter_begin( void )
+{
+ fword("iterate-tree-begin");
+ return POP_ph();
+}
+
+phandle_t
+dt_iterate( phandle_t last_tree )
+{
+ if( !last_tree )
+ return dt_iter_begin();
+
+ PUSH_ph( last_tree );
+ fword("iterate-tree");
+ return POP_ph();
+}
+
+phandle_t
+dt_iterate_type( phandle_t last_tree, const char *type )
+{
+ if( !last_tree )
+ last_tree = dt_iter_begin();
+
+ /* root node is never matched but we don't care about that */
+ while( (last_tree = dt_iterate(last_tree)) ) {
+ char *s = get_property( last_tree, "device_type", NULL );
+ if( s && !strcmp(type, s) )
+ break;
+ }
+ return last_tree;
+}
+
+
+/************************************************************************/
+/* node methods */
+/************************************************************************/
+
+void
+make_openable( int only_parents )
+{
+ phandle_t ph, save_ph = get_cur_dev();
+ PUSH_ph( save_ph );
+
+ for( ;; ) {
+ if( only_parents++ )
+ fword("parent");
+ if( !(ph=POP_ph()) )
+ break;
+ activate_dev( ph );
+ PUSH_ph( ph );
+ fword("is-open");
+ }
+ activate_dev( save_ph );
+}
+
+static void
+call1_func( void )
+{
+ void (*func)(cell v);
+ func = (void*)cell2pointer(POP());
+
+ (*func)( POP() );
+}
+
+
+static void
+add_methods( int flags, int size, const method_t *methods, int nmet )
+{
+ xt_t xt=0;
+ int i;
+
+ /* nodes might be matched multiple times */
+ if( find_package_method(methods[0].name, get_cur_dev()) )
+ return;
+
+ if( size ) {
+ PUSH( size );
+ fword("is-ibuf");
+ xt = POP_xt();
+ }
+
+ for( i=0; i<nmet; i++ ) {
+ /* null-name methods specify static initializers */
+ if( !methods[i].name ) {
+ typedef void (*initfunc)( void *p );
+ char *buf = NULL;
+ if( xt ) {
+ enterforth( xt );
+ buf = (char*)cell2pointer(POP());
+ }
+ (*(initfunc)methods[i].func)( buf );
+ continue;
+ }
+ if( !size )
+ bind_func( methods[i].name, methods[i].func );
+ else
+ bind_xtfunc( methods[i].name, xt, pointer2cell(methods[i].func),
+ &call1_func );
+ }
+
+ if( flags & INSTALL_OPEN )
+ make_openable(0);
+}
+
+void
+bind_node( int flags, int size, const char * const *paths, int npaths,
+ const method_t *methods, int nmet )
+{
+ phandle_t save_ph = get_cur_dev();
+ int i;
+
+ for( i=0; i<npaths; i++ ) {
+ const char *name = paths[i];
+
+ /* type matching? */
+ if( *name == 'T' ) {
+ phandle_t ph = 0;
+ name++;
+ while( (ph=dt_iterate_type(ph, name)) ) {
+ activate_dev( ph );
+ add_methods( flags, size, methods, nmet );
+ }
+ continue;
+ }
+
+ /* path patching */
+ if( activate_device(name) )
+ add_methods( flags, size, methods, nmet );
+ else if( *name == '+' ) {
+ /* create node (and missing parents) */
+ if( !activate_device(++name) ) {
+ push_str( name );
+ fword("create-node");
+ }
+ add_methods( flags, size, methods, nmet );
+ }
+ }
+ activate_dev( save_ph );
+}
+
+phandle_t
+bind_new_node( int flags, int size, const char *name,
+ const method_t *methods, int nmet )
+{
+ phandle_t save_ph = get_cur_dev();
+ phandle_t new_ph;
+ /* create node */
+ push_str( name );
+ fword("create-node");
+ add_methods( flags, size, methods, nmet );
+ new_ph = get_cur_dev();
+
+ activate_dev( save_ph );
+ return new_ph;
+}
diff --git a/roms/openbios/libopenbios/bootcode_load.c b/roms/openbios/libopenbios/bootcode_load.c
new file mode 100644
index 00000000..0fabf55c
--- /dev/null
+++ b/roms/openbios/libopenbios/bootcode_load.c
@@ -0,0 +1,99 @@
+/*
+ * Raw bootcode loader (CHRP/Apple %BOOT)
+ * Written by Mark Cave-Ayland 2013
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/bootcode_load.h"
+#include "libc/diskio.h"
+#include "drivers/drivers.h"
+#define printf printk
+#define debug printk
+
+
+int
+bootcode_load(ihandle_t dev)
+{
+ int retval = -1, count = 0, fd;
+ unsigned long bootcode, loadbase, entry, size, offset;
+ ihandle_t bootcode_info;
+
+ /* Mark the saved-program-state as invalid */
+ feval("0 state-valid !");
+
+ fd = open_ih(dev);
+ if (fd == -1) {
+ goto out;
+ }
+
+ /* If we don't have the get-bootcode-info word then we don't support
+ loading bootcode via %BOOT */
+ bootcode_info = find_ih_method("get-bootcode-info", dev);
+ if (!bootcode_info) {
+ goto out;
+ }
+
+ /* Default to loading at load-base */
+ fword("load-base");
+ loadbase = POP();
+ entry = loadbase;
+ size = 0;
+
+#ifdef CONFIG_PPC
+ /*
+ * Apple OF does not honor load-base and instead uses pmBootLoad
+ * value from the boot partition descriptor.
+ *
+ * Tested with:
+ * a debian image with QUIK installed
+ * a debian image with iQUIK installed (https://github.com/andreiw/quik)
+ * an IQUIK boot floppy
+ * a NetBSD boot floppy (boots stage 2)
+ */
+ if (is_apple()) {
+ PUSH(bootcode_info);
+ fword("execute");
+
+ loadbase = POP();
+ entry = POP();
+ size = POP();
+ }
+#endif
+
+ bootcode = loadbase;
+ offset = 0;
+
+ while(1) {
+ if (seek_io(fd, offset) == -1)
+ break;
+ count = read_io(fd, (void *)bootcode, 512);
+ offset += count;
+ bootcode += count;
+ }
+
+ /* If we didn't read anything then exit */
+ if (!count) {
+ goto out;
+ }
+
+ /* Use proper file size if we got it from bootcode info */
+ if (size == 0) {
+ size = offset;
+ }
+
+ /* Initialise saved-program-state */
+ PUSH(entry);
+ feval("saved-program-state >sps.entry !");
+ PUSH(size);
+ feval("saved-program-state >sps.file-size !");
+ feval("bootcode saved-program-state >sps.file-type !");
+
+ feval("-1 state-valid !");
+
+out:
+ close_io(fd);
+ return retval;
+}
+
diff --git a/roms/openbios/libopenbios/bootinfo_load.c b/roms/openbios/libopenbios/bootinfo_load.c
new file mode 100644
index 00000000..fa9e36bd
--- /dev/null
+++ b/roms/openbios/libopenbios/bootinfo_load.c
@@ -0,0 +1,263 @@
+/*
+ *
+ * <bootinfo_load.c>
+ *
+ * bootinfo file loader
+ *
+ * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
+ *
+ * Original XML parser by Blue Swirl <blauwirbel@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/bootinfo_load.h"
+#include "libopenbios/ofmem.h"
+#include "libc/vsprintf.h"
+
+//#define DEBUG_BOOTINFO
+
+#ifdef DEBUG_BOOTINFO
+#define DPRINTF(fmt, args...) \
+ do { printk("%s: " fmt, __func__ , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) \
+ do { } while (0)
+#endif
+
+static char *
+get_device( const char *path )
+{
+ int i;
+ static char buf[1024];
+
+ for (i = 0; i < sizeof(buf) && path[i] && path[i] != ':'; i++)
+ buf[i] = path[i];
+ buf[i] = 0;
+
+ return buf;
+}
+
+static char *
+get_partition( const char *path )
+{
+ static char buf[2];
+
+ buf[0] = '\0';
+ buf[1] = '\0';
+
+ while ( *path && *path != ':' )
+ path++;
+
+ if (!*path)
+ return buf;
+ path++;
+
+ if (path[0] == ',' || !strchr(path, ',')) /* if there is not a ',' or no partition id then return */
+ return buf;
+
+ /* Must be a partition id */
+ buf[0] = path[0];
+
+ return buf;
+}
+
+static char *
+get_filename( const char * path , char **dirname)
+{
+ static char buf[1024];
+ char *filename;
+
+ while ( *path && *path != ':' )
+ path++;
+
+ if (!*path) {
+ *dirname = NULL;
+ return NULL;
+ }
+ path++;
+
+ while ( *path && isdigit(*path) )
+ path++;
+
+ if (*path == ',')
+ path++;
+
+ strncpy(buf, path, sizeof(buf));
+ buf[sizeof(buf) - 1] = 0;
+
+ filename = strrchr(buf, '\\');
+ if (filename) {
+ *dirname = buf;
+ (*filename++) = 0;
+ } else {
+ *dirname = NULL;
+ filename = buf;
+ }
+
+ return filename;
+}
+
+int
+is_bootinfo(char *bootinfo)
+{
+ return (strncasecmp(bootinfo, "<chrp-boot", 10) ? 0 : -1);
+}
+
+int
+bootinfo_load(struct sys_info *info, const char *filename)
+{
+ // Currently not implemented
+ return LOADER_NOT_SUPPORT;
+}
+
+/*
+ Parse SGML structure like:
+ <chrp-boot>
+ <description>Debian/GNU Linux Installation on IBM CHRP hardware</description>
+ <os-name>Debian/GNU Linux for PowerPC</os-name>
+ <boot-script>boot &device;:\install\yaboot</boot-script>
+ <icon size=64,64 color-space=3,3,2>
+
+ CHRP system bindings are described at:
+ http://playground.sun.com/1275/bindings/chrp/chrp1_7a.ps
+*/
+
+void
+bootinfo_init_program(void)
+{
+ char *base;
+ int proplen;
+ phandle_t chosen;
+ int tag, taglen, script, scriptlen, scriptvalid, entity, chrp;
+ char tagbuf[128], c;
+ char *device, *filename, *directory, *partition;
+ int current, size;
+ char *bootscript;
+ char *tmp;
+ char bootpath[1024];
+
+ /* Parse the boot script */
+
+ chosen = find_dev("/chosen");
+ tmp = get_property(chosen, "bootpath", &proplen);
+ memcpy(bootpath, tmp, proplen);
+ bootpath[proplen] = 0;
+
+ DPRINTF("bootpath %s\n", bootpath);
+
+ device = get_device(bootpath);
+ partition = get_partition(bootpath);
+ filename = get_filename(bootpath, &directory);
+
+ feval("load-base");
+ base = (char*)cell2pointer(POP());
+
+ feval("load-size");
+ size = POP();
+
+ bootscript = malloc(size);
+ if (bootscript == NULL) {
+ DPRINTF("Can't malloc %d bytes\n", size);
+ return;
+ }
+
+ if (!is_bootinfo(base)) {
+ DPRINTF("Not a valid bootinfo memory image\n");
+ free(bootscript);
+ return;
+ }
+
+ chrp = 0;
+ tag = 0;
+ taglen = 0;
+ script = 0;
+ scriptvalid = 0;
+ scriptlen = 0;
+ entity = 0;
+ current = 0;
+ while (current < size) {
+
+ c = base[current++];
+
+ if (c == '<') {
+ script = 0;
+ tag = 1;
+ taglen = 0;
+ } else if (c == '>') {
+ tag = 0;
+ tagbuf[taglen] = '\0';
+ if (strncasecmp(tagbuf, "chrp-boot", 9) == 0) {
+ chrp = 1;
+ } else if (chrp == 1) {
+ if (strncasecmp(tagbuf, "boot-script", 11) == 0) {
+ script = 1;
+ scriptlen = 0;
+ } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) {
+
+ script = 0;
+ bootscript[scriptlen] = '\0';
+
+ DPRINTF("got bootscript %s\n",
+ bootscript);
+
+ scriptvalid = -1;
+
+ break;
+ } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0)
+ break;
+ }
+ } else if (tag && taglen < sizeof(tagbuf)) {
+ tagbuf[taglen++] = c;
+ } else if (script && c == '&') {
+ entity = 1;
+ taglen = 0;
+ } else if (entity && c ==';') {
+ entity = 0;
+ tagbuf[taglen] = '\0';
+ if (strncasecmp(tagbuf, "lt", 2) == 0) {
+ bootscript[scriptlen++] = '<';
+ } else if (strncasecmp(tagbuf, "gt", 2) == 0) {
+ bootscript[scriptlen++] = '>';
+ } else if (strncasecmp(tagbuf, "device", 6) == 0) {
+ strcpy(bootscript + scriptlen, device);
+ scriptlen += strlen(device);
+ } else if (strncasecmp(tagbuf, "partition", 9) == 0) {
+ strcpy(bootscript + scriptlen, partition);
+ scriptlen += strlen(partition);
+ } else if (strncasecmp(tagbuf, "directory", 9) == 0) {
+ strcpy(bootscript + scriptlen, directory);
+ scriptlen += strlen(directory);
+ } else if (strncasecmp(tagbuf, "filename", 8) == 0) {
+ strcpy(bootscript + scriptlen, filename);
+ scriptlen += strlen(filename);
+ } else if (strncasecmp(tagbuf, "full-path", 9) == 0) {
+ strcpy(bootscript + scriptlen, bootpath);
+ scriptlen += strlen(bootpath);
+ } else { /* unknown, keep it */
+ bootscript[scriptlen] = '&';
+ strcpy(bootscript + scriptlen + 1, tagbuf);
+ scriptlen += taglen + 1;
+ bootscript[scriptlen] = ';';
+ scriptlen++;
+ }
+ } else if (entity && taglen < sizeof(tagbuf)) {
+ tagbuf[taglen++] = c;
+ } else if (script && scriptlen < size) {
+ bootscript[scriptlen++] = c;
+ }
+ }
+
+ /* If the payload is bootinfo then we execute it immediately */
+ if (scriptvalid) {
+ DPRINTF("bootscript: %s\n", bootscript);
+ feval(bootscript);
+ }
+ else
+ DPRINTF("Unable to parse bootinfo bootscript\n");
+}
diff --git a/roms/openbios/libopenbios/build.xml b/roms/openbios/libopenbios/build.xml
new file mode 100644
index 00000000..feb8f6c7
--- /dev/null
+++ b/roms/openbios/libopenbios/build.xml
@@ -0,0 +1,31 @@
+<build>
+
+ <library name="openbios" type="static" target="target">
+ <object source="aout_load.c" condition="LOADER_AOUT"/>
+ <object source="bindings.c"/>
+ <object source="bootcode_load.c" condition="LOADER_BOOTCODE"/>
+ <object source="bootinfo_load.c" condition="LOADER_BOOTINFO"/>
+ <object source="client.c"/>
+ <object source="console.c"/>
+ <object source="elf_info.c" />
+ <object source="elf_load.c" condition="LOADER_ELF"/>
+ <object source="font_8x8.c" condition="FONT_8X8"/>
+ <object source="font_8x16.c" condition="FONT_8X16"/>
+ <object source="fcode_load.c" condition="LOADER_FCODE"/>
+ <object source="forth_load.c" condition="LOADER_FORTH"/>
+ <object source="init.c"/>
+ <object source="initprogram.c"/>
+ <object source="ipchecksum.c"/>
+ <object source="load.c"/>
+ <object source="linuxbios_info.c" condition="LINUXBIOS"/>
+ <object source="ofmem_common.c" condition="OFMEM"/>
+ <object source="xcoff_load.c" condition="LOADER_XCOFF"/>
+ <object source="video_common.c"/>
+ </library>
+
+ <dictionary name="openbios" target="forth">
+ <object source="clib.fs"/>
+ <object source="helpers.fs"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/libopenbios/clib.fs b/roms/openbios/libopenbios/clib.fs
new file mode 100644
index 00000000..04dd0aa4
--- /dev/null
+++ b/roms/openbios/libopenbios/clib.fs
@@ -0,0 +1,36 @@
+\ tag: C helpers
+\
+\ Misc C helpers
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ should perhaps be moved somewhere else
+: set-property ( buf len propname propname-len phandle -- )
+ >r 2swap encode-bytes 2swap r> encode-property
+;
+
+\ install C function
+: is-cfunc ( funcaddr word word-len -- )
+ $create , does> @ call
+;
+
+\ install a nameless C function
+: is-noname-cfunc ( funcaddr -- xt )
+ 0 0 is-cfunc last-xt
+;
+
+\ is-xt-cfunc installs a function which does the following:
+\ - xt is executes
+\ - funcarg is pushed
+\ - funcaddr is called
+
+: is-xt-cfunc ( xt|0 funcarg funcaddr word word-len -- )
+ is-func-begin
+ rot ?dup if , then
+ swap ['] (lit) , , ['] (lit) , , ['] call ,
+ is-func-end
+;
diff --git a/roms/openbios/libopenbios/client.c b/roms/openbios/libopenbios/client.c
new file mode 100644
index 00000000..8b3d582b
--- /dev/null
+++ b/roms/openbios/libopenbios/client.c
@@ -0,0 +1,367 @@
+/*
+ * Creation Date: <2003/11/25 14:29:08 samuel>
+ * Time-stamp: <2004/03/27 01:13:53 samuel>
+ *
+ * <client.c>
+ *
+ * OpenFirmware client interface
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/of.h"
+
+/* Uncomment to enable debug printout of client interface calls */
+//#define DEBUG_CIF
+//#define DUMP_IO
+
+/* OF client interface. r3 points to the argument array. On return,
+ * r3 should contain 0==true or -1==false. r4-r12,cr0,cr1 may
+ * be modified freely.
+ *
+ * -1 should only be returned if the control transfer to OF fails
+ * (it doesn't) or if the function is unimplemented.
+ */
+
+#define PROM_MAX_ARGS 10
+typedef struct prom_args {
+ prom_uarg_t service;
+ prom_arg_t nargs;
+ prom_arg_t nret;
+ prom_uarg_t args[PROM_MAX_ARGS];
+} __attribute__((packed)) prom_args_t;
+
+static inline const char *
+arg2pointer(prom_uarg_t value)
+{
+ return (char*)(uintptr_t)value;
+}
+
+static inline const char *
+get_service(prom_args_t *pb)
+{
+ return arg2pointer(pb->service);
+}
+
+#ifdef DEBUG_CIF
+static void memdump(const char *mem, unsigned long size)
+{
+ int i;
+
+ if (size == (unsigned long) -1)
+ return;
+
+ for (i = 0; i < size; i += 16) {
+ int j;
+
+ printk("0x%08lx ", (unsigned long)mem + i);
+
+ for (j = 0; j < 16 && i + j < size; j++)
+ printk(" %02x", *(unsigned char*)(mem + i + j));
+
+ for ( ; j < 16; j++)
+ printk(" __");
+
+ printk(" ");
+
+ for (j = 0; j < 16 && i + j < size; j++) {
+ unsigned char c = *(mem + i + j);
+ if (isprint(c))
+ printk("%c", c);
+ else
+ printk(".");
+ }
+ printk("\n");
+ }
+}
+
+static void dump_service(prom_args_t *pb)
+{
+ int i;
+ const char *service = get_service(pb);
+ if (strcmp(service, "test") == 0) {
+ printk("test(\"%s\") = ", arg2pointer(pb->args[0]));
+ } else if (strcmp(service, "peer") == 0) {
+ printk("peer(0x" FMT_prom_uargx ") = ", pb->args[0]);
+ } else if (strcmp(service, "child") == 0) {
+ printk("child(0x" FMT_prom_uargx ") = ", pb->args[0]);
+ } else if (strcmp(service, "parent") == 0) {
+ printk("parent(0x" FMT_prom_uargx ") = ", pb->args[0]);
+ } else if (strcmp(service, "instance-to-package") == 0) {
+ printk("instance-to-package(0x" FMT_prom_uargx ") = ", pb->args[0]);
+ } else if (strcmp(service, "getproplen") == 0) {
+ printk("getproplen(0x" FMT_prom_uargx ", \"%s\") = ",
+ pb->args[0], arg2pointer(pb->args[1]));
+ } else if (strcmp(service, "getprop") == 0) {
+ printk("getprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ",
+ pb->args[0], arg2pointer(pb->args[1]),
+ pb->args[2], pb->args[3]);
+ } else if (strcmp(service, "nextprop") == 0) {
+ printk("nextprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ") = ",
+ pb->args[0], arg2pointer(pb->args[1]), pb->args[2]);
+ } else if (strcmp(service, "setprop") == 0) {
+ printk("setprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n",
+ pb->args[0], arg2pointer(pb->args[1]),
+ pb->args[2], pb->args[3]);
+ memdump(arg2pointer(pb->args[2]), pb->args[3]);
+ printk(" = ");
+ } else if (strcmp(service, "canon") == 0) {
+ printk("canon(\"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n",
+ arg2pointer(pb->args[0]), pb->args[1], pb->args[2]);
+ } else if (strcmp(service, "finddevice") == 0) {
+ printk("finddevice(\"%s\") = ", arg2pointer(pb->args[0]));
+ } else if (strcmp(service, "instance-to-path") == 0) {
+ printk("instance-to-path(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ",
+ pb->args[0], pb->args[1], pb->args[2]);
+ } else if (strcmp(service, "package-to-path") == 0) {
+ printk("package-to-path(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ",
+ pb->args[0], pb->args[1], pb->args[2]);
+ } else if (strcmp(service, "open") == 0) {
+ printk("open(\"%s\") = ", arg2pointer(pb->args[0]));
+ } else if (strcmp(service, "close") == 0) {
+ printk("close(0x" FMT_prom_uargx ")\n", pb->args[0]);
+ } else if (strcmp(service, "read") == 0) {
+#ifdef DUMP_IO
+ printk("read(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ",
+ pb->args[0], pb->args[1], pb->args[2]);
+#endif
+ } else if (strcmp(service, "write") == 0) {
+#ifdef DUMP_IO
+ printk("write(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n",
+ pb->args[0], pb->args[1], pb->args[2]);
+ memdump(arg2pointer(pb->args[1]), pb->args[2]);
+ printk(" = ");
+#endif
+ } else if (strcmp(service, "seek") == 0) {
+#ifdef DUMP_IO
+ printk("seek(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ") = ",
+ pb->args[0], pb->args[1], pb->args[2]);
+#endif
+ } else if (strcmp(service, "claim") == 0) {
+ printk("claim(0x" FMT_prom_uargx ", " FMT_prom_arg ", " FMT_prom_arg ") = ",
+ pb->args[0], pb->args[1], pb->args[2]);
+ } else if (strcmp(service, "release") == 0) {
+ printk("release(0x" FMT_prom_uargx ", " FMT_prom_arg ")\n",
+ pb->args[0], pb->args[1]);
+ } else if (strcmp(service, "boot") == 0) {
+ printk("boot \"%s\"\n", arg2pointer(pb->args[0]));
+ } else if (strcmp(service, "enter") == 0) {
+ printk("enter()\n");
+ } else if (strcmp(service, "exit") == 0) {
+ printk("exit()\n");
+ } else if (strcmp(service, "test-method") == 0) {
+ printk("test-method(0x" FMT_prom_uargx ", \"%s\") = ",
+ pb->args[0], arg2pointer(pb->args[1]));
+ } else {
+ printk("of_client_interface: %s", service);
+ for( i = 0; i < pb->nargs; i++ )
+ printk(" " FMT_prom_uargx, pb->args[i]);
+ printk("\n");
+ }
+}
+
+static void dump_return(prom_args_t *pb)
+{
+ int i;
+ const char *service = get_service(pb);
+ if (strcmp(service, "test") == 0) {
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "peer") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "child") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "parent") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "instance-to-package") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "getproplen") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "getprop") == 0) {
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+ if ((prom_arg_t)pb->args[pb->nargs] != -1)
+ memdump(arg2pointer(pb->args[2]), MIN(pb->args[3], pb->args[pb->nargs]));
+ } else if (strcmp(service, "nextprop") == 0) {
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+ memdump(arg2pointer(pb->args[2]), 32);
+ } else if (strcmp(service, "setprop") == 0) {
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "canon") == 0) {
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+ memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]);
+ } else if (strcmp(service, "finddevice") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "instance-to-path") == 0) {
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+ memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]);
+ } else if (strcmp(service, "package-to-path") == 0) {
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+ memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]);
+ } else if (strcmp(service, "open") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "close") == 0) {
+ /* do nothing */
+ } else if (strcmp(service, "read") == 0) {
+#ifdef DUMP_IO
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+ memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]);
+#endif
+ } else if (strcmp(service, "write") == 0) {
+#ifdef DUMP_IO
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+#endif
+ } else if (strcmp(service, "seek") == 0) {
+#ifdef DUMP_IO
+ printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
+#endif
+ } else if (strcmp(service, "claim") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else if (strcmp(service, "release") == 0) {
+ /* do nothing */
+ } else if (strcmp(service, "boot") == 0) {
+ /* do nothing */
+ } else if (strcmp(service, "enter") == 0) {
+ /* do nothing */
+ } else if (strcmp(service, "exit") == 0) {
+ /* do nothing */
+ } else if (strcmp(service, "test-method") == 0) {
+ printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
+ } else {
+ printk("of_client_interface return:");
+ for (i = 0; i < pb->nret; i++) {
+ printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]);
+ }
+ printk("\n");
+ }
+}
+#endif
+
+/* call-method, interpret */
+static int
+handle_calls(prom_args_t *pb)
+{
+ int i, j, dstacksave;
+ ucell val;
+
+#ifdef DEBUG_CIF
+ printk("%s %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n",
+ get_service(pb), arg2pointer(pb->args[0]), pb->nargs, pb->nret);
+#endif
+
+ dstacksave = dstackcnt;
+ for (i = pb->nargs - 1; i >= 0; i--)
+ PUSH(pb->args[i]);
+
+ push_str(get_service(pb));
+ fword("client-call-iface");
+
+ /* Ignore client-call-iface return */
+ POP();
+
+ /* If the catch result is non-zero, restore stack and exit */
+ val = POP();
+ if (val) {
+ printk("%s %s failed with error " FMT_ucellx "\n", get_service(pb), arg2pointer(pb->args[0]), val);
+ dstackcnt = dstacksave;
+ return 0;
+ }
+
+ /* Store catch result */
+ pb->args[pb->nargs] = val;
+
+ j = dstackcnt;
+ for (i = 1; i < pb->nret; i++, j--) {
+ if (dstackcnt > dstacksave) {
+ pb->args[pb->nargs + i] = POP();
+ }
+ }
+
+#ifdef DEBUG_CIF
+ /* useful for debug but not necessarily an error */
+ if (j != dstacksave) {
+ printk("%s '%s': possible argument error (" FMT_prom_arg "--" FMT_prom_arg ") got %d\n",
+ get_service(pb), arg2pointer(pb->args[0]),
+ pb->nargs - 2, pb->nret, j - dstacksave);
+ }
+
+ printk("handle_calls return:");
+ for (i = 0; i < pb->nret; i++) {
+ printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]);
+ }
+ printk("\n");
+#endif
+
+ dstackcnt = dstacksave;
+ return 0;
+}
+
+int
+of_client_interface(int *params)
+{
+ prom_args_t *pb = (prom_args_t*)params;
+ ucell val;
+ int i, j, dstacksave;
+
+ if (pb->nargs < 0 || pb->nret < 0 ||
+ pb->nargs + pb->nret > PROM_MAX_ARGS)
+ return -1;
+
+#ifdef DEBUG_CIF
+ dump_service(pb);
+#endif
+
+ /* call-method exceptions are special */
+ if (!strcmp("call-method", get_service(pb)) || !strcmp("interpret", get_service(pb)))
+ return handle_calls(pb);
+
+ dstacksave = dstackcnt;
+ for (i = pb->nargs - 1; i >= 0; i--)
+ PUSH(pb->args[i]);
+
+ push_str(get_service(pb));
+ fword("client-iface");
+
+ val = POP();
+ if (val) {
+ if (val == -1) {
+ printk("Unimplemented service %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n",
+ get_service(pb), pb->nargs, pb->nret);
+ } else {
+#ifdef DEBUG_CIF
+ printk("Error calling client interface: " FMT_ucellx "\n", val);
+#endif
+ }
+
+ dstackcnt = dstacksave;
+ return -1;
+ }
+
+ j = dstackcnt;
+ for (i = 0; i < pb->nret; i++, j--) {
+ if (dstackcnt > dstacksave) {
+ pb->args[pb->nargs + i] = POP();
+ }
+ }
+
+#ifdef DEBUG_CIF
+ if (j != dstacksave) {
+ printk("service %s: possible argument error (%d %d)\n",
+ get_service(pb), i, j - dstacksave);
+
+ /* Some clients request less parameters than the CIF method
+ returns, e.g. getprop with OpenSolaris. Hence we drop any
+ stack parameters on exit after issuing a warning above */
+ }
+
+ dump_return(pb);
+#endif
+
+ dstackcnt = dstacksave;
+ return 0;
+}
diff --git a/roms/openbios/libopenbios/console.c b/roms/openbios/libopenbios/console.c
new file mode 100644
index 00000000..7f3aad8e
--- /dev/null
+++ b/roms/openbios/libopenbios/console.c
@@ -0,0 +1,68 @@
+/*
+ * <console.c>
+ *
+ * Simple text console
+ *
+ * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
+ * Copyright (C) 2013 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "drivers/drivers.h"
+
+/* ******************************************************************
+ * common functions, implementing simple concurrent console
+ * ****************************************************************** */
+
+/* Dummy routines for when console is unassigned */
+
+static int dummy_putchar(int c)
+{
+ return c;
+}
+
+static int dummy_availchar(void)
+{
+ return 0;
+}
+
+static int dummy_getchar(void)
+{
+ return 0;
+}
+
+struct _console_ops console_ops = {
+ .putchar = dummy_putchar,
+ .availchar = dummy_availchar,
+ .getchar = dummy_getchar
+};
+
+#ifdef CONFIG_DEBUG_CONSOLE
+
+void init_console(struct _console_ops ops)
+{
+ console_ops = ops;
+}
+
+int putchar(int c)
+{
+ return (*console_ops.putchar)(c);
+}
+
+int availchar(void)
+{
+ return (*console_ops.availchar)();
+}
+
+int getchar(void)
+{
+ return (*console_ops.getchar)();
+}
+#endif // CONFIG_DEBUG_CONSOLE
diff --git a/roms/openbios/libopenbios/elf_info.c b/roms/openbios/libopenbios/elf_info.c
new file mode 100644
index 00000000..f7febef9
--- /dev/null
+++ b/roms/openbios/libopenbios/elf_info.c
@@ -0,0 +1,151 @@
+/* Support for ELF Boot Proposal as a boot image */
+#include "config.h"
+#include "arch/common/elf_boot.h"
+#include "libopenbios/sys_info.h"
+#include "asm/io.h"
+#include "libopenbios/ipchecksum.h"
+#include "openbios-version.h"
+#define printf printk
+#define debug printk
+
+/* ELF image notes provide information to the loader who boots us */
+
+/* This compiles and generates correct PT_NOTE segment for me.
+ * If it doesn't, use assembly version below. */
+
+struct elf_image_note {
+ Elf_Nhdr hdr0;
+ char name0[sizeof(ELF_NOTE_BOOT)];
+ char prog_name[sizeof(PROGRAM_NAME)];
+
+ Elf_Nhdr hdr1;
+ char name1[sizeof(ELF_NOTE_BOOT)];
+ char version[sizeof(OPENBIOS_VERSION_STR)];
+
+ Elf_Nhdr hdr2;
+ char name2[sizeof(ELF_NOTE_BOOT)];
+ unsigned short checksum;
+};
+
+const struct elf_image_note elf_image_notes
+ __attribute__ ((section (".note.ELFBoot"))) =
+{
+ .hdr0 = {
+ .n_namesz = sizeof(ELF_NOTE_BOOT),
+ .n_descsz = sizeof(PROGRAM_NAME),
+ .n_type = EIN_PROGRAM_NAME,
+ },
+ .name0 = ELF_NOTE_BOOT,
+ .prog_name = PROGRAM_NAME,
+
+ .hdr1 = {
+ .n_namesz = sizeof(ELF_NOTE_BOOT),
+ .n_descsz = sizeof(OPENBIOS_VERSION_STR),
+ .n_type = EIN_PROGRAM_VERSION,
+ },
+ .name1 = ELF_NOTE_BOOT,
+ .version = OPENBIOS_VERSION_STR,
+
+ .hdr2 = {
+ .n_namesz = sizeof(ELF_NOTE_BOOT),
+ .n_descsz = sizeof(unsigned short),
+ .n_type = EIN_PROGRAM_CHECKSUM,
+ },
+ .name2 = ELF_NOTE_BOOT,
+ .checksum = 0, /* to be computed by external tool */
+};
+
+/* This is refered by other files */
+const char *program_name = elf_image_notes.prog_name;
+const char *program_version = elf_image_notes.version;
+
+#if 0
+
+ /* This tells the linker to make a PT_NOTE segment.
+ * If the section is named just ".note", it will be
+ * mixed up with useless .version notes generated by GCC.
+ */
+ .section ".note.ELFBoot", "a"
+
+ .align 4
+ .int 2f - 1f
+ .int 4f - 3f
+ .int EIN_PROGRAM_NAME
+1: .asciz "ELFBoot"
+2: .align 4
+3: .asciz PROGRAM_NAME
+4:
+
+ .align 4
+ .int 2f - 1f
+ .int 4f - 3f
+ .int EIN_PROGRAM_VERSION
+1: .asciz "ELFBoot"
+2: .align 4
+3: .asciz OPENBIOS_VERSION_STR
+4:
+
+ .align 4
+ .int 2f - 1f
+ .int 4f - 3f
+ .int EIN_PROGRAM_CHECKSUM
+1: .asciz "ELFBoot"
+2: .align 4
+3: .short 0
+4:
+#endif
+
+/* Collect information from the ELF bootloader
+ * Note that we have to copy them to our own memory,
+ * otherwise they might be overwritten afterward. */
+void collect_elfboot_info(struct sys_info *info)
+{
+ Elf_Bhdr *hdr = NULL;
+ char *addr, *end;
+ Elf_Nhdr *nhdr;
+ char *desc;
+
+ if (info->boot_type == ELF_BHDR_MAGIC)
+ hdr = phys_to_virt(info->boot_data);
+ else
+ hdr = phys_to_virt(info->boot_arg);
+
+ if (hdr->b_signature != ELF_BHDR_MAGIC)
+ return;
+
+ if (ipchksum(hdr, hdr->b_size) != 0) {
+ printf("Broken ELF boot notes\n");
+ return;
+ }
+
+ addr = (char *) (hdr + 1);
+ end = addr + hdr->b_size;
+ while (addr < end) {
+ nhdr = (Elf_Nhdr *) addr;
+ addr += sizeof(Elf_Nhdr);
+ addr += (nhdr->n_namesz + 3) & ~3;
+ desc = addr;
+ addr += (nhdr->n_descsz + 3) & ~3;
+
+ if (nhdr->n_namesz == 0) {
+ /* Standard notes */
+ switch (nhdr->n_type) {
+ case EBN_FIRMWARE_TYPE:
+ info->firmware = strdup(desc);
+ break;
+ case EBN_BOOTLOADER_NAME:
+ debug("Bootloader: %s\n", desc);
+ break;
+ case EBN_BOOTLOADER_VERSION:
+ debug("Version: %s\n", desc);
+ break;
+ case EBN_COMMAND_LINE:
+ info->command_line = strdup(desc);
+ break;
+ case EBN_LOADED_IMAGE:
+ debug("Image name: %s\n", desc);
+ break;
+ }
+ }
+ }
+}
diff --git a/roms/openbios/libopenbios/elf_load.c b/roms/openbios/libopenbios/elf_load.c
new file mode 100644
index 00000000..9c7850e1
--- /dev/null
+++ b/roms/openbios/libopenbios/elf_load.c
@@ -0,0 +1,537 @@
+/* ELF Boot loader
+ * As we have seek, this implementation can be straightforward.
+ * 2003-07 by SONE Takeshi
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libc/diskio.h"
+#include "arch/common/elf_boot.h"
+#include "libopenbios/elf_load.h"
+#include "libopenbios/sys_info.h"
+#include "libopenbios/ipchecksum.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/ofmem.h"
+#define printf printk
+#define debug printk
+
+#define DEBUG 0
+
+#define MAX_HEADERS 0x20
+#define BS 0x100 /* smallest step used when looking for the ELF header */
+
+#ifdef CONFIG_PPC
+extern void flush_icache_range( char *start, char *stop );
+#endif
+
+/* FreeBSD and possibly others mask the high 8 bits */
+#define addr_fixup(addr) ((addr) & 0x00ffffff)
+
+static char *image_name, *image_version;
+static int fd;
+
+/* Note: avoid name collision with platforms which have their own version of calloc() */
+static void *ob_calloc(size_t nmemb, size_t size)
+{
+ size_t alloc_size = nmemb * size;
+ void *mem;
+
+ if (alloc_size < nmemb || alloc_size < size) {
+ printf("calloc overflow: %u, %u\n", nmemb, size);
+ return NULL;
+ }
+
+ mem = malloc(alloc_size);
+ memset(mem, 0, alloc_size);
+
+ return mem;
+}
+
+static int check_mem_ranges(struct sys_info *info,
+ Elf_phdr *phdr, int phnum)
+{
+ int i, j;
+ unsigned long start, end;
+ unsigned long prog_start, prog_end;
+ struct memrange *mem;
+
+ prog_start = virt_to_phys(&_start);
+ prog_end = virt_to_phys(&_end);
+
+ for (i = 0; i < phnum; i++) {
+ if (phdr[i].p_type != PT_LOAD)
+ continue;
+ start = addr_fixup(phdr[i].p_paddr);
+ end = start + phdr[i].p_memsz;
+ if (start < prog_start && end > prog_start)
+ goto conflict;
+ if (start < prog_end && end > prog_end)
+ goto conflict;
+ mem=info->memrange;
+ for (j = 0; j < info->n_memranges; j++) {
+ if (mem[j].base <= start && mem[j].base + mem[j].size >= end)
+ break;
+ }
+ if (j >= info->n_memranges)
+ goto badseg;
+ }
+ return 1;
+
+conflict:
+ printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end);
+
+badseg:
+ printf("Segment %d [%#lx-%#lx] doesn't fit into memory\n", i, start, end-1);
+ return 0;
+}
+
+static unsigned long process_image_notes(Elf_phdr *phdr, int phnum,
+ unsigned short *sum_ptr,
+ unsigned int offset)
+{
+ int i;
+ char *buf = NULL;
+ int retval = 0;
+ unsigned long addr, end;
+ Elf_Nhdr *nhdr;
+ const char *name;
+ void *desc;
+
+ for (i = 0; i < phnum; i++) {
+ if (phdr[i].p_type != PT_NOTE)
+ continue;
+ buf = malloc(phdr[i].p_filesz);
+ seek_io(fd, offset + phdr[i].p_offset);
+ if ((size_t)read_io(fd, buf, phdr[i].p_filesz) != phdr[i].p_filesz) {
+ printf("Can't read note segment\n");
+ goto out;
+ }
+ addr = (unsigned long) buf;
+ end = addr + phdr[i].p_filesz;
+ while (addr < end) {
+ nhdr = (Elf_Nhdr *) addr;
+ addr += sizeof(Elf_Nhdr);
+ name = (const char *) addr;
+ addr += (nhdr->n_namesz+3) & ~3;
+ desc = (void *) addr;
+ addr += (nhdr->n_descsz+3) & ~3;
+
+ if (nhdr->n_namesz==sizeof(ELF_NOTE_BOOT)
+ && memcmp(name, ELF_NOTE_BOOT, sizeof(ELF_NOTE_BOOT))==0) {
+ if (nhdr->n_type == EIN_PROGRAM_NAME) {
+ image_name = ob_calloc(1, nhdr->n_descsz + 1);
+ memcpy(image_name, desc, nhdr->n_descsz);
+ }
+ if (nhdr->n_type == EIN_PROGRAM_VERSION) {
+ image_version = ob_calloc(1, nhdr->n_descsz + 1);
+ memcpy(image_version, desc, nhdr->n_descsz);
+ }
+ if (nhdr->n_type == EIN_PROGRAM_CHECKSUM) {
+ *sum_ptr = *(unsigned short *) desc;
+ debug("Image checksum: %#04x\n", *sum_ptr);
+ /* Where in the file */
+ retval = phdr[i].p_offset
+ + (unsigned long) desc - (unsigned long) buf;
+ }
+ }
+ }
+ }
+out:
+ close_io(fd);
+ if (buf)
+ free(buf);
+ return retval;
+}
+
+static int load_segments(Elf_phdr *phdr, int phnum,
+ unsigned long checksum_offset,
+ unsigned int offset, unsigned long *bytes)
+{
+ //unsigned int start_time, time;
+ int i;
+
+ *bytes = 0;
+ // start_time = currticks();
+ for (i = 0; i < phnum; i++) {
+ if (phdr[i].p_type != PT_LOAD)
+ continue;
+ debug("segment %d addr:" FMT_elf " file:" FMT_elf " mem:" FMT_elf " ",
+ i, addr_fixup(phdr[i].p_paddr), phdr[i].p_filesz, phdr[i].p_memsz);
+ seek_io(fd, offset + phdr[i].p_offset);
+ debug("loading... ");
+ if ((size_t)read_io(fd, phys_to_virt(addr_fixup(phdr[i].p_paddr)), phdr[i].p_filesz)
+ != phdr[i].p_filesz) {
+ printf("Can't read program segment %d\n", i);
+ return 0;
+ }
+ bytes += phdr[i].p_filesz;
+ debug("clearing... ");
+ memset(phys_to_virt(addr_fixup(phdr[i].p_paddr) + phdr[i].p_filesz), 0,
+ phdr[i].p_memsz - phdr[i].p_filesz);
+ if (phdr[i].p_offset <= checksum_offset
+ && phdr[i].p_offset + phdr[i].p_filesz >= checksum_offset+2) {
+ debug("clearing checksum... ");
+ memset(phys_to_virt(addr_fixup(phdr[i].p_paddr) + checksum_offset
+ - phdr[i].p_offset), 0, 2);
+ }
+ debug("ok\n");
+
+ }
+ // time = currticks() - start_time;
+ //debug("Loaded %lu bytes in %ums (%luKB/s)\n", bytes, time,
+ // time? bytes/time : 0);
+ debug("Loaded %lu bytes \n", *bytes);
+
+ return 1;
+}
+
+static int verify_image(Elf_ehdr *ehdr, Elf_phdr *phdr, int phnum,
+ unsigned short image_sum)
+{
+ unsigned short sum, part_sum;
+ unsigned long offset;
+ int i;
+
+ sum = 0;
+ offset = 0;
+
+ part_sum = ipchksum(ehdr, sizeof *ehdr);
+ sum = add_ipchksums(offset, sum, part_sum);
+ offset += sizeof *ehdr;
+
+ part_sum = ipchksum(phdr, phnum * sizeof(*phdr));
+ sum = add_ipchksums(offset, sum, part_sum);
+ offset += phnum * sizeof(*phdr);
+
+ for (i = 0; i < phnum; i++) {
+ if (phdr[i].p_type != PT_LOAD)
+ continue;
+ part_sum = ipchksum(phys_to_virt(addr_fixup(phdr[i].p_paddr)), phdr[i].p_memsz);
+ sum = add_ipchksums(offset, sum, part_sum);
+ offset += phdr[i].p_memsz;
+ }
+
+ if (sum != image_sum) {
+ printf("Verify FAILED (image:%#04x vs computed:%#04x)\n",
+ image_sum, sum);
+ return 0;
+ }
+ return 1;
+}
+
+static inline unsigned padded(unsigned s)
+{
+ return (s + 3) & ~3;
+}
+
+static Elf_Bhdr *add_boot_note(Elf_Bhdr *bhdr, const char *name,
+ unsigned type, const char *desc, unsigned descsz)
+{
+ Elf_Nhdr nhdr;
+ unsigned ent_size, new_size, pad;
+ char *addr;
+
+ if (!bhdr)
+ return NULL;
+
+ nhdr.n_namesz = name? strlen(name)+1 : 0;
+ nhdr.n_descsz = descsz;
+ nhdr.n_type = type;
+ ent_size = sizeof(nhdr) + padded(nhdr.n_namesz) + padded(nhdr.n_descsz);
+ if (bhdr->b_size + ent_size > 0xffff) {
+ printf("Boot notes too big\n");
+ free(bhdr);
+ return NULL;
+ }
+ if (bhdr->b_size + ent_size > bhdr->b_checksum) {
+ do {
+ new_size = bhdr->b_checksum * 2;
+ } while (new_size < bhdr->b_size + ent_size);
+ if (new_size > 0xffff)
+ new_size = 0xffff;
+ debug("expanding boot note size to %u\n", new_size);
+#ifdef HAVE_REALLOC
+ bhdr = realloc(bhdr, new_size);
+ bhdr->b_checksum = new_size;
+#else
+ printf("Boot notes too big\n");
+ free(bhdr);
+ return NULL;
+#endif
+ }
+
+ addr = (char *) bhdr;
+ addr += bhdr->b_size;
+ memcpy(addr, &nhdr, sizeof(nhdr));
+ addr += sizeof(nhdr);
+
+ if (name && nhdr.n_namesz) {
+ memcpy(addr, name, nhdr.n_namesz);
+ addr += nhdr.n_namesz;
+ pad = padded(nhdr.n_namesz) - nhdr.n_namesz;
+ memset(addr, 0, pad);
+ addr += pad;
+ }
+
+ memcpy(addr, desc, nhdr.n_descsz);
+ addr += nhdr.n_descsz;
+ pad = padded(nhdr.n_descsz) - nhdr.n_descsz;
+ memset(addr, 0, pad);
+
+ bhdr->b_size += ent_size;
+ bhdr->b_records++;
+ return bhdr;
+}
+
+static inline Elf_Bhdr *add_note_string(Elf_Bhdr *bhdr, const char *name,
+ unsigned type, const char *desc)
+{
+ return add_boot_note(bhdr, name, type, desc, strlen(desc) + 1);
+}
+
+static Elf_Bhdr *build_boot_notes(struct sys_info *info, const char *cmdline)
+{
+ Elf_Bhdr *bhdr;
+
+ bhdr = malloc(256);
+ bhdr->b_signature = ELF_BHDR_MAGIC;
+ bhdr->b_size = sizeof *bhdr;
+ bhdr->b_checksum = 256; /* XXX cache the current buffer size here */
+ bhdr->b_records = 0;
+
+ if (info->firmware)
+ bhdr = add_note_string(bhdr, NULL, EBN_FIRMWARE_TYPE, info->firmware);
+ bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_NAME, program_name);
+ bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_VERSION, program_version);
+ if (cmdline)
+ bhdr = add_note_string(bhdr, NULL, EBN_COMMAND_LINE, cmdline);
+ if (!bhdr)
+ return bhdr;
+ bhdr->b_checksum = 0;
+ bhdr->b_checksum = ipchksum(bhdr, bhdr->b_size);
+ return bhdr;
+}
+
+int
+is_elf(Elf_ehdr *ehdr)
+{
+ return (ehdr->e_ident[EI_MAG0] == ELFMAG0
+ && ehdr->e_ident[EI_MAG1] == ELFMAG1
+ && ehdr->e_ident[EI_MAG2] == ELFMAG2
+ && ehdr->e_ident[EI_MAG3] == ELFMAG3
+ && ehdr->e_ident[EI_CLASS] == ARCH_ELF_CLASS
+ && ehdr->e_ident[EI_DATA] == ARCH_ELF_DATA
+ && ehdr->e_ident[EI_VERSION] == EV_CURRENT
+ && ehdr->e_type == ET_EXEC
+ && ARCH_ELF_MACHINE_OK(ehdr->e_machine)
+ && ehdr->e_version == EV_CURRENT
+ && ehdr->e_phentsize == sizeof(Elf_phdr));
+}
+
+int
+find_elf(Elf_ehdr *ehdr)
+{
+ int offset;
+
+ for (offset = 0; offset < MAX_HEADERS * BS; offset += BS) {
+ if ((size_t)read_io(fd, ehdr, sizeof ehdr) != sizeof ehdr) {
+ debug("Can't read ELF header\n");
+ return 0;
+ }
+
+ if (is_elf(ehdr)) {
+ debug("Found ELF header at offset %d\n", offset);
+ return offset;
+ }
+
+ seek_io(fd, offset);
+ }
+
+ debug("Not a bootable ELF image\n");
+ return 0;
+}
+
+Elf_phdr *
+elf_readhdrs(int offset, Elf_ehdr *ehdr)
+{
+ unsigned long phdr_size;
+ Elf_phdr *phdr;
+
+ phdr_size = ehdr->e_phnum * sizeof(Elf_phdr);
+ phdr = malloc(phdr_size);
+ seek_io(fd, offset + ehdr->e_phoff);
+ if ((size_t)read_io(fd, phdr, phdr_size) != phdr_size) {
+ printf("Can't read program header\n");
+ return NULL;
+ }
+
+ return phdr;
+}
+
+int
+elf_load(struct sys_info *info, ihandle_t dev, const char *cmdline, void **boot_notes)
+{
+ Elf_ehdr ehdr;
+ Elf_phdr *phdr = NULL;
+ unsigned long checksum_offset, file_size;
+ unsigned short checksum = 0;
+ int retval = -1;
+ unsigned int offset;
+
+ image_name = image_version = NULL;
+
+ /* Mark the saved-program-state as invalid */
+ feval("0 state-valid !");
+
+ fd = open_ih(dev);
+ if (fd == -1) {
+ goto out;
+ }
+
+ offset = find_elf(&ehdr);
+ if (!offset) {
+ retval = LOADER_NOT_SUPPORT;
+ goto out;
+ }
+
+#if DEBUG
+ printk("ELF header:\n");
+ printk(" ehdr.e_type = %d\n", (int)ehdr.e_type);
+ printk(" ehdr.e_machine = %d\n", (int)ehdr.e_machine);
+ printk(" ehdr.e_version = %d\n", (int)ehdr.e_version);
+ printk(" ehdr.e_entry = 0x%08x\n", (int)ehdr.e_entry);
+ printk(" ehdr.e_phoff = 0x%08x\n", (int)ehdr.e_phoff);
+ printk(" ehdr.e_shoff = 0x%08x\n", (int)ehdr.e_shoff);
+ printk(" ehdr.e_flags = %d\n", (int)ehdr.e_flags);
+ printk(" ehdr.e_ehsize = 0x%08x\n", (int)ehdr.e_ehsize);
+ printk(" ehdr.e_phentsize = 0x%08x\n", (int)ehdr.e_phentsize);
+ printk(" ehdr.e_phnum = %d\n", (int)ehdr.e_phnum);
+#endif
+
+ if (ehdr.e_phnum > MAX_HEADERS) {
+ printk ("elfload: too many program headers (MAX_HEADERS)\n");
+ retval = 0;
+ goto out;
+ }
+
+ phdr = elf_readhdrs(offset, &ehdr);
+ if (!phdr)
+ goto out;
+
+ if (!check_mem_ranges(info, phdr, ehdr.e_phnum))
+ goto out;
+
+ checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum, offset);
+
+ printf("Loading %s", image_name ? image_name : "image");
+ if (image_version)
+ printf(" version %s", image_version);
+ printf("...\n");
+
+ if (!load_segments(phdr, ehdr.e_phnum, checksum_offset, offset, &file_size))
+ goto out;
+
+ if (checksum_offset) {
+ if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum))
+ goto out;
+ }
+
+ /* If we are attempting an ELF boot image, we pass a non-NULL pointer
+ into boot_notes and mark the image as elf-boot rather than standard
+ ELF */
+ if (boot_notes) {
+ *boot_notes = (void *)virt_to_phys(build_boot_notes(info, cmdline));
+ feval("elf-boot saved-program-state >sps.file-type !");
+ } else {
+ feval("elf saved-program-state >sps.file-type !");
+ }
+
+ //debug("current time: %lu\n", currticks());
+
+ debug("entry point is " FMT_elf "\n", addr_fixup(ehdr.e_entry));
+
+ // Initialise saved-program-state
+ PUSH(addr_fixup(ehdr.e_entry));
+ feval("saved-program-state >sps.entry !");
+ PUSH(file_size);
+ feval("saved-program-state >sps.file-size !");
+
+ feval("-1 state-valid !");
+
+out:
+ close_io(fd);
+ if (phdr)
+ free(phdr);
+ if (image_name)
+ free(image_name);
+ if (image_version)
+ free(image_version);
+ return retval;
+}
+
+void
+elf_init_program(void)
+{
+ char *base;
+ int i;
+ Elf_ehdr *ehdr;
+ Elf_phdr *phdr;
+ size_t size, total_size = 0;
+ char *addr;
+ uintptr_t tmp;
+
+ /* TODO: manage ELF notes section */
+ feval("0 state-valid !");
+ feval("load-base");
+ base = (char*)cell2pointer(POP());
+
+ ehdr = (Elf_ehdr *)base;
+
+ if (!is_elf(ehdr)) {
+ debug("Not a valid ELF memory image\n");
+ return;
+ }
+
+ phdr = (Elf_phdr *)(base + ehdr->e_phoff);
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+
+#if DEBUG
+ debug("filesz: %08lX memsz: %08lX p_offset: %08lX "
+ "p_vaddr %08lX\n",
+ (unsigned long)phdr[i].p_filesz, (unsigned long)phdr[i].p_memsz,
+ (unsigned long)phdr[i].p_offset, (unsigned long)phdr[i].p_vaddr );
+#endif
+
+ size = MIN(phdr[i].p_filesz, phdr[i].p_memsz);
+ if (!size)
+ continue;
+#if !defined(CONFIG_SPARC32) && !defined(CONFIG_X86)
+ if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 ) {
+ printk("Ignoring failed claim for va %lx memsz %lx!\n",
+ (unsigned long)phdr[i].p_vaddr,
+ (unsigned long)phdr[i].p_memsz);
+ }
+#endif
+ /* Workaround for archs where sizeof(int) != pointer size */
+ tmp = phdr[i].p_vaddr;
+ addr = (char *)tmp;
+
+ memcpy(addr, base + phdr[i].p_offset, size);
+
+ total_size += size;
+
+#ifdef CONFIG_PPC
+ flush_icache_range( addr, addr + size );
+#endif
+ }
+
+ // Initialise saved-program-state
+ PUSH(ehdr->e_entry);
+ feval("saved-program-state >sps.entry !");
+ PUSH(total_size);
+ feval("saved-program-state >sps.file-size !");
+ feval("elf saved-program-state >sps.file-type !");
+
+ feval("-1 state-valid !");
+}
diff --git a/roms/openbios/libopenbios/fcode_load.c b/roms/openbios/libopenbios/fcode_load.c
new file mode 100644
index 00000000..f4eb7bf3
--- /dev/null
+++ b/roms/openbios/libopenbios/fcode_load.c
@@ -0,0 +1,109 @@
+/*
+ * FCode boot loader
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/fcode_load.h"
+#include "libopenbios/sys_info.h"
+#include "libc/diskio.h"
+#define printf printk
+#define debug printk
+
+static int fd;
+
+int
+is_fcode(unsigned char *fcode)
+{
+ return (fcode[0] == 0xf0 // start0
+ || fcode[0] == 0xf1 // start1
+ || fcode[0] == 0xf2 // start2
+ || fcode[0] == 0xf3 // start4
+ || fcode[0] == 0xfd); // version1
+}
+
+int
+fcode_load(ihandle_t dev)
+{
+ int retval = -1;
+ uint8_t fcode_header[8];
+ unsigned long start, size;
+ unsigned int offset;
+
+ /* Mark the saved-program-state as invalid */
+ feval("0 state-valid !");
+
+ fd = open_ih(dev);
+ if (fd == -1) {
+ goto out;
+ }
+
+ for (offset = 0; offset < 16 * 512; offset += 512) {
+ seek_io(fd, offset);
+ if (read_io(fd, &fcode_header, sizeof(fcode_header))
+ != sizeof(fcode_header)) {
+ debug("Can't read FCode header from ihandle " FMT_ucellx "\n", dev);
+ retval = LOADER_NOT_SUPPORT;
+ goto out;
+ }
+
+ if (is_fcode(fcode_header))
+ goto found;
+ }
+
+ debug("Not a bootable FCode image\n");
+ retval = LOADER_NOT_SUPPORT;
+ goto out;
+
+ found:
+ size = (fcode_header[4] << 24) | (fcode_header[5] << 16) |
+ (fcode_header[6] << 8) | fcode_header[7];
+
+ fword("load-base");
+ start = POP();
+
+ printf("\nLoading FCode image...\n");
+
+ seek_io(fd, offset);
+
+ if ((size_t)read_io(fd, (void *)start, size) != size) {
+ printf("Can't read file (size 0x%lx)\n", size);
+ goto out;
+ }
+
+ debug("Loaded %lu bytes\n", size);
+ debug("entry point is %#lx\n", start);
+
+ // Initialise saved-program-state
+ PUSH(start);
+ feval("saved-program-state >sps.entry !");
+ PUSH(size);
+ feval("saved-program-state >sps.file-size !");
+ feval("fcode saved-program-state >sps.file-type !");
+
+ feval("-1 state-valid !");
+
+out:
+ close_io(fd);
+ return retval;
+}
+
+void
+fcode_init_program(void)
+{
+ /* If the payload is Fcode then we execute it immediately */
+ ucell address;
+
+ fword("load-base");
+ address = POP();
+
+ if (!is_fcode((unsigned char *)address)) {
+ debug("Not a valid Fcode memory image\n");
+ return;
+ }
+
+ PUSH(address);
+ PUSH(1);
+ fword("byte-load");
+}
diff --git a/roms/openbios/libopenbios/font_8x16.c b/roms/openbios/libopenbios/font_8x16.c
new file mode 100644
index 00000000..26c4e449
--- /dev/null
+++ b/roms/openbios/libopenbios/font_8x16.c
@@ -0,0 +1,4622 @@
+/**********************************************/
+/* */
+/* Font file generated by cpi2fnt */
+/* *
+ * *
+ * originally from the Linux distribution *
+ * *
+ **********************************************/
+
+#include "libopenbios/fontdata.h"
+
+const unsigned char fontdata_8x16[FONTDATAMAX_8X16] = {
+
+ /* 0 0x00 '^@' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 1 0x01 '^A' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x81, /* 10000001 */
+ 0xa5, /* 10100101 */
+ 0x81, /* 10000001 */
+ 0x81, /* 10000001 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0x81, /* 10000001 */
+ 0x81, /* 10000001 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 2 0x02 '^B' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xdb, /* 11011011 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 3 0x03 '^C' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 4 0x04 '^D' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 5 0x05 '^E' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0xe7, /* 11100111 */
+ 0xe7, /* 11100111 */
+ 0xe7, /* 11100111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 6 0x06 '^F' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 7 0x07 '^G' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 8 0x08 '^H' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xe7, /* 11100111 */
+ 0xc3, /* 11000011 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 9 0x09 '^I' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x42, /* 01000010 */
+ 0x42, /* 01000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 10 0x0a '^J' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0x99, /* 10011001 */
+ 0xbd, /* 10111101 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0xc3, /* 11000011 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 11 0x0b '^K' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1e, /* 00011110 */
+ 0x0e, /* 00001110 */
+ 0x1a, /* 00011010 */
+ 0x32, /* 00110010 */
+ 0x78, /* 01111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 12 0x0c '^L' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 13 0x0d '^M' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x33, /* 00110011 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x70, /* 01110000 */
+ 0xf0, /* 11110000 */
+ 0xe0, /* 11100000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 14 0x0e '^N' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x67, /* 01100111 */
+ 0xe7, /* 11100111 */
+ 0xe6, /* 11100110 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 15 0x0f '^O' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xdb, /* 11011011 */
+ 0x3c, /* 00111100 */
+ 0xe7, /* 11100111 */
+ 0x3c, /* 00111100 */
+ 0xdb, /* 11011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 16 0x10 '^P' */
+ 0x00, /* 00000000 */
+ 0x80, /* 10000000 */
+ 0xc0, /* 11000000 */
+ 0xe0, /* 11100000 */
+ 0xf0, /* 11110000 */
+ 0xf8, /* 11111000 */
+ 0xfe, /* 11111110 */
+ 0xf8, /* 11111000 */
+ 0xf0, /* 11110000 */
+ 0xe0, /* 11100000 */
+ 0xc0, /* 11000000 */
+ 0x80, /* 10000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 17 0x11 '^Q' */
+ 0x00, /* 00000000 */
+ 0x02, /* 00000010 */
+ 0x06, /* 00000110 */
+ 0x0e, /* 00001110 */
+ 0x1e, /* 00011110 */
+ 0x3e, /* 00111110 */
+ 0xfe, /* 11111110 */
+ 0x3e, /* 00111110 */
+ 0x1e, /* 00011110 */
+ 0x0e, /* 00001110 */
+ 0x06, /* 00000110 */
+ 0x02, /* 00000010 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 18 0x12 '^R' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 19 0x13 '^S' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 20 0x14 '^T' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7f, /* 01111111 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7b, /* 01111011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 21 0x15 '^U' */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x0c, /* 00001100 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 22 0x16 '^V' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 23 0x17 '^W' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 24 0x18 '^X' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 25 0x19 '^Y' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 26 0x1a '^Z' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 27 0x1b '^[' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xfe, /* 11111110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 28 0x1c '^\' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 29 0x1d '^]' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x28, /* 00101000 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x28, /* 00101000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 30 0x1e '^^' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 31 0x1f '^_' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 32 0x20 ' ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 33 0x21 '!' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 34 0x22 '"' */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x24, /* 00100100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 35 0x23 '#' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 36 0x24 '$' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc2, /* 11000010 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x86, /* 10000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 37 0x25 '%' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc2, /* 11000010 */
+ 0xc6, /* 11000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc6, /* 11000110 */
+ 0x86, /* 10000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 38 0x26 '&' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 39 0x27 ''' */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 40 0x28 '(' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 41 0x29 ')' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 42 0x2a '*' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0xff, /* 11111111 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 43 0x2b '+' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 44 0x2c ',' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 45 0x2d '-' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 46 0x2e '.' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 47 0x2f '/' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x02, /* 00000010 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0x80, /* 10000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 48 0x30 '0' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 49 0x31 '1' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x38, /* 00111000 */
+ 0x78, /* 01111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 50 0x32 '2' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 51 0x33 '3' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x3c, /* 00111100 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 52 0x34 '4' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x1c, /* 00011100 */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x1e, /* 00011110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 53 0x35 '5' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 54 0x36 '6' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 55 0x37 '7' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 56 0x38 '8' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 57 0x39 '9' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 58 0x3a ':' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 59 0x3b ';' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 60 0x3c '<' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 61 0x3d '=' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 62 0x3e '>' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 63 0x3f '?' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 64 0x40 '@' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xde, /* 11011110 */
+ 0xde, /* 11011110 */
+ 0xde, /* 11011110 */
+ 0xdc, /* 11011100 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 65 0x41 'A' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 66 0x42 'B' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xfc, /* 11111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 67 0x43 'C' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc2, /* 11000010 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc2, /* 11000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 68 0x44 'D' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 69 0x45 'E' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x66, /* 01100110 */
+ 0x62, /* 01100010 */
+ 0x68, /* 01101000 */
+ 0x78, /* 01111000 */
+ 0x68, /* 01101000 */
+ 0x60, /* 01100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 70 0x46 'F' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x66, /* 01100110 */
+ 0x62, /* 01100010 */
+ 0x68, /* 01101000 */
+ 0x78, /* 01111000 */
+ 0x68, /* 01101000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 71 0x47 'G' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc2, /* 11000010 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xde, /* 11011110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x66, /* 01100110 */
+ 0x3a, /* 00111010 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 72 0x48 'H' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 73 0x49 'I' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 74 0x4a 'J' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1e, /* 00011110 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 75 0x4b 'K' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xe6, /* 11100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x78, /* 01111000 */
+ 0x78, /* 01111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 76 0x4c 'L' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf0, /* 11110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 77 0x4d 'M' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xee, /* 11101110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 78 0x4e 'N' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xe6, /* 11100110 */
+ 0xf6, /* 11110110 */
+ 0xfe, /* 11111110 */
+ 0xde, /* 11011110 */
+ 0xce, /* 11001110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 79 0x4f 'O' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 80 0x50 'P' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 81 0x51 'Q' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xde, /* 11011110 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0x0e, /* 00001110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 82 0x52 'R' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 83 0x53 'S' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x38, /* 00111000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 84 0x54 'T' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x5a, /* 01011010 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 85 0x55 'U' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 86 0x56 'V' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 87 0x57 'W' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xfe, /* 11111110 */
+ 0xee, /* 11101110 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 88 0x58 'X' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 89 0x59 'Y' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 90 0x5a 'Z' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x86, /* 10000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc2, /* 11000010 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 91 0x5b '[' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 92 0x5c '\' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x80, /* 10000000 */
+ 0xc0, /* 11000000 */
+ 0xe0, /* 11100000 */
+ 0x70, /* 01110000 */
+ 0x38, /* 00111000 */
+ 0x1c, /* 00011100 */
+ 0x0e, /* 00001110 */
+ 0x06, /* 00000110 */
+ 0x02, /* 00000010 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 93 0x5d ']' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 94 0x5e '^' */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 95 0x5f '_' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 96 0x60 '`' */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 97 0x61 'a' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 98 0x62 'b' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x78, /* 01111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 99 0x63 'c' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 100 0x64 'd' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1c, /* 00011100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 101 0x65 'e' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 102 0x66 'f' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1c, /* 00011100 */
+ 0x36, /* 00110110 */
+ 0x32, /* 00110010 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 103 0x67 'g' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+
+ /* 104 0x68 'h' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x6c, /* 01101100 */
+ 0x76, /* 01110110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 105 0x69 'i' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 106 0x6a 'j' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x0e, /* 00001110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 107 0x6b 'k' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x78, /* 01111000 */
+ 0x78, /* 01111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 108 0x6c 'l' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 109 0x6d 'm' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xec, /* 11101100 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 110 0x6e 'n' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 111 0x6f 'o' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 112 0x70 'p' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+
+ /* 113 0x71 'q' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x1e, /* 00011110 */
+ 0x00, /* 00000000 */
+
+ /* 114 0x72 'r' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x76, /* 01110110 */
+ 0x66, /* 01100110 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 115 0x73 's' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x38, /* 00111000 */
+ 0x0c, /* 00001100 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 116 0x74 't' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0xfc, /* 11111100 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x36, /* 00110110 */
+ 0x1c, /* 00011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 117 0x75 'u' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 118 0x76 'v' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 119 0x77 'w' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 120 0x78 'x' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 121 0x79 'y' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+
+ /* 122 0x7a 'z' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xcc, /* 11001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 123 0x7b '{' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0e, /* 00001110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 124 0x7c '|' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 125 0x7d '}' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x70, /* 01110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 126 0x7e '~' */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 127 0x7f '' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 128 0x80 '€' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc2, /* 11000010 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc2, /* 11000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 129 0x81 '' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 130 0x82 '‚' */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 131 0x83 'ƒ' */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 132 0x84 '„' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 133 0x85 '…' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 134 0x86 '†' */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 135 0x87 '‡' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 136 0x88 'ˆ' */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 137 0x89 '‰' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 138 0x8a 'Š' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 139 0x8b '‹' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 140 0x8c 'Œ' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 141 0x8d '' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 142 0x8e 'Ž' */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 143 0x8f '' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 144 0x90 '' */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x66, /* 01100110 */
+ 0x62, /* 01100010 */
+ 0x68, /* 01101000 */
+ 0x78, /* 01111000 */
+ 0x68, /* 01101000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 145 0x91 '‘' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xec, /* 11101100 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x7e, /* 01111110 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x6e, /* 01101110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 146 0x92 '’' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3e, /* 00111110 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xfe, /* 11111110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xce, /* 11001110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 147 0x93 '“' */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 148 0x94 '”' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 149 0x95 '•' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 150 0x96 '–' */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 151 0x97 '—' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 152 0x98 '˜' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+
+ /* 153 0x99 '™' */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 154 0x9a 'š' */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 155 0x9b '›' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 156 0x9c 'œ' */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x64, /* 01100100 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xe6, /* 11100110 */
+ 0xfc, /* 11111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 157 0x9d '' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 158 0x9e 'ž' */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xf8, /* 11111000 */
+ 0xc4, /* 11000100 */
+ 0xcc, /* 11001100 */
+ 0xde, /* 11011110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 159 0x9f 'Ÿ' */
+ 0x00, /* 00000000 */
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 160 0xa0 ' ' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 161 0xa1 '¡' */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 162 0xa2 '¢' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 163 0xa3 '£' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 164 0xa4 '¤' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 165 0xa5 '¥' */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xe6, /* 11100110 */
+ 0xf6, /* 11110110 */
+ 0xfe, /* 11111110 */
+ 0xde, /* 11011110 */
+ 0xce, /* 11001110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 166 0xa6 '¦' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x3e, /* 00111110 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 167 0xa7 '§' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 168 0xa8 '¨' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 169 0xa9 '©' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 170 0xaa 'ª' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 171 0xab '«' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0xe0, /* 11100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xdc, /* 11011100 */
+ 0x86, /* 10000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x3e, /* 00111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 172 0xac '¬' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0xe0, /* 11100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x66, /* 01100110 */
+ 0xce, /* 11001110 */
+ 0x9a, /* 10011010 */
+ 0x3f, /* 00111111 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 173 0xad '­' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 174 0xae '®' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x36, /* 00110110 */
+ 0x6c, /* 01101100 */
+ 0xd8, /* 11011000 */
+ 0x6c, /* 01101100 */
+ 0x36, /* 00110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 175 0xaf '¯' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xd8, /* 11011000 */
+ 0x6c, /* 01101100 */
+ 0x36, /* 00110110 */
+ 0x6c, /* 01101100 */
+ 0xd8, /* 11011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 176 0xb0 '°' */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+
+ /* 177 0xb1 '±' */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+
+ /* 178 0xb2 '²' */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+
+ /* 179 0xb3 '³' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 180 0xb4 '´' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 181 0xb5 'µ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 182 0xb6 '¶' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 183 0xb7 '·' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 184 0xb8 '¸' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 185 0xb9 '¹' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x06, /* 00000110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 186 0xba 'º' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 187 0xbb '»' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 188 0xbc '¼' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x06, /* 00000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 189 0xbd '½' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 190 0xbe '¾' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 191 0xbf '¿' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 192 0xc0 'À' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 193 0xc1 'Á' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 194 0xc2 'Â' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 195 0xc3 'Ã' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 196 0xc4 'Ä' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 197 0xc5 'Å' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 198 0xc6 'Æ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 199 0xc7 'Ç' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 200 0xc8 'È' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x30, /* 00110000 */
+ 0x3f, /* 00111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 201 0xc9 'É' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 202 0xca 'Ê' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf7, /* 11110111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 203 0xcb 'Ë' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xf7, /* 11110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 204 0xcc 'Ì' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x30, /* 00110000 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 205 0xcd 'Í' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 206 0xce 'Î' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf7, /* 11110111 */
+ 0x00, /* 00000000 */
+ 0xf7, /* 11110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 207 0xcf 'Ï' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 208 0xd0 'Ð' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 209 0xd1 'Ñ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 210 0xd2 'Ò' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 211 0xd3 'Ó' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x3f, /* 00111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 212 0xd4 'Ô' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 213 0xd5 'Õ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 214 0xd6 'Ö' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 215 0xd7 '×' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xff, /* 11111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 216 0xd8 'Ø' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 217 0xd9 'Ù' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 218 0xda 'Ú' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 219 0xdb 'Û' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 220 0xdc 'Ü' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 221 0xdd 'Ý' */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+
+ /* 222 0xde 'Þ' */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+
+ /* 223 0xdf 'ß' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 224 0xe0 'à' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xdc, /* 11011100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 225 0xe1 'á' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xd8, /* 11011000 */
+ 0xcc, /* 11001100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 226 0xe2 'â' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 227 0xe3 'ã' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 228 0xe4 'ä' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 229 0xe5 'å' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 230 0xe6 'æ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+
+ /* 231 0xe7 'ç' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 232 0xe8 'è' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 233 0xe9 'é' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 234 0xea 'ê' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xee, /* 11101110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 235 0xeb 'ë' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1e, /* 00011110 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x3e, /* 00111110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 236 0xec 'ì' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 237 0xed 'í' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x03, /* 00000011 */
+ 0x06, /* 00000110 */
+ 0x7e, /* 01111110 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0xf3, /* 11110011 */
+ 0x7e, /* 01111110 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 238 0xee 'î' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1c, /* 00011100 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x1c, /* 00011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 239 0xef 'ï' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 240 0xf0 'ð' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 241 0xf1 'ñ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 242 0xf2 'ò' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 243 0xf3 'ó' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 244 0xf4 'ô' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 245 0xf5 'õ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 246 0xf6 'ö' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 247 0xf7 '÷' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 248 0xf8 'ø' */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 249 0xf9 'ù' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 250 0xfa 'ú' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 251 0xfb 'û' */
+ 0x00, /* 00000000 */
+ 0x0f, /* 00001111 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0xec, /* 11101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x3c, /* 00111100 */
+ 0x1c, /* 00011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 252 0xfc 'ü' */
+ 0x00, /* 00000000 */
+ 0x6c, /* 01101100 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 253 0xfd 'ý' */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x32, /* 00110010 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 254 0xfe 'þ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 255 0xff 'ÿ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+};
diff --git a/roms/openbios/libopenbios/font_8x8.c b/roms/openbios/libopenbios/font_8x8.c
new file mode 100644
index 00000000..861929ea
--- /dev/null
+++ b/roms/openbios/libopenbios/font_8x8.c
@@ -0,0 +1,2571 @@
+/**********************************************/
+/* */
+/* Font file generated by cpi2fnt */
+/* */
+/**********************************************/
+
+#include "libopenbios/fontdata.h"
+
+const unsigned char fontdata_8x8[FONTDATAMAX_8X8] = {
+
+ /* 0 0x00 '^@' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 1 0x01 '^A' */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+
+ /* 2 0x02 '^B' */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 3 0x03 '^C' */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+
+ /* 4 0x04 '^D' */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+
+ /* 5 0x05 '^E' */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+
+ /* 6 0x06 '^F' */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+
+ /* 7 0x07 '^G' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 8 0x08 '^H' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xe7, /* 11100111 */
+ 0xc3, /* 11000011 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 9 0x09 '^I' */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x42, /* 01000010 */
+ 0x42, /* 01000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 10 0x0a '^J' */
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0x99, /* 10011001 */
+ 0xbd, /* 10111101 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0xc3, /* 11000011 */
+ 0xff, /* 11111111 */
+
+ /* 11 0x0b '^K' */
+ 0x0f, /* 00001111 */
+ 0x07, /* 00000111 */
+ 0x0f, /* 00001111 */
+ 0x7d, /* 01111101 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+
+ /* 12 0x0c '^L' */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+
+ /* 13 0x0d '^M' */
+ 0x3f, /* 00111111 */
+ 0x33, /* 00110011 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x70, /* 01110000 */
+ 0xf0, /* 11110000 */
+ 0xe0, /* 11100000 */
+
+ /* 14 0x0e '^N' */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x67, /* 01100111 */
+ 0xe6, /* 11100110 */
+ 0xc0, /* 11000000 */
+
+ /* 15 0x0f '^O' */
+ 0x18, /* 00011000 */
+ 0xdb, /* 11011011 */
+ 0x3c, /* 00111100 */
+ 0xe7, /* 11100111 */
+ 0xe7, /* 11100111 */
+ 0x3c, /* 00111100 */
+ 0xdb, /* 11011011 */
+ 0x18, /* 00011000 */
+
+ /* 16 0x10 '^P' */
+ 0x80, /* 10000000 */
+ 0xe0, /* 11100000 */
+ 0xf8, /* 11111000 */
+ 0xfe, /* 11111110 */
+ 0xf8, /* 11111000 */
+ 0xe0, /* 11100000 */
+ 0x80, /* 10000000 */
+ 0x00, /* 00000000 */
+
+ /* 17 0x11 '^Q' */
+ 0x02, /* 00000010 */
+ 0x0e, /* 00001110 */
+ 0x3e, /* 00111110 */
+ 0xfe, /* 11111110 */
+ 0x3e, /* 00111110 */
+ 0x0e, /* 00001110 */
+ 0x02, /* 00000010 */
+ 0x00, /* 00000000 */
+
+ /* 18 0x12 '^R' */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+
+ /* 19 0x13 '^S' */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+
+ /* 20 0x14 '^T' */
+ 0x7f, /* 01111111 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7b, /* 01111011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x00, /* 00000000 */
+
+ /* 21 0x15 '^U' */
+ 0x3e, /* 00111110 */
+ 0x61, /* 01100001 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x86, /* 10000110 */
+ 0x7c, /* 01111100 */
+
+ /* 22 0x16 '^V' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+
+ /* 23 0x17 '^W' */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+
+ /* 24 0x18 '^X' */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 25 0x19 '^Y' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 26 0x1a '^Z' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 27 0x1b '^[' */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xfe, /* 11111110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 28 0x1c '^\' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 29 0x1d '^]' */
+ 0x00, /* 00000000 */
+ 0x24, /* 00100100 */
+ 0x66, /* 01100110 */
+ 0xff, /* 11111111 */
+ 0x66, /* 01100110 */
+ 0x24, /* 00100100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 30 0x1e '^^' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 31 0x1f '^_' */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 32 0x20 ' ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 33 0x21 '!' */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 34 0x22 '"' */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x24, /* 00100100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 35 0x23 '#' */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+
+ /* 36 0x24 '$' */
+ 0x18, /* 00011000 */
+ 0x3e, /* 00111110 */
+ 0x60, /* 01100000 */
+ 0x3c, /* 00111100 */
+ 0x06, /* 00000110 */
+ 0x7c, /* 01111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 37 0x25 '%' */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xcc, /* 11001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x66, /* 01100110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 38 0x26 '&' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 39 0x27 ''' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 40 0x28 '(' */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+
+ /* 41 0x29 ')' */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+
+ /* 42 0x2a '*' */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0xff, /* 11111111 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 43 0x2b '+' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 44 0x2c ',' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+
+ /* 45 0x2d '-' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 46 0x2e '.' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 47 0x2f '/' */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0x80, /* 10000000 */
+ 0x00, /* 00000000 */
+
+ /* 48 0x30 '0' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+
+ /* 49 0x31 '1' */
+ 0x18, /* 00011000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+
+ /* 50 0x32 '2' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x1c, /* 00011100 */
+ 0x30, /* 00110000 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+
+ /* 51 0x33 '3' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x3c, /* 00111100 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 52 0x34 '4' */
+ 0x1c, /* 00011100 */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x1e, /* 00011110 */
+ 0x00, /* 00000000 */
+
+ /* 53 0x35 '5' */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 54 0x36 '6' */
+ 0x38, /* 00111000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 55 0x37 '7' */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+
+ /* 56 0x38 '8' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 57 0x39 '9' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+
+ /* 58 0x3a ':' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 59 0x3b ';' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+
+ /* 60 0x3c '<' */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+
+ /* 61 0x3d '=' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 62 0x3e '>' */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+
+ /* 63 0x3f '?' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 64 0x40 '@' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xde, /* 11011110 */
+ 0xde, /* 11011110 */
+ 0xde, /* 11011110 */
+ 0xc0, /* 11000000 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+
+ /* 65 0x41 'A' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 66 0x42 'B' */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xfc, /* 11111100 */
+ 0x00, /* 00000000 */
+
+ /* 67 0x43 'C' */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 68 0x44 'D' */
+ 0xf8, /* 11111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+
+ /* 69 0x45 'E' */
+ 0xfe, /* 11111110 */
+ 0x62, /* 01100010 */
+ 0x68, /* 01101000 */
+ 0x78, /* 01111000 */
+ 0x68, /* 01101000 */
+ 0x62, /* 01100010 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+
+ /* 70 0x46 'F' */
+ 0xfe, /* 11111110 */
+ 0x62, /* 01100010 */
+ 0x68, /* 01101000 */
+ 0x78, /* 01111000 */
+ 0x68, /* 01101000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+
+ /* 71 0x47 'G' */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xce, /* 11001110 */
+ 0x66, /* 01100110 */
+ 0x3a, /* 00111010 */
+ 0x00, /* 00000000 */
+
+ /* 72 0x48 'H' */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 73 0x49 'I' */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 74 0x4a 'J' */
+ 0x1e, /* 00011110 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+
+ /* 75 0x4b 'K' */
+ 0xe6, /* 11100110 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x78, /* 01111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+
+ /* 76 0x4c 'L' */
+ 0xf0, /* 11110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+
+ /* 77 0x4d 'M' */
+ 0xc6, /* 11000110 */
+ 0xee, /* 11101110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 78 0x4e 'N' */
+ 0xc6, /* 11000110 */
+ 0xe6, /* 11100110 */
+ 0xf6, /* 11110110 */
+ 0xde, /* 11011110 */
+ 0xce, /* 11001110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 79 0x4f 'O' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 80 0x50 'P' */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+
+ /* 81 0x51 'Q' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xce, /* 11001110 */
+ 0x7c, /* 01111100 */
+ 0x0e, /* 00001110 */
+
+ /* 82 0x52 'R' */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+
+ /* 83 0x53 'S' */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 84 0x54 'T' */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x5a, /* 01011010 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 85 0x55 'U' */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 86 0x56 'V' */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+
+ /* 87 0x57 'W' */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+
+ /* 88 0x58 'X' */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 89 0x59 'Y' */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 90 0x5a 'Z' */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x8c, /* 10001100 */
+ 0x18, /* 00011000 */
+ 0x32, /* 00110010 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+
+ /* 91 0x5b '[' */
+ 0x3c, /* 00111100 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 92 0x5c '\' */
+ 0xc0, /* 11000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x02, /* 00000010 */
+ 0x00, /* 00000000 */
+
+ /* 93 0x5d ']' */
+ 0x3c, /* 00111100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 94 0x5e '^' */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 95 0x5f '_' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+
+ /* 96 0x60 '`' */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 97 0x61 'a' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 98 0x62 'b' */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x7c, /* 01111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+
+ /* 99 0x63 'c' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 100 0x64 'd' */
+ 0x1c, /* 00011100 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 101 0x65 'e' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 102 0x66 'f' */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x60, /* 01100000 */
+ 0xf8, /* 11111000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+
+ /* 103 0x67 'g' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0xf8, /* 11111000 */
+
+ /* 104 0x68 'h' */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x6c, /* 01101100 */
+ 0x76, /* 01110110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+
+ /* 105 0x69 'i' */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 106 0x6a 'j' */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+
+ /* 107 0x6b 'k' */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x78, /* 01111000 */
+ 0x6c, /* 01101100 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+
+ /* 108 0x6c 'l' */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 109 0x6d 'm' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xec, /* 11101100 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0x00, /* 00000000 */
+
+ /* 110 0x6e 'n' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+
+ /* 111 0x6f 'o' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 112 0x70 'p' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+
+ /* 113 0x71 'q' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0x1e, /* 00011110 */
+
+ /* 114 0x72 'r' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x76, /* 01110110 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+
+ /* 115 0x73 's' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x06, /* 00000110 */
+ 0xfc, /* 11111100 */
+ 0x00, /* 00000000 */
+
+ /* 116 0x74 't' */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0xfc, /* 11111100 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x36, /* 00110110 */
+ 0x1c, /* 00011100 */
+ 0x00, /* 00000000 */
+
+ /* 117 0x75 'u' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 118 0x76 'v' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+
+ /* 119 0x77 'w' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+
+ /* 120 0x78 'x' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 121 0x79 'y' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0xfc, /* 11111100 */
+
+ /* 122 0x7a 'z' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x4c, /* 01001100 */
+ 0x18, /* 00011000 */
+ 0x32, /* 00110010 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+
+ /* 123 0x7b '{' */
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0e, /* 00001110 */
+ 0x00, /* 00000000 */
+
+ /* 124 0x7c '|' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 125 0x7d '}' */
+ 0x70, /* 01110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+
+ /* 126 0x7e '~' */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 127 0x7f '' */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+
+ /* 128 0x80 '€' */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0x78, /* 01111000 */
+
+ /* 129 0x81 '' */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 130 0x82 '‚' */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 131 0x83 'ƒ' */
+ 0x7c, /* 01111100 */
+ 0x82, /* 10000010 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 132 0x84 '„' */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 133 0x85 '…' */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 134 0x86 '†' */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 135 0x87 '‡' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x7e, /* 01111110 */
+ 0x0c, /* 00001100 */
+ 0x38, /* 00111000 */
+
+ /* 136 0x88 'ˆ' */
+ 0x7c, /* 01111100 */
+ 0x82, /* 10000010 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 137 0x89 '‰' */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 138 0x8a 'Š' */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 139 0x8b '‹' */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 140 0x8c 'Œ' */
+ 0x7c, /* 01111100 */
+ 0x82, /* 10000010 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 141 0x8d '' */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 142 0x8e 'Ž' */
+ 0xc6, /* 11000110 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 143 0x8f '' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 144 0x90 '' */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xf8, /* 11111000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+
+ /* 145 0x91 '‘' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0xd8, /* 11011000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+
+ /* 146 0x92 '’' */
+ 0x3e, /* 00111110 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xfe, /* 11111110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xce, /* 11001110 */
+ 0x00, /* 00000000 */
+
+ /* 147 0x93 '“' */
+ 0x7c, /* 01111100 */
+ 0x82, /* 10000010 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 148 0x94 '”' */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 149 0x95 '•' */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 150 0x96 '–' */
+ 0x78, /* 01111000 */
+ 0x84, /* 10000100 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 151 0x97 '—' */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 152 0x98 '˜' */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0xfc, /* 11111100 */
+
+ /* 153 0x99 '™' */
+ 0xc6, /* 11000110 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+
+ /* 154 0x9a 'š' */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 155 0x9b '›' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 156 0x9c 'œ' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x64, /* 01100100 */
+ 0xf0, /* 11110000 */
+ 0x60, /* 01100000 */
+ 0x66, /* 01100110 */
+ 0xfc, /* 11111100 */
+ 0x00, /* 00000000 */
+
+ /* 157 0x9d '' */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 158 0x9e 'ž' */
+ 0xf8, /* 11111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xfa, /* 11111010 */
+ 0xc6, /* 11000110 */
+ 0xcf, /* 11001111 */
+ 0xc6, /* 11000110 */
+ 0xc7, /* 11000111 */
+
+ /* 159 0x9f 'Ÿ' */
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+
+ /* 160 0xa0 ' ' */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 161 0xa1 '¡' */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 162 0xa2 '¢' */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+
+ /* 163 0xa3 '£' */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 164 0xa4 '¤' */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+
+ /* 165 0xa5 '¥' */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0xe6, /* 11100110 */
+ 0xf6, /* 11110110 */
+ 0xde, /* 11011110 */
+ 0xce, /* 11001110 */
+ 0x00, /* 00000000 */
+
+ /* 166 0xa6 '¦' */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x3e, /* 00111110 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 167 0xa7 '§' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 168 0xa8 '¨' */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x63, /* 01100011 */
+ 0x3e, /* 00111110 */
+ 0x00, /* 00000000 */
+
+ /* 169 0xa9 '©' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 170 0xaa 'ª' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 171 0xab '«' */
+ 0x63, /* 01100011 */
+ 0xe6, /* 11100110 */
+ 0x6c, /* 01101100 */
+ 0x7e, /* 01111110 */
+ 0x33, /* 00110011 */
+ 0x66, /* 01100110 */
+ 0xcc, /* 11001100 */
+ 0x0f, /* 00001111 */
+
+ /* 172 0xac '¬' */
+ 0x63, /* 01100011 */
+ 0xe6, /* 11100110 */
+ 0x6c, /* 01101100 */
+ 0x7a, /* 01111010 */
+ 0x36, /* 00110110 */
+ 0x6a, /* 01101010 */
+ 0xdf, /* 11011111 */
+ 0x06, /* 00000110 */
+
+ /* 173 0xad '­' */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 174 0xae '®' */
+ 0x00, /* 00000000 */
+ 0x33, /* 00110011 */
+ 0x66, /* 01100110 */
+ 0xcc, /* 11001100 */
+ 0x66, /* 01100110 */
+ 0x33, /* 00110011 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 175 0xaf '¯' */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0x66, /* 01100110 */
+ 0x33, /* 00110011 */
+ 0x66, /* 01100110 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 176 0xb0 '°' */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+ 0x22, /* 00100010 */
+ 0x88, /* 10001000 */
+
+ /* 177 0xb1 '±' */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+
+ /* 178 0xb2 '²' */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+
+ /* 179 0xb3 '³' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 180 0xb4 '´' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 181 0xb5 'µ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 182 0xb6 '¶' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 183 0xb7 '·' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 184 0xb8 '¸' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 185 0xb9 '¹' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x06, /* 00000110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 186 0xba 'º' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 187 0xbb '»' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 188 0xbc '¼' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x06, /* 00000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 189 0xbd '½' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 190 0xbe '¾' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 191 0xbf '¿' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 192 0xc0 'À' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 193 0xc1 'Á' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 194 0xc2 'Â' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 195 0xc3 'Ã' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 196 0xc4 'Ä' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 197 0xc5 'Å' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 198 0xc6 'Æ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 199 0xc7 'Ç' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 200 0xc8 'È' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x30, /* 00110000 */
+ 0x3f, /* 00111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 201 0xc9 'É' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 202 0xca 'Ê' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf7, /* 11110111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 203 0xcb 'Ë' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xf7, /* 11110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 204 0xcc 'Ì' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x30, /* 00110000 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 205 0xcd 'Í' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 206 0xce 'Î' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf7, /* 11110111 */
+ 0x00, /* 00000000 */
+ 0xf7, /* 11110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 207 0xcf 'Ï' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 208 0xd0 'Ð' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 209 0xd1 'Ñ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 210 0xd2 'Ò' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 211 0xd3 'Ó' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x3f, /* 00111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 212 0xd4 'Ô' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 213 0xd5 'Õ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 214 0xd6 'Ö' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 215 0xd7 '×' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xff, /* 11111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 216 0xd8 'Ø' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 217 0xd9 'Ù' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 218 0xda 'Ú' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 219 0xdb 'Û' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 220 0xdc 'Ü' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 221 0xdd 'Ý' */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+
+ /* 222 0xde 'Þ' */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+
+ /* 223 0xdf 'ß' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 224 0xe0 'à' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0xc8, /* 11001000 */
+ 0xdc, /* 11011100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+
+ /* 225 0xe1 'á' */
+ 0x78, /* 01111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xd8, /* 11011000 */
+ 0xcc, /* 11001100 */
+ 0xc6, /* 11000110 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+
+ /* 226 0xe2 'â' */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+
+ /* 227 0xe3 'ã' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+
+ /* 228 0xe4 'ä' */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+
+ /* 229 0xe5 'å' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+
+ /* 230 0xe6 'æ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0xc0, /* 11000000 */
+
+ /* 231 0xe7 'ç' */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+
+ /* 232 0xe8 'è' */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+
+ /* 233 0xe9 'é' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+
+ /* 234 0xea 'ê' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xee, /* 11101110 */
+ 0x00, /* 00000000 */
+
+ /* 235 0xeb 'ë' */
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x3e, /* 00111110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 236 0xec 'ì' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 237 0xed 'í' */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x7e, /* 01111110 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7e, /* 01111110 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+
+ /* 238 0xee 'î' */
+ 0x1e, /* 00011110 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x7e, /* 01111110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x1e, /* 00011110 */
+ 0x00, /* 00000000 */
+
+ /* 239 0xef 'ï' */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+
+ /* 240 0xf0 'ð' */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 241 0xf1 'ñ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+
+ /* 242 0xf2 'ò' */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+
+ /* 243 0xf3 'ó' */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+
+ /* 244 0xf4 'ô' */
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 245 0xf5 'õ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+
+ /* 246 0xf6 'ö' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 247 0xf7 '÷' */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 248 0xf8 'ø' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 249 0xf9 'ù' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 250 0xfa 'ú' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 251 0xfb 'û' */
+ 0x0f, /* 00001111 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0xec, /* 11101100 */
+ 0x6c, /* 01101100 */
+ 0x3c, /* 00111100 */
+ 0x1c, /* 00011100 */
+
+ /* 252 0xfc 'ü' */
+ 0x6c, /* 01101100 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 253 0xfd 'ý' */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 254 0xfe 'þ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 255 0xff 'ÿ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+};
diff --git a/roms/openbios/libopenbios/forth_load.c b/roms/openbios/libopenbios/forth_load.c
new file mode 100644
index 00000000..c3a1929f
--- /dev/null
+++ b/roms/openbios/libopenbios/forth_load.c
@@ -0,0 +1,88 @@
+/* tag: forth source loader
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * See the file "COPYING" for further information about
+ * the copyright and warranty status of this work.
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/sys_info.h"
+#include "libc/diskio.h"
+#include "libopenbios/forth_load.h"
+#define printk printk
+#define debug printk
+
+static int fd;
+static char *forthtext=NULL;
+
+int is_forth(char *forth)
+{
+ return (forth[0] == '\\' && forth[1] == ' ');
+}
+
+int forth_load(ihandle_t dev)
+{
+ char magic[2];
+ unsigned long forthsize;
+ int retval = -1;
+
+ /* Mark the saved-program-state as invalid */
+ feval("0 state-valid !");
+
+ fd = open_ih(dev);
+ if (fd == -1) {
+ goto out;
+ }
+
+ if (read_io(fd, magic, 2) != 2) {
+ debug("Can't read magic header\n");
+ retval = LOADER_NOT_SUPPORT;
+ goto out;
+ }
+
+ if (!is_forth(magic)) {
+ debug("No forth source image\n");
+ retval = LOADER_NOT_SUPPORT;
+ goto out;
+ }
+
+ /* Calculate the file size by seeking to the end of the file */
+ seek_io(fd, -1);
+ forthsize = tell(fd);
+ forthtext = malloc(forthsize+1);
+ seek_io(fd, 0);
+
+ printk("Loading forth source ...");
+ if ((size_t)read_io(fd, forthtext, forthsize) != forthsize) {
+ printk("Can't read forth text\n");
+ goto out;
+ }
+ forthtext[forthsize]=0;
+ printk("ok\n");
+
+ // Initialise saved-program-state
+ PUSH((ucell)forthtext);
+ feval("saved-program-state >sps.entry !");
+ PUSH((ucell)forthsize);
+ feval("saved-program-state >sps.file-size !");
+ feval("forth saved-program-state >sps.file-type !");
+
+ feval("-1 state-valid !");
+
+ retval=0;
+
+out:
+ //if (forthtext)
+ // free(forthtext);
+ return retval;
+}
+
+void
+forth_init_program(void)
+{
+ // Currently not implemented
+ feval("0 state-valid !");
+}
diff --git a/roms/openbios/libopenbios/helpers.fs b/roms/openbios/libopenbios/helpers.fs
new file mode 100644
index 00000000..8f5db9ff
--- /dev/null
+++ b/roms/openbios/libopenbios/helpers.fs
@@ -0,0 +1,35 @@
+\ tag: helper functions
+\
+\ deblocker / filesystem support
+\
+\ Copyright (C) 2003 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+
+\ create device node and any missing parents.
+\ The new node becomes the active package
+
+: create-node ( nodepath -- )
+ recursive
+ ascii / right-split
+ 2dup find-dev if
+ active-package!
+ 2drop
+ else
+ ( nodename path )
+ dup if
+ create-node
+ else
+ device-tree @ active-package!
+ 2drop
+ then
+ then
+ new-device
+ device-name
+ active-package
+ finish-device
+ active-package!
+;
diff --git a/roms/openbios/libopenbios/init.c b/roms/openbios/libopenbios/init.c
new file mode 100644
index 00000000..10fb55cd
--- /dev/null
+++ b/roms/openbios/libopenbios/init.c
@@ -0,0 +1,27 @@
+/*
+ * Creation Date: <2010/04/02 12:00:00 mcayland>
+ * Time-stamp: <2010/04/02 12:00:00 mcayland>
+ *
+ * <init.c>
+ *
+ * OpenBIOS intialization
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/openbios.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/initprogram.h"
+
+void
+openbios_init( void )
+{
+ // Bind the C implementation of (init-program) into Forth
+ bind_func("(init-program)", init_program);
+}
diff --git a/roms/openbios/libopenbios/initprogram.c b/roms/openbios/libopenbios/initprogram.c
new file mode 100644
index 00000000..1fa33ba6
--- /dev/null
+++ b/roms/openbios/libopenbios/initprogram.c
@@ -0,0 +1,85 @@
+/*
+ * Creation Date: <2010/04/02 13:00:00 mcayland>
+ * Time-stamp: <2010/04/02 13:00:00 mcayland>
+ *
+ * <initprogram.c>
+ *
+ * C implementation of (init-program) word
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/initprogram.h"
+
+/* Because the a.out loader requires platform-specific headers */
+#ifdef CONFIG_LOADER_AOUT
+#include "libopenbios/aout_load.h"
+#endif
+
+#include "libopenbios/bootinfo_load.h"
+#include "libopenbios/elf_load.h"
+#include "libopenbios/fcode_load.h"
+#include "libopenbios/forth_load.h"
+#include "libopenbios/xcoff_load.h"
+
+
+void init_program(void)
+{
+ /* Get the value of load-base and use it to determine the correct loader
+ to use */
+ ucell addr;
+
+ feval("load-base");
+ addr = POP();
+
+#ifdef CONFIG_LOADER_AOUT
+ if (is_aout((struct exec *)cell2pointer(addr))) {
+ aout_init_program();
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_BOOTINFO
+ if (is_bootinfo((char *)cell2pointer(addr))) {
+ bootinfo_init_program();
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_ELF
+ if (is_elf((Elf_ehdr *)cell2pointer(addr))) {
+ elf_init_program();
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_FCODE
+ if (is_fcode((unsigned char *)cell2pointer(addr))) {
+ fcode_init_program();
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_FORTH
+ if (is_forth((char *)cell2pointer(addr))) {
+ forth_init_program();
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_XCOFF
+ if (is_xcoff((COFF_filehdr_t *)cell2pointer(addr))) {
+ xcoff_init_program();
+ return;
+ }
+#endif
+
+}
diff --git a/roms/openbios/libopenbios/ipchecksum.c b/roms/openbios/libopenbios/ipchecksum.c
new file mode 100644
index 00000000..83f39bce
--- /dev/null
+++ b/roms/openbios/libopenbios/ipchecksum.c
@@ -0,0 +1,55 @@
+/* Taken from Etherboot */
+
+#include "libopenbios/ipchecksum.h"
+
+unsigned short ipchksum(const void *data, unsigned long length)
+{
+ unsigned long sum;
+ unsigned long i;
+ const unsigned char *ptr;
+ union {
+ unsigned char byte[2];
+ unsigned short word;
+ } u;
+
+ /* In the most straight forward way possible,
+ * compute an ip style checksum.
+ */
+ sum = 0;
+ ptr = data;
+ for(i = 0; i < length; i++) {
+ unsigned long value;
+ value = ptr[i];
+ if (i & 1) {
+ value <<= 8;
+ }
+ /* Add the new value */
+ sum += value;
+ /* Wrap around the carry */
+ if (sum > 0xFFFF) {
+ sum = (sum + (sum >> 16)) & 0xFFFF;
+ }
+ }
+ u.byte[0] = (unsigned char) sum;
+ u.byte[1] = (unsigned char) (sum >> 8);
+ return (unsigned short) ~u.word;
+}
+
+unsigned short add_ipchksums(unsigned long offset, unsigned short sum, unsigned short new)
+{
+ unsigned long checksum;
+ sum = ~sum & 0xFFFF;
+ new = ~new & 0xFFFF;
+ if (offset & 1) {
+ /* byte swap the sum if it came from an odd offset
+ * since the computation is endian independant this
+ * works.
+ */
+ new = (new << 8) | (new >> 8);
+ }
+ checksum = sum + new;
+ if (checksum > 0xFFFF) {
+ checksum -= 0xFFFF;
+ }
+ return (~checksum) & 0xFFFF;
+}
diff --git a/roms/openbios/libopenbios/linuxbios.h b/roms/openbios/libopenbios/linuxbios.h
new file mode 100644
index 00000000..0f7cba96
--- /dev/null
+++ b/roms/openbios/libopenbios/linuxbios.h
@@ -0,0 +1,181 @@
+#ifndef LINUXBIOS_TABLES_H
+#define LINUXBIOS_TABLES_H
+
+/* The linuxbios table information is for conveying information
+ * from the firmware to the loaded OS image. Primarily this
+ * is expected to be information that cannot be discovered by
+ * other means, such as quering the hardware directly.
+ *
+ * All of the information should be Position Independent Data.
+ * That is it should be safe to relocated any of the information
+ * without it's meaning/correctnes changing. For table that
+ * can reasonably be used on multiple architectures the data
+ * size should be fixed. This should ease the transition between
+ * 32 bit and 64 bit architectures etc.
+ *
+ * The completeness test for the information in this table is:
+ * - Can all of the hardware be detected?
+ * - Are the per motherboard constants available?
+ * - Is there enough to allow a kernel to run that was written before
+ * a particular motherboard is constructed? (Assuming the kernel
+ * has drivers for all of the hardware but it does not have
+ * assumptions on how the hardware is connected together).
+ *
+ * With this test it should be straight forward to determine if a
+ * table entry is required or not. This should remove much of the
+ * long term compatibility burden as table entries which are
+ * irrelevant or have been replaced by better alternatives may be
+ * dropped. Of course it is polite and expidite to include extra
+ * table entries and be backwards compatible, but it is not required.
+ */
+
+
+struct lb_header
+{
+ uint8_t signature[4]; /* LBIO */
+ uint32_t header_bytes;
+ uint32_t header_checksum;
+ uint32_t table_bytes;
+ uint32_t table_checksum;
+ uint32_t table_entries;
+};
+
+/* Every entry in the boot enviroment list will correspond to a boot
+ * info record. Encoding both type and size. The type is obviously
+ * so you can tell what it is. The size allows you to skip that
+ * boot enviroment record if you don't know what it easy. This allows
+ * forward compatibility with records not yet defined.
+ */
+struct lb_record {
+ uint32_t tag; /* tag ID */
+ uint32_t size; /* size of record (in bytes) */
+};
+
+#define LB_TAG_UNUSED 0x0000
+
+#define LB_TAG_MEMORY 0x0001
+
+struct lb_memory_range {
+ uint64_t start;
+ uint64_t size;
+ uint32_t type;
+#define LB_MEM_RAM 1 /* Memory anyone can use */
+#define LB_MEM_RESERVED 2 /* Don't use this memory region */
+#define LB_MEM_TABLE 16 /* Ram configuration tables are kept in */
+
+};
+
+struct lb_memory {
+ uint32_t tag;
+ uint32_t size;
+ struct lb_memory_range map[0];
+};
+
+#define LB_TAG_HWRPB 0x0002
+struct lb_hwrpb {
+ uint32_t tag;
+ uint32_t size;
+ uint64_t hwrpb;
+};
+
+#define LB_TAG_MAINBOARD 0x0003
+struct lb_mainboard {
+ uint32_t tag;
+ uint32_t size;
+ uint8_t vendor_idx;
+ uint8_t part_number_idx;
+ uint8_t strings[0];
+};
+
+#define LB_TAG_VERSION 0x0004
+#define LB_TAG_EXTRA_VERSION 0x0005
+#define LB_TAG_BUILD 0x0006
+#define LB_TAG_COMPILE_TIME 0x0007
+#define LB_TAG_COMPILE_BY 0x0008
+#define LB_TAG_COMPILE_HOST 0x0009
+#define LB_TAG_COMPILE_DOMAIN 0x000a
+#define LB_TAG_COMPILER 0x000b
+#define LB_TAG_LINKER 0x000c
+#define LB_TAG_ASSEMBLER 0x000d
+struct lb_string {
+ uint32_t tag;
+ uint32_t size;
+ uint8_t string[0];
+};
+
+/* The following structures are for the cmos definitions table */
+#define LB_TAG_CMOS_OPTION_TABLE 200
+/* cmos header record */
+struct cmos_option_table {
+ uint32_t tag; /* CMOS definitions table type */
+ uint32_t size; /* size of the entire table */
+ uint32_t header_length; /* length of header */
+};
+
+/* cmos entry record
+ This record is variable length. The name field may be
+ shorter than CMOS_MAX_NAME_LENGTH. The entry may start
+ anywhere in the byte, but can not span bytes unless it
+ starts at the beginning of the byte and the length is
+ fills complete bytes.
+*/
+#define LB_TAG_OPTION 201
+struct cmos_entries {
+ uint32_t tag; /* entry type */
+ uint32_t size; /* length of this record */
+ uint32_t bit; /* starting bit from start of image */
+ uint32_t length; /* length of field in bits */
+ uint32_t config; /* e=enumeration, h=hex, r=reserved */
+ uint32_t config_id; /* a number linking to an enumeration record */
+#define CMOS_MAX_NAME_LENGTH 32
+ uint8_t name[CMOS_MAX_NAME_LENGTH]; /* name of entry in ascii,
+ variable length int aligned */
+};
+
+
+/* cmos enumerations record
+ This record is variable length. The text field may be
+ shorter than CMOS_MAX_TEXT_LENGTH.
+*/
+#define LB_TAG_OPTION_ENUM 202
+struct cmos_enums {
+ uint32_t tag; /* enumeration type */
+ uint32_t size; /* length of this record */
+ uint32_t config_id; /* a number identifying the config id */
+ uint32_t value; /* the value associated with the text */
+#define CMOS_MAX_TEXT_LENGTH 32
+ uint8_t text[CMOS_MAX_TEXT_LENGTH]; /* enum description in ascii,
+ variable length int aligned */
+};
+
+/* cmos defaults record
+ This record contains default settings for the cmos ram.
+*/
+#define LB_TAG_OPTION_DEFAULTS 203
+struct cmos_defaults {
+ uint32_t tag; /* default type */
+ uint32_t size; /* length of this record */
+ uint32_t name_length; /* length of the following name field */
+ uint8_t name[CMOS_MAX_NAME_LENGTH]; /* name identifying the default */
+#define CMOS_IMAGE_BUFFER_SIZE 128
+ uint8_t default_set[CMOS_IMAGE_BUFFER_SIZE]; /* default settings */
+};
+
+#define LB_TAG_OPTION_CHECKSUM 204
+struct cmos_checksum {
+ uint32_t tag;
+ uint32_t size;
+ /* In practice everything is byte aligned, but things are measured
+ * in bits to be consistent.
+ */
+ uint32_t range_start; /* First bit that is checksummed (byte aligned) */
+ uint32_t range_end; /* Last bit that is checksummed (byte aligned) */
+ uint32_t location; /* First bit of the checksum (byte aligned) */
+ uint32_t type; /* Checksum algorithm that is used */
+#define CHECKSUM_NONE 0
+#define CHECKSUM_PCBIOS 1
+};
+
+
+
+#endif /* LINUXBIOS_TABLES_H */
diff --git a/roms/openbios/libopenbios/linuxbios_info.c b/roms/openbios/libopenbios/linuxbios_info.c
new file mode 100644
index 00000000..bef996cf
--- /dev/null
+++ b/roms/openbios/libopenbios/linuxbios_info.c
@@ -0,0 +1,130 @@
+/* Adapted from Etherboot 5.1.8 */
+
+#include "config.h"
+#include "sysinclude.h"
+#include "asm/types.h"
+#include "asm/io.h"
+#include "linuxbios.h"
+#include "libopenbios/ipchecksum.h"
+#include "libopenbios/sys_info.h"
+
+#ifdef CONFIG_DEBUG_BOOT
+#define debug printk
+#else
+#define debug(x...)
+#endif
+
+#define for_each_lbrec(head, rec) \
+ for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \
+ (((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes)) && \
+ (rec->size >= 1) && \
+ ((((char *)rec) + rec->size) <= (((char *)head) + sizeof(*head) + head->table_bytes)); \
+ rec = (struct lb_record *)(((char *)rec) + rec->size))
+
+static void convert_memmap(struct lb_memory *lbmem, struct sys_info *info)
+{
+ int lbcount;
+ int i;
+
+ lbcount = lbmem->size / sizeof(struct lb_memory_range);
+ info->memrange = malloc(lbcount * sizeof(struct memrange));
+ info->n_memranges = 0;
+ for (i = 0; i < lbcount; i++) {
+ debug("%#016llx %#016llx %d\n",
+ (long long)lbmem->map[i].start, (long long)lbmem->map[i].size,
+ (int) lbmem->map[i].type);
+ if (lbmem->map[i].type != LB_MEM_RAM)
+ continue;
+ info->memrange[info->n_memranges].base = lbmem->map[i].start;
+ info->memrange[info->n_memranges].size = lbmem->map[i].size;
+ info->n_memranges++;
+ }
+}
+
+static int read_lbtable(struct lb_header *head, struct sys_info *info)
+{
+ int retval = 0;
+
+ /* Read linuxbios tables... */
+ struct lb_record *rec;
+
+ for_each_lbrec(head, rec) {
+ switch(rec->tag) {
+ case LB_TAG_MEMORY:
+ convert_memmap((struct lb_memory *) rec, info);
+ retval = 1;
+ break;
+ };
+ }
+ return retval;
+}
+
+static unsigned long count_lb_records(void *start, unsigned long length)
+{
+ struct lb_record *rec;
+ void *end;
+ unsigned long count;
+ count = 0;
+ end = ((char *)start) + length;
+ for(rec = start; ((void *)rec < end) &&
+ ((signed long)rec->size <=
+ ((signed long)end - (signed long)rec));
+ rec = (void *)(((char *)rec) + rec->size)) {
+ count++;
+ }
+ return count;
+}
+
+static int find_lb_table(void *start, void *end, struct lb_header **result)
+{
+ unsigned char *ptr;
+ /* For now be stupid.... */
+ for(ptr = start; (void *)ptr < end; ptr += 16) {
+ struct lb_header *head = (struct lb_header *)ptr;
+ if ( (head->signature[0] != 'L') ||
+ (head->signature[1] != 'B') ||
+ (head->signature[2] != 'I') ||
+ (head->signature[3] != 'O')) {
+ continue;
+ }
+ if (head->header_bytes != sizeof(*head))
+ continue;
+ debug("Found canidate at: %p\n", head);
+ if (ipchksum((uint16_t *)head, sizeof(*head)) != 0)
+ continue;
+ debug("header checksum o.k.\n");
+ if (ipchksum((uint16_t *)(ptr + sizeof(*head)), head->table_bytes) !=
+ head->table_checksum) {
+ continue;
+ }
+ debug("table checksum o.k.\n");
+ if (count_lb_records(ptr + sizeof(*head), head->table_bytes) !=
+ head->table_entries) {
+ continue;
+ }
+ debug("record count o.k.\n");
+ *result = head;
+ return 1;
+ };
+ return 0;
+}
+
+void collect_linuxbios_info(struct sys_info *info)
+{
+ struct lb_header *lb_table;
+ int found;
+ debug("Searching for LinuxBIOS tables...\n");
+ found = 0;
+ if (!found) {
+ found = find_lb_table(phys_to_virt(0x00000), phys_to_virt(0x01000), &lb_table);
+ }
+ if (!found) {
+ found = find_lb_table(phys_to_virt(0xf0000), phys_to_virt(0x100000), &lb_table);
+ }
+ if (!found)
+ return;
+
+ debug("Found LinuxBIOS table at: %p\n", lb_table);
+ info->firmware = "LinuxBIOS";
+ read_lbtable(lb_table, info);
+}
diff --git a/roms/openbios/libopenbios/load.c b/roms/openbios/libopenbios/load.c
new file mode 100644
index 00000000..4bc12ea3
--- /dev/null
+++ b/roms/openbios/libopenbios/load.c
@@ -0,0 +1,122 @@
+/*
+ * Creation Date: <2010/06/25 20:00:00 mcayland>
+ * Time-stamp: <2010/06/25 20:00:00 mcayland>
+ *
+ * <load.c>
+ *
+ * C implementation of load
+ *
+ * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/sys_info.h"
+#include "libopenbios/load.h"
+
+#ifdef CONFIG_LOADER_ELF
+#include "libopenbios/elf_load.h"
+#endif
+
+#ifdef CONFIG_LOADER_AOUT
+#include "libopenbios/aout_load.h"
+#endif
+
+#ifdef CONFIG_LOADER_FCODE
+#include "libopenbios/fcode_load.h"
+#endif
+
+#ifdef CONFIG_LOADER_FORTH
+#include "libopenbios/forth_load.h"
+#endif
+
+#ifdef CONFIG_LOADER_BOOTCODE
+#include "libopenbios/bootcode_load.h"
+#endif
+
+
+struct sys_info sys_info;
+void *elf_boot_notes = NULL;
+
+/* ( addr -- size ) */
+
+void load(ihandle_t dev)
+{
+ /* Invoke the loaders on the specified device */
+ char *param;
+ ucell valid;
+
+ /* TODO: Currently the internal loader APIs use load-base directly, so
+ drop the address */
+ POP();
+
+#ifdef CONFIG_LOADER_ELF
+
+ /* Grab the boot arguments */
+ push_str("bootargs");
+ push_str("/chosen");
+ fword("(find-dev)");
+ POP();
+ fword("get-package-property");
+ POP();
+ param = pop_fstr_copy();
+
+ elf_load(&sys_info, dev, param, &elf_boot_notes);
+ feval("state-valid @");
+ valid = POP();
+ if (valid) {
+ feval("saved-program-state >sps.file-size @");
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_AOUT
+ aout_load(&sys_info, dev);
+ feval("state-valid @");
+ valid = POP();
+ if (valid) {
+ feval("saved-program-state >sps.file-size @");
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_FCODE
+ fcode_load(dev);
+ feval("state-valid @");
+ valid = POP();
+ if (valid) {
+ feval("saved-program-state >sps.file-size @");
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_FORTH
+ forth_load(dev);
+ feval("state-valid @");
+ valid = POP();
+ if (valid) {
+ feval("saved-program-state >sps.file-size @");
+ return;
+ }
+#endif
+
+#ifdef CONFIG_LOADER_BOOTCODE
+ /* Check for a "raw" %BOOT bootcode payload */
+ bootcode_load(dev);
+ feval("state-valid @");
+ valid = POP();
+ if (valid) {
+ feval("saved-program-state >sps.file-size @");
+ return;
+ }
+#endif
+
+ /* Didn't load anything, so return zero size */
+ PUSH(0);
+}
diff --git a/roms/openbios/libopenbios/ofmem_common.c b/roms/openbios/libopenbios/ofmem_common.c
new file mode 100644
index 00000000..052aa2f4
--- /dev/null
+++ b/roms/openbios/libopenbios/ofmem_common.c
@@ -0,0 +1,990 @@
+/*
+ * <ofmem_common.c>
+ *
+ * OF Memory manager
+ *
+ * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se)
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/ofmem.h"
+
+/* Default size of memory allocated for each of the MMU properties (in bytes) */
+#define OFMEM_DEFAULT_PROP_SIZE 2048
+
+/*
+ * define OFMEM_FILL_RANGE to claim any unclaimed virtual and
+ * physical memory in the range for ofmem_map
+ *
+ * TODO: remove this macro and wrapped code if not needed by implementations
+ */
+//#define OFMEM_FILL_RANGE
+
+
+static inline size_t align_size(size_t x, size_t a)
+{
+ return (x + a - 1) & ~(a - 1);
+}
+
+static inline phys_addr_t align_ptr(uintptr_t x, size_t a)
+{
+ return (x + a - 1) & ~(a - 1);
+}
+
+static ucell get_ram_size( void )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ return ofmem->ramsize;
+}
+
+/************************************************************************/
+/* debug */
+/************************************************************************/
+
+#if 0
+static void
+print_range( range_t *r, const char *str )
+{
+ printk("--- Range %s ---\n", str );
+ for( ; r; r=r->next )
+ printk("%p : " FMT_plx " - " FMT_plx "\n", r, r->start, r->start + r->size - 1);
+ printk("\n");
+}
+
+static void
+print_phys_range(void)
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ print_range( ofmem->phys_range, "phys" );
+}
+
+static void
+print_virt_range(void)
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ print_range( ofmem->virt_range, "virt" );
+}
+
+static void
+print_trans( void )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ translation_t *t = ofmem->trans;
+
+ printk("--- Translations ---\n");
+ for( ; t; t=t->next )
+ printk("%p : " FMT_ucellx " -> " FMT_plx " [size " FMT_ucellx "]\n", t, t->virt, t->phys, t->size);
+ printk("\n");
+}
+#endif
+
+/************************************************************************/
+/* OF private allocations */
+/************************************************************************/
+
+int ofmem_posix_memalign( void **memptr, size_t alignment, size_t size )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ alloc_desc_t *d, **pp;
+ void *ret;
+ ucell top;
+ phys_addr_t pa;
+
+ if( !size )
+ return ENOMEM;
+
+ if( !ofmem->next_malloc )
+ ofmem->next_malloc = (char*)ofmem_arch_get_malloc_base();
+
+ size = align_size(size + sizeof(alloc_desc_t), alignment);
+
+ /* look in the freelist */
+ for( pp=&ofmem->mfree; *pp && (**pp).size < size; pp = &(**pp).next ) {
+ }
+
+ /* waste at most 4K by taking an entry from the freelist */
+ if( *pp && (**pp).size > size + 0x1000 ) {
+ /* Alignment should be on physical not virtual address */
+ pa = va2pa((uintptr_t)*pp + sizeof(alloc_desc_t));
+ pa = align_ptr(pa, alignment);
+ ret = (void *)pa2va(pa);
+
+ memset( ret, 0, (**pp).size - sizeof(alloc_desc_t) );
+ *pp = (**pp).next;
+
+ *memptr = ret;
+ return 0;
+ }
+
+ top = ofmem_arch_get_heap_top();
+
+ /* Alignment should be on physical not virtual address */
+ pa = va2pa((uintptr_t)ofmem->next_malloc + sizeof(alloc_desc_t));
+ pa = align_ptr(pa, alignment);
+ ret = (void *)pa2va(pa);
+
+ if( pointer2cell(ret) + size > top ) {
+ printk("out of malloc memory (%x)!\n", size );
+ return ENOMEM;
+ }
+
+ d = (alloc_desc_t*)((uintptr_t)ret - sizeof(alloc_desc_t));
+ ofmem->next_malloc += size;
+
+ d->next = NULL;
+ d->size = size;
+
+ memset( ret, 0, size - sizeof(alloc_desc_t) );
+
+ *memptr = ret;
+ return 0;
+}
+
+void* ofmem_malloc( size_t size )
+{
+ void *memptr;
+ int res;
+
+ res = ofmem_posix_memalign( &memptr, CONFIG_OFMEM_MALLOC_ALIGN, size );
+ if (!res) {
+ /* Success */
+ return memptr;
+ } else {
+ /* Failure */
+ return NULL;
+ }
+}
+
+void ofmem_free( void *ptr )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ alloc_desc_t **pp, *d;
+
+ /* it is legal to free NULL pointers (size zero allocations) */
+ if( !ptr )
+ return;
+
+ d = (alloc_desc_t*)((char *)ptr - sizeof(alloc_desc_t));
+ d->next = ofmem->mfree;
+
+ /* insert in the (sorted) freelist */
+ for( pp=&ofmem->mfree; *pp && (**pp).size < d->size ; pp = &(**pp).next ) {
+ }
+
+ d->next = *pp;
+ *pp = d;
+}
+
+void* ofmem_realloc( void *ptr, size_t size )
+{
+ alloc_desc_t *d = (alloc_desc_t*)((char *)ptr - sizeof(alloc_desc_t));
+ char *p;
+
+ if( !ptr )
+ return malloc( size );
+ if( !size ) {
+ free( ptr );
+ return NULL;
+ }
+ p = malloc( size );
+ memcpy( p, ptr, MIN(d->size - sizeof(alloc_desc_t),size) );
+ free( ptr );
+ return p;
+}
+
+
+/************************************************************************/
+/* "translations" and "available" property tracking */
+/************************************************************************/
+
+static int trans_prop_size = 0, phys_range_prop_size = 0, virt_range_prop_size = 0;
+static int trans_prop_used = 0, phys_range_prop_used = 0, virt_range_prop_used = 0;
+static ucell *trans_prop, *phys_range_prop, *virt_range_prop;
+
+static void
+ofmem_set_property( phandle_t ph, const char *name, const char *buf, int len )
+{
+ /* This is very similar to set_property() in libopenbios/bindings.c but allows
+ us to set the property pointer directly, rather than having to copy it
+ into the Forth dictonary every time we update the memory properties */
+ if( !ph ) {
+ printk("ofmem_set_property: NULL phandle\n");
+ return;
+ }
+ PUSH(pointer2cell(buf));
+ PUSH(len);
+ push_str(name);
+ PUSH_ph(ph);
+ fword("encode-property");
+}
+
+phandle_t s_phandle_memory = 0;
+phandle_t s_phandle_mmu = 0;
+
+static void ofmem_update_mmu_translations( void )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ translation_t *t;
+ int ncells, prop_used, prop_size;
+
+ if (s_phandle_mmu == 0)
+ return;
+
+ for( t = ofmem->trans, ncells = 0; t ; t=t->next, ncells++ ) {
+ }
+
+ /* Get the current number of bytes required for the MMU translation property */
+ prop_used = ncells * sizeof(ucell) * ofmem_arch_get_translation_entry_size();
+
+ if (prop_used > trans_prop_size) {
+
+ /* The property doesn't fit within the existing space, so keep doubling it
+ until it does */
+ prop_size = trans_prop_size;
+ while (prop_size < prop_used) {
+ prop_size *= 2;
+ }
+
+ /* Allocate the new memory and copy all of the existing information across */
+ trans_prop = realloc(trans_prop, prop_size);
+ trans_prop_size = prop_size;
+ trans_prop_used = prop_used;
+ }
+
+ if (trans_prop == NULL) {
+ /* out of memory! */
+ printk("Unable to allocate memory for translations property!\n");
+ return;
+ }
+
+ /* Call architecture-specific routines to generate translation entries */
+ for( t = ofmem->trans, ncells = 0 ; t ; t=t->next ) {
+ ofmem_arch_create_translation_entry(&trans_prop[ncells], t);
+ ncells += ofmem_arch_get_translation_entry_size();
+ }
+
+ ofmem_set_property(s_phandle_mmu, "translations",
+ (char*)trans_prop, ncells * sizeof(trans_prop[0]));
+
+}
+
+
+static void ofmem_update_memory_available( phandle_t ph, range_t *range,
+ ucell **mem_prop, int *mem_prop_size, int *mem_prop_used, u64 top_address )
+{
+ range_t *r;
+ int ncells, prop_used, prop_size;
+ phys_addr_t start;
+ ucell size, *prop;
+
+ if (s_phandle_memory == 0)
+ return;
+
+ /* count phys_range list entries */
+ for( r = range, ncells = 0; r ; r=r->next, ncells++ ) {
+ }
+
+ /* inverse of phys_range list could take 2 or more additional cells for the tail
+ For /memory, physical addresses may be wider than one ucell. */
+ prop_used = (ncells + 1) * sizeof(ucell) * ofmem_arch_get_available_entry_size(ph) + 1;
+
+ if (prop_used > *mem_prop_size) {
+
+ /* The property doesn't fit within the existing space, so keep doubling it
+ until it does */
+ prop_size = *mem_prop_size;
+ while (prop_size < prop_used) {
+ prop_size *= 2;
+ }
+
+ /* Allocate the new memory and copy all of the existing information across */
+ *mem_prop = realloc(*mem_prop, prop_size);
+ *mem_prop_size = prop_size;
+ *mem_prop_used = prop_used;
+ }
+
+ if (*mem_prop == NULL) {
+ /* out of memory! */
+ printk("Unable to allocate memory for memory range property!\n");
+ return;
+ }
+
+ start = 0;
+ ncells = 0;
+ prop = *mem_prop;
+
+ for (r = range; r; r=r->next) {
+ if (r->start >= top_address) {
+ break;
+ }
+
+ size = r->start - start;
+ if (size) {
+ ofmem_arch_create_available_entry(ph, &prop[ncells], start, size);
+ ncells += ofmem_arch_get_available_entry_size(ph);
+ }
+ start = r->start + r->size;
+ }
+
+ /* tail */
+ if ((start - 1) < top_address) {
+ ofmem_arch_create_available_entry(ph, &prop[ncells], start, top_address - start + 1);
+ ncells += ofmem_arch_get_available_entry_size(ph);
+ }
+
+ ofmem_set_property(ph, "available",
+ (char*)prop, ncells * sizeof(prop[0]));
+}
+
+static void ofmem_update_translations( void )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+
+ ofmem_update_memory_available(s_phandle_memory, ofmem->phys_range,
+ &phys_range_prop, &phys_range_prop_size, &phys_range_prop_used, get_ram_size() - 1);
+ ofmem_update_memory_available(s_phandle_mmu, ofmem->virt_range,
+ &virt_range_prop, &virt_range_prop_size, &virt_range_prop_used, (ucell)-1);
+ ofmem_update_mmu_translations();
+}
+
+
+/************************************************************************/
+/* client interface */
+/************************************************************************/
+
+static int is_free( phys_addr_t ea, ucell size, range_t *r )
+{
+ if( size == 0 )
+ return 1;
+ for( ; r ; r=r->next ) {
+ if( r->start + r->size - 1 >= ea && r->start <= ea )
+ return 0;
+ if( r->start >= ea && r->start <= ea + size - 1 )
+ return 0;
+ }
+ return 1;
+}
+
+static void add_entry_( phys_addr_t ea, ucell size, range_t **r )
+{
+ range_t *nr;
+
+ for( ; *r && (**r).start < ea; r=&(**r).next ) {
+ }
+
+ nr = (range_t*)malloc( sizeof(range_t) );
+ nr->next = *r;
+ nr->start = ea;
+ nr->size = size;
+ *r = nr;
+}
+
+static int add_entry( phys_addr_t ea, ucell size, range_t **r )
+{
+ if( !is_free( ea, size, *r ) ) {
+ OFMEM_TRACE("add_entry: range not free!\n");
+ return -1;
+ }
+ add_entry_( ea, size, r );
+ return 0;
+}
+
+#if defined(OFMEM_FILL_RANGE)
+static void join_ranges( range_t **rr )
+{
+ range_t *n, *r = *rr;
+ while( r ) {
+ if( !(n=r->next) )
+ break;
+
+ if( r->start + r->size - 1 >= n->start -1 ) {
+ int s = n->size + (n->start - r->start - r->size);
+ if( s > 0 )
+ r->size += s;
+ r->next = n->next;
+ free( n );
+ continue;
+ }
+ r=r->next;
+ }
+}
+
+static void fill_range( phys_addr_t ea, ucell size, range_t **rr )
+{
+ add_entry_( ea, size, rr );
+ join_ranges( rr );
+}
+#endif
+
+static ucell find_area( ucell align, ucell size, range_t *r,
+ phys_addr_t min, phys_addr_t max, int reverse )
+{
+ phys_addr_t base = min;
+ range_t *r2;
+ ucell old_align = align;
+ int i;
+
+ if( (align < PAGE_SIZE) ) {
+
+ /* Minimum alignment is page size */
+ align = PAGE_SIZE;
+
+ OFMEM_TRACE("warning: bad alignment " FMT_ucellx " rounded up to " FMT_ucellx "\n", old_align, align);
+ }
+
+ if( (align & (align-1)) ) {
+
+ /* As per IEEE1275 specification, round up to the nearest power of 2 */
+ align--;
+ for (i = 1; i < sizeof(ucell) * 8; i<<=1) {
+ align |= align >> i;
+ }
+ align++;
+
+ OFMEM_TRACE("warning: bad alignment " FMT_ucellx " rounded up to " FMT_ucellx "\n", old_align, align);
+ }
+
+ base = reverse ? max - size : min;
+ r2 = reverse ? NULL : r;
+
+ for( ;; ) {
+ if( !reverse ) {
+ base = (base + align - 1) & ~(align-1);
+ if( base < min )
+ base = min;
+ if( base + size - 1 >= max -1 )
+ break;
+ } else {
+ if( base > max - size )
+ base = max - size;
+ base -= base & (align-1);
+ }
+ if( is_free( base, size, r ) )
+ return base;
+
+ if( !reverse ) {
+ if( !r2 )
+ break;
+ base = r2->start + r2->size;
+ r2 = r2->next;
+ } else {
+ range_t *rp;
+
+ for( rp=r; rp && rp->next != r2 ; rp=rp->next ) {
+ }
+
+ r2 = rp;
+ if( !r2 )
+ break;
+ base = r2->start - size;
+ }
+ }
+ return -1;
+}
+
+static phys_addr_t ofmem_claim_phys_( phys_addr_t phys, ucell size, ucell align,
+ phys_addr_t min, phys_addr_t max, int reverse )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ if( !align ) {
+ if( !is_free( phys, size, ofmem->phys_range ) ) {
+ OFMEM_TRACE("Non-free physical memory claimed!\n");
+ return -1;
+ }
+ add_entry( phys, size, &ofmem->phys_range );
+ ofmem_update_translations();
+ return phys;
+ }
+ phys = find_area( align, size, ofmem->phys_range, min, max, reverse );
+ if( phys == -1 ) {
+ printk("ofmem_claim_phys - out of space (failed request for " FMT_ucellx " bytes)\n", size);
+ return -1;
+ }
+ add_entry( phys, size, &ofmem->phys_range );
+
+ ofmem_update_translations();
+
+ return phys;
+}
+
+/* if align != 0, phys is ignored. Returns -1 on error */
+phys_addr_t ofmem_claim_phys( phys_addr_t phys, ucell size, ucell align )
+{
+ OFMEM_TRACE("ofmem_claim_phys phys=" FMT_plx " size=" FMT_ucellx
+ " align=" FMT_ucellx "\n",
+ phys, size, align);
+
+ return ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 1 );
+}
+
+static ucell ofmem_claim_virt_( ucell virt, ucell size, ucell align,
+ ucell min, ucell max, int reverse )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ if( !align ) {
+ if( !is_free( virt, size, ofmem->virt_range ) ) {
+ OFMEM_TRACE("Non-free virtual memory claimed!\n");
+ return -1;
+ }
+ add_entry( virt, size, &ofmem->virt_range );
+ ofmem_update_translations();
+ return virt;
+ }
+
+ virt = find_area( align, size, ofmem->virt_range, min, max, reverse );
+ if( virt == -1 ) {
+ printk("ofmem_claim_virt - out of space (failed request for " FMT_ucellx " bytes)\n", size);
+ return -1;
+ }
+ add_entry( virt, size, &ofmem->virt_range );
+
+ ofmem_update_translations();
+
+ return virt;
+}
+
+ucell ofmem_claim_virt( ucell virt, ucell size, ucell align )
+{
+ OFMEM_TRACE("ofmem_claim_virt virt=" FMT_ucellx " size=" FMT_ucellx
+ " align=" FMT_ucellx "\n",
+ virt, size, align);
+
+ /* printk("+ ofmem_claim virt %08lx %lx %ld\n", virt, size, align ); */
+ return ofmem_claim_virt_( virt, size, align,
+ get_ram_size(), ofmem_arch_get_virt_top(), 1 );
+}
+
+static ucell ofmem_claim_io_( ucell virt, ucell size, ucell align,
+ ucell min, ucell max, int reverse )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ if( !align ) {
+ if( !is_free( virt, size, ofmem->io_range ) ) {
+ OFMEM_TRACE("Non-free I/O memory claimed!\n");
+ return -1;
+ }
+ add_entry( virt, size, &ofmem->io_range );
+ return virt;
+ }
+
+ virt = find_area( align, size, ofmem->io_range, min, max, reverse );
+ if( virt == -1 ) {
+ printk("ofmem_claim_io - out of space (failed request for " FMT_ucellx " bytes)\n", size);
+ return -1;
+ }
+ add_entry( virt, size, &ofmem->io_range );
+ return virt;
+}
+
+ucell ofmem_claim_io( ucell virt, ucell size, ucell align )
+{
+ /* Claim a section of memory from the I/O range */
+ return ofmem_claim_io_( virt, size, align,
+ ofmem_arch_get_iomem_base(), ofmem_arch_get_iomem_top(), 0 );
+}
+
+/* if align != 0, phys is ignored. Returns -1 on error */
+phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align )
+{
+ retain_t *retained = ofmem_arch_get_retained();
+ phys_addr_t retain_phys;
+
+ OFMEM_TRACE("ofmem_retain phys=" FMT_plx " size=" FMT_ucellx
+ " align=" FMT_ucellx "\n",
+ phys, size, align);
+
+ retain_phys = ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 1 /* reverse */ );
+
+ /* Add to the retain_phys_range list */
+ retained->retain_phys_range[retained->numentries].next = NULL;
+ retained->retain_phys_range[retained->numentries].start = retain_phys;
+ retained->retain_phys_range[retained->numentries].size = size;
+ retained->numentries++;
+
+ return retain_phys;
+}
+
+/* allocate both physical and virtual space and add a translation */
+ucell ofmem_claim( ucell addr, ucell size, ucell align )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ ucell virt;
+ phys_addr_t phys;
+ ucell offs = addr & (PAGE_SIZE - 1);
+
+ OFMEM_TRACE("ofmem_claim " FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n", addr, size, align );
+ virt = phys = 0;
+ if( !align ) {
+ if( is_free(addr, size, ofmem->virt_range) &&
+ is_free(addr, size, ofmem->phys_range) ) {
+ ofmem_claim_phys_( addr, size, 0, 0, 0, 0 );
+ ofmem_claim_virt_( addr, size, 0, 0, 0, 0 );
+ virt = phys = addr;
+ } else {
+ OFMEM_TRACE("**** ofmem_claim failure ***!\n");
+ return -1;
+ }
+ } else {
+ if( align < PAGE_SIZE )
+ align = PAGE_SIZE;
+ phys = ofmem_claim_phys_( -1, size, align, 0, get_ram_size(), 1 /* reverse */ );
+ virt = ofmem_claim_virt_( phys, size, 0, 0, 0, 0 );
+ if( phys == -1 || virt == -1 ) {
+ OFMEM_TRACE("ofmem_claim failed\n");
+ return -1;
+ }
+ /* printk("...phys = %08lX, virt = %08lX, size = %08lX\n", phys, virt, size ); */
+ }
+
+ /* align */
+ if( phys & (PAGE_SIZE - 1) ) {
+ size += (phys & (PAGE_SIZE - 1));
+ virt -= (phys & (PAGE_SIZE - 1));
+ phys &= PAGE_MASK;
+ }
+ if( size & (PAGE_SIZE - 1) )
+ size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+ /* printk("...free memory found... phys: %08lX, virt: %08lX, size %lX\n", phys, virt, size ); */
+ ofmem_map( phys, virt, size, -1 );
+ return virt + offs;
+}
+
+
+/************************************************************************/
+/* keep track of ea -> phys translations */
+/************************************************************************/
+
+static void split_trans( ucell virt )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ translation_t *t, *t2;
+
+ for( t=ofmem->trans; t; t=t->next ) {
+ if( virt > t->virt && virt < t->virt + t->size-1 ) {
+ t2 = (translation_t*)malloc( sizeof(translation_t) );
+ t2->virt = virt;
+ t2->size = t->size - (virt - t->virt);
+ t->size = virt - t->virt;
+ t2->phys = t->phys + t->size;
+ t2->mode = t->mode;
+ t2->next = t->next;
+ t->next = t2;
+ }
+ }
+}
+
+int ofmem_map_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ translation_t *t, **tt;
+
+ OFMEM_TRACE("ofmem_map_page_range " FMT_ucellx
+ " -> " FMT_plx " " FMT_ucellx " mode " FMT_ucellx "\n",
+ virt, phys, size, mode );
+
+ split_trans( virt );
+ split_trans( virt + size );
+
+ /* detect remappings */
+ for( t=ofmem->trans; t; ) {
+ if( virt == t->virt || (virt < t->virt && virt + size > t->virt )) {
+ if( t->phys + virt - t->virt != phys ) {
+ OFMEM_TRACE("mapping altered virt=" FMT_ucellx ")\n", t->virt );
+ } else if( t->mode != mode ){
+ OFMEM_TRACE("mapping mode altered virt=" FMT_ucellx
+ " old mode=" FMT_ucellx " new mode=" FMT_ucellx "\n",
+ t->virt, t->mode, mode);
+ }
+
+ for( tt=&ofmem->trans; *tt != t ; tt=&(**tt).next ) {
+ }
+
+ *tt = t->next;
+
+ /* really unmap these pages */
+ ofmem_arch_unmap_pages(t->virt, t->size);
+
+ free((char*)t);
+
+ t=ofmem->trans;
+ continue;
+ }
+ t=t->next;
+ }
+
+ /* add mapping */
+ for( tt=&ofmem->trans; *tt && (**tt).virt < virt ; tt=&(**tt).next ) {
+ }
+
+ t = (translation_t*)malloc( sizeof(translation_t) );
+ t->virt = virt;
+ t->phys = phys;
+ t->size = size;
+ t->mode = mode;
+ t->next = *tt;
+ *tt = t;
+
+ ofmem_update_translations();
+
+ return 0;
+}
+
+static int unmap_page_range( ucell virt, ucell size )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ translation_t **plink;
+
+ /* make sure there is exactly one matching translation entry */
+
+ split_trans( virt );
+ split_trans( virt + size );
+
+ /* find and unlink entries in range */
+ plink = &ofmem->trans;
+
+ while (*plink && (*plink)->virt < virt+size) {
+ translation_t **plinkentry = plink;
+ translation_t *t = *plink;
+
+ /* move ahead */
+ plink = &t->next;
+
+ if (t->virt >= virt && t->virt + t->size <= virt+size) {
+
+ /* unlink entry */
+ *plinkentry = t->next;
+
+ OFMEM_TRACE("unmap_page_range found "
+ FMT_ucellx " -> " FMT_plx " " FMT_ucellx
+ " mode " FMT_ucellx "\n",
+ t->virt, t->phys, t->size, t->mode );
+
+ // really map these pages
+ ofmem_arch_unmap_pages(t->virt, t->size);
+
+ free((char*)t);
+ }
+ }
+
+ ofmem_update_translations();
+
+ return 0;
+}
+
+int ofmem_map( phys_addr_t phys, ucell virt, ucell size, ucell mode )
+{
+ /* printk("+ofmem_map: %08lX --> %08lX (size %08lX, mode 0x%02X)\n",
+ virt, phys, size, mode ); */
+
+ if( (phys & (PAGE_SIZE - 1)) || (virt & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) ) {
+
+ OFMEM_TRACE("ofmem_map: Bad parameters ("
+ FMT_plx " " FMT_ucellx " " FMT_ucellx ")\n",
+ phys, virt, size );
+
+ phys &= PAGE_MASK;
+ virt &= PAGE_MASK;
+ size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
+ }
+
+#if defined(OFMEM_FILL_RANGE)
+ {
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ /* claim any unclaimed virtual memory in the range */
+ fill_range( virt, size, &ofmem->virt_range );
+ /* hmm... we better claim the physical range too */
+ fill_range( phys, size, &ofmem->phys_range );
+ }
+#endif
+
+ if (mode==-1) {
+ mode = ofmem_arch_default_translation_mode(phys);
+ }
+
+ /* install translations */
+ ofmem_map_page_range(phys, virt, size, mode);
+
+ /* allow arch to map the pages */
+ ofmem_arch_map_pages(phys, virt, size, mode);
+
+ return 0;
+}
+
+int ofmem_unmap( ucell virt, ucell size )
+{
+ OFMEM_TRACE("ofmem_unmap " FMT_ucellx " " FMT_ucellx "\n",
+ virt, size );
+
+ if( (virt & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) ) {
+ /* printk("ofmem_unmap: Bad parameters (%08lX %08lX)\n",
+ virt, size ); */
+ virt &= PAGE_MASK;
+ size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
+ }
+
+ /* remove translations and unmap pages */
+ unmap_page_range(virt, size);
+
+ return 0;
+}
+
+ucell ofmem_map_io( phys_addr_t phys, ucell size )
+{
+ /* Claim virtual memory from the I/O range and map the page-aligned
+ physical address phys to it, returning the newly allocated
+ virtual address */
+ ucell virt, mode;
+ phys_addr_t off;
+ int npages;
+
+ off = phys & (PAGE_SIZE - 1);
+ npages = (off + size - 1) / PAGE_SIZE + 1;
+ phys &= ~(PAGE_SIZE - 1);
+
+ virt = ofmem_claim_io(-1, npages * PAGE_SIZE, PAGE_SIZE);
+
+ mode = ofmem_arch_io_translation_mode(off);
+
+ ofmem_map_page_range(phys, virt, npages * PAGE_SIZE, mode);
+ ofmem_arch_map_pages(phys, virt, npages * PAGE_SIZE, mode);
+
+ return (virt + off);
+}
+
+/* virtual -> physical. */
+phys_addr_t ofmem_translate( ucell virt, ucell *mode )
+{
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ translation_t *t;
+
+ for( t=ofmem->trans; t && t->virt <= virt ; t=t->next ) {
+ ucell offs;
+ if( t->virt + t->size - 1 < virt )
+ continue;
+ offs = virt - t->virt;
+ *mode = t->mode;
+ return t->phys + offs;
+ }
+
+ /*printk("ofmem_translate: no translation defined (%08lx)\n", virt);*/
+ /*print_trans();*/
+ return -1;
+}
+
+static void remove_range_( phys_addr_t ea, ucell size, range_t **r )
+{
+ range_t **t, *u;
+
+ /* If not an exact match then split the range */
+ for (t = r; *t; t = &(**t).next) {
+ if (ea > (**t).start && ea < (**t).start + (**t).size - 1) {
+ u = (range_t*)malloc(sizeof(range_t));
+ u->start = ea;
+ u->size = size;
+ u->next = (**t).next;
+
+ OFMEM_TRACE("remove_range_ splitting range with addr=" FMT_plx
+ " size=" FMT_ucellx " -> addr=" FMT_plx " size=" FMT_ucellx ", "
+ "addr=" FMT_plx " size=" FMT_ucellx "\n",
+ (**t).start, (**t).size, (**t).start, (**t).size - size,
+ u->start, u->size);
+
+ (**t).size = (**t).size - size;
+ (**t).next = u;
+ }
+ }
+
+ for (t = r; *t; t = &(**t).next) {
+ if (ea >= (**t).start && ea + size <= (**t).start + (**t).size) {
+ OFMEM_TRACE("remove_range_ freeing range with addr=" FMT_plx
+ " size=" FMT_ucellx "\n", (**t).start, (**t).size);
+ u = *t;
+ *t = (**t).next;
+ free(u);
+ break;
+ }
+ }
+}
+
+static int remove_range( phys_addr_t ea, ucell size, range_t **r )
+{
+ if( is_free( ea, size, *r ) ) {
+ OFMEM_TRACE("remove_range: range isn't occupied\n");
+ return -1;
+ }
+ remove_range_( ea, size, r );
+ return 0;
+}
+
+/* release memory allocated by ofmem_claim_phys */
+void ofmem_release_phys( phys_addr_t phys, ucell size )
+{
+ OFMEM_TRACE("ofmem_release_phys addr=" FMT_plx " size=" FMT_ucellx "\n",
+ phys, size);
+
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ remove_range(phys, size, &ofmem->phys_range);
+}
+
+/* release memory allocated by ofmem_claim_virt */
+void ofmem_release_virt( ucell virt, ucell size )
+{
+ OFMEM_TRACE("ofmem_release_virt addr=" FMT_ucellx " size=" FMT_ucellx "\n",
+ virt, size);
+
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ remove_range(virt, size, &ofmem->virt_range);
+}
+
+/* release memory allocated by ofmem_claim_io */
+void ofmem_release_io( ucell virt, ucell size )
+{
+ OFMEM_TRACE("ofmem_release_io addr=" FMT_ucellx " size=" FMT_ucellx "\n",
+ virt, size);
+
+ ofmem_t *ofmem = ofmem_arch_get_private();
+ remove_range(virt, size, &ofmem->io_range);
+}
+
+/* release memory allocated by ofmem_claim - 6.3.2.4 */
+void ofmem_release( ucell virt, ucell size )
+{
+ OFMEM_TRACE("%s addr=" FMT_ucellx " size=" FMT_ucellx "\n",
+ __func__, virt, size);
+
+ ucell mode;
+ phys_addr_t phys = ofmem_translate(virt, &mode);
+ if (phys == (phys_addr_t)-1) {
+ OFMEM_TRACE("%s: no mapping\n", __func__);
+ return;
+ }
+ ofmem_unmap(virt, size);
+ ofmem_release_virt(virt, size);
+ ofmem_release_phys(phys, size);
+}
+
+/************************************************************************/
+/* init / cleanup */
+/************************************************************************/
+
+void ofmem_register( phandle_t ph_memory, phandle_t ph_mmu )
+{
+ s_phandle_memory = ph_memory;
+ s_phandle_mmu = ph_mmu;
+
+ /* Initialise some default property sizes */
+ trans_prop_size = phys_range_prop_size = virt_range_prop_size = OFMEM_DEFAULT_PROP_SIZE;
+ trans_prop = malloc(trans_prop_size);
+ phys_range_prop = malloc(phys_range_prop_size);
+ virt_range_prop = malloc(virt_range_prop_size);
+
+ ofmem_update_translations();
+}
diff --git a/roms/openbios/libopenbios/video_common.c b/roms/openbios/libopenbios/video_common.c
new file mode 100644
index 00000000..9bbc18c3
--- /dev/null
+++ b/roms/openbios/libopenbios/video_common.c
@@ -0,0 +1,258 @@
+/*
+ * Creation Date: <2002/10/23 20:26:40 samuel>
+ * Time-stamp: <2004/01/07 19:39:15 samuel>
+ *
+ * <video_common.c>
+ *
+ * Shared video routines
+ *
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libc/vsprintf.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/fontdata.h"
+#include "libopenbios/ofmem.h"
+#include "libopenbios/video.h"
+#include "packages/video.h"
+#include "drivers/vga.h"
+#define NO_QEMU_PROTOS
+#include "arch/common/fw_cfg.h"
+
+struct video_info video;
+
+unsigned long
+video_get_color( int col_ind )
+{
+ unsigned long col;
+ if( !VIDEO_DICT_VALUE(video.ih) || col_ind < 0 || col_ind > 255 )
+ return 0;
+ if( VIDEO_DICT_VALUE(video.depth) == 8 )
+ return col_ind;
+ col = video.pal[col_ind];
+ if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 )
+ return col;
+ if( VIDEO_DICT_VALUE(video.depth) == 15 )
+ return ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
+ return 0;
+}
+
+/* ( fbaddr maskaddr width height fgcolor bgcolor -- ) */
+
+void
+video_mask_blit(void)
+{
+ ucell bgcolor = POP();
+ ucell fgcolor = POP();
+ ucell height = POP();
+ ucell width = POP();
+ unsigned char *mask = (unsigned char *)POP();
+ unsigned char *fbaddr = (unsigned char *)POP();
+
+ ucell color;
+ unsigned char *dst, *rowdst;
+ int x, y, m, b, d, depthbytes;
+
+ fgcolor = video_get_color(fgcolor);
+ bgcolor = video_get_color(bgcolor);
+ d = VIDEO_DICT_VALUE(video.depth);
+ depthbytes = (d + 1) >> 3;
+
+ dst = fbaddr;
+ for( y = 0; y < height; y++) {
+ rowdst = dst;
+ for( x = 0; x < (width + 1) >> 3; x++ ) {
+ for (b = 0; b < 8; b++) {
+ m = (1 << (7 - b));
+
+ if (*mask & m) {
+ color = fgcolor;
+ } else {
+ color = bgcolor;
+ }
+
+ if( d >= 24 )
+ *((uint32_t*)dst) = color;
+ else if( d >= 15 )
+ *((uint16_t*)dst) = color;
+ else
+ *dst = color;
+
+ dst += depthbytes;
+ }
+ mask++;
+ }
+ dst = rowdst;
+ dst += VIDEO_DICT_VALUE(video.rb);
+ }
+}
+
+/* ( x y w h fgcolor bgcolor -- ) */
+
+void
+video_invert_rect( void )
+{
+ ucell bgcolor = POP();
+ ucell fgcolor = POP();
+ int h = POP();
+ int w = POP();
+ int y = POP();
+ int x = POP();
+ char *pp;
+
+ bgcolor = video_get_color(bgcolor);
+ fgcolor = video_get_color(fgcolor);
+
+ if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 ||
+ x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h))
+ return;
+
+ pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y;
+ for( ; h--; pp += *(video.rb) ) {
+ int ww = w;
+ if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) {
+ uint32_t *p = (uint32_t*)pp + x;
+ while( ww-- ) {
+ if (*p == fgcolor) {
+ *p++ = bgcolor;
+ } else if (*p == bgcolor) {
+ *p++ = fgcolor;
+ }
+ }
+ } else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) {
+ uint16_t *p = (uint16_t*)pp + x;
+ while( ww-- ) {
+ if (*p == (uint16_t)fgcolor) {
+ *p++ = bgcolor;
+ } else if (*p == (uint16_t)bgcolor) {
+ *p++ = fgcolor;
+ }
+ }
+ } else {
+ char *p = (char *)(pp + x);
+
+ while( ww-- ) {
+ if (*p == (char)fgcolor) {
+ *p++ = bgcolor;
+ } else if (*p == (char)bgcolor) {
+ *p++ = fgcolor;
+ }
+ }
+ }
+ }
+}
+
+/* ( color_ind x y width height -- ) (?) */
+void
+video_fill_rect(void)
+{
+ int h = POP();
+ int w = POP();
+ int y = POP();
+ int x = POP();
+ int col_ind = POP();
+
+ char *pp;
+ unsigned long col = video_get_color(col_ind);
+
+ if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 ||
+ x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h))
+ return;
+
+ pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y;
+ for( ; h--; pp += VIDEO_DICT_VALUE(video.rb) ) {
+ int ww = w;
+ if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) {
+ uint32_t *p = (uint32_t*)pp + x;
+ while( ww-- )
+ *p++ = col;
+ } else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) {
+ uint16_t *p = (uint16_t*)pp + x;
+ while( ww-- )
+ *p++ = col;
+ } else {
+ char *p = (char *)(pp + x);
+
+ while( ww-- )
+ *p++ = col;
+ }
+ }
+}
+
+void setup_video()
+{
+ /* Make everything inside the video_info structure point to the
+ values in the Forth dictionary. Hence everything is always in
+ sync. */
+ phandle_t options;
+ char buf[6];
+
+ feval("['] display-ih cell+");
+ video.ih = cell2pointer(POP());
+
+ feval("['] frame-buffer-adr cell+");
+ video.mvirt = cell2pointer(POP());
+ feval("['] openbios-video-width cell+");
+ video.w = cell2pointer(POP());
+ feval("['] openbios-video-height cell+");
+ video.h = cell2pointer(POP());
+ feval("['] depth-bits cell+");
+ video.depth = cell2pointer(POP());
+ feval("['] line-bytes cell+");
+ video.rb = cell2pointer(POP());
+ feval("['] color-palette cell+");
+ video.pal = cell2pointer(POP());
+
+ /* Set global variables ready for fb8-install */
+ PUSH( pointer2cell(video_mask_blit) );
+ fword("is-noname-cfunc");
+ feval("to fb8-blitmask");
+ PUSH( pointer2cell(video_fill_rect) );
+ fword("is-noname-cfunc");
+ feval("to fb8-fillrect");
+ PUSH( pointer2cell(video_invert_rect) );
+ fword("is-noname-cfunc");
+ feval("to fb8-invertrect");
+
+ /* Static information */
+ PUSH((ucell)fontdata);
+ feval("to (romfont)");
+ PUSH(FONT_HEIGHT);
+ feval("to (romfont-height)");
+ PUSH(FONT_WIDTH);
+ feval("to (romfont-width)");
+
+ /* Initialise the structure */
+ VIDEO_DICT_VALUE(video.w) = VGA_DEFAULT_WIDTH;
+ VIDEO_DICT_VALUE(video.h) = VGA_DEFAULT_HEIGHT;
+ VIDEO_DICT_VALUE(video.depth) = VGA_DEFAULT_DEPTH;
+ VIDEO_DICT_VALUE(video.rb) = VGA_DEFAULT_LINEBYTES;
+
+#if defined(CONFIG_QEMU) && (defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64))
+ /* If running from QEMU, grab the parameters from the firmware interface */
+ int w, h, d;
+
+ w = fw_cfg_read_i16(FW_CFG_ARCH_WIDTH);
+ h = fw_cfg_read_i16(FW_CFG_ARCH_HEIGHT);
+ d = fw_cfg_read_i16(FW_CFG_ARCH_DEPTH);
+ if (w && h && d) {
+ VIDEO_DICT_VALUE(video.w) = w;
+ VIDEO_DICT_VALUE(video.h) = h;
+ VIDEO_DICT_VALUE(video.depth) = d;
+ VIDEO_DICT_VALUE(video.rb) = (w * ((d + 7) / 8));
+ }
+#endif
+
+ /* Setup screen-#rows/screen-#columns */
+ options = find_dev("/options");
+ snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.w) / FONT_WIDTH);
+ set_property(options, "screen-#columns", buf, strlen(buf) + 1);
+ snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.h) / FONT_HEIGHT);
+ set_property(options, "screen-#rows", buf, strlen(buf) + 1);
+}
diff --git a/roms/openbios/libopenbios/xcoff_load.c b/roms/openbios/libopenbios/xcoff_load.c
new file mode 100644
index 00000000..0dcb28ca
--- /dev/null
+++ b/roms/openbios/libopenbios/xcoff_load.c
@@ -0,0 +1,147 @@
+/*
+ *
+ * <xcoff_load.c>
+ *
+ * XCOFF file loader
+ *
+ * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
+ *
+ * from original XCOFF loader by Steven Noonan <steven@uplinklabs.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/xcoff_load.h"
+
+#include "arch/common/xcoff.h"
+
+#ifdef CONFIG_PPC
+extern void flush_icache_range( char *start, char *stop );
+#endif
+
+//#define DEBUG_XCOFF
+
+#ifdef DEBUG_XCOFF
+#define DPRINTF(fmt, args...) \
+ do { printk("%s: " fmt, __func__ , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) \
+ do { } while (0)
+#endif
+
+int
+is_xcoff(COFF_filehdr_t *fhdr)
+{
+ return (fhdr->f_magic == U802WRMAGIC
+ || fhdr->f_magic == U802ROMAGIC
+ || fhdr->f_magic == U802TOCMAGIC
+ || fhdr->f_magic == U802TOMAGIC);
+}
+
+int
+xcoff_load(struct sys_info *info, const char *filename)
+{
+ // Currently not implemented
+ return LOADER_NOT_SUPPORT;
+}
+
+void
+xcoff_init_program(void)
+{
+ char *base;
+ COFF_filehdr_t *fhdr;
+ COFF_aouthdr_t *ahdr;
+ COFF_scnhdr_t *shdr;
+ uint32_t offset;
+ size_t total_size = 0;
+ int i;
+
+ feval("0 state-valid !");
+
+ feval("load-base");
+ base = (char*)cell2pointer(POP());
+
+ fhdr = (COFF_filehdr_t*)base;
+
+ /* Is it an XCOFF file ? */
+ if (!is_xcoff(fhdr)) {
+ DPRINTF("Not a XCOFF file %02x\n", fhdr->f_magic);
+ return;
+ }
+
+ /* Is it executable ? */
+ if (fhdr->f_magic != 0x01DF &&
+ (fhdr->f_flags & COFF_F_EXEC) == 0) {
+ DPRINTF("Not an executable XCOFF file %02x\n", fhdr->f_flags);
+ return;
+ }
+
+ /* Optional header is a.out ? */
+ if (fhdr->f_opthdr != sizeof(COFF_aouthdr_t)) {
+ DPRINTF("AOUT optional error size mismatch in XCOFF file\n");
+ return;
+ }
+
+ ahdr = (COFF_aouthdr_t*)(base + sizeof(COFF_filehdr_t));
+
+ /* check a.out magic number */
+ if (ahdr->magic != AOUT_MAGIC) {
+ DPRINTF("Invalid AOUT optional header\n");
+ return;
+ }
+
+ offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t);
+
+ DPRINTF("XCOFF file with %d sections\n", fhdr->f_nscns);
+
+ for (i = 0; i < fhdr->f_nscns; i++) {
+
+ DPRINTF("Read header at offset %0x\n", offset);
+
+ shdr = (COFF_scnhdr_t*)(base + offset);
+
+ DPRINTF("Initializing '%s' section from %0x %0x to %0x (%0x)\n",
+ shdr->s_name, offset, shdr->s_scnptr,
+ shdr->s_vaddr, shdr->s_size);
+
+ if (strcmp(shdr->s_name, ".text") == 0) {
+
+ memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
+ shdr->s_size);
+ total_size += shdr->s_size;
+#ifdef CONFIG_PPC
+ flush_icache_range((char*)(uintptr_t)shdr->s_vaddr,
+ (char*)(uintptr_t)(shdr->s_vaddr + shdr->s_size));
+#endif
+ } else if (strcmp(shdr->s_name, ".data") == 0) {
+
+ memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
+ shdr->s_size);
+ total_size += shdr->s_size;
+
+ } else if (strcmp(shdr->s_name, ".bss") == 0) {
+
+ memset((void *)(uintptr_t)shdr->s_vaddr, 0, shdr->s_size);
+ total_size += shdr->s_size;
+ } else {
+ DPRINTF(" Skip '%s' section\n", shdr->s_name);
+ }
+ offset += sizeof(COFF_scnhdr_t);
+ }
+
+ DPRINTF("XCOFF entry point: %x\n", *(uint32_t*)ahdr->entry);
+
+ // Initialise saved-program-state
+ PUSH(*(uint32_t*)(uintptr_t)ahdr->entry);
+ feval("saved-program-state >sps.entry !");
+ PUSH(total_size);
+ feval("saved-program-state >sps.file-size !");
+ feval("xcoff saved-program-state >sps.file-type !");
+
+ feval("-1 state-valid !");
+}
diff --git a/roms/openbios/packages/bootinfo-loader.c b/roms/openbios/packages/bootinfo-loader.c
new file mode 100644
index 00000000..1497227c
--- /dev/null
+++ b/roms/openbios/packages/bootinfo-loader.c
@@ -0,0 +1,29 @@
+/*
+ *
+ * <bootinfo-loader.c>
+ *
+ * bootinfo file loader
+ *
+ * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/bootinfo_load.h"
+#include "packages.h"
+
+DECLARE_NODE(bootinfo_loader, INSTALL_OPEN, 0, "+/packages/bootinfo-loader" );
+
+NODE_METHODS( bootinfo_loader ) = {
+ { "init-program", bootinfo_init_program },
+};
+
+void bootinfo_loader_init( void )
+{
+ REGISTER_NODE( bootinfo_loader );
+}
diff --git a/roms/openbios/packages/build.xml b/roms/openbios/packages/build.xml
new file mode 100644
index 00000000..bf49099c
--- /dev/null
+++ b/roms/openbios/packages/build.xml
@@ -0,0 +1,23 @@
+<build>
+
+ <library name="packages" type="static" target="target">
+ <object source="bootinfo-loader.c" condition="LOADER_BOOTINFO"/>
+ <object source="cmdline.c" condition="CMDLINE"/>
+ <object source="deblocker.c" condition="DEBLOCKER"/>
+ <object source="disk-label.c" condition="DISK_LABEL"/>
+ <object source="elf-loader.c" condition="LOADER_ELF"/>
+ <object source="init.c"/>
+ <object source="mac-parts.c" condition="MAC_PARTS"/>
+ <object source="nvram.c"/>
+ <object source="pc-parts.c" condition="PC_PARTS"/>
+ <object source="sun-parts.c" condition="SUN_PARTS"/>
+ <object source="molvideo.c" condition="MOL"/>
+ <object source="xcoff-loader.c" condition="LOADER_XCOFF"/>
+ </library>
+
+ <dictionary name="openbios" target="forth">
+ <object source="cmdline.fs"/>
+ <object source="disk-label.fs"/>
+ </dictionary>
+
+</build>
diff --git a/roms/openbios/packages/cmdline.c b/roms/openbios/packages/cmdline.c
new file mode 100644
index 00000000..ea6bca3d
--- /dev/null
+++ b/roms/openbios/packages/cmdline.c
@@ -0,0 +1,415 @@
+/*
+ * Creation Date: <2003/12/28 14:16:31 samuel>
+ * Time-stamp: <2004/01/07 10:37:40 samuel>
+ *
+ * <cmdline.c>
+ *
+ * OpenFirmwware User Interface
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "packages.h"
+#include "libc/vsprintf.h"
+
+typedef struct {
+ char *buf; /* size: ncol+1 */
+ char *killbuf; /* size: ncol+1 */
+ char *history;
+ int hsize; /* size of history buffer */
+ int ncol; /* #columns */
+} cmdline_info_t;
+
+DECLARE_NODE( cmdline, INSTALL_OPEN, sizeof(cmdline_info_t),
+ "+/packages/cmdline" );
+
+static void
+emit( int ch )
+{
+ PUSH( ch );
+ fword("emit");
+}
+
+static int
+emit_str( const char *str )
+{
+ int n = 0;
+ while( *str ) {
+ n++;
+ emit( *str++ );
+ }
+ return n;
+}
+
+static void
+move_cursor( int n )
+{
+ if( n >= 0 ) {
+ while( n-- )
+ emit( '\f' );
+ } else {
+ while( n++ )
+ emit( 8 );
+ }
+}
+
+static void
+clear( int n )
+{
+ int i;
+ for( i=0; i<n; i++ )
+ emit(' ');
+ move_cursor( -n );
+}
+
+static void
+clearline( int pos, int n )
+{
+ move_cursor( -pos );
+ clear( n );
+}
+
+static int
+key( void )
+{
+ fword("key");
+ return POP();
+}
+
+/* ( -- flag ) */
+static void
+cmdline_open( cmdline_info_t *ci )
+{
+ ci->ncol = 80;
+ ci->buf = malloc( ci->ncol + 1 );
+ ci->killbuf = malloc( ci->ncol + 1 );
+
+ ci->hsize = 40;
+ ci->history = malloc( ci->hsize );
+ ci->history[0] = 0;
+
+ RET( -1 );
+}
+
+/* ( -- ) */
+static void
+cmdline_close( cmdline_info_t *ci )
+{
+ free( ci->buf );
+ free( ci->killbuf );
+ free( ci->history );
+}
+
+
+static char *
+history_get( cmdline_info_t *ci, int n )
+{
+ char *p = ci->history;
+ int len;
+
+ while( n-- && p )
+ if( (p=strchr(p,'\n')) )
+ p++;
+
+ ci->buf[0] = 0;
+ if( !p )
+ return NULL;
+
+ for( len=0; len <= ci->ncol && p[len] != '\n' && p[len] ; len++ )
+ ;
+ memcpy( ci->buf, p, len );
+ ci->buf[len] = 0;
+ return p;
+}
+
+static int
+history_remove( cmdline_info_t *ci, int line )
+{
+ char *s, *p = history_get( ci, line );
+
+ if( !p || !(s=strchr(p, '\n')) )
+ return 1;
+ s++;
+ memmove( p, s, strlen(s)+1 );
+ return 0;
+}
+
+static int /* ( -- ) */
+add_to_history( cmdline_info_t *ci, char *str )
+{
+ int n, len;
+
+ if( !ci->history )
+ return 0;
+ len = strlen(str);
+ if( !len )
+ return 0;
+
+ /* make room for line in history */
+ for( ;; ) {
+ char *p;
+ n = strlen(ci->history) + 1;
+
+ if( n + len + 1 <= ci->hsize )
+ break;
+
+ if( !(p=strrchr(ci->history,'\n')) )
+ return 0;
+ *p = 0;
+ if( !(p=strrchr(ci->history, '\n')) )
+ p = ci->history-1;
+ p[1] = 0;
+ }
+
+ memmove( ci->history + len + 1, ci->history, n );
+ memcpy( ci->history, str, len );
+ ci->history[ len ] = '\n';
+ return 1;
+}
+
+static void /* ( -- ) */
+cmdline_prompt( cmdline_info_t *ci )
+{
+ int cur_added=0, histind=0, ch, i, pos=0, n=0, prompt=1;
+ char *buf;
+ int terminate = 0;
+
+ buf = ci->buf;
+ selfword("prepare");
+
+ emit('\n');
+#ifdef NOLEAVE
+ for (;;)
+#else
+ while (rstackcnt && !terminate)
+#endif
+ {
+ int drop = 0;
+ terminate = 0;
+
+ if( prompt ) {
+ fword("print-prompt");
+ buf[0] = 0;
+ cur_added = prompt = histind = pos = n = 0;
+ }
+
+ ch = key();
+ switch( ch ) {
+ case 27:
+ switch( key() ) {
+ case 'f':
+ while( buf[pos] == ' ' )
+ emit( buf[pos++] );
+ while( buf[pos] && buf[pos] != ' ' )
+ emit( buf[pos++] );
+ break;
+
+ case 'b':
+ while( pos && buf[pos-1] == ' ' ) {
+ move_cursor( -1 );
+ pos--;
+ }
+ while( pos && buf[pos-1] != ' ' ) {
+ move_cursor( -1 );
+ pos--;
+ }
+ break;
+ case '[':
+ switch( key() ) {
+ case 'A':
+ goto go_up;
+ case 'B':
+ goto go_down;
+ case 'C':
+ goto go_right;
+ case 'D':
+ goto go_left;
+ case '3':
+ key();
+ goto delete;
+ }
+ break;
+ case 'O':
+ switch(key()) {
+ case 'F':
+ goto go_end;
+ case 'H':
+ goto go_home;
+ }
+ break;
+ }
+ break;
+ case '\n':
+ case '\r':
+ if( cur_added )
+ history_remove( ci, 0 );
+ add_to_history( ci, ci->buf );
+
+ emit_str( &buf[pos] );
+ emit(' ');
+ PUSH( feval(buf) );
+ fword("print-status");
+
+ /* Leave the interpreter if terminate? value set */
+ fword("terminate?");
+ if (POP())
+ terminate = 1;
+
+ prompt = 1;
+ break;
+
+ case 3: /* ^c */
+ emit_str("\n");
+ prompt = 1;
+ if( cur_added )
+ history_remove( ci, 0 );
+ break;
+
+ case 4: /* ^d */
+delete:
+ if( pos == n )
+ break;
+ emit( buf[pos++] );
+ /* fall through */
+
+ case 8: /* ^h */
+ case 127: /* backspace */
+ drop = 1;
+ if( !pos )
+ break;
+ move_cursor( -1 );
+ emit_str( &buf[pos] );
+ emit(' ');
+ memmove( &buf[pos-1], &buf[pos], n+1-pos );
+ move_cursor( pos-n-1 );
+ pos--;
+ n--;
+ break;
+
+ case 1: /* ^a */
+go_home:
+ move_cursor( -pos );
+ pos = 0;
+ break;
+
+ case 5: /* ^e */
+go_end:
+ pos += emit_str( &buf[pos] );
+ break;
+
+ //case 68: /* left */
+ // drop = 1;
+ case 2: /* ^b */
+go_left:
+ if( pos ) {
+ move_cursor( -1 );
+ pos--;
+ }
+ break;
+
+ //case 67: /* right */
+ // drop = 1;
+ case 6: /* ^f */
+go_right:
+ if( pos < n )
+ emit( buf[pos++] );
+ break;
+
+ case 11: /* ^k */
+ strcpy( ci->killbuf, &buf[pos] );
+ clear( n-pos );
+ n = pos;
+ buf[pos] = 0;
+ break;
+
+ case 25: /* ^y */
+ for( i=0; n < ci->ncol && ci->killbuf[i] ; i++, n++ ) {
+ memmove( &buf[pos+1], &buf[pos], n+1-pos );
+ buf[pos] = ci->killbuf[i];
+ move_cursor( 1-emit_str(&buf[pos++]) );
+ }
+ break;
+
+ case 9: /* TAB */
+ for( i=0; n < ci->ncol && (!i || (pos%4)) ; i++, n++ ) {
+ memmove( &buf[pos+1], &buf[pos], n+1-pos );
+ buf[pos] = ' ';
+ move_cursor( 1-emit_str(&buf[pos++]) );
+ }
+ break;
+
+ case 12: /* ^l */
+ move_cursor( -ci->ncol -pos );
+ fword("print-prompt");
+ move_cursor( pos-emit_str(buf) );
+ break;
+
+ //case 66: /* down */
+ // drop = 1;
+ case 14: /* ^n */
+go_down:
+ if( !histind )
+ break;
+ history_get( ci, --histind - 1);
+ clearline( pos, n );
+ emit_str( buf );
+ pos = n = strlen( buf );
+ if( !histind && cur_added ) {
+ cur_added = 0;
+ history_remove( ci, 0 );
+ }
+ break;
+
+ //case 65: /* up */
+ // drop = 1;
+ case 16: /* ^p */
+go_up:
+ if( !histind && add_to_history(ci, ci->buf) ) {
+ cur_added = 1;
+ histind++;
+ }
+ if( history_get(ci, histind) )
+ histind++;
+ clearline( pos, n );
+ emit_str( buf );
+ pos = n = strlen( buf );
+ break;
+ }
+ if( (unsigned int)ch < 32 )
+ drop = 1;
+
+ if( !drop && n < ci->ncol ) {
+ memmove( &buf[pos+1], &buf[pos], n+1-pos );
+ n++;
+ buf[pos] = ch;
+ move_cursor( 1-emit_str(&buf[pos++]) );
+ }
+ }
+
+ /* we only get here if terminate? is non-zero; this should
+ * only ever be done for a subordinate forth interpreter
+ * e.g. for debugging */
+
+ /* Reset stack and terminate? */
+ rstackcnt = dbgrstackcnt;
+ feval("0 to terminate?");
+}
+
+NODE_METHODS( cmdline ) = {
+ { "open", cmdline_open },
+ { "close", cmdline_close },
+ { "cmdline", cmdline_prompt },
+};
+
+void
+cmdline_init( void )
+{
+ REGISTER_NODE( cmdline );
+}
diff --git a/roms/openbios/packages/cmdline.fs b/roms/openbios/packages/cmdline.fs
new file mode 100644
index 00000000..70d3aa2d
--- /dev/null
+++ b/roms/openbios/packages/cmdline.fs
@@ -0,0 +1,41 @@
+\ tag: Utility functions
+\
+\ deblocker / filesystem support
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+\ -------------------------------------------------------------
+\ command line editor (/packages/cmdline)
+\ -------------------------------------------------------------
+
+[IFDEF] CONFIG_CMDLINE
+
+dev /packages
+new-device
+ " cmdline" device-name
+
+ :noname
+ " " [active-package], open-package
+ ?dup if
+ " cmdline" rot $call-method
+ else
+ ." cmdline is missing!" cr
+ then
+ \ cmdline must close itself upon return
+ ;
+
+ :noname
+ [ ['] (lit) , swap , ] to outer-interpreter
+ ; SYSTEM-initializer
+
+ external
+ : prepare 0 to my-self ;
+
+finish-device
+
+[THEN]
+device-end
diff --git a/roms/openbios/packages/deblocker.c b/roms/openbios/packages/deblocker.c
new file mode 100644
index 00000000..50071854
--- /dev/null
+++ b/roms/openbios/packages/deblocker.c
@@ -0,0 +1,221 @@
+/*
+ * Creation Date: <2003/12/03 21:20:58 samuel>
+ * Time-stamp: <2004/01/07 19:34:50 samuel>
+ *
+ * <deblocker.c>
+ *
+ * deblocker implementation
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+#include "packages.h"
+
+typedef struct {
+ ucell mark_hi, mark_lo;
+ xt_t read_xt;
+ xt_t write_xt;
+
+ int max_xfer;
+ int blksize;
+ char *buf;
+} deblk_info_t;
+
+DECLARE_NODE( deblocker, 0, sizeof(deblk_info_t), "+/packages/deblocker" );
+
+/* ( -- flag ) */
+static void
+deblk_open( deblk_info_t *di )
+{
+ xt_t xt;
+
+ di->read_xt = find_parent_method("read-blocks");
+ di->write_xt = find_parent_method("write-blocks");
+
+ if( !di->read_xt )
+ RET(0);
+
+ di->blksize = di->max_xfer = 512;
+ if( (xt=find_parent_method("block-size")) ) {
+ call_parent( xt );
+ di->blksize = POP();
+ }
+ if( (xt=find_parent_method("max-transfer")) ) {
+ call_parent( xt );
+ di->max_xfer = POP();
+ }
+ /* printk("block-size: %x max_xfer: %x read_xt %x write_xt %x\n",
+ di->blksize, di->max_xfer, di->write_xt, di->read_xt ); */
+
+ di->buf = malloc( di->blksize );
+ PUSH(-1);
+}
+
+/* ( -- ) */
+static void
+deblk_close( deblk_info_t *di )
+{
+ free( di->buf );
+}
+
+/* ( pos_lo pos_hi -- status ) */
+static void
+deblk_seek( deblk_info_t *di )
+{
+ ucell pos_hi = POP();
+ ucell pos_lo = POP();
+ ducell mark = ((ducell)pos_hi << BITS) | pos_lo;
+
+ /* printk("deblk_seek %x %08x\n", pos_hi, pos_lo ); */
+
+ /* -1 means seek to EOF (at least in our implementation) */
+ if( (dcell)mark == -1 )
+ RET(-1);
+ di->mark_hi = pos_hi;
+ di->mark_lo = pos_lo;
+
+ /* 0,1 == success, -1 == error */
+ PUSH(0);
+}
+
+/* ( -- mark.d ) */
+static void
+deblk_tell( deblk_info_t *di )
+{
+ PUSH( di->mark_lo );
+ PUSH( di->mark_hi );
+}
+
+
+#define DO_IO( xt, buf, blk, n ) \
+ ({ PUSH3(pointer2cell(buf), blk, n); call_parent(xt); POP(); })
+
+typedef struct {
+ /* block operation */
+ char *blk_buf;
+ int nblks;
+
+ /* byte operation */
+ cell offs;
+ int len;
+ char *data; /* start of data */
+} work_t;
+
+static void
+split( deblk_info_t *di, char *data, int len, work_t w[3] )
+{
+ ducell mark = ((ducell)di->mark_hi << BITS) | di->mark_lo;
+ memset( w, 0, sizeof(work_t[3]) );
+
+ w[0].offs = mark % di->blksize;
+ w[0].blk_buf = di->buf;
+ w[0].data = data;
+ if( w[0].offs ) {
+ w[0].len = MIN( len, di->blksize - w[0].offs );
+ w[0].nblks = w[0].len ? 1:0;
+ data += w[0].len;
+ len -= w[0].len;
+ }
+
+ w[1].blk_buf = data;
+ w[1].nblks = (len / di->blksize);
+ w[1].len = w[1].nblks * di->blksize;
+ data += w[1].len;
+ len -= w[1].len;
+
+ w[2].blk_buf = di->buf;
+ w[2].data = data;
+ w[2].len = len;
+ w[2].nblks = len ? 1:0;
+}
+
+static int
+do_readwrite( deblk_info_t *di, int is_write, xt_t xt )
+{
+ int blk, i, n, len = POP();
+ char *dest = (char*)cell2pointer(POP());
+ int last=0, retlen=0;
+ work_t w[3];
+ ducell mark = ((ducell)di->mark_hi << BITS) | di->mark_lo;
+
+ /* printk("read: %x %x\n", (int)dest, len ); */
+
+ if( !xt )
+ return -1;
+
+ blk = mark / di->blksize;
+ split( di, dest, len, w );
+
+ for( i=0; !last && i<3; i++ ) {
+ if( !w[i].nblks )
+ continue;
+
+ if( is_write && i != 1 ) {
+ DO_IO( di->read_xt, w[i].blk_buf, blk, w[i].nblks );
+ memcpy( w[i].blk_buf + w[i].offs, w[i].data, w[i].len );
+ }
+
+ n = DO_IO( xt, w[i].blk_buf, blk, w[i].nblks );
+ if( n < 0 ) {
+ if( !retlen )
+ retlen = -1;
+ break;
+ }
+ if( n != w[i].nblks ) {
+ w[i].len = MIN( n*di->blksize, w[i].len );
+ last = 1;
+ }
+ if( !is_write && i != 1 )
+ memcpy( w[i].data, w[i].blk_buf + w[i].offs, w[i].len );
+ retlen += w[i].len;
+ blk += n;
+ }
+ if( retlen > 0 ) {
+ mark += retlen;
+ di->mark_hi = mark >> BITS;
+ di->mark_lo = mark & (ucell) -1;
+ }
+ return retlen;
+}
+
+/* ( addr len -- actual ) */
+static void
+deblk_read( deblk_info_t *di )
+{
+ /* printk("deblk_read\n"); */
+ int ret = do_readwrite( di, 0, di->read_xt );
+ PUSH( ret );
+}
+
+/* ( buf len --- actlen ) */
+static void
+deblk_write( deblk_info_t *di )
+{
+ int ret = do_readwrite( di, 1, di->write_xt );
+ PUSH( ret );
+}
+
+/* remember to fix is-deblocker if new methods are added */
+NODE_METHODS( deblocker ) = {
+ { "open", deblk_open },
+ { "close", deblk_close },
+ { "read", deblk_read },
+ { "write", deblk_write },
+ { "seek", deblk_seek },
+ { "tell", deblk_tell },
+};
+
+
+void
+deblocker_init( void )
+{
+ REGISTER_NODE( deblocker );
+}
diff --git a/roms/openbios/packages/disk-label.c b/roms/openbios/packages/disk-label.c
new file mode 100644
index 00000000..1ca9bd86
--- /dev/null
+++ b/roms/openbios/packages/disk-label.c
@@ -0,0 +1,245 @@
+/*
+ * Creation Date: <2003/12/03 22:10:45 samuel>
+ * Time-stamp: <2004/01/07 19:17:45 samuel>
+ *
+ * <disk-label.c>
+ *
+ * Partition support
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/load.h"
+#include "libc/diskio.h"
+#include "libc/vsprintf.h"
+#include "packages.h"
+
+//#define DEBUG_DISK_LABEL
+
+#ifdef DEBUG_DISK_LABEL
+#define DPRINTF(fmt, args...) \
+do { printk("DISK-LABEL - %s: " fmt, __func__ , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do { } while (0)
+#endif
+
+typedef struct {
+ xt_t parent_seek_xt;
+ xt_t parent_tell_xt;
+ xt_t parent_read_xt;
+
+ ucell offs_hi, offs_lo;
+ ucell size_hi, size_lo;
+ int block_size;
+ int type; /* partition type or -1 */
+
+ ihandle_t part_ih;
+ phandle_t filesystem_ph;
+} dlabel_info_t;
+
+DECLARE_NODE( dlabel, 0, sizeof(dlabel_info_t), "/packages/disk-label" );
+
+
+/* ( -- ) */
+static void
+dlabel_close( __attribute__((unused))dlabel_info_t *di )
+{
+}
+
+/* ( -- success? ) */
+static void
+dlabel_open( dlabel_info_t *di )
+{
+ char *path;
+ char block0[512];
+ phandle_t ph;
+ int success=0;
+ cell status;
+
+ path = my_args_copy();
+
+ DPRINTF("dlabel-open '%s'\n", path );
+
+ di->part_ih = 0;
+
+ /* Find parent methods */
+ di->filesystem_ph = 0;
+ di->parent_seek_xt = find_parent_method("seek");
+ di->parent_tell_xt = find_parent_method("tell");
+ di->parent_read_xt = find_parent_method("read");
+
+ /* If arguments have been passed, determine the partition/filesystem type */
+ if (path && strlen(path)) {
+
+ /* Read first block from parent device */
+ DPUSH(0);
+ call_package(di->parent_seek_xt, my_parent());
+ POP();
+
+ PUSH(pointer2cell(block0));
+ PUSH(sizeof(block0));
+ call_package(di->parent_read_xt, my_parent());
+ status = POP();
+ if (status != sizeof(block0))
+ goto out;
+
+ /* Find partition handler */
+ PUSH( pointer2cell(block0) );
+ selfword("find-part-handler");
+ ph = POP_ph();
+ if( ph ) {
+ /* We found a suitable partition handler, so interpose it */
+ DPRINTF("Partition found on disk - scheduling interpose with ph " FMT_ucellx "\n", ph);
+
+ push_str(path);
+ PUSH_ph(ph);
+ fword("interpose");
+
+ success = 1;
+ } else {
+ /* unknown (or missing) partition map,
+ * try the whole disk
+ */
+
+ DPRINTF("Unknown or missing partition map; trying whole disk\n");
+
+ /* Probe for filesystem from start of device */
+ DPUSH ( 0 );
+ PUSH_ih( my_self() );
+ selfword("find-filesystem");
+ ph = POP_ph();
+ if( ph ) {
+ /* If we have been asked to open a particular file, interpose the filesystem package with the passed filename as an argument */
+ di->filesystem_ph = ph;
+
+ DPRINTF("Located filesystem with ph " FMT_ucellx "\n", ph);
+ DPRINTF("path: %s length: %d\n", path, strlen(path));
+
+ if (path && strlen(path)) {
+ DPRINTF("INTERPOSE!\n");
+
+ push_str( path );
+ PUSH_ph( ph );
+ fword("interpose");
+ }
+ } else if (path && strcmp(path, "%BOOT") != 0) {
+ goto out;
+ }
+
+ success = 1;
+ }
+ } else {
+ /* No arguments were passed, so we just use the parent raw device directly */
+ success = 1;
+ }
+
+out:
+ if( path )
+ free( path );
+ if( !success ) {
+ dlabel_close( di );
+ RET(0);
+ }
+ PUSH(-1);
+}
+
+/* ( addr len -- actual ) */
+static void
+dlabel_read( dlabel_info_t *di )
+{
+ /* Call back up to parent */
+ call_package(di->parent_read_xt, my_parent());
+}
+
+/* ( pos.d -- status ) */
+static void
+dlabel_seek( dlabel_info_t *di )
+{
+ /* Call back up to parent */
+ call_package(di->parent_seek_xt, my_parent());
+}
+
+/* ( -- filepos.d ) */
+static void
+dlabel_tell( dlabel_info_t *di )
+{
+ /* Call back up to parent */
+ call_package(di->parent_tell_xt, my_parent());
+}
+
+/* ( addr len -- actual ) */
+static void
+dlabel_write( __attribute__((unused)) dlabel_info_t *di )
+{
+ DDROP();
+ PUSH( -1 );
+}
+
+/* ( addr -- size ) */
+static void
+dlabel_load( __attribute__((unused)) dlabel_info_t *di )
+{
+ /* Try the load method of the part package */
+ xt_t xt;
+
+ /* If we have a partition handle, invoke the load word on it */
+ if (di->part_ih) {
+ xt = find_ih_method("load", di->part_ih);
+ if (!xt) {
+ forth_printf("load currently not implemented for ihandle " FMT_ucellx "\n", di->part_ih);
+ PUSH(0);
+ return;
+ }
+
+ DPRINTF("calling load on ihandle " FMT_ucellx "\n", di->part_ih);
+
+ call_package(xt, di->part_ih);
+ } else {
+ /* Otherwise attempt load directly on the raw disk */
+ DPRINTF("calling load on raw disk ihandle " FMT_ucellx "\n", my_self());
+
+ load(my_self());
+ }
+}
+
+/* ( pathstr len -- ) */
+static void
+dlabel_dir( dlabel_info_t *di )
+{
+ if ( di->filesystem_ph ) {
+ PUSH( my_self() );
+ push_str("dir");
+ PUSH( di->filesystem_ph );
+ fword("find-method");
+ POP();
+ fword("execute");
+ } else {
+ forth_printf("disk-label: Unable to determine filesystem\n");
+ POP();
+ POP();
+ }
+}
+
+NODE_METHODS( dlabel ) = {
+ { "open", dlabel_open },
+ { "close", dlabel_close },
+ { "load", dlabel_load },
+ { "read", dlabel_read },
+ { "write", dlabel_write },
+ { "seek", dlabel_seek },
+ { "tell", dlabel_tell },
+ { "dir", dlabel_dir },
+};
+
+void
+disklabel_init( void )
+{
+ REGISTER_NODE( dlabel );
+}
diff --git a/roms/openbios/packages/disk-label.fs b/roms/openbios/packages/disk-label.fs
new file mode 100644
index 00000000..8354f878
--- /dev/null
+++ b/roms/openbios/packages/disk-label.fs
@@ -0,0 +1,102 @@
+\ tag: Utility functions
+\
+\ deblocker / filesystem support
+\
+\ Copyright (C) 2003, 2004 Samuel Rydh
+\
+\ See the file "COPYING" for further information about
+\ the copyright and warranty status of this work.
+\
+
+dev /packages
+
+\ -------------------------------------------------------------
+\ /packages/disk-label (partition handling)
+\ -------------------------------------------------------------
+
+[IFDEF] CONFIG_DISK_LABEL
+
+new-device
+ " disk-label" device-name
+ external
+
+ variable part-handlers \ list with (probe-xt, phandle) elements
+ variable fs-handlers \ list with (fs-probe-xt, phandle) elements
+
+ : find-part-handler ( block0 -- phandle | 0 )
+ >r part-handlers
+ begin list-get while
+ ( nextlist dictptr )
+ r@ over @ execute if
+ ( nextlist dictptr )
+ na1+ @ r> rot 2drop exit
+ then
+ drop
+ repeat
+ r> drop 0
+ ;
+
+ : find-filesystem ( offs.d ih -- ph | 0 )
+ >r fs-handlers ( offs.d listhead )
+ begin list-get while
+ 2over ( offs.d nextlist dictptr offs.d )
+ r@ ( offs.d nextlist dictptr offs.d ih )
+ 3 pick ( offs.d nextlist dictptr offs.d ih dictptr )
+ @ ( offs.d nextlist dictptr offs.d ih probe-xt )
+ execute ( offs.d nextlist dictptr flag? )
+ if
+ ( offs.d nextlist dictptr )
+ na1+ ( offs.d nextlist dictptr+1 )
+ @ ( offs.d nextlist phandle )
+ r> ( offs.d nextlist phandle ih )
+ rot ( offs.d phandle ih nextlist )
+ 2drop ( offs.d phandle )
+ -rot ( phandle offs.d )
+ 2drop ( phandle )
+ exit
+ then
+ drop ( offs.d nextlist )
+ repeat
+ 2drop ( offs.d )
+ r> drop 0
+ ;
+
+
+ : register-part-handler ( handler-ph -- )
+ dup " probe" rot find-method
+ 0= abort" Missing probe method!"
+ ( phandle probe-xt )
+ part-handlers list-add , ,
+ ;
+
+ : register-fs-handler ( handler-ph -- )
+ dup " probe" rot find-method
+ 0= abort" Missing probe method!"
+ ( phandle probe-xt )
+ fs-handlers list-add , ,
+ ;
+finish-device
+
+\ ---------------------------------------------------------------------------
+\ methods to register partion and filesystem packages used by disk-label
+\ ---------------------------------------------------------------------------
+
+device-end
+: register-partition-package ( -- )
+ " register-part-handler" " disk-label" $find-package-method ?dup if
+ active-package swap execute
+ else
+ ." [disk-label] internal error" cr
+ then
+;
+
+: register-fs-package ( -- )
+ " register-fs-handler" " disk-label" $find-package-method ?dup if
+ active-package swap execute
+ else
+ ." [misc-files] internal error" cr
+ then
+;
+
+[THEN]
+device-end
diff --git a/roms/openbios/packages/elf-loader.c b/roms/openbios/packages/elf-loader.c
new file mode 100644
index 00000000..1665f0d0
--- /dev/null
+++ b/roms/openbios/packages/elf-loader.c
@@ -0,0 +1,31 @@
+/*
+ *
+ * <elf-loader.c>
+ *
+ * ELF file loader
+ *
+ * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
+ *
+ * Some parts Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/elf_load.h"
+#include "packages.h"
+
+DECLARE_NODE(elf_loader, INSTALL_OPEN, 0, "+/packages/elf-loader" );
+
+NODE_METHODS( elf_loader ) = {
+ { "init-program", elf_init_program },
+};
+
+void elf_loader_init( void )
+{
+ REGISTER_NODE( elf_loader );
+}
diff --git a/roms/openbios/packages/init.c b/roms/openbios/packages/init.c
new file mode 100644
index 00000000..bff8558a
--- /dev/null
+++ b/roms/openbios/packages/init.c
@@ -0,0 +1,67 @@
+/*
+ * Creation Date: <2003/12/23 00:28:05 samuel>
+ * Time-stamp: <2003/12/28 19:43:41 samuel>
+ *
+ * <init.c>
+ *
+ * Module intialization
+ *
+ * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "kernel/kernel.h"
+#include "packages.h"
+
+void
+modules_init( void )
+{
+#ifdef CONFIG_CMDLINE
+ cmdline_init();
+#endif
+#ifdef CONFIG_DEBLOCKER
+ deblocker_init();
+#endif
+#ifdef CONFIG_DISK_LABEL
+ disklabel_init();
+#endif
+#ifdef CONFIG_HFSP
+ hfsp_init();
+#endif
+#ifdef CONFIG_HFS
+ hfs_init();
+#endif
+#ifdef CONFIG_EXT2
+ ext2_init();
+#endif
+#ifdef CONFIG_ISO9660
+ iso9660_init();
+#endif
+#ifdef CONFIG_GRUBFS
+ grubfs_init();
+#endif
+#ifdef CONFIG_MAC_PARTS
+ macparts_init();
+#endif
+#ifdef CONFIG_PC_PARTS
+ pcparts_init();
+#endif
+#ifdef CONFIG_SUN_PARTS
+ sunparts_init();
+#endif
+#ifdef CONFIG_LOADER_XCOFF
+ xcoff_loader_init();
+#endif
+#ifdef CONFIG_LOADER_ELF
+ elf_loader_init();
+#endif
+#ifdef CONFIG_LOADER_BOOTINFO
+ bootinfo_loader_init();
+#endif
+
+}
diff --git a/roms/openbios/packages/mac-parts.c b/roms/openbios/packages/mac-parts.c
new file mode 100644
index 00000000..16c87caf
--- /dev/null
+++ b/roms/openbios/packages/mac-parts.c
@@ -0,0 +1,447 @@
+/*
+ * Creation Date: <2003/12/04 17:07:05 samuel>
+ * Time-stamp: <2004/01/07 19:36:09 samuel>
+ *
+ * <mac-parts.c>
+ *
+ * macintosh partition support
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/load.h"
+#include "mac-parts.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "packages.h"
+
+//#define CONFIG_DEBUG_MAC_PARTS
+
+#ifdef CONFIG_DEBUG_MAC_PARTS
+#define DPRINTF(fmt, args...) \
+do { printk("MAC-PARTS: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+typedef struct {
+ xt_t seek_xt, read_xt;
+ ucell offs_hi, offs_lo;
+ ucell size_hi, size_lo;
+ ucell bootcode_addr, bootcode_entry;
+ unsigned int blocksize;
+ phandle_t filesystem_ph;
+} macparts_info_t;
+
+DECLARE_NODE( macparts, INSTALL_OPEN, sizeof(macparts_info_t), "+/packages/mac-parts" );
+
+#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
+#define READ( buf, size ) ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); })
+
+/* ( open -- flag ) */
+static void
+macparts_open( macparts_info_t *di )
+{
+ char *str = my_args_copy();
+ char *parstr = NULL, *argstr = NULL;
+ char *tmpstr;
+ int bs, parnum=-1, apple_parnum=-1;
+ int parlist[2], parlist_size = 0;
+ desc_map_t dmap;
+ part_entry_t par;
+ int ret = 0, i = 0, j = 0;
+ int want_bootcode = 0;
+ phandle_t ph;
+ ducell offs = 0, size = -1;
+
+ DPRINTF("macparts_open '%s'\n", str );
+
+ /*
+ Arguments that we accept:
+ id: [0-7]
+ [(id)][,][filespec]
+ */
+
+ if ( str && strlen(str) ) {
+ /* Detect the arguments */
+ if ((*str >= '0' && *str <= '9') || (*str == ',')) {
+ push_str(str);
+ PUSH(',');
+ fword("left-parse-string");
+ parstr = pop_fstr_copy();
+ argstr = pop_fstr_copy();
+ } else {
+ argstr = str;
+ }
+
+ /* Make sure argstr is not null */
+ if (argstr == NULL)
+ argstr = strdup("");
+
+ /* Convert the id to a partition number */
+ if (parstr && strlen(parstr))
+ parnum = atol(parstr);
+
+ /* Detect if we are looking for the bootcode */
+ if (strcmp(argstr, "%BOOT") == 0) {
+ want_bootcode = 1;
+ }
+ }
+
+ DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
+
+ DPRINTF("want_bootcode %d\n", want_bootcode);
+ DPRINTF("macparts_open %d\n", parnum);
+
+ di->filesystem_ph = 0;
+ di->read_xt = find_parent_method("read");
+ di->seek_xt = find_parent_method("seek");
+
+ SEEK( 0 );
+ if( READ(&dmap, sizeof(dmap)) != sizeof(dmap) )
+ goto out;
+
+ /* partition maps might support multiple block sizes; in this case,
+ * pmPyPartStart is typically given in terms of 512 byte blocks.
+ */
+ bs = __be16_to_cpu(dmap.sbBlockSize);
+ if( bs != 512 ) {
+ SEEK( 512 );
+ READ( &par, sizeof(par) );
+ if( __be16_to_cpu(par.pmSig) == DESC_PART_SIGNATURE )
+ bs = 512;
+ }
+ SEEK( bs );
+ if( READ(&par, sizeof(par)) != sizeof(par) )
+ goto out;
+ if (__be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE)
+ goto out;
+
+ /*
+ * Implement partition selection as per the PowerPC Microprocessor CHRP bindings
+ */
+
+ if (argstr == NULL || parnum == 0) {
+ /* According to the spec, partition 0 as well as no arguments means the whole disk */
+ offs = (long long)0;
+ size = (long long)__be32_to_cpu(dmap.sbBlkCount) * bs;
+
+ di->blocksize = (unsigned int)bs;
+
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+
+ ret = -1;
+ goto out;
+
+ } else if (parnum == -1) {
+
+ DPRINTF("mac-parts: counted %d partitions\n", __be32_to_cpu(par.pmMapBlkCnt));
+
+ /* No partition was explicitly requested so let's find a suitable partition... */
+ for (i = 1; i <= __be32_to_cpu(par.pmMapBlkCnt); i++) {
+ SEEK( bs * i );
+ READ( &par, sizeof(par) );
+ if ( __be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE ||
+ !__be32_to_cpu(par.pmPartBlkCnt) )
+ continue;
+
+ DPRINTF("found partition %d type: %s with status %x\n", i, par.pmPartType, __be32_to_cpu(par.pmPartStatus));
+
+ /* If we have a valid, allocated and readable partition... */
+ if( (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
+ (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
+ (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) ) {
+
+ /* Unfortunately Apple's OF implementation doesn't follow the OF PowerPC CHRP bindings
+ * and instead will brute-force boot the first valid partition it finds with a
+ * type of either "Apple_Boot", "Apple_HFS" or "DOS_FAT_". Here we store the id
+ * of the first partition that matches these criteria to use as a fallback later
+ * if required. */
+
+ if (apple_parnum == -1 &&
+ (strcmp(par.pmPartType, "Apple_Boot") == 0 ||
+ strcmp(par.pmPartType, "Apple_Bootstrap") == 0 ||
+ strcmp(par.pmPartType, "Apple_HFS") == 0 ||
+ strcmp(par.pmPartType, "DOS_FAT_") == 0)) {
+ apple_parnum = i;
+
+ DPRINTF("Located Apple OF fallback partition %d\n", apple_parnum);
+ }
+
+ /* If the partition is also bootable and the pmProcessor field matches "PowerPC" (insensitive
+ * match), then according to the CHRP bindings this is our chosen partition */
+ for (j = 0; j < strlen(par.pmProcessor); j++) {
+ par.pmProcessor[j] = tolower(par.pmProcessor[j]);
+ }
+
+ if ((__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsBootValid) &&
+ strcmp(par.pmProcessor, "powerpc") == 0) {
+ parnum = i;
+
+ DPRINTF("Located CHRP-compliant boot partition %d\n", parnum);
+ }
+ }
+ }
+
+ /* If we found a valid CHRP partition, add it to the list */
+ if (parnum > 0) {
+ parlist[parlist_size++] = parnum;
+ }
+
+ /* If we found an Apple OF fallback partition, add it to the list */
+ if (apple_parnum > 0 && apple_parnum != parnum) {
+ parlist[parlist_size++] = apple_parnum;
+ }
+
+ } else {
+ /* Another partition was explicitly requested */
+ parlist[parlist_size++] = parnum;
+
+ DPRINTF("Partition %d explicitly requested\n", parnum);
+ }
+
+ /* Attempt to use our CHRP partition, optionally followed by our Apple OF fallback partition */
+ for (j = 0; j < parlist_size; j++) {
+
+ /* Make sure our partition is valid */
+ parnum = parlist[j];
+
+ DPRINTF("Selected partition %d\n", parnum);
+
+ SEEK( bs * parnum );
+ READ( &par, sizeof(par) );
+
+ if(! ((__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
+ (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
+ (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable)) ) {
+ DPRINTF("Partition %d is not valid, allocated and readable\n", parnum);
+ goto out;
+ }
+
+ ret = -1;
+
+ offs = (long long)__be32_to_cpu(par.pmPyPartStart) * bs;
+ size = (long long)__be32_to_cpu(par.pmPartBlkCnt) * bs;
+
+ if (want_bootcode) {
+
+ /* If size == 0 then fail because we requested bootcode but it doesn't exist */
+ size = (long long)__be32_to_cpu(par.pmBootSize);
+ if (!size) {
+ ret = 0;
+ goto out;
+ }
+
+ /* Adjust seek position so 0 = start of bootcode */
+ offs += (long long)__be32_to_cpu(par.pmLgBootStart) * bs;
+
+ di->bootcode_addr = __be32_to_cpu(par.pmBootLoad);
+ di->bootcode_entry = __be32_to_cpu(par.pmBootEntry);
+ }
+
+ di->blocksize = (unsigned int)bs;
+
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+
+ /* If we're trying to execute bootcode then we're all done */
+ if (want_bootcode) {
+ goto out;
+ }
+
+ /* We have a valid partition - so probe for a filesystem at the current offset */
+ DPRINTF("mac-parts: about to probe for fs\n");
+ DPUSH( offs );
+ PUSH_ih( my_parent() );
+ parword("find-filesystem");
+ DPRINTF("mac-parts: done fs probe\n");
+
+ ph = POP_ph();
+ if( ph ) {
+ DPRINTF("mac-parts: filesystem found on partition %d with ph " FMT_ucellx " and args %s\n", parnum, ph, argstr);
+ di->filesystem_ph = ph;
+
+ /* In case no partition was specified, set a special selected-partition-args property
+ giving the device parameters that we can use to generate bootpath */
+ tmpstr = malloc(strlen(argstr) + 2 + 1);
+ if (strlen(argstr)) {
+ sprintf(tmpstr, "%d,%s", parnum, argstr);
+ } else {
+ sprintf(tmpstr, "%d", parnum);
+ }
+
+ push_str(tmpstr);
+ feval("strdup encode-string \" selected-partition-args\" property");
+
+ free(tmpstr);
+
+ /* If we have been asked to open a particular file, interpose the filesystem package with
+ the passed filename as an argument */
+ if (strlen(argstr)) {
+ push_str( argstr );
+ PUSH_ph( ph );
+ fword("interpose");
+ }
+
+ goto out;
+ } else {
+ DPRINTF("mac-parts: no filesystem found on partition %d; bypassing misc-files interpose\n", parnum);
+
+ /* Here we have a valid partition; however if we tried to pass in a file argument for a
+ partition that doesn't contain a filesystem, then we must fail */
+ if (strlen(argstr)) {
+ ret = 0;
+ }
+ }
+ }
+
+ free( str );
+
+out:
+ PUSH( ret );
+}
+
+/* ( block0 -- flag? ) */
+static void
+macparts_probe( macparts_info_t *dummy )
+{
+ desc_map_t *dmap = (desc_map_t*)cell2pointer(POP());
+
+ DPRINTF("macparts_probe %x ?= %x\n", dmap->sbSig, DESC_MAP_SIGNATURE);
+ if( __be16_to_cpu(dmap->sbSig) != DESC_MAP_SIGNATURE )
+ RET(0);
+ RET(-1);
+}
+
+/* ( -- type offset.d size.d ) */
+static void
+macparts_get_info( macparts_info_t *di )
+{
+ DPRINTF("macparts_get_info");
+
+ PUSH( -1 ); /* no type */
+ PUSH( di->offs_lo );
+ PUSH( di->offs_hi );
+ PUSH( di->size_lo );
+ PUSH( di->size_hi );
+}
+
+/* ( -- size entry addr ) */
+static void
+macparts_get_bootcode_info( macparts_info_t *di )
+{
+ DPRINTF("macparts_get_bootcode_info");
+
+ PUSH( di->size_lo );
+ PUSH( di->bootcode_entry );
+ PUSH( di->bootcode_addr );
+}
+
+static void
+macparts_block_size( macparts_info_t *di )
+{
+ DPRINTF("macparts_block_size = %x\n", di->blocksize);
+ PUSH(di->blocksize);
+}
+
+static void
+macparts_initialize( macparts_info_t *di )
+{
+ fword("register-partition-package");
+}
+
+/* ( pos.d -- status ) */
+static void
+macparts_seek(macparts_info_t *di )
+{
+ long long pos = DPOP();
+ long long offs, size;
+
+ DPRINTF("macparts_seek %llx:\n", pos);
+
+ /* Seek is invalid if we reach the end of the device */
+ size = ((ducell)di->size_hi << BITS) | di->size_lo;
+ if (pos > size)
+ RET( -1 );
+
+ /* Calculate the seek offset for the parent */
+ offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
+ offs += pos;
+ DPUSH(offs);
+
+ DPRINTF("macparts_seek parent offset %llx:\n", offs);
+
+ call_package(di->seek_xt, my_parent());
+}
+
+/* ( buf len -- actlen ) */
+static void
+macparts_read(macparts_info_t *di )
+{
+ DPRINTF("macparts_read\n");
+
+ /* Pass the read back up to the parent */
+ call_package(di->read_xt, my_parent());
+}
+
+/* ( addr -- size ) */
+static void
+macparts_load( __attribute__((unused))macparts_info_t *di )
+{
+ /* Invoke the loader */
+ load(my_self());
+}
+
+/* ( pathstr len -- ) */
+static void
+macparts_dir( macparts_info_t *di )
+{
+ /* On PPC Mac, the first partition chosen according to the CHRP boot
+ specification (i.e. marked as bootable) may not necessarily contain
+ a valid FS */
+ if ( di->filesystem_ph ) {
+ PUSH( my_self() );
+ push_str("dir");
+ PUSH( di->filesystem_ph );
+ fword("find-method");
+ POP();
+ fword("execute");
+ } else {
+ forth_printf("mac-parts: Unable to determine filesystem\n");
+ POP();
+ POP();
+ }
+}
+
+NODE_METHODS( macparts ) = {
+ { "probe", macparts_probe },
+ { "open", macparts_open },
+ { "seek", macparts_seek },
+ { "read", macparts_read },
+ { "load", macparts_load },
+ { "dir", macparts_dir },
+ { "get-info", macparts_get_info },
+ { "get-bootcode-info", macparts_get_bootcode_info },
+ { "block-size", macparts_block_size },
+ { NULL, macparts_initialize },
+};
+
+void
+macparts_init( void )
+{
+ REGISTER_NODE( macparts );
+}
diff --git a/roms/openbios/packages/mac-parts.h b/roms/openbios/packages/mac-parts.h
new file mode 100644
index 00000000..acfcbe04
--- /dev/null
+++ b/roms/openbios/packages/mac-parts.h
@@ -0,0 +1,88 @@
+/*
+ * Creation Date: <1999/07/06 15:45:12 samuel>
+ * Time-stamp: <2002/10/20 16:31:48 samuel>
+ *
+ * <partition_table.h>
+ *
+ * Headers describing the partition table
+ *
+ * Copyright (C) 1999, 2002 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#ifndef _H_PARTITION_TABLE
+#define _H_PARTITION_TABLE
+
+/* This information is based upon IM vol V. */
+
+#define DESC_MAP_SIGNATURE 0x4552
+#define DESC_PART_SIGNATURE 0x504d
+
+enum {
+ kPartitionAUXIsValid = 0x00000001,
+ kPartitionAUXIsAllocated = 0x00000002,
+ kPartitionAUXIsInUse = 0x00000004,
+ kPartitionAUXIsBootValid = 0x00000008,
+ kPartitionAUXIsReadable = 0x00000010,
+ kPartitionAUXIsWriteable = 0x00000020,
+ kPartitionAUXIsBootCodePositionIndependent = 0x00000040,
+ kPartitionISMountedAtStartup = 0x40000000,
+ kPartitionIsStartup = 0x80000000,
+ kPartitionIsChainCompatible = 0x00000100,
+ kPartitionIsRealDeviceDriver = 0x00000200,
+ kPartitionCanChainToNext = 0x00000400,
+};
+
+typedef struct {
+ u32 ddBlock; /* first block of driver */
+ u16 ddSize; /* driver size in blocks */
+ s16 ddType; /* 1 & -1 for SCSI */
+} driver_entry_t;
+
+typedef struct { /* Block 0 of a device */
+ u16 sbSig; /* always 0x4552 */
+ u16 sbBlockSize; /* 512 */
+ s32 sbBlkCount; /* #blocks on device */
+ u16 sbDevType; /* 0 */
+ u16 sbDevID; /* 0 */
+ u32 sbData; /* 0 */
+ s16 sbDrvrCount; /* #driver descriptors */
+
+ /* driver entries goes here */
+ driver_entry_t drivers[61] __attribute__ ((packed));
+
+ u16 filler1;
+ u32 filler2;
+} desc_map_t;
+
+typedef struct { /* Partition descriptor */
+ u16 pmSig; /* always 0x504d 'PM' */
+ u16 pmSigPad; /* 0 */
+ u32 pmMapBlkCnt; /* #blocks in partition map */
+ u32 pmPyPartStart; /* first physical block of part. */
+ u32 pmPartBlkCnt; /* #blocks in partition */
+ char pmPartName[32]; /* partition name */
+ char pmPartType[32]; /* partition type */
+
+ /* these fields may or may not be used */
+ u32 pmLgDataStart;
+ u32 pmDataCnt;
+ u32 pmPartStatus;
+ u32 pmLgBootStart;
+ u32 pmBootSize;
+ u32 pmBootLoad;
+ u32 pmBootLoad2;
+ u32 pmBootEntry;
+ u32 pmBootEntry2;
+ u32 pmBootCksum;
+ char pmProcessor[16];
+
+ char filler[376]; /* might contain extra information */
+} part_entry_t;
+
+
+#endif /* _H_PARTITION_TABLE */
diff --git a/roms/openbios/packages/molvideo.c b/roms/openbios/packages/molvideo.c
new file mode 100644
index 00000000..787c4dc0
--- /dev/null
+++ b/roms/openbios/packages/molvideo.c
@@ -0,0 +1,124 @@
+/*
+ * Creation Date: <2002/10/23 20:26:40 samuel>
+ * Time-stamp: <2004/01/07 19:39:15 samuel>
+ *
+ * <molvideo.c>
+ *
+ * Mac-on-Linux display node
+ *
+ * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+#include "libopenbios/ofmem.h"
+#include "drivers/drivers.h"
+#include "packages/video.h"
+#include "libopenbios/video.h"
+#include "drivers/vga.h"
+
+
+/************************************************************************/
+/* OF methods */
+/************************************************************************/
+
+DECLARE_NODE( video, 0, 0, "Tdisplay" );
+
+/* ( r g b index -- ) */
+static void
+molvideo_color_bang( void )
+{
+ int index = POP();
+ int b = POP();
+ int g = POP();
+ int r = POP();
+ unsigned long col = ((r << 16) & 0xff0000) | ((g << 8) & 0x00ff00) | (b & 0xff);
+ /* printk("color!: %08lx %08lx %08lx %08lx\n", r, g, b, index ); */
+
+ if( VIDEO_DICT_VALUE(video.depth) == 8 ) {
+ OSI_SetColor( index, col );
+ OSI_RefreshPalette();
+ }
+}
+
+/* ( -- ) - really should be reworked as draw-logo */
+static void
+molvideo_startup_splash( void )
+{
+ int fd, s, i, y, x, dx, dy;
+ int width, height;
+ char *pp, *p;
+ char buf[64];
+
+ /* only draw logo in 24-bit mode (for now) */
+ if( VIDEO_DICT_VALUE(video.depth) < 15 )
+ return;
+
+ for( i=0; i<2; i++ ) {
+ if( !BootHGetStrResInd("bootlogo", buf, sizeof(buf), 0, i) )
+ return;
+ *(!i ? &width : &height) = atol(buf);
+ }
+
+ if( (s=width * height * 3) > 0x20000 )
+ return;
+
+ if( (fd=open_io("pseudo:,bootlogo")) >= 0 ) {
+ p = malloc( s );
+ if( read_io(fd, p, s) != s )
+ printk("bootlogo size error\n");
+ close_io( fd );
+
+ dx = (VIDEO_DICT_VALUE(video.w) - width)/2;
+ dy = (VIDEO_DICT_VALUE(video.h) - height)/3;
+
+ pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + dy * VIDEO_DICT_VALUE(video.rb) + dx * (VIDEO_DICT_VALUE(video.depth) >= 24 ? 4 : 2);
+
+ for( y=0 ; y<height; y++, pp += VIDEO_DICT_VALUE(video.rb) ) {
+ if( VIDEO_DICT_VALUE(video.depth) >= 24 ) {
+ unsigned long *d = (unsigned long*)pp;
+ for( x=0; x<width; x++, p+=3, d++ )
+ *d = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2];
+ } else if( VIDEO_DICT_VALUE(video.depth) == 15 ) {
+ unsigned short *d = (unsigned short*)pp;
+ for( x=0; x<width; x++, p+=3, d++ ) {
+ int col = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2];
+ *d = ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
+ }
+ }
+ }
+ free( p );
+ }
+
+ /* No bootlogo support yet on other platforms */
+ return;
+}
+
+
+NODE_METHODS( video ) = {
+ {"mol-startup-splash", molvideo_startup_splash },
+};
+
+
+/************************************************************************/
+/* init */
+/************************************************************************/
+
+void
+molvideo_init(void)
+{
+ xt_t color_bang;
+
+ REGISTER_NODE( video );
+
+ /* Bind the MOL graphic routines to the mol-color! defer */
+ color_bang = bind_noname_func(molvideo_color_bang);
+ PUSH(color_bang);
+ feval(" to mol-color!");
+}
diff --git a/roms/openbios/packages/nvram.c b/roms/openbios/packages/nvram.c
new file mode 100644
index 00000000..3182edf5
--- /dev/null
+++ b/roms/openbios/packages/nvram.c
@@ -0,0 +1,308 @@
+/*
+ * Creation Date: <2003/12/01 00:26:13 samuel>
+ * Time-stamp: <2004/01/07 19:59:53 samuel>
+ *
+ * <nvram.c>
+ *
+ * medium-level NVRAM handling
+ *
+ * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "arch/common/nvram.h"
+#include "packages/nvram.h"
+
+//#define CONFIG_DEBUG_NVRAM 1
+
+#ifdef CONFIG_DEBUG_NVRAM
+#define DPRINTF(fmt, args...) \
+do { printk("NVRAM: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+#define DEF_SYSTEM_SIZE 0xc10
+
+#define NV_SIG_SYSTEM 0x70
+#define NV_SIG_FREE 0x7f
+
+
+typedef struct {
+ unsigned char signature;
+ unsigned char checksum;
+ unsigned char len_hi;
+ unsigned char len_lo;
+ char name[12];
+ char data[0];
+} nvpart_t;
+
+static struct {
+ char *data;
+ int size;
+
+ nvpart_t *config;
+ int config_size;
+} nvram;
+
+
+/************************************************************************/
+/* generic */
+/************************************************************************/
+
+static unsigned int
+nvpart_checksum( nvpart_t* hdr )
+{
+ unsigned char *p = (unsigned char*)hdr;
+ int i, val = p[0];
+
+ for( i=2; i<16; i++ ) {
+ val += p[i];
+ if( val > 255 )
+ val = (val - 256 + 1) & 0xff;
+ }
+ return val;
+}
+
+static inline int
+nvpart_size( nvpart_t *p )
+{
+ return (p->len_lo | ((int)p->len_hi<<8)) * 16;
+}
+
+static int
+next_nvpart( nvpart_t **p )
+{
+ nvpart_t *end = (nvpart_t*)(nvram.data + nvram.size);
+ int len;
+
+ if( !*p ) {
+ *p = (nvpart_t*)nvram.data;
+ return 1;
+ }
+
+ if( !(len=nvpart_size(*p)) ) {
+ printk("invalid nvram partition length\n");
+ return -1;
+ }
+ *p = (nvpart_t*)((char*)*p + len);
+ if( *p < end )
+ return 1;
+ if( *p == end )
+ return 0;
+ return -1;
+}
+
+static void
+create_free_part( char *ptr, int size )
+{
+ nvpart_t *nvp = (nvpart_t*)ptr;
+ memset( nvp, 0, size );
+
+ strncpy( nvp->name, "777777777777", sizeof(nvp->name) );
+ nvp->signature = NV_SIG_FREE;
+ nvp->len_hi = (size /16) >> 8;
+ nvp->len_lo = size /16;
+ nvp->checksum = nvpart_checksum(nvp);
+}
+
+static int
+create_nv_part( int signature, const char *name, int size )
+{
+ nvpart_t *p = NULL;
+ int fs;
+
+ while( next_nvpart(&p) > 0 ) {
+ if( p->signature != NV_SIG_FREE )
+ continue;
+
+ fs = nvpart_size( p );
+ if( fs < size )
+ size = fs;
+ p->signature = signature;
+ memset( p->name, 0, sizeof(p->name) );
+ strncpy( p->name, name, sizeof(p->name) );
+ p->len_hi = (size>>8)/16;
+ p->len_lo = size/16;
+ p->checksum = nvpart_checksum(p);
+ if( fs > size ) {
+ char *fp = (char*)p + size;
+ create_free_part( fp, fs-size );
+ }
+ return size;
+ }
+ printk("create-failed\n");
+ return -1;
+}
+
+static void
+zap_nvram( void )
+{
+ create_free_part( nvram.data, nvram.size );
+ create_nv_part( NV_SIG_SYSTEM, "common", DEF_SYSTEM_SIZE );
+}
+
+#if 0
+static void
+show_partitions( void )
+{
+ nvpart_t *p = NULL;
+ char buf[13];
+
+ while( next_nvpart(&p) > 0 ) {
+ memcpy( buf, p->name, sizeof(p->name) );
+ buf[12] = 0;
+ printk("[%02x] %-13s: %03x\n",
+ p->signature, buf, nvpart_size(p));
+ }
+}
+#endif
+
+void
+update_nvram( void )
+{
+ PUSH( pointer2cell(nvram.config->data) );
+ PUSH( nvram.config_size );
+ fword("nvram-store-configs");
+ arch_nvram_put( nvram.data );
+}
+
+void
+nvconf_init( void )
+{
+ int once=0;
+
+ /* initialize nvram structure completely */
+ nvram.config = NULL;
+ nvram.config_size = 0;
+
+ nvram.size = arch_nvram_size();
+ nvram.data = malloc( nvram.size );
+ arch_nvram_get( nvram.data );
+
+ bind_func( "update-nvram", update_nvram );
+
+ for( ;; ) {
+ nvpart_t *p = NULL;
+ int err;
+
+ while( (err=next_nvpart(&p)) > 0 ) {
+ if( nvpart_checksum(p) != p->checksum ) {
+ err = -1;
+ break;
+ }
+ if( p->signature == NV_SIG_SYSTEM ) {
+ nvram.config = p;
+ nvram.config_size = nvpart_size(p) - 0x10;
+
+ if( !once++ ) {
+ PUSH( pointer2cell(p->data) );
+ PUSH( nvram.config_size );
+ fword("nvram-load-configs");
+ }
+ }
+ }
+ if( err || !nvram.config ) {
+ printk("nvram error detected, zapping pram\n");
+ zap_nvram();
+ if( !once++ )
+ fword("set-defaults");
+ continue;
+ }
+ break;
+ }
+}
+
+
+/************************************************************************/
+/* nvram */
+/************************************************************************/
+
+typedef struct {
+ unsigned int mark_hi;
+ unsigned int mark_lo;
+} nvram_ibuf_t;
+
+DECLARE_UNNAMED_NODE( nvram, INSTALL_OPEN, sizeof(nvram_ibuf_t ));
+
+/* ( pos_lo pos_hi -- status ) */
+static void
+nvram_seek( nvram_ibuf_t *nd )
+{
+ int pos_hi = POP();
+ int pos_lo = POP();
+
+ DPRINTF("seek %08x %08x\n", pos_hi, pos_lo );
+ nd->mark_lo = pos_lo;
+ nd->mark_hi = pos_hi;
+
+ if( nd->mark_lo >= nvram.size ) {
+ PUSH(-1);
+ return;
+ }
+
+ /* 0=success, -1=failure (1=legacy success) */
+ PUSH(0);
+}
+
+/* ( addr len -- actual ) */
+static void
+nvram_read( nvram_ibuf_t *nd )
+{
+ int len = POP();
+ char *p = (char*)cell2pointer(POP());
+ int n=0;
+
+ while( nd->mark_lo < nvram.size && n < len ) {
+ *p++ = nvram.data[nd->mark_lo++];
+ n++;
+ }
+ PUSH(n);
+ DPRINTF("read %p %x -- %x\n", p, len, n);
+}
+
+/* ( addr len -- actual ) */
+static void
+nvram_write( nvram_ibuf_t *nd )
+{
+ int len = POP();
+ char *p = (char*)cell2pointer(POP());
+ int n=0;
+
+ while( nd->mark_lo < nvram.size && n < len ) {
+ nvram.data[nd->mark_lo++] = *p++;
+ n++;
+ }
+ PUSH(n);
+ DPRINTF("write %p %x -- %x\n", p, len, n );
+}
+
+/* ( -- size ) */
+static void
+nvram_size( __attribute__((unused)) nvram_ibuf_t *nd )
+{
+ DPRINTF("nvram_size %d\n", nvram.size);
+ PUSH( nvram.size );
+}
+
+NODE_METHODS( nvram ) = {
+ { "size", (void*)nvram_size },
+ { "read", (void*)nvram_read },
+ { "write", (void*)nvram_write },
+ { "seek", (void*)nvram_seek },
+};
+
+
+void
+nvram_init( const char *path )
+{
+ nvconf_init();
+
+ REGISTER_NAMED_NODE( nvram, path );
+}
diff --git a/roms/openbios/packages/packages.h b/roms/openbios/packages/packages.h
new file mode 100644
index 00000000..1ed6f1ca
--- /dev/null
+++ b/roms/openbios/packages/packages.h
@@ -0,0 +1,36 @@
+/*
+ * Creation Date: <2003/12/23 00:32:12 samuel>
+ * Time-stamp: <2003/12/28 14:47:02 samuel>
+ *
+ * <packages.h>
+ *
+ * Package initialization
+ *
+ * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#ifndef _H_MODULES
+#define _H_MODULES
+
+extern void deblocker_init( void );
+extern void disklabel_init( void );
+extern void files_init( void );
+extern void iso9660_init( void );
+extern void hfsp_init( void );
+extern void hfs_init( void );
+extern void ext2_init( void );
+extern void grubfs_init( void );
+extern void macparts_init( void );
+extern void pcparts_init( void );
+extern void sunparts_init( void );
+extern void cmdline_init( void );
+extern void elf_loader_init( void );
+extern void xcoff_loader_init( void );
+extern void bootinfo_loader_init( void );
+
+#endif /* _H_MODULES */
diff --git a/roms/openbios/packages/pc-parts.c b/roms/openbios/packages/pc-parts.c
new file mode 100644
index 00000000..771923ef
--- /dev/null
+++ b/roms/openbios/packages/pc-parts.c
@@ -0,0 +1,393 @@
+/*
+ * pc partition support
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This code is based (and copied in many places) from
+ * mac partition support by Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/load.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "packages.h"
+
+//#define DEBUG_PC_PARTS
+
+#ifdef DEBUG_PC_PARTS
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+typedef struct {
+ xt_t seek_xt, read_xt;
+ ucell offs_hi, offs_lo;
+ ucell size_hi, size_lo;
+ phandle_t filesystem_ph;
+} pcparts_info_t;
+
+DECLARE_NODE( pcparts, INSTALL_OPEN, sizeof(pcparts_info_t), "+/packages/pc-parts" );
+
+#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
+#define READ( buf, size ) ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); })
+
+/* three helper functions */
+
+static inline int has_pc_valid_partition(unsigned char *sect)
+{
+ /* Make sure the partition table contains at least one valid entry */
+ return (sect[0x1c2] != 0 || sect[0x1d2] != 0 || sect[0x1e2] != 0);
+}
+
+static inline int has_pc_part_magic(unsigned char *sect)
+{
+ return sect[0x1fe]==0x55 && sect[0x1ff]==0xAA;
+}
+
+static inline int is_pc_extended_part(unsigned char type)
+{
+ return type==5 || type==0xf || type==0x85;
+}
+
+/* ( open -- flag ) */
+static void
+pcparts_open( pcparts_info_t *di )
+{
+ char *str = my_args_copy();
+ char *argstr = strdup("");
+ char *parstr = strdup("");
+ int bs, parnum=-1;
+ int found = 0;
+ phandle_t ph;
+ ducell offs, size;
+
+ /* Layout of PC partition table */
+ struct pc_partition {
+ unsigned char boot;
+ unsigned char head;
+ unsigned char sector;
+ unsigned char cyl;
+ unsigned char type;
+ unsigned char e_head;
+ unsigned char e_sector;
+ unsigned char e_cyl;
+ u32 start_sect; /* unaligned little endian */
+ u32 nr_sects; /* ditto */
+ } *p, *partition;
+
+ unsigned char buf[512];
+
+ DPRINTF("pcparts_open '%s'\n", str );
+
+ /*
+ Arguments that we accept:
+ id: [0-7]
+ [(id)][,][filespec]
+ */
+
+ if ( strlen(str) ) {
+ /* Detect the arguments */
+ if ((*str >= '0' && *str <= '7') || (*str == ',')) {
+ push_str(str);
+ PUSH(',');
+ fword("left-parse-string");
+ parstr = pop_fstr_copy();
+ argstr = pop_fstr_copy();
+ } else {
+ argstr = str;
+ }
+
+ /* Convert the id to a partition number */
+ if (parstr && strlen(parstr))
+ parnum = atol(parstr);
+ }
+
+ /* Make sure argstr is not null */
+ if (argstr == NULL)
+ argstr = strdup("");
+
+ DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
+ free(parstr);
+
+ if( parnum < 0 )
+ parnum = 0;
+
+ di->filesystem_ph = 0;
+ di->read_xt = find_parent_method("read");
+ di->seek_xt = find_parent_method("seek");
+
+ SEEK( 0 );
+ if( READ(buf, 512) != 512 )
+ RET(0);
+
+ /* Check Magic */
+ if (!has_pc_part_magic(buf)) {
+ DPRINTF("pc partition magic not found.\n");
+ RET(0);
+ }
+
+ /* Actual partition data */
+ partition = (struct pc_partition *) (buf + 0x1be);
+
+ /* Make sure we use a copy accessible from an aligned pointer (some archs
+ e.g. SPARC will crash otherwise) */
+ p = malloc(sizeof(struct pc_partition));
+
+ bs = 512;
+
+ if (parnum < 4) {
+ /* primary partition */
+ partition += parnum;
+ memcpy(p, partition, sizeof(struct pc_partition));
+
+ if (p->type == 0 || is_pc_extended_part(p->type)) {
+ DPRINTF("partition %d does not exist\n", parnum+1 );
+ RET( 0 );
+ }
+
+ offs = (long long)(__le32_to_cpu(p->start_sect)) * bs;
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+
+ size = (long long)(__le32_to_cpu(p->nr_sects)) * bs;
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+
+ DPRINTF("Primary partition at sector %x\n", __le32_to_cpu(p->start_sect));
+
+ found = 1;
+ } else {
+ /* Extended partition */
+ int i, cur_part;
+ unsigned long ext_start, cur_table;
+
+ /* Search for the extended partition
+ * which contains logical partitions */
+ for (i = 0; i < 4; i++) {
+ if (is_pc_extended_part(p[i].type))
+ break;
+ }
+
+ if (i >= 4) {
+ DPRINTF("Extended partition not found\n");
+ RET( 0 );
+ }
+
+ DPRINTF("Extended partition at %d\n", i+1);
+
+ /* Visit each logical partition labels */
+ ext_start = __le32_to_cpu(p[i].start_sect);
+ cur_table = ext_start;
+ cur_part = 4;
+
+ while (cur_part <= parnum) {
+ DPRINTF("cur_part=%d at %lx\n", cur_part, cur_table);
+
+ SEEK( cur_table * bs );
+ if( READ(buf, sizeof(512)) != sizeof(512) )
+ RET( 0 );
+
+ if (!has_pc_part_magic(buf)) {
+ DPRINTF("Extended partition has no magic\n");
+ break;
+ }
+
+ /* Read the extended partition, making sure we are aligned again */
+ partition = (struct pc_partition *) (buf + 0x1be);
+ memcpy(p, partition, sizeof(struct pc_partition));
+
+ /* First entry is the logical partition */
+ if (cur_part == parnum) {
+ if (p->type == 0) {
+ DPRINTF("Partition %d is empty\n", parnum+1);
+ RET( 0 );
+ }
+
+ offs = (long long)(cur_table+__le32_to_cpu(p->start_sect)) * bs;
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+
+ size = (long long)__le32_to_cpu(p->nr_sects) * bs;
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+
+ found = 1;
+ break;
+ }
+
+ /* Second entry is link to next partition */
+ if (!is_pc_extended_part(p[1].type)) {
+ DPRINTF("no link\n");
+ break;
+ }
+
+ cur_table = ext_start + __le32_to_cpu(p[1].start_sect);
+ cur_part++;
+ }
+
+ if (!found) {
+ DPRINTF("Logical partition %d does not exist\n", parnum+1);
+ RET( 0 );
+ }
+ }
+
+ free(p);
+
+ if (found) {
+ /* We have a valid partition - so probe for a filesystem at the current offset */
+ DPRINTF("pc-parts: about to probe for fs\n");
+ DPUSH( offs );
+ PUSH_ih( my_parent() );
+ parword("find-filesystem");
+ DPRINTF("pc-parts: done fs probe\n");
+
+ ph = POP_ph();
+ if( ph ) {
+ DPRINTF("pc-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
+ di->filesystem_ph = ph;
+
+ /* If we have been asked to open a particular file, interpose the filesystem package with
+ the passed filename as an argument */
+ if (strlen(argstr)) {
+ push_str( argstr );
+ PUSH_ph( ph );
+ fword("interpose");
+ }
+ } else {
+ DPRINTF("pc-parts: no filesystem found; bypassing misc-files interpose\n");
+ }
+
+ free( str );
+ RET( -1 );
+ } else {
+ DPRINTF("pc-parts: unable to locate partition\n");
+
+ free( str );
+ RET( 0 );
+ }
+}
+
+/* ( block0 -- flag? ) */
+static void
+pcparts_probe( pcparts_info_t *dummy )
+{
+ unsigned char *buf = (unsigned char *)cell2pointer(POP());
+
+ DPRINTF("probing for PC partitions\n");
+
+ /* We also check that at least one valid partition exists; this is because
+ some CDs seem broken in that they have a partition table but it is empty
+ e.g. MorphOS. */
+ RET ( has_pc_part_magic(buf) && has_pc_valid_partition(buf) );
+}
+
+/* ( -- type offset.d size.d ) */
+static void
+pcparts_get_info( pcparts_info_t *di )
+{
+ DPRINTF("PC get_info\n");
+ PUSH( -1 ); /* no type */
+ PUSH( di->offs_lo );
+ PUSH( di->offs_hi );
+ PUSH( di->size_lo );
+ PUSH( di->size_hi );
+}
+
+static void
+pcparts_block_size( __attribute__((unused))pcparts_info_t *di )
+{
+ PUSH(512);
+}
+
+static void
+pcparts_initialize( pcparts_info_t *di )
+{
+ fword("register-partition-package");
+}
+
+/* ( pos.d -- status ) */
+static void
+pcparts_seek(pcparts_info_t *di )
+{
+ long long pos = DPOP();
+ long long offs, size;
+
+ DPRINTF("pcparts_seek %llx:\n", pos);
+
+ /* Seek is invalid if we reach the end of the device */
+ size = ((ducell)di->size_hi << BITS) | di->size_lo;
+ if (pos > size)
+ RET( -1 );
+
+ /* Calculate the seek offset for the parent */
+ offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
+ offs += pos;
+ DPUSH(offs);
+
+ DPRINTF("pcparts_seek parent offset %llx:\n", offs);
+
+ call_package(di->seek_xt, my_parent());
+}
+
+/* ( buf len -- actlen ) */
+static void
+pcparts_read(pcparts_info_t *di )
+{
+ DPRINTF("pcparts_read\n");
+
+ /* Pass the read back up to the parent */
+ call_package(di->read_xt, my_parent());
+}
+
+/* ( addr -- size ) */
+static void
+pcparts_load( __attribute__((unused))pcparts_info_t *di )
+{
+ /* Invoke the loader */
+ load(my_self());
+}
+
+/* ( pathstr len -- ) */
+static void
+pcparts_dir( pcparts_info_t *di )
+{
+ if ( di->filesystem_ph ) {
+ PUSH( my_self() );
+ push_str("dir");
+ PUSH( di->filesystem_ph );
+ fword("find-method");
+ POP();
+ fword("execute");
+ } else {
+ forth_printf("pc-parts: Unable to determine filesystem\n");
+ POP();
+ POP();
+ }
+}
+
+NODE_METHODS( pcparts ) = {
+ { "probe", pcparts_probe },
+ { "open", pcparts_open },
+ { "seek", pcparts_seek },
+ { "read", pcparts_read },
+ { "load", pcparts_load },
+ { "dir", pcparts_dir },
+ { "get-info", pcparts_get_info },
+ { "block-size", pcparts_block_size },
+ { NULL, pcparts_initialize },
+};
+
+void
+pcparts_init( void )
+{
+ REGISTER_NODE( pcparts );
+}
diff --git a/roms/openbios/packages/sun-parts.c b/roms/openbios/packages/sun-parts.c
new file mode 100644
index 00000000..16b281b6
--- /dev/null
+++ b/roms/openbios/packages/sun-parts.c
@@ -0,0 +1,343 @@
+/*
+ * Sun (Sparc32/64) partition support
+ *
+ * Copyright (C) 2004 Stefan Reinauer
+ *
+ * This code is based (and copied in many places) from
+ * mac partition support by Samuel Rydh (samuel@ibrium.se)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/load.h"
+#include "libc/byteorder.h"
+#include "libc/vsprintf.h"
+#include "packages.h"
+
+//#define DEBUG_SUN_PARTS
+
+#ifdef DEBUG_SUN_PARTS
+#define DPRINTF(fmt, args...) \
+ do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+typedef struct {
+ xt_t seek_xt, read_xt;
+ ucell offs_hi, offs_lo;
+ ucell size_hi, size_lo;
+ int type;
+ phandle_t filesystem_ph;
+} sunparts_info_t;
+
+DECLARE_NODE( sunparts, INSTALL_OPEN, sizeof(sunparts_info_t), "+/packages/sun-parts" );
+
+#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
+#define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(di->read_xt); POP(); })
+
+/* Layout of SUN partition table */
+struct sun_disklabel {
+ uint8_t info[128]; /* Informative text string */
+ uint8_t spare0[14];
+ struct sun_info {
+ uint16_t id;
+ uint16_t flags;
+ } infos[8];
+ uint8_t spare[246]; /* Boot information etc. */
+ uint16_t rspeed; /* Disk rotational speed */
+ uint16_t pcylcount; /* Physical cylinder count */
+ uint16_t sparecyl; /* extra sects per cylinder */
+ uint8_t spare2[4]; /* More magic... */
+ uint16_t ilfact; /* Interleave factor */
+ uint16_t ncyl; /* Data cylinder count */
+ uint16_t nacyl; /* Alt. cylinder count */
+ uint16_t ntrks; /* Tracks per cylinder */
+ uint16_t nsect; /* Sectors per track */
+ uint8_t spare3[4]; /* Even more magic... */
+ struct sun_partition {
+ uint32_t start_cylinder;
+ uint32_t num_sectors;
+ } partitions[8];
+ uint16_t magic; /* Magic number */
+ uint16_t csum; /* Label xor'd checksum */
+};
+
+/* two helper functions */
+
+static inline int
+has_sun_part_magic(unsigned char *sect)
+{
+ struct sun_disklabel *p = (struct sun_disklabel *)sect;
+ uint16_t csum, *ush, tmp16;
+
+ if (__be16_to_cpu(p->magic) != 0xDABE)
+ return 0;
+
+ csum = 0;
+ for (ush = (uint16_t *)p; ush < (uint16_t *)(p + 1); ush++) {
+ tmp16 = __be16_to_cpu(*ush);
+ csum ^= tmp16;
+ }
+ return csum == 0;
+}
+
+/* ( open -- flag ) */
+static void
+sunparts_open( sunparts_info_t *di )
+{
+ char *str = my_args_copy();
+ char *argstr = NULL;
+ char *parstr = NULL;
+ int parnum = -1;
+ unsigned char buf[512];
+ struct sun_disklabel *p;
+ unsigned int i, bs;
+ ducell offs, size;
+ phandle_t ph;
+
+ DPRINTF("sunparts_open '%s'\n", str );
+
+ /*
+ Arguments that we accept:
+ id: [0-7] | [a-h]
+ [(id)][,][filespec]
+ */
+
+ if ( str && strlen(str) ) {
+ /* Detect the arguments */
+ if ((*str >= '0' && *str <= '9') || (*str >= 'a' && *str < ('a' + 8)) || (*str == ',')) {
+ push_str(str);
+ PUSH(',');
+ fword("left-parse-string");
+ parstr = pop_fstr_copy();
+ argstr = pop_fstr_copy();
+ } else {
+ argstr = str;
+ }
+
+ /* Convert the id to a partition number */
+ if (parstr && strlen(parstr)) {
+ if (parstr[0] >= 'a' && parstr[0] < ('a' + 8))
+ parnum = parstr[0] - 'a';
+ else
+ parnum = atol(parstr);
+ }
+ }
+
+ /* Make sure argstr is not null */
+ if (argstr == NULL)
+ argstr = strdup("");
+
+ DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
+
+ di->filesystem_ph = 0;
+ di->read_xt = find_parent_method("read");
+ di->seek_xt = find_parent_method("seek");
+
+ SEEK( 0 );
+ if (READ(buf, 512) != 512) {
+ free(str);
+ RET(0);
+ }
+
+ /* Check Magic */
+ if (!has_sun_part_magic(buf)) {
+ DPRINTF("Sun partition magic not found.\n");
+ free(str);
+ RET(0);
+ }
+
+ bs = 512;
+ /* get partition data */
+ p = (struct sun_disklabel *)buf;
+
+ for (i = 0; i < 8; i++) {
+ DPRINTF("%c: %d + %d, id %x, flags %x\n", 'a' + i,
+ __be32_to_cpu(p->partitions[i].start_cylinder),
+ __be32_to_cpu(p->partitions[i].num_sectors),
+ __be16_to_cpu(p->infos[i].id),
+ __be16_to_cpu(p->infos[i].flags));
+ }
+
+ if (parnum < 0)
+ parnum = 0;
+
+ DPRINTF("Selected partition %d\n", parnum);
+
+ offs = (long long)__be32_to_cpu(p->partitions[parnum].start_cylinder) *
+ __be16_to_cpu(p->ntrks) * __be16_to_cpu(p->nsect) * bs;
+
+ di->offs_hi = offs >> BITS;
+ di->offs_lo = offs & (ucell) -1;
+ size = (long long)__be32_to_cpu(p->partitions[parnum].num_sectors) * bs;
+ if (size == 0) {
+ DPRINTF("Partition size is 0, exiting\n");
+ free(str);
+ RET(0);
+ }
+ di->size_hi = size >> BITS;
+ di->size_lo = size & (ucell) -1;
+ di->type = __be16_to_cpu(p->infos[parnum].id);
+
+ DPRINTF("Found Sun partition, offs %lld size %lld\n",
+ (long long)offs, (long long)size);
+
+ /* Probe for filesystem at current offset */
+ DPRINTF("sun-parts: about to probe for fs\n");
+ DPUSH( offs );
+ PUSH_ih( my_parent() );
+ parword("find-filesystem");
+ DPRINTF("sun-parts: done fs probe\n");
+
+ ph = POP_ph();
+ if( ph ) {
+ DPRINTF("sun-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
+ di->filesystem_ph = ph;
+
+ /* If we have been asked to open a particular file, interpose the filesystem package with
+ the passed filename as an argument */
+ if (argstr && strlen(argstr)) {
+ push_str( argstr );
+ PUSH_ph( ph );
+ fword("interpose");
+ }
+ } else {
+ DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n");
+
+ /* Solaris Fcode boot blocks assume that the disk-label package will always
+ automatically interpose the "ufs-file-system" package if it exists! We
+ need to mimic this behaviour in order for the boot to work. */
+ push_str("ufs-file-system");
+ feval("find-package");
+ ph = POP_ph();
+
+ if (argstr && strlen(argstr) && ph) {
+ ph = POP_ph();
+ push_str(argstr);
+ PUSH_ph(ph);
+ fword("interpose");
+ }
+ }
+
+ free( str );
+ RET( -1 );
+}
+
+/* ( block0 -- flag? ) */
+static void
+sunparts_probe( __attribute__((unused))sunparts_info_t *dummy )
+{
+ unsigned char *buf = (unsigned char *)POP();
+
+ DPRINTF("probing for Sun partitions\n");
+
+ RET ( has_sun_part_magic(buf) );
+}
+
+/* ( -- type offset.d size.d ) */
+static void
+sunparts_get_info( sunparts_info_t *di )
+{
+ DPRINTF("Sun get_info\n");
+ PUSH( di->type );
+ PUSH( di->offs_lo );
+ PUSH( di->offs_hi );
+ PUSH( di->size_lo );
+ PUSH( di->size_hi );
+}
+
+static void
+sunparts_block_size( __attribute__((unused))sunparts_info_t *di )
+{
+ PUSH(512);
+}
+
+static void
+sunparts_initialize( __attribute__((unused))sunparts_info_t *di )
+{
+ fword("register-partition-package");
+}
+
+/* ( pos.d -- status ) */
+static void
+sunparts_seek(sunparts_info_t *di )
+{
+ long long pos = DPOP();
+ long long offs, size;;
+
+ DPRINTF("sunparts_seek %llx:\n", pos);
+
+ /* Seek is invalid if we reach the end of the device */
+ size = ((ducell)di->size_hi << BITS) | di->size_lo;
+ if (pos > size)
+ RET( -1 );
+
+ /* Calculate the seek offset for the parent */
+ offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
+ offs += pos;
+ DPUSH(offs);
+
+ DPRINTF("sunparts_seek parent offset %llx:\n", offs);
+
+ call_package(di->seek_xt, my_parent());
+}
+
+/* ( buf len -- actlen ) */
+static void
+sunparts_read(sunparts_info_t *di )
+{
+ DPRINTF("sunparts_read\n");
+
+ /* Pass the read back up to the parent */
+ call_package(di->read_xt, my_parent());
+}
+
+/* ( addr -- size ) */
+static void
+sunparts_load( __attribute__((unused))sunparts_info_t *di )
+{
+ /* Invoke the loader */
+ load(my_self());
+}
+
+/* ( pathstr len -- ) */
+static void
+sunparts_dir( sunparts_info_t *di )
+{
+ if ( di->filesystem_ph) {
+ PUSH( my_self() );
+ push_str("dir");
+ PUSH( di->filesystem_ph );
+ fword("find-method");
+ POP();
+ fword("execute");
+ } else {
+ forth_printf("sun-parts: Unable to determine filesystem\n");
+ POP();
+ POP();
+ }
+}
+
+NODE_METHODS( sunparts ) = {
+ { "probe", sunparts_probe },
+ { "open", sunparts_open },
+ { "get-info", sunparts_get_info },
+ { "block-size", sunparts_block_size },
+ { "seek", sunparts_seek },
+ { "read", sunparts_read },
+ { "load", sunparts_load },
+ { "dir", sunparts_dir },
+ { NULL, sunparts_initialize },
+};
+
+void
+sunparts_init( void )
+{
+ REGISTER_NODE( sunparts );
+}
diff --git a/roms/openbios/packages/xcoff-loader.c b/roms/openbios/packages/xcoff-loader.c
new file mode 100644
index 00000000..5213cc10
--- /dev/null
+++ b/roms/openbios/packages/xcoff-loader.c
@@ -0,0 +1,31 @@
+/*
+ *
+ * <xcoff-loader.c>
+ *
+ * XCOFF file loader
+ *
+ * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
+ *
+ * from original XCOFF loader by Steven Noonan <steven@uplinklabs.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/xcoff_load.h"
+#include "packages.h"
+
+DECLARE_NODE(xcoff_loader, INSTALL_OPEN, 0, "+/packages/xcoff-loader" );
+
+NODE_METHODS( xcoff_loader ) = {
+ { "init-program", xcoff_init_program },
+};
+
+void xcoff_loader_init( void )
+{
+ REGISTER_NODE( xcoff_loader );
+}
diff --git a/roms/openbios/utils/README b/roms/openbios/utils/README
new file mode 100644
index 00000000..1cfea456
--- /dev/null
+++ b/roms/openbios/utils/README
@@ -0,0 +1,52 @@
+Here you find utilities useful for development and debugging of Open
+Firmware systems.
+
+ofclient
+--------
+
+Sample OpenFirmware client. Can be booted directly from OpenFirmware
+and demonstrates how an operating system can use the OpenFirmware
+client interface. This example should work on PPC and x86 without
+changes.
+
+romheaders
+----------
+Romheaders is a small utility that dumps PCI expansion rom header
+information in human readable form. It knows about Images with
+multiple platform support and prints platform dependant information
+for x86 and open firmware roms.
+
+
+detok
+-----
+Detok is a GPLed FCode detokenizer. It can detokenize (disassemble)
+fcode bytecode files as described by the IEEE 1275-1994 standard. This
+program aims towards IEEE 1275-1994 compliancy, but there is no
+warranty that it is actually compliant. bytecode files normally
+contain Open Firmware drivers or other packages for use with an Open
+Firmware compliant system.
+See http://www.openbios.org/development/detok.html for more
+information.
+
+devbios
+-------
+This is a kernel driver for different kind of (Flash)BIOSs that are
+available in today's x86, ia64 (Itantium) or Alpha based hardware.
+
+fccc
+----
+initial, incomplete implementation of an C to forth compiler.
+
+
+dist
+----
+rpm specfile and debian files for packing openbios with various
+distributions. Changes/addons from distributors are explicitly
+welcome.
+
+
+
+
+
+
+
diff --git a/roms/openbios/utils/devbios/COPYING b/roms/openbios/utils/devbios/COPYING
new file mode 100644
index 00000000..486e6387
--- /dev/null
+++ b/roms/openbios/utils/devbios/COPYING
@@ -0,0 +1,353 @@
+
+ NOTE! The GPL below is copyrighted by the Free Software
+ Foundation, but the instance of code that it refers to (/dev/bios
+ driver)is copyrighted by me and others who actually wrote it.
+
+ Also note that the only valid version of the GPL as far as this driver
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
+
+ Stefan Reinauer
+
+----------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/roms/openbios/utils/devbios/CREDITS b/roms/openbios/utils/devbios/CREDITS
new file mode 100644
index 00000000..cd642676
--- /dev/null
+++ b/roms/openbios/utils/devbios/CREDITS
@@ -0,0 +1,4 @@
+
+Thanks to Michael Gibson from eSeSiX for donating a cs5530
+based thin client for porting /dev/bios.
+
diff --git a/roms/openbios/utils/devbios/ChangeLog b/roms/openbios/utils/devbios/ChangeLog
new file mode 100644
index 00000000..3c8e5654
--- /dev/null
+++ b/roms/openbios/utils/devbios/ChangeLog
@@ -0,0 +1,295 @@
+NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
+
+/dev/bios is obsolete and no longer under development. Please adapt all
+changes to the "flashrom" utility of LinuxBIOS. This utility can be found
+at LinuxBIOSv2/utils/flashrom in the LinuxBIOS v2 repository. LinuxBIOS
+is available at http://www.linuxbios.org/
+
+I'm also looking for volunteers to port all features available in /dev/bios
+to flashrom so /dev/bios can be dropped from the OpenBIOS tree. These features
+include
+
+- block information about flash chips
+- block wise writing of flash chips
+- lots of supported flash chips and vendors.
+
+If you have questions, contact Stefan Reinauer <stepan@coresystems.de>
+
+NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
+
+
+ChangeLog for /dev/bios
+
+** 2004/03/31 ********************************************************
+
+ * Added fix from Alex Beregszaszi to remove global *bios
+
+** 2004/03/05 ********************************************************
+
+ * fix compiling for 2.6 kernels.
+
+** 03/06/04 **********************************************************
+
+ * add SST49LF080A
+ * small 2.5 fix.
+
+** 02/06/10 **********************************************************
+
+ * some changes to detect pci cards firmware.
+ * pci cards firmware can be read even if flashing is not possible.
+ This is a new feature and might cause problems on some systems.
+
+** 02/04/16 **********************************************************
+
+ * reorganize Makefile, include .config from kernel.
+ * platform fixes for clean compilation.
+
+** 02/04/12 **********************************************************
+
+ * proprietary x86-64 support.
+ * change ruffian probe address
+
+** 02/03/28 **********************************************************
+
+ * proper implementation of system firmware detection on LX164 Alphas
+ * partly include jedec command cleanup patch from Pierrick Hascoet
+ <pierrick.hascoet@hydromel.net>
+
+** 02/03/11 **********************************************************
+
+ * only probe 512k on CS5530(A)
+ * add EON EN29F002 chips.
+
+** 02/02/22 **********************************************************
+
+ * rewrite major parts of bridge probing to make driver more generic.
+ * add Ali chipset support
+ * Saner iounmap() of flash devices.
+
+** 02/02/18 * 0.3.2 **************************************************
+
+ * change cs5530 driver to map high rom range instead of low one
+ and don't use positive decode.
+ * remove ruffian flag. Alpha (164LX/UX) almost works with pc code.
+ * don't rely on register defaults in intel 8xx driver.
+ * updated pci device list. more entries, join amd and via entry.
+ * fix error handling in chipset detection.
+ * add support for Reliance/ServerWorks chipsets
+ * enable 1M 512k on intel 4x0 chips where it's possible
+ * cleanup proc file handling
+
+** 02/02/17 **********************************************************
+
+ * rewrote chipset initialisation skeleton.
+ * fix pci bios (un)mapping.
+ * experimental support for AlphaPC 164UX (Ruffian)
+ (probes at 0xfffffffffffc0000 instead of 0xfffffc87C0000000
+ * initial code for FWH mode chips
+ * Fix Toggle-Until-Ready code.
+
+** 02/02/16 **********************************************************
+
+ * iounmapping fixed. no more address space wasted.
+ * /proc/bios shows physical address now. dmesg shows
+ physical address and virtual memory area and offset.
+
+** 02/02/13 **********************************************************
+
+ * added i820/i830 chipset support
+ * added AMD 751/760MP(X) support
+ * added support for Itanium and 84460GX chipset
+ * added experimental support for some flash chips (ST, Intel,
+ Winbond)
+ * use spinlocks instead of hard cli()
+
+** 02/02/11 **********************************************************
+
+ * added GPL licence tag
+ * remove low bios area access tweaking for intel drivers
+ * speed up SST 39SF020 write
+ * fix compilation for 2.5 kernels
+
+** 02/02/05 **********************************************************
+
+ * added support for cs5530 (nsc/cyrix mediagx) chipset
+ * reorganized shadow/wp handling
+ * probe for 2mb high memory area instead of 256k only
+
+** 01/08/01 * 0.3.1 **************************************************
+
+ * compiles and works with Linux kernel 2.4
+ * rewrote flash chip probing
+ * always use ioremap now
+ * flash chips above 128k should work transparent
+ * Support for newer VIA chipsets
+
+** 00/10/15 * 0.3.0pre1 **********************************************
+
+ * added patch from Eric Estabrook
+ * support for 256k flash chips on intel 430/440 chipsets and via vp3
+ * split up source into several files
+ * Changes for Ruffian AXP machines. Does not work (yet).
+
+** 99/07/29 * 0.2.101 ************************************************
+
+ * Oh well.. 11 months? Impossible. I am a lazy guy. Implemented
+ some support for VIA Apollo VP3. Don't know whether it works, since
+ I don't have one.
+
+** 98/09/06 **********************************************************
+
+patches by prumpf@jcsbs.lanobis.de:
+ * The pointer to bios_release in bios.c was on the flush pointer's
+ position. This caused Oopses.
+ * When bios_read was called with a file position after the actual end
+ of bios, it tried to read non-existant memory positions due to size
+ being unsigned (it isn't anymore) , causing spontaneous reboots on
+ my system
+
+** 98/08/22 **********************************************************
+
+ * Well,.. The diskless spectacle (0.2.100) was caused by a little bug
+ in in handling Intel PCI chipsets. Works now.
+ * Threw out the chipset_backout stuff. the PCI chipset handling should
+ always leave the machine in the same state it was before. ALWAYS.
+
+** 98/08/18 * 0.2.100 ************************************************
+
+ * Threw out the mem_type stuff. There are more important things than
+ this.
+ * Argh! After flashing fine on an Intel 28F001BT, the computer kept
+ hanging in an endless loop and refused writing the emergency boot
+ block to the end :-( There's some work until 0.3 is ready.
+ Implemented a timeout so that the system will not hang forever if
+ the flashchip behaves unexpected.
+ * Removed x86 probing in a loop. I think it never found anything else
+ but the system bios and *maybe* the graphics adapter bios. On the
+ other hand, it reconfigures some networking cards to silence.
+ Bad thing on diskless Linux boxes :)
+
+** 98/08/15 **********************************************************
+
+ * added some changes for intel to compile without warnings..
+
+** 98/08/02 **********************************************************
+
+ * What a boring job! Checked some dozen of flash chip entries today
+ and added a lot of new ones. I bet it gets hard to find anything
+ this driver does not know.
+
+** 98/07/28 **********************************************************
+
+ * Yeah! Atmel Chips finally work.. These Atmel guys are really weird.
+ * Testing last instead of first written byte now, when polling for the
+ end of a write access.
+
+** 98/07/28 **********************************************************
+
+ * Well, I am definitely spending too much time in IRC, but detecting
+ PCI cards' bioses works now (at least for me)
+ * Thrown out some obsolete stuff.
+ * Declared PCI and Flash reading/writing __inline__. Don't know,
+ whether this is a good idea. But let's try it for a while.
+ * Aaaargh! Some major mistakes in handling whether a flash has to
+ be erased before programming. FIXED!
+ * Even worse. An endless loop made it into writing in 0.2.99. Sorry!
+ I had no chance to test writing on an intel board with that release.
+ At least my warning, not to write, made sense.
+ * Intel flashchips are supported now!! It's at least tested on my
+ Alpha AXP LX164 Board (1MByte i28f008 chip) But all Intel flash chips
+ seem to work in the same way.
+ * Atmel 64kByte flash chips supported.
+
+** 98/07/27 **********************************************************
+
+ * Split up flash_probe in 2 parts to be able to expand probing on
+ PCI bioses and others correctly.
+ * Turned around 1st and 2nd probing codes. This is funny, Atmel
+ Flashroms give some wrong numbers if they are probed with the
+ 0x80/0x60 way. I only hope that no flashchips react on the
+ 0x90 method with wrong values.
+
+** 98/07/19 * V0.2.99 ************************************************
+
+ * Reading the flashchip works now on Alpha AXP (at least on my LX164
+ Board)
+ Writing ought to work, too, but Intel Flashchips are not supported
+ yet. This should be done until 0.3.0.
+ NOTE: I have no idea whether this driver still works on intel
+ boards or not. There have been too many changes. Please try, but
+ do not flash with this release of the driver.
+ * Minor Changes and fixes. Naming scheme changed a bit. This version
+ might work on James Mastros' machine again ?!?
+
+** 98/07/11 **********************************************************
+
+ * Started porting stuff to Alpha AXP architecture to continue testing
+ the flashing routines. We have a lot of tests next week, so I
+ won't get much stuff done..
+ Porting to AXP seems to be much more work than I thought. It may
+ take some time until the next version is released.
+ * Moved major number again. This time we have an official major
+ number for /dev/bios. Thanks to Hans Peter Anvin.
+ (Well, we have this one since May 1st, sorry for the delay)
+
+** 98/06/26 * V0.2.95 ************************************************
+
+ * added all Manufacturer IDs from the JEDEC standards publication.
+ * sorry for not having released a new version since months, but
+ my x86 machine died and I have no chance to do any testing right
+ now. I guess I must get a new Intel box, as Alpha AXP are all
+ delivered with the same Intel flash chips.
+
+** 98/04/30 * V0.2.9 *************************************************
+
+ * removed ioctls. They have been really unneccesary and did not fit
+ into the new driver layout.
+ * cleaned up the code. Hey, it should be readable again.
+ * Moved device minors from 10+ to 0+
+ * Rewrote most of the documentation
+ * changed intel shadowing routines. Now original values are saved
+ and shadowing is turned off for 0xc0000 to 0xdffff, too (This
+ was needed to support 2MBit system bios flash chips. Thanks again
+ to Matthew Harrell for intensive testing.
+ * Removed dirty hacks from bios_read_proc()
+ * Added some fields to struct flashdevice to support all ROM types,
+ not only flash roms. Probing for other types still missing.
+ * Implemented probing for some strange Winbond chips (0x80/0x20).
+
+** 98/04/27 * V0.2.8 *************************************************
+
+ *** Attention *** This version has a lot of changes since
+ 0.2.7, so be very careful, when testing. Things may
+ be broken that used to work.
+
+ * Rewrote big parts of the driver to (theoretically) support
+ multiple flash chips and/or ROM areas.
+ * Tried to implement support for 2MBit System BIOS chips, but
+ I have no idea, whether it works. I don't have one.
+ * added some more OPTi, SiS and VIA PCI chipsets to chipset list.
+ They have no function yet, though.
+ * Some weird computers have an ISA bridge, but don't have it declared
+ as one. Now probing for known ISA bridge IDs. (Thanks to Matthew
+ Harrell for reporting this.)
+ * Added some new flashchip IDs and made some old ones work.
+
+** 98/04/24 * V0.2.7 *************************************************
+
+ * rewrote shadowing and wp functions to use a pci_functions structure
+ This makes it very easy to include new PCI chipsets.
+ * function chipset_init() detects PCI chipset.
+ * modversions support. Thanks to Matthew Harrell.
+ * moved PCI bridge detection to chipset_init()
+
+** 98/04/23 * V0.2.6 *************************************************
+
+ * repaired flashchip_ready_toggle and flashchip_ready_poll.
+ * Set WRITE_DELAY to 300 as it should be (works now)
+ * NOTE: These two changes make the operation of /dev/bios
+ theoretically correct, and by that quite secure.
+
+**********************************************************************
+
+There was no ChangeLog for versions prior to 0.2.6
+
+Stefan Reinauer, <stepan@openbios.org>
diff --git a/roms/openbios/utils/devbios/Makefile b/roms/openbios/utils/devbios/Makefile
new file mode 100644
index 00000000..b6f7611b
--- /dev/null
+++ b/roms/openbios/utils/devbios/Makefile
@@ -0,0 +1,22 @@
+# comment this if you don't want debugging information
+CFLAGS += -DDEBUG
+
+TARGET = bios.o
+OBJS = bios_core.o flashchips.o pcisets.o \
+ filesystem.o procfs.o programming.o
+
+obj-m := $(TARGET)
+bios-objs := $(OBJS)
+
+all: module comp
+
+clean:
+ -rm -f $(TARGET) $(OBJS) comp *.o bios.ko
+ -rm -rf .*.cmd .tmp_versions
+module:
+ make -C /usr/src/linux SUBDIRS=`pwd` modules
+
+comp: comp.c
+ $(CC) comp.c -O2 -o comp
+ strip comp
+
diff --git a/roms/openbios/utils/devbios/Makefile.24 b/roms/openbios/utils/devbios/Makefile.24
new file mode 100644
index 00000000..85717c4d
--- /dev/null
+++ b/roms/openbios/utils/devbios/Makefile.24
@@ -0,0 +1,81 @@
+CC = gcc
+LD = ld
+
+KERNEL = /usr/src/linux
+#KERNEL = /lib/modules/`uname -r`/build
+
+ARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
+
+ifeq ($(KERNEL)/.config,$(wildcard $(KERNEL)/.config))
+include $(KERNEL)/.config
+endif
+
+CFLAGS = -D__KERNEL__ -I${KERNEL}/include -Wall \
+ -Wstrict-prototypes -Wno-trigraphs -O2 \
+ -fomit-frame-pointer -fno-common \
+ -fno-strict-aliasing -pipe -DMODULE
+
+# comment this if you don't want debugging information
+CFLAGS += -DDEBUG
+
+# see if we need module versions
+ifdef CONFIG_MODVERSIONS
+CFLAGS += -DMODVERSIONS
+endif
+
+ifeq ($(ARCH),alpha)
+CFLAGS += -mno-fp-regs -ffixed-8 -mcpu=ev5 -Wa,-mev6
+LDFLAGS = -m elf64alpha
+endif
+
+ifeq ($(ARCH),sparc64)
+CFLAGS += -mno-fpu -mtune=ultrasparc -mmedlow -ffixed-g4 \
+ -fcall-used-g5 -fcall-used-g7
+LDFLAGS = -m elf_sparc64
+endif
+
+ifeq ($(ARCH),i386)
+CFLAGS += -mpreferred-stack-boundary=2 -march=i586
+LDFLAGS = -m elf_i386
+endif
+
+ifeq ($(ARCH), x86_64)
+CFLAGS += -mno-red-zone -mcmodel=kernel -fno-reorder-blocks \
+ -finline-limit=2000 -fno-strength-reduce
+LDFLAGS = -m elf_x86_64
+endif
+
+ifeq ($(ARCH),ia64)
+CFLAGS += -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \
+ -falign-functions=32
+LDFLAGS = -m elf64_ia64
+endif
+
+.SUFFIXES: .o .c .h
+
+TARGET = bios.o
+OBJS = bios_core.o flashchips.o pcisets.o \
+ filesystem.o procfs.o programming.o
+
+all: $(TARGET) comp
+
+$(TARGET): $(OBJS)
+ $(LD) $(LDFLAGS) -r -o $(TARGET) $(OBJS)
+
+clean:
+ -rm -f $(TARGET) $(OBJS) comp *.o
+
+.c.o:
+ $(CC) $(INCLUDES) -c $(INCDIRS) $(CFLAGS) $(X_CFLAGS) $(DEBUGFLAGS) $*.c -o $@
+
+comp: comp.c
+ $(CC) comp.c -O2 -o comp
+ strip comp
+
+bios_core.o: bios_core.c bios.h pcisets.h flashchips.h programming.h
+filesystem.o: filesystem.c bios.h pcisets.h flashchips.h programming.h
+flashchips.o: flashchips.c bios.h flashchips.h
+pcisets.o: pcisets.c bios.h pcisets.h flashchips.h programming.h
+procfs.o: procfs.c bios.h pcisets.h flashchips.h programming.h
+programming.o: programming.c bios.h pcisets.h flashchips.h programming.h
+
diff --git a/roms/openbios/utils/devbios/README.bios b/roms/openbios/utils/devbios/README.bios
new file mode 100644
index 00000000..45bd9a80
--- /dev/null
+++ b/roms/openbios/utils/devbios/README.bios
@@ -0,0 +1,256 @@
+NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
+
+/dev/bios is obsolete and no longer under development. Please adapt all
+changes to the "flashrom" utility of LinuxBIOS. This utility can be found
+at LinuxBIOSv2/utils/flashrom in the LinuxBIOS v2 repository. LinuxBIOS
+is available at http://www.linuxbios.org/
+
+I'm also looking for volunteers to port all features available in /dev/bios
+to flashrom so /dev/bios can be dropped from the OpenBIOS tree. These features
+include
+
+- block information about flash chips
+- block wise writing of flash chips
+- lots of supported flash chips and vendors.
+
+If you have questions, contact Stefan Reinauer <stepan@coresystems.de>
+
+NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
+
+
+/dev/bios documentation 2002/02/19
+
+Table of contents
+------------------
+
+ 1. What is /dev/bios?
+ 2. What hardware/software do I need to run /dev/bios?
+ 3. Where to get the latest release of /dev/bios
+ 4. How to get /dev/bios work
+ 5. Writing to the devices
+ 6. About PCI chipsets (ix86 only)
+ 7. About APM Powermanagement (ix86 only)
+ 8. About different flashchips.
+ 9. Hints for BIOS flashing
+
+If you want better information on this driver, read the ChangeLog,
+mail me or read the source, Luke :-)
+
+1. What is /dev/bios?
+----------------------
+
+This is a kernel driver for different kinds of (Flash)BIOSs that are
+available in today's hardware.
+
+There are well known BIOSs for
+ - System BIOS (resides at 0xe0000 on Intel PCs)
+ - graphics hardware
+ - SCSI host adapters
+ - networking interfaces with 'BOOT ROM'
+ - ...
+
+While in former times these BIOSs were implemented by using ROM or
+EPROM (both can't be updated without opening your computer) today's
+PC hardware is often delivered with so called FLASH ROMs. These
+can simply be updated by software. This driver has the approach to
+make Linux read and write flash roms.
+
+One word before you read ahead: This is still alpha software and
+writing to your flash roms may destroy them. So if you notice anything
+strange, don't even think about going on, but write some mail to:
+
+ Stefan Reinauer <stepan@openbios.org>
+
+Please note that I am not responsible in any way for what you
+do with this code or for what this code does with your computer.
+
+2. What hardware/software do I need to run /dev/bios?
+------------------------------------------------------
+
+Currently this driver supports ix86 (mainly Pentium,
+PPro, PII/III, Athlon, but some 486s), Itanium and Alpha
+architecture.
+It supports all flash chips from 32k to 2M (theoretically).
+Minimum kernel version is v2.2.x, but it's wise to use a
+2.4.x kernel.
+
+3. Where to get the latest release of /dev/bios?
+-------------------------------------------------
+
+/dev/bios was recently integrated into the OpenBIOS CVS
+tree for easier maintainance. General information can be
+found on the /dev/bios status page:
+http://www.freiburg.linux.de/OpenBIOS/status/devbios.html
+Latest releases of /dev/bios can be found at the download page:
+http://www.freiburg.linux.de/OpenBIOS/dev/download.html
+Latest development trees of /dev/bios can be found in the
+OpenBIOS CVS. For information how to access it, go to
+http://www.freiburg.linux.de/OpenBIOS/dev/cvs.html
+
+4. How do I get /dev/bios work
+-------------------------------
+
+Create the system bios device with
+
+ mknod /dev/bios c 104 0
+
+Now you can add devices for the other BIOSs (often known as option
+roms) in your Computer, i.e. like this:
+
+ mknod /dev/gfxbios c 104 1
+ mknod /dev/hddbios c 104 2
+ mknod /dev/netbios c 104 3
+
+The order of the devices may vary on your computer, maybe you even don't
+have a flash bios on your network card or on your scsi host adapter. You will
+have to decide this after playing around a bit.
+
+Now you have to compile and insert the kernel driver module:
+
+ cd devbios
+ make clean && make
+ insmod bios.o
+
+Now you have a new device, /dev/bios and, if you have
+your kernel configured to have the /proc/ interface,
+you have a status file /proc/bios.
+
+Since this driver is in an early state, you should have
+a look at dmesg very often.
+
+5. Writing to the devices
+--------------------------
+
+If you insert bios.o without any options, you are not able
+to write any of the devices. To enable writing, you should
+use
+ insmod bios.o write=1
+
+Writing is now possible with i.e.
+ dd if=yourbios.bin of=/dev/bios bs=128k count=1
+or
+ dd if=yourbios.bin of=/dev/bios bs=256k count=1
+
+depending on the size of your flash chip.
+
+You can use 'cat' for flashing as well. Note: Many flashchips are
+sectored and the whole sector has to be rewritten, the 4k clusters
+of cat may be very slow (and an 112 kb sector has to be written 28
+times completely instead of 1 time with dd)
+
+Make sure that your file "yourbios.bin" is a valid bios image for
+your motherboard and that it is not pkzipped or exe-pkzipped.
+(Usually, a 128kb bios images consist of 112kb lha-compressed data,
+2*4kb ESCD and DMI (PnP) Data and an 8 kb emergency boot block.)
+
+Writing to /dev/bios does not work for many chips right now. Write
+accesses are ignored in this case. If you want an unsupported flash
+rom supported, please mail me.
+WARNING: Setting an unsupported chip to "supported" without changing
+the rest of the code will *very likely* destroy the contents of your
+chip.
+
+On machines with an AWARD bios you can test whether writing works
+safely by only deleting the ESCD/DMI memory on the flash chip.
+This data is rewritten by the bios when empty, corrupted or when
+you put in a new expansion device. In that case you should see a
+message stating "Updating ESCD" during the next boot.
+
+Please have a close look at the size of your flash chip. For 128k
+flash chips, try
+
+ dd if=/dev/zero of=/dev/bios bs=4096 seek=28 count=2
+
+For 256k flash chips, you _MUST_ use the following line instead,
+or your system bios is going byebye:
+
+ dd if=/dev/zero of=/dev/bios bs=4096 seek=56 count=2
+
+Attention: I found other machines with their ESCD memory in the
+first sectors of the flash chip. These are afaics 512k+ chips
+often connected via a firmware hub.
+Behaviour of other BIOSs may be similar, but I can't give you
+any warranty it works.
+
+NOTE: If you listen to music from your soundcard while flashing,
+you may get errors like this:
+ Sound: DMA (output) timed out - IRQ/DRQ config error?
+
+Second, sound switches off while flashing. This is because all
+IRQs are blocked while the write procedure to ensure it doesn't
+get disturbed by any other hardware.
+
+6. About PCI chipsets
+----------------------
+
+Because this driver uses direct PCI accesses to switch shadowing
+and write protection of the bios off on PC architecture, each PCI
+chipset (or at least chipset group) has to be implemented and
+tested seperately. Successfully tested PCI chipsets are
+
+ * Intel 430HX/TX, 440BX/ZX, 460, 8x0
+ * UMC 486 (8881F/8886A)
+ * VIA (M)VP3
+ * AMD Irongate and others
+ * ServerWorks chipsets
+ * NSC CS5530 (geode companion)
+
+Any success/error reports are highly welcome. If you need a certain
+system type supported, contact me.
+
+
+7. About APM Power Management (ix86 only)
+------------------------------------------
+
+This driver is known to cause kernel oopses with some of the chipset
+drivers when APM is enabled. Reason is that the flash chip is mapped
+to the low bios address space which makes the unpacked bios image vanish
+so all pointers to APM functions are invalid.
+Nowadays most of the chipset drivers only map the high bios area, so
+this problem should not occur on any but old UMC/SiS chipsets. If you
+encounter oopses while reading/probing flash devices, disable power
+management before any write attempts. To achieve so, please pass "apm=off"
+as a kernel option, if your kernel is compiled with APM support.
+
+
+
+8. About different flashchips
+------------------------------
+
+Flash chips, /dev/bios has been successfully tested (writing) on:
+
+ * Winbond 29EE011
+ * Intel 28F008(SA)
+ * Atmel AT29C512
+ * SST 29EE010, 39SF020
+
+It *should* work, if you see a "Supported: yes" in /proc/bios, but
+I am not responsible in any way for what you do.. Please be careful.
+Please report any working flash chips so that this list can be completed.
+Currently many more flash chips than mentioned here will work.
+If you need a certain flash device supported, contact me.
+
+9. Hints for BIOS-Flashing
+---------------------------
+
+* Always try to write to the ESCD/DMI Memory before you overwrite the rest
+ of a bios (ix86) If you get ANY errors in dmesg output, DO NOT CONTINUE!
+* Always "diff" the new bios with the written image before rebooting
+* You may use comp, a little utility in the devbios source tree instead
+ of diff. It has a nicer output for binary files.
+* on Intel, only write the first 120k of an image to the System ROM, this keeps
+ the emergency bootblock working.
+
+************** FINAL NOTE *****************************
+
+If you want to help this project, send me
+
+ * /proc/bios-output
+ * dmesg-output (after insmodding the driver)
+ * your system-configuration
+ (e.g. output of lspci or /proc/bus/pci/devices)
+ * any comments
+ * any ideas
+
+ Stefan Reinauer <stepan@openbios.org>
+
diff --git a/roms/openbios/utils/devbios/ToDo b/roms/openbios/utils/devbios/ToDo
new file mode 100644
index 00000000..2d320a9e
--- /dev/null
+++ b/roms/openbios/utils/devbios/ToDo
@@ -0,0 +1,33 @@
+ToDo-/Buglist 2003/06/04 (0.4pre6)
+----------------------------------
+
+Memory Stuff
+ * devbios does not find any flash chip on some systems even though
+ they are supported. One of the reasons this might happen is that
+ the flash memory area is hidden using the CPUs mtrrs. If you have
+ a Pentium II/III/IV or AMD K6/K7 board, you might try
+ echo "base=0xffe00000 size=0x200000 type=uncachable" >| /proc/mtrr
+ before loading the module.
+
+Misc Stuff
+ * port this driver to fit into the linux kernel's
+ mtd device drivers.
+ * join with ctflasher code
+ * port to *BSD (if anybody wants that)
+ * disable NMI watchdog while flashing, if active
+
+PCI Stuff
+ * unshadow functions do not work on certain 440BX/GX chipsets?
+ when loading the module, no system flashchip is detected.
+ * change unshadow functions not to touch low bios area to
+ be apm and pci bios safe.
+
+Module stuff
+ * /proc/sys/kernel/bios-writable
+
+Flashchip Stuff
+ * Finnish FWH support.
+ * Implement writing for Macronix and AMD.
+ (Catalyst have Intel and AMD compatible chips)
+ * Implement write protection checking some flash chips have.
+ * Test/complete existing support
diff --git a/roms/openbios/utils/devbios/bios.h b/roms/openbios/utils/devbios/bios.h
new file mode 100644
index 00000000..b27372d0
--- /dev/null
+++ b/roms/openbios/utils/devbios/bios.h
@@ -0,0 +1,38 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * bios.h - compile time configuration and globals
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+#include <linux/spinlock.h>
+
+#define BIOS_MAJOR 104
+#define BIOS_MAXDEV 8
+#define BIOS_VERSION "0.4rc1"
+
+// #define UTC_BIOS
+
+extern int write;
+extern unsigned char *bios;
+extern spinlock_t bios_lock;
+
diff --git a/roms/openbios/utils/devbios/bios_core.c b/roms/openbios/utils/devbios/bios_core.c
new file mode 100644
index 00000000..d165cdb3
--- /dev/null
+++ b/roms/openbios/utils/devbios/bios_core.c
@@ -0,0 +1,198 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * bios_core.c - core skeleton
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#endif
+#include <linux/module.h>
+#endif
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#include "bios.h"
+#include "pcisets.h"
+#include "flashchips.h"
+#include "programming.h"
+
+extern struct file_operations bios_fops;
+int bios_proc_register(void);
+int bios_proc_unregister(void);
+
+int write = 0;
+
+spinlock_t bios_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * ******************************************
+ *
+ * Cleanup
+ *
+ * ******************************************
+ */
+
+static void free_iomaps(void)
+{
+ unsigned long lastmapped=0;
+ unsigned int i;
+
+ /* We remember the last mapped area to be sure that we only iounmap
+ * every mapped area once. If two flash devices are in the same
+ * area but do not occur sequentially during probing you have a
+ * seriously strange hardware
+ */
+ for (i=0; i<flashcount; i++) {
+ if (lastmapped==flashdevices[i].mapped)
+ continue;
+ iounmap((void *)flashdevices[i].mapped);
+ lastmapped=flashdevices[i].mapped;
+ }
+}
+
+/*
+ * ******************************************
+ *
+ * Initialization
+ *
+ * ******************************************
+ */
+
+void probe_system(void)
+{
+#ifdef __alpha__
+ probe_alphafw();
+#endif
+ /* This function checks all flash media attached to
+ * PCI devices in the system. This means NON-PCI systems
+ * don't work. This causes machine checks on my LX164 test
+ * machine, so leave it away until it's fixed. This is
+ * needed for Ruffians, so we check the machine type
+ * in probe_alphafw() and call probe_pcibus from there.
+ * This could use some cleanup
+ */
+#ifndef __alpha__
+ probe_pcibus();
+#endif
+}
+
+static __init int bios_init(void)
+{
+ printk(KERN_INFO "BIOS driver v" BIOS_VERSION " (writing %s) for "
+ UTS_RELEASE "\n", write?"enabled":"disabled");
+
+#if !defined(UTC_BIOS) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ if (!pci_present()) {
+ printk(KERN_WARNING "BIOS: No PCI system.");
+ return -EBUSY;
+ }
+#endif
+
+ /* Probe for flash devices */
+ probe_system();
+
+ if (flashcount==0) {
+ printk(KERN_WARNING "BIOS: No flash devices found.\n");
+ return -EBUSY;
+ }
+
+ if (register_chrdev(BIOS_MAJOR, "bios", &bios_fops) == -EBUSY) {
+ printk(KERN_WARNING "BIOS: Could not register bios device.\n");
+ free_iomaps();
+ return -EBUSY;
+ }
+
+#ifdef CONFIG_PROC_FS
+ bios_proc_register();
+#endif
+ return 0;
+}
+
+/*
+ * ******************************************
+ *
+ * module handling
+ *
+ * ******************************************
+ */
+
+#ifdef MODULE
+MODULE_PARM(write,"i");
+MODULE_AUTHOR("Stefan Reinauer <stepan@openbios.org>");
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,10)
+MODULE_LICENSE("GPL");
+#endif
+
+static __exit void cleanup_bios_module (void)
+{
+#ifdef CONFIG_PROC_FS
+ bios_proc_unregister();
+#endif
+ free_iomaps();
+
+ unregister_chrdev(BIOS_MAJOR, "bios");
+ printk(KERN_INFO "BIOS driver removed.\n");
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+int init_module(void)
+{
+ return bios_init();
+}
+
+void cleanup_module(void)
+{
+ cleanup_bios_module();
+}
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,74)
+module_init(bios_init);
+module_exit(cleanup_bios_module);
+#endif
+
+void inc_mod(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ MOD_INC_USE_COUNT;
+#endif
+}
+
+void dec_mod(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
+#endif
diff --git a/roms/openbios/utils/devbios/comp.c b/roms/openbios/utils/devbios/comp.c
new file mode 100644
index 00000000..9d2acb14
--- /dev/null
+++ b/roms/openbios/utils/devbios/comp.c
@@ -0,0 +1,47 @@
+/* Simple utility to compare 2 files.
+ * Diff or cmp are not sufficient, when
+ * comparing bioses :-)
+ *
+ * Copyright (c) 1998-2000 by Stefan Reinauer
+ */
+
+
+#include <stdio.h>
+
+int main (int argc, char *argv[])
+{
+ FILE *eins,*zwei;
+ int a,b,i=0,flag=0;
+
+ if(argv[1]==NULL||argv[2]==NULL) {
+ printf ("Usage: %s file1 file2\n %s compares two files.\n",argv[0],argv[0]);
+ return 0;
+ }
+ eins=fopen(argv[1],"r");
+ zwei=fopen(argv[2],"r");
+
+ if (eins==NULL) {
+ printf ("File %s not found or unreadable.\n",argv[1]);
+ return 0;
+ }
+ if (zwei==NULL) {
+ printf ("File %s not found or unreadable.\n",argv[2]);
+ fclose (eins);
+ return 0;
+ }
+
+ while (!feof(eins)) {
+ a=fgetc(eins);
+ b=fgetc(zwei);
+ if (flag==0 && (a==-1||b==-1) && (a!=-1||b!=-1)) {
+ printf ("One file ended. Printing the rest of the other.\n");
+ flag=1;
+ }
+ if(a!=b) printf ("0x%06x: 0x%02x -> 0x%02x\n",i,a,b);
+ i++;
+ }
+
+ fclose(eins);
+ fclose(zwei);
+ return 0;
+}
diff --git a/roms/openbios/utils/devbios/filesystem.c b/roms/openbios/utils/devbios/filesystem.c
new file mode 100644
index 00000000..0dab7112
--- /dev/null
+++ b/roms/openbios/utils/devbios/filesystem.c
@@ -0,0 +1,300 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * filesystem.c - vfs character device interface
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS)
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+
+#include "bios.h"
+#include "flashchips.h"
+#include "pcisets.h"
+#include "programming.h"
+
+#ifdef MODULE
+void inc_mod(void);
+void dec_mod(void);
+#endif
+
+/*
+ * ******************************************
+ *
+ * /dev/bios filesystem operations
+ *
+ * ******************************************
+ */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#define FDEV (MINOR(file->f_dentry->d_inode->i_rdev))
+#else
+#define FDEV (iminor(file->f_dentry->d_inode))
+#endif
+#define CFLASH flashdevices[FDEV]
+// #define BIOS_SIZE ((flashchips[CFLASH.flashnum].size)*1024)
+#define BIOS_SIZE (CFLASH.size)
+
+static loff_t bios_llseek(struct file *file, loff_t offset, int origin )
+{
+ currflash=FDEV;
+ switch(origin) {
+ case 0:
+ break;
+ case 1:
+ offset += file->f_pos;
+ break;
+ case 2:
+ offset += BIOS_SIZE;
+ break;
+ }
+ return((offset >= 0)?(file->f_pos = offset):-EINVAL);
+}
+
+static ssize_t bios_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+ signed int size=((BIOS_SIZE-*ppos>count) ? count : BIOS_SIZE-*ppos);
+ unsigned char *addr = (unsigned char*)CFLASH.mapped + CFLASH.offset;
+ int i;
+
+ currflash = FDEV;
+
+ devices[flashdevices[currflash].idx].activate();
+
+ for (i=0;i<size;i++)
+ buffer[i]=flash_readb(addr,*ppos+i);
+
+ devices[flashdevices[currflash].idx].deactivate();
+
+ *ppos+=size;
+ return size;
+}
+
+static ssize_t bios_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+ unsigned long flags;
+ unsigned int offset=0, startsec=0, endsec=0;
+ unsigned int secnum=0, size=0, writeoffs=0;
+ unsigned int i, fn;
+ unsigned char *clipboard;
+ unsigned char *addr = (unsigned char*)CFLASH.mapped + CFLASH.offset;
+
+ currflash=FDEV;
+ fn=CFLASH.flashnum;
+
+ /* Some security checks. */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ if (!suser())
+ return -EACCES;
+#endif
+
+ if (!write) {
+ printk (KERN_WARNING "Writing is disabled for security reasons. RTFM.\n");
+ return -EACCES;
+ }
+
+ if (!flashchips[fn].supported) {
+ printk (KERN_ERR "BIOS: Flash device not supported.\n");
+ return -EMEDIUMTYPE;
+ }
+
+ if ( count > BIOS_SIZE-*ppos )
+ return -EFBIG;
+
+ /* FIXME: Autoselect(AMD) BC-90
+ * -> 00/MID;
+ * 01/PID;
+ * 02/Protected (1=yes/0=no)
+ */
+
+ /* Determine size of data to be written */
+
+ if (!(flashchips[fn].flags & f_needs_erase) ) {
+ offset=(unsigned int)*ppos&~(flashchips[fn].pagesize-1);
+ size=(((unsigned int)*ppos+count+(flashchips[fn].pagesize-1))&
+ ~(flashchips[CFLASH.flashnum].pagesize-1))-offset;
+ } else {
+ while (flashchips[fn].sectors[secnum] <= flashchips[fn].size ) {
+ if ((unsigned int)*ppos >= flashchips[fn].sectors[secnum]*1024) {
+ offset=flashchips[fn].sectors[secnum]*1024;
+ startsec=secnum;
+ }
+ if ((unsigned int)*ppos+count-1 <= flashchips[fn].sectors[secnum]*1024) {
+ size=(flashchips[fn].sectors[secnum]*1024)-offset;
+ endsec=secnum-1;
+ break;
+ }
+ secnum++;
+ }
+ }
+
+#ifdef DEBUG
+ printk (KERN_DEBUG "BIOS: Write [0x%06x..0x%06x] [0x%06x..0x%06x]\n",
+ (unsigned int)(*ppos),(unsigned int)(*ppos+count-1),offset,offset+size-1);
+#endif
+
+ /* prepare data for writing */
+
+ clipboard=vmalloc(size);
+
+ spin_lock_irqsave(&bios_lock, flags);
+
+ devices[flashdevices[currflash].idx].activate();
+
+ for (i=0; i < size; i++)
+ clipboard[i] = flash_readb(addr,offset+i);
+
+ copy_from_user(clipboard+(*ppos-offset), buffer, count);
+
+ /* start write access */
+
+ if (flashchips[fn].flags & f_intel_compl) {
+ iflash_erase_sectors(addr,fn,startsec,endsec);
+
+ for (i=0;i<size;i++)
+ iflash_program_byte(addr, offset+i, clipboard[i]);
+
+ flash_command(addr, 0xff);
+
+ } else {
+
+ if (flashchips[fn].flags & f_needs_erase) {
+ if (size == flashchips[fn].size*1024) { /* whole chip erase */
+ printk (KERN_DEBUG "BIOS: Erasing via whole chip method\n");
+ flash_erase(addr, fn);
+ } else {
+ printk (KERN_DEBUG "BIOS: Erasing via sector method\n");
+ flash_erase_sectors(addr, fn,startsec,endsec);
+ }
+ }
+
+ while (size>0) {
+ if ((flashchips[fn].flags & f_manuf_compl) != f_atmel_compl) {
+ flash_program(addr);
+ } else {
+ flash_program_atmel(addr);
+ }
+ for (i=0;i<flashchips[fn].pagesize;i++) {
+ flash_writeb(addr,offset+writeoffs+i,clipboard[writeoffs+i]);
+ }
+ if ((flashchips[fn].flags & f_manuf_compl) == f_atmel_compl) {
+ udelay(750);
+ } else {
+ if (flashchips[fn].pagesize==1)
+ udelay(30);
+ else
+ udelay(300);
+ }
+
+ if (flash_ready_poll(addr,offset+writeoffs+flashchips[fn].pagesize-1,
+ clipboard[writeoffs+flashchips[fn].pagesize-1])) {
+ printk (KERN_ERR "BIOS: Error occured, please repeat write operation.\n");
+ }
+ flash_command(addr, 0xf0);
+
+ writeoffs += flashchips[fn].pagesize;
+ size -= flashchips[fn].pagesize;
+ }
+ }
+
+ devices[flashdevices[currflash].idx].deactivate();
+
+ spin_unlock_irqrestore(&bios_lock, flags);
+
+ vfree(clipboard);
+
+ *ppos+=count;
+ return count;
+}
+
+static int bios_open(struct inode *inode, struct file *file)
+{
+ currflash=FDEV;
+
+ if (flashcount<=FDEV) {
+ printk (KERN_ERR "BIOS: There is no device (%d).\n",FDEV);
+ return -ENODEV;
+ }
+
+#ifdef DEBUG
+ printk(KERN_DEBUG "BIOS: Opening device %d\n",FDEV);
+#endif
+ /* Only one shall open for writing */
+
+ if ((CFLASH.open_cnt && (file->f_flags & O_EXCL)) ||
+ (CFLASH.open_mode & O_EXCL) ||
+ ((file->f_mode & 2) && (CFLASH.open_mode & O_RDWR)))
+ return -EBUSY;
+
+ if (file->f_flags & O_EXCL)
+ CFLASH.open_mode |= O_EXCL;
+
+ if (file->f_mode & 2)
+ CFLASH.open_mode |= O_RDWR;
+
+ CFLASH.open_cnt++;
+
+
+#ifdef MODULE
+ inc_mod();
+#endif
+ return 0;
+}
+
+static int bios_release(struct inode *inode, struct file *file)
+{
+ currflash=FDEV;
+ if (file->f_flags & O_EXCL)
+ CFLASH.open_mode &= ~O_EXCL;
+
+ if (file->f_mode & 2)
+ CFLASH.open_mode &= ~O_RDWR;
+
+ CFLASH.open_cnt--;
+
+#ifdef MODULE
+ dec_mod();
+#endif
+ return 0;
+}
+
+struct file_operations bios_fops = {
+ .owner = THIS_MODULE,
+ .llseek = bios_llseek,
+ .read = bios_read,
+ .write = bios_write,
+ .open = bios_open,
+ .release = bios_release,
+};
+
diff --git a/roms/openbios/utils/devbios/flashchips.c b/roms/openbios/utils/devbios/flashchips.c
new file mode 100644
index 00000000..460a85de
--- /dev/null
+++ b/roms/openbios/utils/devbios/flashchips.c
@@ -0,0 +1,313 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * flashchips.c - contains all information about supported flash devices.
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+// <-- C++ style comments are for experimental comments only.
+// They will disappear as soon as I fixed all the stuff.
+
+#include "bios.h"
+#include "flashchips.h"
+
+unsigned int currflash=0;
+
+const manufacturer_t manufacturers[] =
+{
+ { "AMD", 0x01 },
+ { "AMI", 0x02 },
+ { "Fairchild", 0x83 },
+ { "Fujitsu", 0x04 },
+ { "GTE", 0x85 },
+ { "Harris", 0x86 },
+ { "Hitachi", 0x07 },
+ { "Inmos", 0x08 },
+ { "Intel", 0x89 },
+ { "I.T.T.", 0x8A },
+ { "Intersil", 0x0B },
+ { "Monolithic Memories",0x8C },
+ { "Mostek", 0x0D },
+ { "Motorola", 0x0E },
+ { "National", 0x8F },
+ { "NEC", 0x10 },
+ { "RCA", 0x91 },
+ { "Raytheon", 0x92 },
+ { "Rockwell", 0x13 },
+ { "Seeq", 0x94 },
+ { "Philips Semi.", 0x15 },
+ { "Synertek", 0x16 },
+ { "Texas Instruments", 0x97 },
+ { "Toshiba", 0x98 },
+ { "Xicor", 0x19 },
+ { "Zilog", 0x1A },
+ { "Eurotechnique", 0x9B },
+ { "Mitsubishi", 0x1C },
+ { "PMC Flash", 0x9D },
+ { "Exel", 0x9E },
+ { "Atmel", 0x1F },
+ { "SGS/Thomson", 0x20 },
+ { "Lattice Semi.", 0xA1 },
+ { "NCR", 0xA2 },
+ { "Wafer Scale Integr.",0x23 },
+ { "IBM", 0xA4 },
+ { "Tristar", 0x25 },
+ { "Visic", 0x26 },
+ { "Intl. CMOS Tech.", 0xA7 },
+ { "SSSI", 0xA8 },
+ { "MicrochipTech.", 0x29 },
+ { "Ricoh Ltd.", 0x2A },
+ { "VLSI", 0xAB },
+ { "Micron Technology", 0x2C },
+ { "Hyundai Elect.", 0xAD },
+ { "OKI Semiconductor", 0xAE },
+ { "ACTEL", 0x2F },
+ { "Sharp", 0xB0 },
+ { "Catalyst", 0x31 },
+ { "Panasonic", 0x32 },
+ { "IDT", 0xB3 },
+ { "Cypress", 0x34 },
+ { "DEC", 0xB5 },
+ { "LSI Logic", 0xB6 },
+ { "Plessey", 0x37 },
+ { "UTMC", 0x38 },
+ { "Thinking Machine", 0xB9 },
+ { "Thomson CSF", 0xBA },
+ { "Integ. CMOS(Vertex)",0x3B },
+ { "Honeywell", 0xBC },
+ { "Tektronix", 0x3D },
+ { "Sun Microsystems", 0x3E },
+ { "SST", 0xBF },
+ { "MOSEL", 0x40 },
+ { "Siemens", 0xC1 },
+ { "Macronix", 0xC2 },
+ { "Xerox", 0x43 },
+ { "Plus Logic", 0xC4 },
+ { "SunDisk", 0x45 },
+ { "Elan Circuit Tech.", 0x46 },
+ { "Europ. Silicon Str.",0xC7 },
+ { "Apple Computer", 0xC8 },
+ { "Xilinx", 0xC9 },
+ { "Compaq", 0x4A },
+ { "Protocol Engines", 0xCB },
+ { "SCI", 0x4C },
+ { "Seiko Instruments", 0xCD },
+ { "Samsung", 0xCE },
+ { "I3 Design System", 0x4F },
+ { "Klic", 0xD0 },
+ { "Crosspoint Sol.", 0x51 },
+ { "Alliance Semicond.", 0x52 },
+ { "Tandem", 0xD3 },
+ { "Hewlett-Packard", 0x54 },
+ { "Intg. Silicon Sol.", 0xD5 },
+ { "Brooktree", 0xD6 },
+ { "New Media", 0x57 },
+ { "MHS Electronic", 0x58 },
+ { "Performance Semi.", 0xD9 },
+ { "Winbond", 0xDA },
+ { "Kawasaki Steel", 0x5B },
+ { "Bright Micro", 0xDC },
+ { "TECMAR", 0x5D },
+ { "Exar", 0x5E },
+ { "PCMCIA", 0xDF },
+ { "Goldstar", 0xE0 },
+ { "Northern Telecom", 0x61 },
+ { "Sanyo", 0x62 },
+ { "Array Microsystems", 0xE3 },
+ { "Crystal Semicond.", 0x64 },
+ { "Analog Devices", 0xE5 },
+ { "PMC-Sierra", 0xE6 },
+ { "Asparix", 0x67 },
+ { "Convex Computer", 0x68 },
+ { "Quality Semicond.", 0xE9 },
+ { "Nimbus Technology", 0xEA },
+ { "Transwitch", 0x6B },
+ { "ITT Intermetall", 0xEC },
+ { "Cannon", 0x6D },
+ { "Altera", 0x6E },
+ { "NEXCOM", 0xEF },
+ { "QUALCOMM", 0x70 },
+ { "Sony", 0xF1 },
+ { "Cray Research", 0xF2 },
+ { "AMS(Austria Micro)", 0x73 },
+ { "Vitesse", 0xF4 },
+ { "Aster Electronics", 0x75 },
+ { "Bay Networks(Synoptic)", 0x76 },
+ { "Zentrum Mikroelec.", 0xF7 },
+ { "TRW", 0xF8 },
+ { "Thesys", 0x79 },
+ { "Solbourne Computer", 0x7A },
+ { "Allied-Signal", 0xFB },
+ { "Dialog", 0x7C },
+ { "Media Vision", 0xFD },
+ { "Level One Commun.", 0xFE },
+ { "Eon", 0x7F },
+
+ { "Unknown", 0x00 }
+};
+
+const flashchip_t flashchips[] =
+{
+ /* AMD */
+ { "29F016B", 0xad01, 5, 2048, 0, 1, 1, (int []) { 0,2048 } },
+ { "29F080B", 0xd501, 5, 1024, 0, 1, 1, (int []) { 0,1024 } },
+ { "29F800BT", 0xd601, 5, 1024, 0, 1, 1, (int []) { 0,1024 } },
+ { "29F800BB", 0x5801, 5, 1024, 0, 1, 1, (int []) { 0,1024 } },
+ { "29F040B", 0xa401, 5, 512, 0, 1, 1, (int []) { 0, 512 } },
+ { "29F400T", 0x2301, 5, 512, 0, 1, 1, (int []) { 0, 512 } },
+ { "29LV004T", 0xb501, 3, 512, 0, 1, 1, (int []) { 0, 512 } },
+ { "29LV400T", 0xb901, 3, 512, 0, 1, 1, (int []) { 0, 512 } },
+ { "29F400B", 0xab01, 5, 512, 0, 1, 1, (int []) { 0, 512 } },
+ { "29LV004B", 0xb601, 3, 512, 0, 1, 1, (int []) { 0, 512 } },
+ { "29LV400B", 0xba01, 3, 512, 0, 1, 1, (int []) { 0, 512 } },
+ { "28F020A", 0x2901, 12, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "28F020", 0x2a01, 12, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29F002T", 0xb001, 5, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29LV002T", 0x4001, 3, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29LV200T", 0x3b01, 3, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29F200T", 0x5101, 5, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29F002B", 0x3401, 5, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29LV002B", 0xc201, 3, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29LV200B", 0xbf01, 3, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29F200B", 0x5701, 5, 256, 0, 1, 1, (int []) { 0, 256 } },
+ { "29F010", 0x2001, 5, 128, 0, 1, 1, (int []) { 0, 128 } },
+ { "28F010A", 0xa201, 12, 128, 0, 1, 1, (int []) { 0, 128 } },
+ { "28F010", 0xa701, 12, 128, 0, 1, 1, (int []) { 0, 128 } },
+ { "29F100T", 0xd901, 5, 64, 0, 1, 1, (int []) { 0, 64 } },
+ { "29F100B", 0xdf01, 5, 64, 0, 1, 1, (int []) { 0, 64 } },
+ { "28F512A", 0xae01, 12, 64, 0, 1, 1, (int []) { 0, 64 } },
+ { "28F512", 0x2501, 12, 64, 0, 1, 1, (int []) { 0, 64 } },
+ { "28F256A", 0x2f01, 12, 32, 0, 1, 1, (int []) { 0, 32 } },
+ { "28F256", 0xa101, 12, 32, 0, 128, 1, (int []) { 0, 32 } },
+
+ /* Atmel */
+ { "AT49BV010", 0x851f, 3, 128, 0, 128, 1, (int []) { 0, 128 } },
+//Word { "AT49F1025", 0x851f, 5, 128, 0, 256, 1, (int []) { 0, 128 } },
+ { "AT49x020", 0x0b1f, 5, 256, 0, 128, 1, (int []) { 0, 256 } },
+ { "AT49F040", 0x131f, 5, 512, 0, 128, 1, (int []) { 0, 512 } },
+ { "AT49F010", 0x171f, 5, 128, 0, 128, 1, (int []) { 0, 128 } },
+ { "AT49F080", 0x231f, 5, 1024, 0, 128, 1, (int []) { 0,1024 } },
+ { "AT29C040A", 0xa41f, 5, 512, 1, 256, 4, (int []) { 0, 512 } },
+//Word { "AT29C1024", 0x251f, 3, 128, 0, 128, 0, (int []) { 0, 128 } },
+//Word { "AT29LV1024", 0x261f, 3, 128, 0, 128, 0, (int []) { 0, 128 } },
+ { "AT49F080T", 0xa71f, 5, 1024, 0, 128, 1, (int []) { 0,1024 } },
+ { "AT29BV010A", 0x351f, 3, 128, 1, 128, 4, (int []) { 0, 128 } },
+ { "AT29BV020", 0xba1f, 3, 256, 1, 256, 4, (int []) { 0, 256 } },
+ { "AT29LV256", 0xbc1f, 3, 32, 1, 64, 4, (int []) { 0, 32 } },
+ { "AT29LV512", 0x3d1f, 3, 64, 1, 128, 4, (int []) { 0, 64 } },
+ { "AT29BV040A", 0xc41f, 3, 512, 1, 256, 4, (int []) { 0, 512 } },
+ { "AT29C010A", 0xd51f, 5, 128, 1, 128, 4, (int []) { 0, 128 } },
+ { "AT29C020", 0xda1f, 5, 256, 1, 256, 4, (int []) { 0, 256 } },
+ { "AT29C256", 0xdc1f, 3, 32, 1, 64, 4, (int []) { 0, 32 } },
+ { "AT29C512", 0x5d1f, 5, 64, 1, 128, 4, (int []) { 0, 64 } },
+
+ /* Catalyst */
+ { "CAT28F150T", 0x0431, 12, 192, 1, 128, 3, (int []) { 0, 64,160,168,176,192 } },
+ { "CAT28F150B", 0x8531, 12, 192, 1, 128, 3, (int []) { 0, 16, 24, 32,128, 192 } },
+ { "CAT28F001T", 0x9431, 12, 128, 1, 128, 3, (int []) { 0,112,116,120,128 } },
+ { "CAT28F001B", 0x1531, 12, 128, 1, 128, 3, (int []) { 0, 8, 12, 16,128 } },
+ { "CAT29F002T", 0xb031, 5, 256, 0, 128, 1, (int []) { 0, 64,128,192,224,232,240,256 } },
+ { "CAT29F002B", 0x3431, 5, 256, 0, 128, 1, (int []) { 0, 16, 24, 32, 64,128,192,256 } },
+ { "CAT28F002T", 0x7c31, 12, 256, 1, 128, 3, (int []) { 0,128,224,232,240,256 } },
+ { "CAT28F002B", 0xfd31, 12, 256, 1, 128, 3, (int []) { 0, 16, 24, 32,128,256 } },
+ { "CAT28F020" , 0xbd31, 12, 256, 0, 1, 1, (int []) { 0,256 } },
+//Word { "CAT28F102" , 0x5131, 12, 128, 0, 0, 0, (int []) { 0,128 } },
+ { "CAT28F010" , 0xb431, 12, 128, 0, 1, 1, (int []) { 0,128 } },
+ { "CAT28F512" , 0xb831, 12, 64, 0, 1, 1, (int []) { 0, 64 } },
+
+ { "29F040", 0xa404, 5, 512, 1, 1, 1, (int []) { 0, 64, 128, 192, 256, 320, 384, 448, 512 } }, /* Fujitsu */
+
+
+ /* Intel */
+ { "28F010", 0x3489, 12, 128, 0, 128, 1, (int []) { 0,128 } },
+ { "28F020", 0x3d89, 12, 256, 0, 128, 1, (int []) { 0,256 } },
+ { "28F001BX-T", 0x9489, 12, 128, 1, 128, 3, (int []) { 0,112,116,120,128 } },
+ { "28F001BX-B", 0x9589, 12, 128, 1, 128, 3, (int []) { 0, 8, 12, 16,128 } },
+//Word { "28F400BX-T", 0x7089, 12, 512, 0, 256, 3, (int []) { 0,128,256,384,480,488,496,512 } },
+//Word { "28F400BX-B", 0xF189, 12, 512, 0, 256, 3, (int []) { 0, 16, 24, 32,128,256,384,512 } },
+//Word { "28F200-T", 0xF489, 12, 256, 0, 256, 3, (int []) { 0,128,224,232,240,256} },
+//Word { "28F200-B", 0x7589, 12, 256, 0, 256, 3, (int []) { 0, 16, 24, 32,128,256 } },
+ { "28F016B3-T", 0xd089, 3, 1024, 0, 1, 3, (int []) { 0, 2048 } },
+ { "28F016B3-B", 0xd189, 3, 1024, 0, 1, 3, (int []) { 0, 2048 } },
+ { "28F008B3-T", 0xd289, 3, 1024, 0, 1, 3, (int []) { 0, 1024 } },
+ { "28F008B3-B", 0xd389, 3, 1024, 0, 1, 3, (int []) { 0, 1024 } },
+ { "28F004B3-T", 0xd489, 3, 512, 0, 128, 3, (int []) { 0,128,256,384,480,488,496,512 } },
+ { "28F004B3-B", 0xd589, 3, 512, 0, 128, 3, (int []) { 0, 16, 24, 32,128,256,384,512 } },
+ { "28F004BX-T", 0xF889, 12, 512, 1, 128, 3, (int []) { 0,128,256,384,480,488,496,512 } },
+ { "28F004BX-B", 0x7989, 12, 512, 1, 128, 3, (int []) { 0, 16, 24, 32,128,256,384,512 } },
+ { "28F002-T", 0x7c89, 12, 256, 1, 128, 3, (int []) { 0,128,224,232,240,256 } },
+ { "28F002-B", 0xfd89, 12, 256, 1, 256, 3, (int []) { 0, 16, 24, 32,128,256 } },
+ { "28F008??", 0xa289, 12, 1024, 1, 1, 3, (int []) { 0, 64,128,192,256,320,384,448,512,576,640,704,768,832,896,960,1024 } },
+ { "28F008SA", 0xa189, 12, 1024, 1, 1, 3, (int []) { 0, 64,128,192,256,320,384,448,512,576,640,704,768,832,896,960,1024 } },
+ { "28F004??", 0xad89, 5, 512, 0, 1, 3, (int []) { 0, 512} },
+ { "28F008??", 0xac89, 5, 1024, 0, 1, 3, (int []) { 0,1024} },
+
+ /* Eon */
+ { "E28F004S5", 0x7f8f, 5, 512, 1, 1, 3, (int []) { 0, 64,128,192,256,320,384,448,512 } },
+ { "EN29F002B", 0x977f, 5, 256, 1, 1, 1, (int []) { 0, 16, 24, 32,128,256 } },
+ { "EN29F002T", 0x927f, 5, 256, 1, 1, 1, (int []) { 0,128,224,232,240,256 } },
+
+ /* SST */
+ { "28EE011", 0x01bf, 5, 128, 0, 128, 0, (int []) { 0, 128 } },
+ { "28EE040", 0x04bf, 5, 512, 0, 128, 0, (int []) { 0, 512 } },
+ { "29EE010", 0x07bf, 5, 128, 1, 128, 0, (int []) { 0, 128 } },
+ { "29x010", 0x08bf, 3, 128, 0, 128, 0, (int []) { 0, 128 } },
+ { "29EE020", 0x10bf, 5, 256, 0, 128, 0, (int []) { 0, 256 } },
+ { "29x020", 0x92bf, 3, 256, 0, 128, 0, (int []) { 0, 256 } },
+ { "29x512", 0x3dbf, 3, 64, 0, 128, 0, (int []) { 0, 64 } },
+ { "29EE512", 0x5dbf, 5, 64, 0, 128, 0, (int []) { 0, 64 } },
+ { "29x020", 0x92bf, 3, 256, 0, 128, 0, (int []) { 0, 256 } },
+ { "39SF020", 0xb6bf, 5, 256, 1, 1, 0x81, (int []) { 0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256 } },
+ { "49LF002A", 0x57bf, 3, 256, 0, 1, 0x81, (int[]) {0,256} },
+ { "49LF003A", 0x1bbf, 3, 384, 0, 1, 0x81, (int[]) {0,384} },
+ { "49LF004A", 0x60bf, 3, 512, 1, 1, 0x09, (int[]) {0, 4, 8, 12, 16, 24,28, 32, 512} },
+ { "49LF008A", 0x5abf, 3, 1024, 0, 1, 0x81, (int[]) {0,1024} },
+ { "49LF020", 0x61bf, 3, 256, 1, 4096, 0, (int[]) {0,256} },
+ { "49LF040", 0x51bf, 3, 512, 1, 4096, 0, (int[]) {0,512} },
+ { "49LF080A", 0x5bbf, 3, 1024, 1, 4096, 0, (int[]) {0,1024} },
+
+ /* Macronix */
+ { "MX28F1000AP",0x1ac2, 12, 128, 0, 1, 1, (int []) { 0, 16, 32, 48, 64, 80, 96,112,116,120,124,128 } },
+ { "MX28F1000P", 0x91c2, 12, 128, 0, 1, 1, (int []) { 0, 16, 32, 48, 64, 80, 96,112,128 } },
+ { "MX28F1000PC",0xf7c2, 12, 128, 0, 1, 1, (int []) { 0, 16, 32, 48, 64, 80, 96,112,128 } },
+//id? { "MX28F1000PPC",0x7fc2,12, 128, 0, 1, 1, (int []) { 0, 16, 32, 48, 64, 80, 96,112,116,120,124,128 } },
+ { "MX29F1610A", 0xfac2, 5, 2048, 1, 128, 0, (int []) { 0, 2048} },
+
+ /* Winbond */
+ { "W29EE011", 0xc1da, 5, 128, 1, 128, 0, (int []) { 0, 128 } },
+ { "W29C020", 0x45da, 5, 256, 1, 128, 0, (int []) { 0, 256 } },
+ { "W29C040/042",0x46da, 5, 512, 1, 256, 0, (int []) { 0, 512 } },
+ { "W29EE512", 0xc8da, 5, 64, 1, 128, 0, (int []) { 0, 64 } },
+ { "W29C101", 0x4fda, 5, 128, 1, 256, 0, (int []) { 0, 128 } },
+ { "W49V002", 0xb0da, 3, 256, 1, 1, 1, (int []) { 0, 64, 128, 192, 224, 232, 240, 256 } },
+ //{ "W49F002", 0x0bda, 5, 256, 1, 1, 1, (int []) { 0, 64, 128, 192, 224, 232, 240, 256 } },
+ { "W49F002U", 0x0bda, 5, 256, 1, 1,0x09, (int []) { 0, 128, 224, 232, 240, 256 } }, /* Winbond */
+
+ /* SGS/Thomson */
+ { "M29F002B(N)T", 0xb020, 5, 256, 0, 1, 0, (int[]) {0, 64, 128, 256 } },
+ { "M29F002B(N)B", 0x3420, 5, 256, 0, 1, 0, (int[]) {0, 256 } },
+ { "M50FW040", 0x2c20, 3, 512, 1, 128, 0x0b, (int []) { 0, 64, 128, 192, 256, 320, 384, 448, 512 } },
+
+ { "Pm29F002T", 0x1d9d, 5, 256, 1, 1, 0x1, (int []) { 0,128,224,232,240,256 } },
+ /* default entry */
+ { "Unknown", 0x0000, 0, 0, 0, 0, 0, (int []) { 0 } }
+};
+
diff --git a/roms/openbios/utils/devbios/flashchips.h b/roms/openbios/utils/devbios/flashchips.h
new file mode 100644
index 00000000..3e6e5a6e
--- /dev/null
+++ b/roms/openbios/utils/devbios/flashchips.h
@@ -0,0 +1,81 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * flashchips.h - flash device structures.
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/*
+ * flags structure
+ * bit 0 = needs erase before write (f_needs_erase)
+ * bit 1-3 flash manu type
+ * bit 4-6 probably needed for more manu
+ * bit 7 = sector erase happens one sector at a time
+ * (f_slow_sector_erase)
+ */
+
+#define f_needs_erase 0x01
+
+/* 3 bit for flashtype */
+#define f_manuf_compl 0x0e /* Mask out bits 1-3 */
+#define f_intel_compl 0x02 /* 001 */
+#define f_atmel_compl 0x04 /* 010 */
+#define f_fwh_compl 0x08 /* 100 */
+
+#define f_slow_sector_erase 0x80
+
+#define FLASH_UNKNOWN 0
+#define FLASH_CFI 1
+#define FLASH_JEDEC 2
+
+typedef struct flashdevice {
+ unsigned long mapped;
+ unsigned long physical;
+ unsigned long offset;
+ unsigned int flashnum, manufnum;
+ unsigned short id;
+ unsigned int size, sectors;
+ unsigned int idx;
+ void *data;
+ int open_mode, open_cnt;
+} flashdevice_t;
+
+typedef struct flashchip {
+ char *name;
+ unsigned short id;
+ unsigned int voltage;
+ unsigned int size; /* KBytes */
+ unsigned int supported;
+ unsigned int pagesize; /* Bytes */
+ unsigned int flags;
+ unsigned int *sectors; /* Kbytes[] including end of last sector */
+} flashchip_t;
+
+typedef struct manufacturer {
+ char *name;
+ unsigned short id;
+} manufacturer_t;
+
+extern unsigned int currflash;
+extern flashdevice_t flashdevices[BIOS_MAXDEV];
+extern const flashchip_t flashchips[];
+extern const manufacturer_t manufacturers[];
diff --git a/roms/openbios/utils/devbios/pcisets.c b/roms/openbios/utils/devbios/pcisets.c
new file mode 100644
index 00000000..91b9e0ea
--- /dev/null
+++ b/roms/openbios/utils/devbios/pcisets.c
@@ -0,0 +1,630 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * pcisets.c - support functions to map flash devices to kernel space
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#endif
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#ifdef __alpha__
+#include <asm/hwrpb.h>
+#endif
+
+#include "bios.h"
+#include "flashchips.h"
+#include "pcisets.h"
+#include "programming.h"
+
+#ifdef CONFIG_PCI
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+#define pci_find_class pci_get_class
+#endif
+
+#define pci_id(dev) ((dev->vendor<<16) | (dev->device))
+struct pci_dev *hostbridge=NULL;
+static unsigned char pci_dummy[4];
+
+/*
+ * ******************************************
+ *
+ * own pci/shadow handling; We can't use
+ * the PCI bios here as it would sweep
+ * itself out!
+ *
+ * ******************************************
+ */
+
+static int pci_read(struct pci_dev *dev, unsigned char where)
+{
+ if (!dev) return 0;
+
+ outl((0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) |
+ (where & ~3)), 0xCF8);
+ mb();
+ return inb(0xCFC + (where&3));
+}
+
+static void pci_write(struct pci_dev *dev, unsigned char where, unsigned char value)
+{
+ if (!dev) return;
+ outl((0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) |
+ (where & ~3)), 0xCF8);
+ mb();
+ outb(value, 0xCFC + (where&3));
+}
+
+/*
+ * standard system firmware adress emitter
+ */
+
+static int system_memarea(unsigned long *address, unsigned long *size,
+ struct pci_dev *dev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ const struct pci_driver *drv;
+ drv = pci_dev_driver(dev);
+#endif
+#ifndef __alpha__
+ *address=0xffe00000;
+ *size=2048*1024;
+#else
+ *address=0xfffffffffc000000;
+ *size=512*1024;
+#endif
+ printk(KERN_INFO "BIOS: Probing system firmware with "
+ "%ldk rom area @0x%lx (%04x:%04x)\n",
+ (*size>>10), *address, dev->vendor, dev->device );
+#ifdef CONFIG_PCI_NAMES
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ if (drv) printk(KERN_INFO "BIOS: System device is %s\n", drv->name);
+#else
+ printk(KERN_INFO "BIOS: System device is %s\n", dev->name);
+#endif
+#endif
+ return 0;
+}
+
+static int memarea_256k(unsigned long *address, unsigned long *size,
+ struct pci_dev *dev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ const struct pci_driver *drv;
+ drv = pci_dev_driver(dev);
+#endif
+ *address=0xfffc0000;
+ *size=256*1024;
+ printk(KERN_INFO "BIOS: Probing system firmware with "
+ "%ldk rom area @0x%lx (%04x:%04x)\n",
+ (*size>>10), *address, dev->vendor, dev->device );
+#ifdef CONFIG_PCI_NAMES
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ if (drv) printk(KERN_INFO "BIOS: System device is %s\n", drv->name);
+#else
+ printk(KERN_INFO "BIOS: System device is %s\n", dev->name);
+#endif
+#endif
+ return 0;
+}
+
+/*
+ * standard address emitter for normal pci devices
+ */
+
+static int default_memarea(unsigned long *address, unsigned long *size,
+ struct pci_dev *dev)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+ *address=dev->resource[PCI_ROM_RESOURCE].start;
+ *size=dev->resource[PCI_ROM_RESOURCE].end - *address + 1;
+#else
+ *address=0xdeadbeef;
+ *size=0x00000000;
+#endif
+ if (*address && (signed long)*address!=-1 ) {
+ printk (KERN_DEBUG "BIOS: Probing PCI device %02x:%02x.%01x "
+ "with %ldk rom area @ 0x%lx\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn),
+ (*size>>10), *address);
+ return 1;
+ }
+ *address=0xdeadbeef;
+ *size=0x00000000;
+ return 0;
+}
+
+#ifdef __alpha__
+void probe_alphafw(void)
+{
+ switch(hwrpb->sys_type) {
+ case ST_DEC_EB164:
+ /* Fall through */
+ break;
+ case ST_DTI_RUFFIAN:
+ /* case ST_DEC_TSUNAMI: // This crashes for whatever reason */
+ probe_pcibus();
+ return;
+ default:
+ printk(KERN_INFO "BIOS: unsupported alpha motherboard.\n");
+ return;
+ }
+
+ /* LX164 has system variation 0x2000 */
+ if (hwrpb->sys_variation == 0x2000)
+ printk(KERN_INFO "BIOS: LX164 detected\n");
+ else
+ printk(KERN_INFO "BIOS: EB164 board detected. Sys_var=0x%lx\n",
+ hwrpb->sys_variation);
+
+ flashdevices[flashcount].data=(void *)0xfff80000;
+ flash_probe_area(0xfff80000, 512*1024, 0);
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+#define pci_for_each_dev(dev) \
+ for(dev = pci_devices->next; dev != pci_devices; dev = dev->next)
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,74)
+#define pci_for_each_dev(dev) \
+ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
+#endif
+
+#define DEVICE(x) devices[g].pcidevs[x]
+void probe_pcibus(void)
+{
+ struct pci_dev *dev=NULL;
+ unsigned int g=0, d, map_always=0;
+ unsigned long addr, size;
+
+ /* Look whether we find something supported */
+ pci_for_each_dev(dev) {
+ /* Search all device groups */
+ for (g=0; DEVICE(0); g++ ) {
+ /* Search all devices in group */
+ for (d=0; DEVICE(d) && DEVICE(d) != pci_id(dev); d++);
+ if(DEVICE(d) == pci_id(dev))
+ break;
+ }
+
+ flashdevices[flashcount].idx=g;
+ flashdevices[flashcount].data=dev;
+
+ map_always=devices[g].memarea(&addr, &size, dev);
+#ifdef DEBUG_PCI
+ printk(KERN_INFO "BIOS: device=%x, cs=%d addr=%lx, size=%ld\n",
+ pci_id(dev),g, addr,size);
+#endif
+ if(!size)
+ continue;
+
+ flash_probe_area(addr, size, map_always);
+ }
+}
+#undef DEVICE
+
+/* Intel 430, 440, 450 PCI Chipsets */
+
+#define CURRENT ((struct pci_dev *)flashdevices[currflash].data)
+static int gporeg_save;
+static void intel4x0_activate(void)
+{
+#ifdef __ABIT_BE6II_v11__
+#define GPONUM 26
+#define GPOREG_OFFSET 0x34
+ register unsigned int gporeg;
+ /* Read Bus 0, Dev 7, Func 3, Reg 40-44 (Power Managment Base Address) */
+ outl (0x80003B40, 0x0CF8);
+ /* calc General Purpose Output Register I/O port address */
+ gporeg = (0xFFFFFFFE & inl (0x0CFC)) + GPOREG_OFFSET;
+
+ /* Set GPO26 to 0 */
+ gporeg_save=inl(gporeg);
+ printk(KERN_DEBUG "BIOS: GPOREG=0x%08x, mask=0x%x, new=0x%x\n",gporeg_save, (~(1<<GPONUM)), gporeg_save&(~(1<<GPONUM)));
+ outl (gporeg_save&(~(1<<GPONUM)), gporeg);
+#undef GPOREG_OFFSET
+#endif
+
+ pci_dummy[0]=pci_read(CURRENT, 0x4e);
+ pci_dummy[1]=pci_read(CURRENT, 0x4f);
+
+ /* Write and 128k enable */
+ pci_dummy[2]=0x44; //0xC4
+
+ if (CURRENT->device < 0x7000) {
+ /* enable 512k */
+ pci_dummy[2]|=0x80;
+ } else {
+ /* enable 1M */
+ pci_write(CURRENT, 0x4f, pci_dummy[1] | 0x02);
+ }
+
+ pci_write(CURRENT, 0x4e, pci_dummy[0] | pci_dummy[2]);
+
+ // printk(KERN_DEBUG "BIOS: isa bridge cfg is 0x%02x\n", pci_dummy[0]);
+}
+
+static void intel4x0_deactivate(void)
+{
+#ifdef __ABIT_BE6II_v11__
+#define GPOREG_OFFSET 0x34
+ register unsigned long gporeg;
+
+ /* Read Bus 0, Dev 7, Func 3, Reg 40-44 (Power Managment Base Address) */
+ outl (0x80003B40, 0x0CF8);
+ /* calc General Purpose Output Register I/O port address */
+ gporeg = (0xFFFFFFFE & inl (0x0CFC)) + GPOREG_OFFSET;
+
+ /* Reset GBO26 */
+ outl (gporeg_save, gporeg);
+#undef GPOREG_OFFSET
+#endif
+ pci_write(CURRENT, 0x4e, pci_dummy[0]);
+ pci_write(CURRENT, 0x4f, pci_dummy[1]);
+}
+
+/* preliminary support for Intel 830 mobile chipset. untested!! */
+
+static void intel8x0_activate(void)
+{
+ pci_dummy[0]=pci_read(CURRENT, 0x4e);
+ pci_dummy[1]=pci_read(CURRENT, 0xe3);
+ pci_write(CURRENT, 0x4e, pci_dummy[0] | 0x01);
+ pci_write(CURRENT, 0xe3, pci_dummy[1] | 0xC0);
+
+ // We don't have to change FWH_DEC_EN1, as it decodes
+ // all memory areas to the FWH per default.
+ // We try it anyways.
+
+ // FWH_DEC_EN1: isabridge, 0xe3, 8bit, default 0xff.
+ // FWH_SEL1: isabridge, 0xe8, 32bit, default 0x00112233 (??)
+
+ //printk(KERN_DEBUG "BIOS: BIOS_CNTL is 0x%02x\n", pci_dummy[0]);
+ //printk(KERN_DEBUG "BIOS: FWH_DEC_EN1 is 0x%02x\n", pci_dummy[1]);
+}
+
+static void intel8x0_deactivate(void)
+{
+ pci_write(CURRENT, 0x4e, pci_dummy[0]);
+ pci_write(CURRENT, 0xe3, pci_dummy[1]);
+}
+
+/* AMD 760/756/751 & VIA (M)VP3 */
+
+static void amd7xx_activate(void)
+{
+ pci_dummy[0]=pci_read(CURRENT, 0x40); /* IO Control 1 */
+ pci_dummy[1]=pci_read(CURRENT, 0x43); /* SEGEN */
+
+ pci_write(CURRENT, 0x40, pci_dummy[0] | 0x01);
+ pci_write(CURRENT, 0x43, pci_dummy[1] | 0x80);
+}
+
+static void amd7xx_deactivate(void)
+{
+ pci_write(CURRENT, 0x43, pci_dummy[1]);
+ pci_write(CURRENT, 0x40, pci_dummy[0]);
+}
+
+static void viamvp3_activate(void)
+{
+ hostbridge = pci_find_class(PCI_CLASS_BRIDGE_HOST<<8,NULL);
+ if (!hostbridge)
+ return;
+ pci_dummy[0]=pci_read(hostbridge,0x52);
+ pci_write(hostbridge, 0x52, pci_dummy[0] & 0xcf);
+ pci_dummy[1]=pci_read(hostbridge, 0x63);
+ pci_write(hostbridge, 0x63, pci_dummy[1] & 0x0f);
+ pci_dummy[2]=pci_read(CURRENT,0x43);
+ pci_write(CURRENT, 0x43, pci_dummy[2] |0xF8);
+
+ pci_write(CURRENT, 0x40, pci_read(CURRENT,0x40) | 0x01);
+}
+
+static void viamvp3_deactivate(void)
+{
+ if (!hostbridge)
+ return;
+ pci_write(CURRENT, 0x40, pci_read(CURRENT,0x40) & 0xfe);
+ pci_write(hostbridge, 0x63, pci_dummy[1]);
+ pci_write(hostbridge, 0x52, pci_dummy[0]);
+ pci_write(CURRENT, 0x43, pci_dummy[2]);
+}
+
+/* SiS works with 530/5595 chipsets */
+
+static void sis_activate(void)
+{
+ char b;
+ hostbridge = pci_find_class(PCI_CLASS_BRIDGE_HOST<<8,NULL);
+ if (!hostbridge)
+ return;
+
+ pci_dummy[0]=pci_read(hostbridge, 0x76);
+ pci_dummy[1]=readb(0x51);
+ pci_dummy[2]=pci_read(CURRENT, 0x40);
+ pci_dummy[3]=pci_read(CURRENT, 0x45);
+
+ /* disable shadow */
+ pci_write(hostbridge, 0x76, 0x00);
+ /* disable cache */
+ writeb(pci_dummy[1] & 0x7f, 0x51);
+
+ /* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630 */
+ pci_write(CURRENT, 0x40, pci_dummy[2]|0x0b);
+ /* Flash write enable on SiS 540/630 */
+ pci_write(CURRENT, 0x45, pci_dummy[3]|0x40);
+
+ /* The same thing on SiS 950 SuperIO side */
+ outb(0x87, 0x2e);
+ outb(0x01, 0x2e);
+ outb(0x55, 0x2e);
+ outb(0x55, 0x2e);
+ if (inb(0x2f) != 0x87) {
+ /* printf("Can not access SiS 950\n"); */
+ return;
+ }
+
+ outb(0x24, 0x2e);
+ b = inb(0x2f) | 0xfc;
+ outb(0x24, 0x2e);
+ outb(b, 0x2f);
+ outb(0x02, 0x2e);
+ outb(0x02, 0x2f);
+}
+
+static void sis_deactivate(void)
+{
+ if (!hostbridge)
+ return;
+
+ /* Restore PCI Registers */
+ pci_write(hostbridge, 0x76, pci_dummy[0]);
+ pci_write(CURRENT, 0x45, pci_dummy[2]);
+ pci_write(CURRENT, 0x45, pci_dummy[3]);
+ /* restore cache to original status */
+ writeb(pci_dummy[1], 0x51);
+}
+
+/* UMC 486 Chipset 8881/886a */
+
+static void umc_activate(void)
+{
+ hostbridge = pci_find_class(PCI_CLASS_BRIDGE_HOST<<8,NULL);
+ if (!hostbridge)
+ return;
+
+ pci_dummy[0]=pci_read(hostbridge, 0x54);
+ pci_dummy[1]=pci_read(hostbridge, 0x55);
+
+ pci_write(hostbridge, 0x54, 0x00);
+ pci_write(hostbridge, 0x55, 0x40);
+
+ pci_write(CURRENT,0x47, pci_read(CURRENT,0x47) & ~0x40);
+}
+
+static void umc_deactivate(void)
+{
+ if (!hostbridge)
+ return;
+
+ pci_write(CURRENT, 0x47, pci_read(CURRENT,0x47) | 0x40);
+
+ pci_write(hostbridge, 0x54, pci_dummy[0]);
+ pci_write(hostbridge, 0x55, pci_dummy[1]);
+}
+
+/* CS5530 functions */
+
+static void cs5530_activate(void)
+{
+ /* Save modified registers for later reset */
+ pci_dummy[0]=pci_read(CURRENT,0x52);
+ pci_dummy[1]=pci_read(CURRENT,0x5b);
+
+ /* enable rom write access */
+ pci_write(CURRENT, 0x52, pci_dummy[0]|0x06);
+
+ /* enable rom positive decode */
+ // pci_write(CURRENT,0x5b, pci_dummy[1]|0x20);
+ // pci_write(CURRENT,0x52, pci_read(CURRENT,0x52)|0x01);
+}
+
+static void cs5530_deactivate(void)
+{
+ pci_write(CURRENT, 0x52, pci_dummy[0]);
+ // pci_write(CURRENT, 0x5b, pci_dummy[1]);
+}
+
+/* Reliance / ServerWorks */
+
+static void reliance_activate(void)
+{
+ pci_dummy[0]=pci_read(CURRENT,0x41);
+ pci_dummy[1]=pci_read(CURRENT,0x70);
+ pci_dummy[2]=inb(0xc6f);
+
+ /* Enable 512k */
+ pci_write(CURRENT, 0x41, pci_dummy[0] | 0x02);
+ /* Enable 4MB */
+ pci_write(CURRENT, 0x70, pci_dummy[1] | 0x80);
+ /* Enable flash write */
+ outb(pci_dummy[2] | 0x40, 0xc6f);
+}
+
+static void reliance_deactivate(void)
+{
+ pci_write(CURRENT, 0x41, pci_dummy[0]);
+ pci_write(CURRENT, 0x70, pci_dummy[1]);
+ outb(pci_dummy[2], 0xc6f);
+}
+
+/* ALi Methods - untested */
+static void ali_activate(void)
+{
+ pci_dummy[0]=pci_read(CURRENT, 0x47);
+ pci_dummy[1]=pci_read(CURRENT, 0x79);
+ pci_dummy[2]=pci_read(CURRENT, 0x7f);
+
+ /* write enable, 256k enable */
+#ifdef OLD_ALi
+ pci_write(CURRENT, 0x47, pci_dummy[0]|0x47);
+#else
+ pci_write(CURRENT, 0x47, pci_dummy[0]|0x43);
+#endif
+
+ /* M1543C rev B1 supports 512k. Register reserved before */
+#ifdef OLD_ALi
+ pci_write(CURRENT, 0x79, pci_dummy[1]|0x10);
+ pci_write(CURRENT, 0x7f, pci_dummy[2]|0x01);
+#else
+ pci_write(CURRENT, 0x7b, pci_dummy[1]|0x10);
+#endif
+}
+
+static void ali_deactivate(void)
+{
+ pci_write(CURRENT, 0x47, pci_dummy[0]);
+ pci_write(CURRENT, 0x79, pci_dummy[1]);
+ pci_write(CURRENT, 0x7f, pci_dummy[2]);
+}
+
+/* Default routines. Use these if nothing else works */
+#if 0
+static unsigned int def_addr;
+#endif
+static void default_activate(void)
+{
+#if 0 && LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)
+ struct resource *r;
+
+ r=&CURRENT->resource[PCI_ROM_RESOURCE];
+
+ r->flags |= PCI_ROM_ADDRESS_ENABLE;
+ r->flags &= ~(IORESOURCE_READONLY|IORESOURCE_CACHEABLE);
+ pci_read_config_dword(CURRENT, CURRENT->rom_base_reg, &def_addr);
+ if (def_addr)
+ pci_write_config_dword (CURRENT, CURRENT->rom_base_reg,
+ def_addr|PCI_ROM_ADDRESS_ENABLE);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+ long ret;
+
+ if (pci_enable_device(CURRENT))
+ return;
+
+ pci_write_config_dword (CURRENT, CURRENT->rom_base_reg,
+ pci_resource_start(CURRENT, PCI_ROM_RESOURCE)|
+ PCI_ROM_ADDRESS_ENABLE);
+
+ ret=(long)request_mem_region( pci_resource_start(CURRENT,
+ PCI_ROM_RESOURCE), pci_resource_len(CURRENT,
+ PCI_ROM_RESOURCE), "Firmware memory");
+ if (!ret)
+ printk (KERN_ERR "BIOS: cannot reserve MMROM region "
+ "0x%lx+0x%lx\n",
+ pci_resource_start(CURRENT, PCI_ROM_RESOURCE),
+ pci_resource_len(CURRENT, PCI_ROM_RESOURCE));
+ else
+ printk (KERN_INFO "BIOS: mapped rom region to 0x%lx\n", ret);
+#endif
+}
+
+static void default_deactivate(void)
+{
+#if 0 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+ struct resource *r;
+ r=&CURRENT->resource[PCI_ROM_RESOURCE];
+ r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+ r->flags |= (IORESOURCE_READONLY|IORESOURCE_CACHEABLE);
+ pci_write_config_dword (CURRENT, CURRENT->rom_base_reg, def_addr);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+ release_mem_region(pci_resource_start(CURRENT, PCI_ROM_RESOURCE),
+ pci_resource_len(CURRENT, PCI_ROM_RESOURCE));
+#endif
+}
+
+const struct flashdev devices[] = {
+ /* Intel 4x0 chipsets */
+ { (int[]) { 0x8086122e, 0x80861234, 0x80867000, 0x80867110,
+ 0x80867198, 0 },
+ intel4x0_activate, intel4x0_deactivate, system_memarea },
+
+ /* Intel 8x0 chipsets */
+ { (int[]) { 0x80862410, 0x80862420, 0x80862440, 0x8086244c,
+ 0x80862480, 0x8086248c, 0x80867600, 0 },
+ intel8x0_activate, intel8x0_deactivate, system_memarea },
+
+ /* Irongate 75x, AMD-76xMP(X), VT8231/3 */
+ { (int[]) { 0x10227400, 0x10227408, 0x10227410, 0x10227440,
+ 0x11068231, 0x11063074, 0 },
+ amd7xx_activate, amd7xx_deactivate, system_memarea },
+
+ /* AMD Hammer (thor chipset) */
+ { (int[]) { 0x10227468, 0 },
+ amd7xx_activate, amd7xx_deactivate, system_memarea },
+
+ /* VIA (M)VP3, VT82C686 [Apollo Super South] */
+ { (int[]) { 0x11060586, 0x11060596, 0x11060686, 0 },
+ viamvp3_activate, viamvp3_deactivate, memarea_256k },
+
+ /* UMC */
+ { (int[]) { 0x1060886a, 0x10600886, 0x1060e886, 0x10608886, 0 },
+ umc_activate, umc_deactivate, system_memarea },
+
+ /* SiS */
+ { (int[]) { 0x10390008, 0x10390018, 0 },
+ sis_activate, sis_deactivate, system_memarea },
+
+ /* OPTi */
+ { (int[]) { 0x1045c558, 0 },
+ default_activate, default_deactivate, system_memarea },
+
+ /* NSC CS5530(A) */
+ { (int[]) { 0x10780100, 0 },
+ cs5530_activate, cs5530_deactivate, memarea_256k },
+
+ /* Reliance/ServerWorks NB6xxx */
+ { (int[]) { 0x11660200, 0 },
+ reliance_activate, reliance_deactivate, system_memarea },
+
+ /* ALi */
+ { (int[]) { 0x10b91523, 0x10b91533, 0x10b91543, 0 },
+ ali_activate, ali_deactivate, system_memarea },
+
+ { (int[]) { 0x00000000 },
+ default_activate, default_deactivate, default_memarea }
+};
+
+#endif /* CONFIG_PCI */
+
diff --git a/roms/openbios/utils/devbios/pcisets.h b/roms/openbios/utils/devbios/pcisets.h
new file mode 100644
index 00000000..1045f0a4
--- /dev/null
+++ b/roms/openbios/utils/devbios/pcisets.h
@@ -0,0 +1,45 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * pcisets.h - structures for device bindings
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+#include <linux/pci.h>
+
+#ifdef CONFIG_PCI
+
+struct flashdev {
+ unsigned int *pcidevs;
+ void (*activate)(void);
+ void (*deactivate) (void);
+ int (*memarea)(unsigned long *address, unsigned long *size,
+ struct pci_dev *dev);
+};
+
+extern const struct flashdev devices[];
+
+void probe_pcibus(void);
+#ifdef __alpha__
+void probe_alphafw(void);
+#endif
+#endif
diff --git a/roms/openbios/utils/devbios/procfs.c b/roms/openbios/utils/devbios/procfs.c
new file mode 100644
index 00000000..12ad17e3
--- /dev/null
+++ b/roms/openbios/utils/devbios/procfs.c
@@ -0,0 +1,162 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * procfs.c - proc filesystem handling for flash device listing.
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS)
+#include <linux/modversions.h>
+#endif
+#include <linux/proc_fs.h>
+
+#ifdef CONFIG_PROC_FS
+#include "bios.h"
+#include "pcisets.h"
+#include "flashchips.h"
+#include "programming.h"
+
+struct proc_dir_entry *proc_bios;
+
+#define PRINT_PROC(fmt,args...) \
+ do { \
+ if (!run) \
+ break; \
+ len += sprintf( buffer+len, fmt, ##args ); \
+ if (begin + len > offset + size) \
+ run=0; \
+ else if (begin + len < offset) { \
+ begin += len; \
+ len = 0; \
+ } \
+ } while (0)
+
+/*
+ * ******************************************
+ *
+ * /proc/bios handling
+ *
+ * ******************************************
+ */
+
+#define CFLASH flashdevices[i]
+#define FLASH flashchips[CFLASH.flashnum]
+#define MANUF manufacturers[CFLASH.manufnum]
+
+int bios_read_proc(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
+{
+ int len=0, run=1, i;
+ off_t begin = 0;
+
+ for (i=0;i<flashcount;i++) {
+#ifdef DEBUG_PROC
+ printk(KERN_DEBUG "BIOS: processing proc info for "
+ "flashchip %d\n",i+1);
+#endif
+ if (i) /* empty line is seperator between flash chips */
+ PRINT_PROC("\n");
+
+ PRINT_PROC("Memory Address : 0x%08lx\n",
+ (unsigned long)CFLASH.physical);
+ PRINT_PROC("Memory Size : %d kByte\n", CFLASH.size>>10);
+ PRINT_PROC("Flash Type : ");
+
+ if (CFLASH.id == 0) {
+ PRINT_PROC("ROM\n");
+ continue;
+ }
+
+ /* Flash chip completely unknown -> output ID and proceed */
+ if (FLASH.id == 0) {
+ PRINT_PROC("unknown %s device (id 0x%04x)\n",
+ MANUF.name, CFLASH.id);
+ PRINT_PROC("Supported : no\n");
+ continue;
+ }
+
+ PRINT_PROC("%s %s (%dV)\n", MANUF.name,
+ FLASH.name, FLASH.voltage);
+
+ PRINT_PROC("Supported : %s\n",
+ FLASH.supported ? "yes": "no");
+#ifdef DEBUG
+ PRINT_PROC("Pagetable : %d Byte\n", FLASH.pagesize );
+
+ PRINT_PROC("Erase first : %s\n",
+ FLASH.flags & f_needs_erase ? "yes": "no");
+
+ PRINT_PROC("Intel compliant : %s\n",
+ FLASH.flags & f_intel_compl ? "yes": "no");
+
+ PRINT_PROC("FWH compliant : %s\n",
+ FLASH.flags & f_fwh_compl ? "yes": "no");
+
+ if (CFLASH.sectors > 1)
+ PRINT_PROC("Sectors : %d\n", CFLASH.sectors);
+#endif
+ }
+#ifdef DEBUG_PROC
+ printk(KERN_DEBUG "BIOS: read_proc done.\n");
+#endif
+ /* set to 1 if we're done */
+ *eof=run;
+
+ if (offset >= begin + len)
+ return 0;
+
+ *start = buffer + (begin - offset);
+
+ return (size < begin + len - offset ? size : begin + len - offset);
+}
+#undef FLASH
+#undef MANUF
+#undef CFLASH
+
+#ifdef PROC_WRITEABLE
+int bios_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
+{
+ printk (KERN_INFO "%s\n",buffer);
+ return count;
+}
+#endif
+
+int bios_proc_register(void)
+{
+ if ((proc_bios = create_proc_entry("bios", 0, 0))) {
+ proc_bios->read_proc = bios_read_proc;
+#ifdef PROC_WRITABLE
+ proc_bios->write_proc = bios_write_proc;
+#endif
+ return 0;
+ }
+ return 1;
+}
+
+int bios_proc_unregister(void)
+{
+ if (proc_bios)
+ remove_proc_entry("bios", 0);
+ return 0;
+}
+#endif
diff --git a/roms/openbios/utils/devbios/programming.c b/roms/openbios/utils/devbios/programming.c
new file mode 100644
index 00000000..e1b35a34
--- /dev/null
+++ b/roms/openbios/utils/devbios/programming.c
@@ -0,0 +1,539 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * programming.c - flash device programming and probing algorithms.
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+// <-- C++ style comments are for experimental comments only.
+// They will disappear as soon as I fixed all the stuff.
+
+/* #define DEBUG_PROBING */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS)
+#include <linux/modversions.h>
+#endif
+
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+
+#include "bios.h"
+#include "pcisets.h"
+#include "flashchips.h"
+#include "programming.h"
+
+struct flashdevice flashdevices[BIOS_MAXDEV];
+int flashcount;
+
+/*
+ * ******************************************
+ *
+ * flashchip handling
+ *
+ * ******************************************
+ */
+
+
+void flash_command (unsigned char *addr, unsigned char command)
+#if 1
+{
+ flash_writeb(addr, 0x5555, 0xaa);
+ flash_writeb(addr, 0x2AAA, 0x55);
+ flash_writeb(addr, 0x5555, command);
+}
+void fwh_flash_command(unsigned char *addr, unsigned char command)
+#endif
+{
+ flash_writeb(addr, 0x75555, 0xaa);
+ flash_writeb(addr, 0x72aaa, 0x55);
+ flash_writeb(addr, 0x75555, command);
+}
+
+#define CFLASH flashdevices[flashcount]
+int flash_probe_address(void *address)
+{
+ int flashnum=0, manufnum=0, sectors=0;
+ unsigned short flash_id, testflash;
+ unsigned long flags;
+#ifdef DEBUG_PROBING
+ printk( KERN_DEBUG "BIOS: Probing for flash chip @0x%08lx\n", (unsigned long) address);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ save_flags(flags);
+#endif
+ spin_lock_irqsave(&bios_lock, flags);
+
+ testflash= (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
+
+ /* 1st method: Intel, Atmel listen to this.. */
+
+ flash_command(address, 0x90);
+ udelay(20);
+
+ flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
+
+#ifdef DEBUG_PROBING
+ printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n",
+ testflash, flash_id);
+#endif
+
+ /* 2nd method: Winbond (I think this is Jedec standard) */
+
+ if (flash_id==testflash) {
+#ifdef DEBUG_PROBING
+ printk (KERN_DEBUG "BIOS: Trying 2nd ID method.\n");
+#endif
+ flash_command(address, 0xf0); /* Reset */
+ udelay(20);
+
+ flash_command(address, 0x80);
+ flash_command(address, 0x60);
+ udelay(20);
+
+ flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
+#ifdef DEBUG_PROBING
+ printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n",
+ testflash, flash_id);
+#endif
+ }
+
+ /* 3rd Method: Some Winbonds seem to want this */
+
+ if (flash_id==testflash) {
+#ifdef DEBUG_PROBING
+ printk (KERN_DEBUG "BIOS: Trying 3rd ID method.\n");
+#endif
+ flash_command(address, 0xf0); /* Reset again */
+ udelay(20);
+
+ flash_command(address, 0x80);
+ flash_command(address, 0x20);
+ udelay(20);
+
+ flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
+#ifdef DEBUG_PROBING
+ printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n",
+ testflash, flash_id);
+#endif
+ }
+
+ if (flash_id==0x7f7f && flash_readb(address, 0x100)==0x1c) {
+ /* We have an Eon flashchip. They keep their
+ * device id at 0x101 instead of 0x1
+ */
+ printk(KERN_INFO "BIOS: Eon flash device detected\n");
+ flash_id=(flash_readb(address, 0x1))+(flash_readb(address, 0x101)<<8);
+ }
+
+ flash_command(address, 0xf0);
+ udelay(20);
+
+ spin_unlock_irqrestore(&bios_lock, flags);
+
+ if (flash_id==testflash) return 0; /* Nothing found :-( */
+
+ while (flashchips[flashnum].id!=0) {
+ if (flash_id==flashchips[flashnum].id)
+ break;
+ flashnum++;
+ }
+
+ while (manufacturers[manufnum].id!=0) {
+ if ((flash_id&0xff)==manufacturers[manufnum].id)
+ break;
+ manufnum++;
+ }
+
+ if (flashchips[flashnum].id) {
+ while (flashchips[flashnum].sectors[sectors]<flashchips[flashnum].size)
+ sectors++;
+ }
+
+ if (flashcount >= BIOS_MAXDEV) {
+ printk(KERN_DEBUG "BIOS: Too many flash devices found.\n");
+ return -1;
+ }
+
+ CFLASH.flashnum = flashnum;
+ CFLASH.manufnum = manufnum;
+ CFLASH.id = flash_id;
+ CFLASH.size = (flashchips[flashnum].size<<10);
+ CFLASH.sectors = sectors;
+ CFLASH.open_mode= 0;
+ CFLASH.open_cnt = 0;
+
+ return 1;
+}
+
+void flash_probe_area(unsigned long romaddr, unsigned long romsize,
+ int map_always)
+{
+ unsigned long probeaddr;
+ unsigned char *mapped;
+
+ mapped=ioremap(romaddr, romsize);
+
+ devices[flashdevices[currflash].idx].activate();
+
+ probeaddr=(unsigned long)mapped;
+
+ while ( probeaddr < (unsigned long)mapped + romsize - 0x5555 ) {
+ if ( flash_probe_address ((void *)probeaddr) != 1) {
+ probeaddr += 4*1024;
+ continue;
+ }
+
+ CFLASH.offset = probeaddr-(unsigned long)mapped;
+ CFLASH.mapped = (unsigned long)mapped;
+ CFLASH.physical = romaddr+CFLASH.offset;
+
+ printk( KERN_INFO "BIOS: flash device with size "
+ "%dk (ID 0x%04x) found.\n",
+ CFLASH.size >> 10, CFLASH.id);
+
+ printk( KERN_INFO "BIOS: physical address "
+ "0x%08lx (va=0x%08lx+0x%lx).\n",
+ CFLASH.physical, (unsigned long)CFLASH.mapped,
+ CFLASH.offset);
+
+ if (flashchips[CFLASH.flashnum].flags&f_fwh_compl) {
+ unsigned long t_lk;
+ unsigned int i=7;
+ printk(KERN_INFO "BIOS: FWH compliant "
+ "chip detected.\n");
+ for (t_lk=0xffb80002; t_lk<=0xffbf0002; t_lk+=0x10000)
+ {
+ printk(KERN_INFO "Lock register %d "
+ "(0x%08lx): 0x%x\n",
+ i, t_lk, (unsigned int)
+ (readb(phys_to_virt(t_lk))));
+ i--;
+ }
+ }
+ flashcount++;
+ currflash++;
+#ifdef MULTIPLE_FLASH
+ probeaddr += flashdevices[flashcount-1].size;
+ flashdevices[flashcount].mapped=flashdevices[flashcount-1].mapped;
+ flashdevices[flashcount].data=flashdevices[flashcount-1].data;
+ continue;
+#else
+ break;
+#endif
+ }
+
+ /* We might want to always map the memory
+ * region in certain cases
+ */
+
+ if (map_always) {
+ CFLASH.flashnum = 0;
+ CFLASH.manufnum = 0;
+ CFLASH.id = 0;
+ CFLASH.size = romsize;
+ CFLASH.sectors = 0;
+ CFLASH.open_mode= 0;
+ CFLASH.open_cnt = 0;
+ CFLASH.offset = 0;
+ CFLASH.mapped = (unsigned long)mapped;
+ CFLASH.physical = romaddr;
+ printk( KERN_INFO "BIOS: rom device with size "
+ "%dk registered.\n", CFLASH.size >> 10);
+ flashcount++; currflash++;
+ return;
+ }
+
+ /* We found nothing in this area, so let's unmap it again */
+
+ if (flashcount && flashdevices[flashcount-1].mapped != (unsigned long)mapped)
+ iounmap(mapped);
+
+ devices[flashdevices[currflash].idx].deactivate();
+}
+
+#undef CFLASH
+
+void flash_program (unsigned char *addr)
+{
+ flash_command(addr, 0xa0);
+}
+
+void flash_program_atmel (unsigned char *addr)
+{
+ flash_command(addr, 0x80);
+ flash_command(addr, 0x20);
+}
+
+int flash_erase (unsigned char *addr, unsigned int flashnum)
+{
+ flash_command(addr, 0x80);
+ flash_command(addr, 0x10);
+ udelay(80);
+ return flash_ready_toggle(addr, 0);
+}
+
+int flash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec)
+{
+ unsigned int sector;
+
+ if (!(flashchips[flashnum].flags & f_slow_sector_erase)) {
+ flash_command(addr, 0x80);
+
+ if (flashchips[flashnum].flags&f_fwh_compl) {
+ flash_writeb(addr, 0x75555,0xaa);
+ flash_writeb(addr, 0x72aaa,0x55);
+ } else {
+ flash_writeb(addr, 0x5555,0xaa);
+ flash_writeb(addr, 0x2aaa,0x55);
+ }
+
+ for (sector=startsec; sector <= endsec; sector++) {
+ flash_writeb (addr, flashchips[flashnum].sectors[sector]*1024, 0x30);
+ }
+
+ udelay(150); // 80 max normally, wait 150usec to be sure
+#if 0
+ if (flashchips[flashnum].flags&f_fwh_compl)
+#endif
+ return flash_ready_toggle(addr, flashchips[flashnum].sectors[sector-1]*1024);
+#if 0
+ else
+ return flash_ready_poll(addr, flashchips[flashnum].sectors[sector-1]*1024, 0xff);
+#endif
+ }
+
+ /* sectors must be sent the sector erase command for every sector */
+ for (sector=startsec; sector <= endsec; sector++) {
+ flash_command(addr, 0x80);
+ if (flashchips[flashnum].flags&f_fwh_compl) {
+ flash_writeb(addr, 0x75555,0xaa);
+ flash_writeb(addr, 0x72aaa,0x55);
+ } else {
+ flash_writeb(addr, 0x5555,0xaa);
+ flash_writeb(addr, 0x2aaa,0x55);
+ }
+
+ flash_writeb(addr, flashchips[flashnum].sectors[sector]*1024, 0x30);
+ udelay(150);
+#if 0
+ if (flashchips[flashnum].flags&f_fwh_compl)
+#endif
+ flash_ready_toggle(addr, flashchips[flashnum].sectors[sector] *1024);
+#if 0
+ else
+ flash_ready_poll(addr, flashchips[flashnum].sectors[sector]*1024, 0xff);
+#endif
+ }
+
+ return 0;
+
+}
+
+/* waiting for the end of programming/erasure by using the toggle method.
+ * As long as there is a programming procedure going on, bit 6 of the last
+ * written byte is toggling it's state with each consecutive read.
+ * The toggling stops as soon as the procedure is completed.
+ * This function returns 0 if everything is ok, 1 if an error occured
+ * while programming was in progress.
+ */
+
+int flash_ready_toggle (unsigned char *addr, unsigned int offset)
+{
+ unsigned long int timeout=0;
+ unsigned char oldflag, flag;
+ int loop=1;
+
+ oldflag=flash_readb(addr, offset) & 0x40;
+
+ while (loop && (timeout<0x7fffffff)) {
+ flag=flash_readb(addr, offset) & 0x40;
+
+ if (flag == oldflag)
+ loop=0;
+
+ oldflag=flag;
+ timeout++;
+ }
+
+ if (loop) {
+ printk(KERN_DEBUG "BIOS: operation timed out (Toggle)\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+/* This functions is similar to the above one. While a programming
+ * procedure is going on, bit 7 of the last written data byte is
+ * inverted. When the procedure is completed, bit 7 contains the
+ * correct data value
+ */
+
+int flash_ready_poll (unsigned char *addr, unsigned int offset, unsigned char data)
+{
+ unsigned long int timeout=0;
+ unsigned char flag;
+
+ flag=flash_readb(addr, offset);
+
+ while ( ( flag & 0x80) != ( data & 0x80)) {
+ if ( ( flag & 0x80 ) == ( data & 0x80 ) ) {
+#ifdef DBGTIMEOUT
+ printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout);
+#endif
+ return 0;
+ }
+ flag=flash_readb(addr, offset);
+ if (timeout++>12800) { // 10 times more than usual.
+ printk(KERN_ERR "BIOS: EOT Polling timed out at 0x%08x."
+ " Try again or increase max. timeout.\n",offset);
+ return 1;
+ }
+ if ((flag & 0x80) == ( data & 0x80)) {
+ flag=flash_readb(addr, offset);
+ }
+ }
+#ifdef DBGTIMEOUT
+ printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout);
+#endif
+
+ flag=flash_readb(addr, offset);
+ if ( ( flag & 0x80 ) == ( data & 0x80 ) ) return 0; else return 1;
+}
+
+
+
+void iflash_program_byte (unsigned char *addr, unsigned int offset, unsigned char data)
+{
+ unsigned long int timeout=0;
+ unsigned char flag;
+
+ flash_writeb (addr, offset, 0x40);
+ flash_writeb (addr, offset, data);
+
+ flash_writeb (addr, offset, 0x70); /* Read Status */
+ do {
+ flag=flash_readb (addr, offset);
+ if (timeout++>100) { // usually 2 or 3 :-)
+ printk(KERN_ERR "BIOS: Intel programming timed out at"
+ "0x%08x. Try again or increase max. timeout.\n",offset);
+ return;
+ }
+ } while ((flag&0x80) != 0x80);
+
+#ifdef DBGTIMEOUT
+ printk (KERN_DEBUG"BIOS: Timeout value (Intel byte program) %ld\n",timeout);
+#endif
+
+ if (flag&0x18) {
+ flash_writeb (addr, offset, 0x50); /* Reset Status Register */
+ printk (KERN_ERR "BIOS: Error occured, please repeat write operation. (intel)\n");
+ }
+
+ flash_writeb (addr, offset, 0xff);
+}
+
+
+
+int iflash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec)
+{
+ unsigned long int timeout;
+ unsigned int sector, offset=0;
+ unsigned char flag;
+
+ for (sector=startsec; sector<=endsec; sector++) {
+ offset=(flashchips[flashnum].sectors[sector]*1024);
+ flash_writeb (addr, offset, 0x20);
+ flash_writeb (addr, offset, 0xd0);
+
+ flash_writeb (addr, offset, 0x70); /* Read Status */
+ timeout=0;
+ do {
+ flag=flash_readb (addr, offset);
+ if (timeout++>1440000) { // usually 144000
+ printk(KERN_ERR "BIOS: Intel sector erase timed out at 0x%08x. Try again or increase max. timeout.\n",offset);
+ return 1;
+ }
+ } while ((flag&0x80) != 0x80);
+
+#ifdef DBGTIMEOUT
+ printk (KERN_DEBUG "BIOS: Timeout value (Intel sector erase) %ld\n",timeout);
+#endif
+
+ if (flag&0x28) {
+ flash_writeb (addr, offset, 0x50);
+ flash_writeb (addr, offset, 0xff);
+ return 1; /* Error! */
+ }
+ }
+
+ flash_writeb (addr, offset, 0xff);
+ return 0;
+}
+
+
+
+unsigned char flash_readb(unsigned char *addr, unsigned int offset)
+{
+#if defined(__alpha__)
+ if (flashdevices[currflash].data==(void *)0xfff80000) {
+ if (offset<0x80000)
+ outb(0x00,0x800);
+ else {
+ outb(0x01, 0x800);
+ offset-=0x80000;
+ }
+ }
+#endif
+ return readb(addr+offset);
+}
+
+
+
+void flash_writeb(unsigned char *addr, unsigned int offset, unsigned char data)
+{
+#if defined(__alpha__)
+ if (flashdevices[currflash].data==(void *)0xfff80000) {
+ if (offset<0x80000)
+ outb(0x00,0x800);
+ else {
+ outb(0x01, 0x800);
+ offset-=0x80000;
+ }
+ }
+#endif
+/*
+ printk(KERN_DEBUG "BIOS: writing 0x%02x to 0x%lx+0x%x\n",
+ data,bios,offset);
+ */
+ writeb(data,addr+offset);
+}
diff --git a/roms/openbios/utils/devbios/programming.h b/roms/openbios/utils/devbios/programming.h
new file mode 100644
index 00000000..3ad104e8
--- /dev/null
+++ b/roms/openbios/utils/devbios/programming.h
@@ -0,0 +1,73 @@
+/*
+ * OpenBIOS - free your system!
+ * ( firmware/flash device driver for Linux )
+ *
+ * programming.h - prototypes for flash device programming
+ *
+ * This program is part of a free implementation of the IEEE 1275-1994
+ * Standard for Boot (Initialization Configuration) Firmware.
+ *
+ * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ *
+ */
+
+/* Addresses */
+#define ADDR_MANUFACTURER 0x0000
+#define ADDR_DEVICE_ID 0x0001
+#define ADDR_SECTOR_LOCK 0x0002
+#define ADDR_HANDSHAKE 0x0003
+
+#define ADDR_UNLOCK_1 0x5555
+#define ADDR_UNLOCK_2 0x2AAA
+#define ADDR_COMMAND 0x5555
+
+/* Commands */
+#define CMD_UNLOCK_DATA_1 0xAA
+#define CMD_UNLOCK_DATA_2 0x55
+#define CMD_MANUFACTURER_UNLOCK_DATA 0x90
+#define CMD_UNLOCK_BYPASS_MODE 0x20
+#define CMD_PROGRAM_UNLOCK_DATA 0xA0
+#define CMD_RESET_DATA 0xF0
+#define CMD_SECTOR_ERASE_UNLOCK_DATA 0x80
+#define CMD_SECTOR_ERASE_UNLOCK_DATA_2 0x30
+#define CMD_ERASE_DATA 0x10
+#define CMD_UNLOCK_SECTOR 0x60
+
+extern int flashcount;
+
+void flash_command(unsigned char *addr, unsigned char command);
+
+void flash_program (unsigned char *addr);
+void flash_program_atmel (unsigned char *addr);
+
+int flash_ready_toggle (unsigned char *addr, unsigned int offset);
+int flash_ready_poll (unsigned char *addr, unsigned int offset, unsigned char data);
+
+int flash_erase (unsigned char *addr, unsigned int flashnum);
+int flash_erase_sectors (unsigned char *addr, unsigned int flashnum,
+ unsigned int startsec, unsigned int endsec);
+
+void iflash_program_byte (unsigned char *addr, unsigned int offset, unsigned char data);
+int iflash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec);
+
+unsigned char flash_readb(unsigned char *addr, unsigned int offset);
+void flash_writeb(unsigned char *addr, unsigned int offset, unsigned char data);
+
+
+int flash_probe_address(void *address);
+void flash_probe_area(unsigned long romaddr, unsigned long romsize,
+ int map_always);
+
diff --git a/roms/openbios/utils/dist/debian/changelog b/roms/openbios/utils/dist/debian/changelog
new file mode 100644
index 00000000..d3c96a56
--- /dev/null
+++ b/roms/openbios/utils/dist/debian/changelog
@@ -0,0 +1,6 @@
+openbios (0.1-1) unstable; urgency=low
+
+ * Initial Debian version.
+
+ -- Patrick Mauritz <oxygene@studentenbude.ath.cx> Mon, 22 Jul 2002 23:24:56 +0200
+
diff --git a/roms/openbios/utils/dist/debian/control b/roms/openbios/utils/dist/debian/control
new file mode 100644
index 00000000..5bf02d76
--- /dev/null
+++ b/roms/openbios/utils/dist/debian/control
@@ -0,0 +1,16 @@
+Source: openbios
+Maintainer: Patrick Mauritz <oxygene@studentenbude.ath.cx>
+Section: devel
+Priority: optional
+Standards-Version: 3.5.2
+Build-Depends: grep-dctrl, yada (>= 0.9.9)
+
+Package: openbios
+Architecture: any
+Depends: ${openbios:Depends}
+Description: OpenBIOS - OpenFirmware development tools
+ It contains:
+ - toke: tokenizer for fcode programs
+ - detok: decompiler for fcode programs
+ - paflof: (yet) incomplete forth environment which will be
+ _the_ core of OpenBIOS
diff --git a/roms/openbios/utils/dist/debian/packages b/roms/openbios/utils/dist/debian/packages
new file mode 100644
index 00000000..5dc56c01
--- /dev/null
+++ b/roms/openbios/utils/dist/debian/packages
@@ -0,0 +1,45 @@
+Source: openbios
+Section: devel
+Priority: optional
+Maintainer: Patrick Mauritz <oxygene@studentenbude.ath.cx>
+Packager: Patrick Mauritz <oxygene@studentenbude.ath.cx>
+Standards-Version: 3.5.2
+Upstream-Source: <URL:http://www.openbios.net>
+Home-Page: <URL:http://www.openbios.net>
+Description: OpenBIOS - OpenFirmware development tools
+Copyright: GPL
+ Copyright 2001-2002 Stefan Reinauer, Segher Boessenkool
+Major-Changes:
+ First release
+Build: sh
+ CC=gcc
+ CFLAGS="-O2 -Wall"
+ cd toke; make; strip toke; cd ..
+ cd detok; make; strip detok; cd ..
+ cd paflof; make; strip paflof; cd ..
+ find toke/examples -name .cvsignore | xargs rm -f
+Clean: sh
+ cd toke; make clean; cd ..
+ cd detok; make clean; cd ..
+ cd paflof; make clean; cd ..
+
+Package: openbios
+Architecture: any
+Depends: [/usr/bin/*]
+Description: OpenBIOS - OpenFirmware development tools
+ It contains:
+ - toke: tokenizer for fcode programs
+ - detok: decompiler for fcode programs
+ - paflof: (yet) incomplete forth environment which will be
+ _the_ core of OpenBIOS
+Install: sh
+ mkdir -p $ROOT/usr/bin
+ mkdir -p $ROOT/usr/share/openbios
+ mkdir -p $ROOT/usr/share/doc/packages/openbios
+ cp toke/toke $ROOT/usr/bin
+ cp detok/detok $ROOT/usr/bin
+ cp paflof/paflof $ROOT/usr/bin
+ cp -a toke/examples $ROOT/usr/share/doc/openbios
+ cp -a forth $ROOT/usr/share/openbios
+ cp toke/README $ROOT/usr/share/doc/openbios/README.toke
+ cp detok/README $ROOT/usr/share/doc/openbios/README.detok
diff --git a/roms/openbios/utils/dist/debian/rules b/roms/openbios/utils/dist/debian/rules
new file mode 100755
index 00000000..6bf53269
--- /dev/null
+++ b/roms/openbios/utils/dist/debian/rules
@@ -0,0 +1,189 @@
+#! /usr/bin/make -f
+# Generated automatically from debian/packages
+# by yada v0.9.9, of Tue, 07 Dec 1999
+# Modified by Piotr Roszatycki <dexter@debian.org>, Mon, 1 Oct 2001 13:14:11 +0200
+
+DEB_HOST_GNU_CPU := $(shell dpkg-architecture -qDEB_HOST_GNU_CPU)
+DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_HOST_GNU_SYSTEM := $(shell dpkg-architecture -qDEB_HOST_GNU_SYSTEM)
+
+DEB_BUILD_GNU_CPU := $(shell dpkg-architecture -qDEB_BUILD_GNU_CPU)
+DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+DEB_BUILD_GNU_SYSTEM := $(shell dpkg-architecture -qDEB_BUILD_GNU_SYSTEM)
+
+VERSION:=$(shell LC_ALL=C dpkg-parsechangelog | sed -ne 's/^Version: *\([^2]*\)/\1/p')
+
+SHELL=/bin/bash
+
+.PHONY: default
+default:
+ @echo "Specify a target:"; \
+ echo " build compile the package"; \
+ echo " binary make all binary packages"; \
+ echo " binary-arch make all architecture-dependent binary packages"; \
+ echo " binary-indep make all architecture-independent binary packages"; \
+ echo " clean clean up the source package"; \
+ echo; \
+ echo " depends check build-time dependencies"; \
+ echo " install-tree compile the package and create the install trees"; \
+ echo " clean-install-tree clean up only under debian/"; \
+ echo
+
+# Check build dependencies and conflicts
+
+.PHONY: depends
+depends: chmod-yada debian/depends-stamp
+debian/depends-stamp:
+ @echo 'Checking build conflicts and dependencies; just a minute...'
+ @echo -n 'grep-dctrl...'; v=$$(grep-status -X -F Package 'grep-dctrl' | grep Version | head -1 | sed -e 's/^Version: //'); \
+ if test ! "$$v"; then echo -n 'grep-dctrl (virtual package)...'; v=$$(grep-status -e -F Provides '(^grep-dctrl, |, grep-dctrl$$|^grep-dctrl$$)' | grep Version | head -1 | sed -e 's/^Version: //'); fi; \
+ if test "$$v"; then \
+ exit 0; \
+ fi; \
+ echo 'Build depends on `grep-dctrl'\'' (any version), which is not satisfied' | fmt; exit 1
+ @echo -n 'yada...'; v=$$(grep-status -X -F Package 'yada' | grep Version | head -1 | sed -e 's/^Version: //'); \
+ if test ! "$$v"; then echo -n 'yada (virtual package)...'; v=$$(grep-status -e -F Provides '(^yada, |, yada$$|^yada$$)' | grep Version | head -1 | sed -e 's/^Version: //'); fi; \
+ if test "$$v"; then \
+ if dpkg --compare-versions "$$v" '>=' '0.9.9'; then \
+ exit 0; \
+ fi; \
+ fi; \
+ echo 'Build depends on `yada'\'' (version >= 0.9.9), which is not satisfied' | fmt; exit 1
+ @echo
+ @echo 'Conflicts and dependencies all satisfied!'
+ touch debian/depends-stamp
+
+# Build the package and prepare the install tree
+
+.PHONY: build-only build
+build-only: debian/build-stamp
+build: chmod-yada build-only
+
+# Make sure these rules and the control file are up-to-date
+
+.PHONY: rules control
+rules: debian/rules
+debian/rules: $(shell which yada) debian/packages
+ $(shell which yada) rebuild rules
+
+control: debian/control
+debian/control: $(shell which yada) debian/packages
+ $(shell which yada) rebuild control
+
+debian/build-stamp: debian/depends-stamp
+ @[ -f $(shell which yada) -a -f debian/rules ]
+ @umask 022 \
+ && export PACKAGE="openbios" \
+ && export VERSION="$(VERSION)" \
+ && export DEB_HOST_GNU_CPU="$(DEB_HOST_GNU_CPU)" \
+ && export DEB_HOST_GNU_TYPE="$(DEB_HOST_GNU_TYPE)" \
+ && export DEB_HOST_GNU_SYSTEM="$(DEB_HOST_GNU_SYSTEM)" \
+ && export DEB_BUILD_GNU_CPU="$(DEB_BUILD_GNU_CPU)" \
+ && export DEB_BUILD_GNU_TYPE="$(DEB_BUILD_GNU_TYPE)" \
+ && export DEB_BUILD_GNU_SYSTEM="$(DEB_BUILD_GNU_SYSTEM)" \
+ && (\
+ echo -E 'eval "yada () { perl $$(which yada) \"\$$@\"; }"; set -e; set -v';\
+ echo -E 'CC=gcc';\
+ echo -E 'CFLAGS="-O2 -Wall"';\
+ echo -E 'cd toke; make; strip toke; cd ..';\
+ echo -E 'cd detok; make; strip detok; cd ..';\
+ echo -E 'cd paflof; make; strip paflof; cd ..';\
+ echo -E 'find toke/examples -name .cvsignore | xargs rm -f') | /bin/sh
+ touch debian/build-stamp
+
+.PHONY: install-tree
+install-tree: chmod-yada install-tree-any
+install-tree-any: \
+ debian/tmp-openbios/DEBIAN/control
+
+debian/tmp-openbios/DEBIAN/control: debian/build-stamp debian/control
+ rm -rf debian/tmp-openbios
+ umask 022 && install -d debian/tmp-openbios/DEBIAN
+ install -d debian/tmp-openbios/usr/share/doc/openbios
+ umask 022; $(shell which yada) generate copyright \
+ >debian/tmp-openbios/usr/share/doc/openbios/copyright
+ install -m 644 -p debian/changelog \
+ debian/tmp-openbios/usr/share/doc/openbios/changelog.Debian
+ @umask 022 \
+ && export PACKAGE="openbios" \
+ && export ROOT="$$(pwd)/debian/tmp-openbios" \
+ && export CONTROL="$$(pwd)/debian/tmp-openbios/DEBIAN" \
+ && export VERSION="$(VERSION)" \
+ && export DEB_HOST_GNU_CPU="$(DEB_HOST_GNU_CPU)" \
+ && export DEB_HOST_GNU_TYPE="$(DEB_HOST_GNU_TYPE)" \
+ && export DEB_HOST_GNU_SYSTEM="$(DEB_HOST_GNU_SYSTEM)" \
+ && export DEB_BUILD_GNU_CPU="$(DEB_BUILD_GNU_CPU)" \
+ && export DEB_BUILD_GNU_TYPE="$(DEB_BUILD_GNU_TYPE)" \
+ && export DEB_BUILD_GNU_SYSTEM="$(DEB_BUILD_GNU_SYSTEM)" \
+ && (\
+ echo -E 'eval "yada () { perl $$(which yada) \"\$$@\"; }"; set -e; set -v';\
+ echo -E 'mkdir -p $$ROOT/usr/bin';\
+ echo -E 'mkdir -p $$ROOT/usr/share/openbios';\
+ echo -E 'mkdir -p $$ROOT/usr/share/doc/packages/openbios';\
+ echo -E 'cp toke/toke $$ROOT/usr/bin';\
+ echo -E 'cp detok/detok $$ROOT/usr/bin';\
+ echo -E 'cp paflof/paflof $$ROOT/usr/bin';\
+ echo -E 'cp -a toke/examples $$ROOT/usr/share/doc/openbios';\
+ echo -E 'cp -a forth $$ROOT/usr/share/openbios';\
+ echo -E 'cp toke/README $$ROOT/usr/share/doc/openbios/README.toke';\
+ echo -E 'cp detok/README $$ROOT/usr/share/doc/openbios/README.detok') | /bin/sh
+ LD_LIBRARY_PATH="debian/tmp-openbios/lib:debian/tmp-openbios/usr/lib:$$LD_LIBRARY_PATH" dpkg-shlibdeps -pshlibs:openbios -dDepends debian/tmp-openbios/usr/bin/*
+ $(shell which yada) compress openbios
+ $(shell which yada) generate maintscripts openbios
+ find debian/tmp-openbios -type f -print \
+ | sed -n 's/^debian\/tmp-openbios\(\/etc\/.*\)$$/\1/p' \
+ > debian/tmp-openbios/DEBIAN/conffiles
+ if test ! -s debian/tmp-openbios/DEBIAN/conffiles; then rm -f debian/tmp-openbios/DEBIAN/conffiles; fi
+ $(shell which yada) rebuild control
+ $(shell which yada) generate substvars openbios
+ umask 022 && dpkg-gencontrol -isp -popenbios -Pdebian/tmp-openbios
+
+# Build package files
+
+.PHONY: binary binary-arch binary-indep
+binary: binary-arch binary-indep
+binary-arch: chmod-yada binary-arch-any
+
+.PHONY: binary-arch-any
+binary-arch-any: \
+ binary-package-openbios
+binary-indep: chmod-yada
+
+.PHONY: binary-package-openbios
+binary-package-openbios: check-root debian/tmp-openbios/DEBIAN/control
+ @[ -f $(shell which yada) -a -f debian/rules ]
+ chown -R 0.0 debian/tmp-openbios
+ chmod -R u=rwX,go=rX debian/tmp-openbios
+ @if [ -d debian/tmp-openbios/usr/doc/openbios ]; then \
+ echo "*** Yada warning: /usr/doc/openbios should be /usr/share/doc/openbios";\
+ fi
+ dpkg-deb --build debian/tmp-openbios ..
+
+.PHONY: check-root
+check-root:
+ @[ `id -u` = 0 ] || (echo "You must be root to do this!"; false)
+
+.PHONY: chmod-yada
+chmod-yada:
+ @if [ -f debian/yada -a ! -x debian/yada ]; then \
+ chmod +x debian/yada; \
+ fi
+
+# Clean up afterwards
+
+.PHONY: clean clean-install-tree clean-build
+clean: chmod-yada clean-install-tree clean-build debian/control debian/rules
+
+clean-build:
+ @[ -f $(shell which yada) -a -f debian/rules ]
+ rm -f debian/build-stamp debian/depends-stamp
+ @umask 022 && (\
+ echo -E 'eval "yada () { perl $$(which yada) \"\$$@\"; }"; set -e; set -v';\
+ echo -E 'cd toke; make clean; cd ..';\
+ echo -E 'cd detok; make clean; cd ..';\
+ echo -E 'cd paflof; make clean; cd ..') | /bin/sh
+
+clean-install-tree: chmod-yada debian/rules
+ @[ -f $(shell which yada) -a -f debian/rules ]
+ rm -f debian/install-tree-stamp
+ rm -rf debian/tmp* debian/files* debian/substvars
diff --git a/roms/openbios/utils/dist/openbios.spec b/roms/openbios/utils/dist/openbios.spec
new file mode 100644
index 00000000..fcce7ab4
--- /dev/null
+++ b/roms/openbios/utils/dist/openbios.spec
@@ -0,0 +1,61 @@
+#
+# spec file for package openbios
+#
+
+Name: openbios
+Version: 0.1
+Release: 0
+Summary: OpenBIOS development utilities
+License: GNU General Public License (GPL) - all versions, Other License(s), see package
+Group: Development/Tools/Other
+Autoreqprov: on
+# Scripts and programs
+Source0: OpenBIOS.tar.bz2
+BuildRoot: %{_tmppath}/%{name}-%{version}-build
+
+%description
+This package contains the OpenBIOS development utilities.
+
+There are
+* toke - an IEEE 1275-1994 compliant FCode tokenizer
+* detok - an IEEE 1275-1994 compliant FCode detokenizer
+* paflof - a forth kernel running in user space
+* an fcode bytecode evaluator running in paflof
+
+See /usr/share/doc/packages/openbios for details and examples.
+
+Authors:
+--------
+ Stefan Reinauer <stepan@openbios.net>
+ Segher Boessenkool <segher@openbios.net>
+
+%prep
+%setup -n openbios
+
+%build
+( cd toke; make; strip toke )
+( cd detok; make; strip detok )
+( cd paflof; make; strip paflof )
+( find toke/examples -name .cvsignore | xargs rm -f )
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+mkdir -p ${RPM_BUILD_ROOT}/usr/bin/
+mkdir -p ${RPM_BUILD_ROOT}/usr/share/openbios
+mkdir -p ${RPM_BUILD_ROOT}/usr/share/doc/packages/openbios
+cp toke/toke ${RPM_BUILD_ROOT}/usr/bin/
+cp detok/detok ${RPM_BUILD_ROOT}/usr/bin/
+cp paflof/paflof ${RPM_BUILD_ROOT}/usr/bin/
+cp -a toke/examples ${RPM_BUILD_ROOT}/usr/share/doc/packages/openbios
+cp -a forth ${RPM_BUILD_ROOT}/usr/share/openbios
+cp toke/README ${RPM_BUILD_ROOT}/usr/share/doc/packages/openbios/README.toke
+cp detok/README ${RPM_BUILD_ROOT}/usr/share/doc/packages/openbios/README.detok
+
+%files
+/usr/bin
+/usr/share/openbios
+%doc /usr/share/doc/packages/openbios
+
+%changelog -n openbios
+* Mon Jul 22 2002 - stepan@suse.de
+- initial version
diff --git a/roms/openbios/utils/iso/README b/roms/openbios/utils/iso/README
new file mode 100644
index 00000000..9211bc05
--- /dev/null
+++ b/roms/openbios/utils/iso/README
@@ -0,0 +1,5 @@
+The files in this directory are packed into the ISO image created with
+
+ $ make runiso
+
+
diff --git a/roms/openbios/utils/iso/boot/grub/README b/roms/openbios/utils/iso/boot/grub/README
new file mode 100644
index 00000000..07ba5bb5
--- /dev/null
+++ b/roms/openbios/utils/iso/boot/grub/README
@@ -0,0 +1 @@
+stage2_eltorito is part of grub and therefore (C) by the FSF.
diff --git a/roms/openbios/utils/iso/boot/grub/menu.lst b/roms/openbios/utils/iso/boot/grub/menu.lst
new file mode 100644
index 00000000..33e96d3a
--- /dev/null
+++ b/roms/openbios/utils/iso/boot/grub/menu.lst
@@ -0,0 +1,7 @@
+timeout 0
+default 0
+hiddenmenu
+title openbios
+kernel (cd)/openbios.multiboot
+module (cd)/openbios-x86.dict
+boot
diff --git a/roms/openbios/utils/iso/boot/grub/stage2_eltorito b/roms/openbios/utils/iso/boot/grub/stage2_eltorito
new file mode 100644
index 00000000..32b87dd4
--- /dev/null
+++ b/roms/openbios/utils/iso/boot/grub/stage2_eltorito
Binary files differ
diff --git a/roms/openbios/utils/ofclient/Makefile b/roms/openbios/utils/ofclient/Makefile
new file mode 100644
index 00000000..f3c51596
--- /dev/null
+++ b/roms/openbios/utils/ofclient/Makefile
@@ -0,0 +1,14 @@
+PROGRAM := ofclient
+OBJECTS := of1275.o of1275_io.o ofclient.o
+CC := gcc
+CFLAGS := -m32 -fpic -fno-builtin-strlen -Os
+LDFLAGS := -melf_i386 -s -N -Ttext 0x200000 -e _start
+
+$(PROGRAM): $(OBJECTS)
+ $(LD) $(LDFLAGS) -Map $(PROGRAM).map -o $(PROGRAM) $(OBJECTS)
+
+clean:
+ rm -f $(OBJECTS)
+
+distclean: clean
+ rm -f $(PROGRAM) $(PROGRAM).map
diff --git a/roms/openbios/utils/ofclient/README b/roms/openbios/utils/ofclient/README
new file mode 100644
index 00000000..785f6ec2
--- /dev/null
+++ b/roms/openbios/utils/ofclient/README
@@ -0,0 +1,4 @@
+This is an example program using the openfirmware client
+interface on x86. The same program can be compiled on ppc.
+
+
diff --git a/roms/openbios/utils/ofclient/endian.h b/roms/openbios/utils/ofclient/endian.h
new file mode 100644
index 00000000..4d20e717
--- /dev/null
+++ b/roms/openbios/utils/ofclient/endian.h
@@ -0,0 +1,18 @@
+
+#define __bswap32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+
+static int little_endian(void)
+{
+ static short one=1;
+ return *(char *)&one==1;
+}
+
+static unsigned int ntohl(unsigned int netlong)
+{
+ if(little_endian())
+ return __bswap32(netlong);
+
+ return netlong;
+}
diff --git a/roms/openbios/utils/ofclient/of1275.c b/roms/openbios/utils/ofclient/of1275.c
new file mode 100644
index 00000000..ff077827
--- /dev/null
+++ b/roms/openbios/utils/ofclient/of1275.c
@@ -0,0 +1,451 @@
+
+#include "of1275.h"
+#include "endian.h"
+static int (*of1275_server) (void *) = (int (*)(void *)) -1;
+
+_start(void *residual_data_structure,
+ void *program_entry_point,
+ int (*client_interface_handler) (void *), void *args, int argslen)
+{
+ int status;
+ of1275_server = client_interface_handler;
+ status = main();
+ of1275_exit(status);
+}
+
+/* 6.3.2.1 Client interface */
+
+
+int of1275_test(const char *name, int *missing)
+{
+ int result;
+ static of1275_test_service s;
+ s.service = "test";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.name = name;
+ result = of1275_server(&s);
+ *missing = s.missing;
+ return result;
+}
+
+
+/* 6.3.2.2 Device tree */
+
+
+int of1275_peer(int phandle, int *sibling_phandle)
+{
+ int result;
+ static of1275_peer_service s;
+ s.service = "peer";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of1275_server(&s);
+ *sibling_phandle = s.sibling_phandle;
+ return result;
+}
+
+int of1275_child(int phandle, int *child_phandle)
+{
+ int result;
+ static of1275_child_service s;
+ s.service = "child";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of1275_server(&s);
+ *child_phandle = s.child_phandle;
+ return result;
+}
+
+int of1275_parent(int phandle, int *parent_phandle)
+{
+ int result;
+ static of1275_parent_service s;
+ s.service = "parent";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ result = of1275_server(&s);
+ *parent_phandle = s.parent_phandle;
+ return result;
+}
+
+int of1275_instance_to_package(int ihandle, int *phandle)
+{
+ int result;
+ static of1275_instance_to_package_service s;
+ s.service = "instance-to-package";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ result = of1275_server(&s);
+ *phandle = s.phandle;
+ return result;
+}
+
+int of1275_getproplen(int phandle, const char *name, int *proplen)
+{
+ int result;
+ static of1275_getproplen_service s;
+ s.service = "getproplen";
+ s.n_args = 2;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ result = of1275_server(&s);
+ *proplen = s.proplen;
+ return result;
+}
+
+int
+of1275_getprop(int phandle, const char *name, void *buf, int buflen,
+ int *size)
+{
+ int result;
+ static of1275_getprop_service s;
+ s.service = "getprop";
+ s.n_args = 4;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of1275_server(&s);
+ *size = s.size;
+ return result;
+}
+
+int
+of1275_nextprop(int phandle, const char *previous, void *buf, int *flag)
+{
+ int result;
+ static of1275_nextprop_service s;
+ s.service = "nextprop";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.previous = previous;
+ s.buf = buf;
+ result = of1275_server(&s);
+ *flag = s.flag;
+ return result;
+}
+
+int
+of1275_setprop(int phandle, const char *name, void *buf, int len,
+ int *size)
+{
+ int result;
+ static of1275_setprop_service s;
+ s.service = "setprop";
+ s.n_args = 4;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.name = name;
+ s.buf = buf;
+ s.len = len;
+ result = of1275_server(&s);
+ *size = s.size;
+ return result;
+}
+
+int
+of1275_canon(const char *device_specifier, void *buf, int buflen,
+ int *length)
+{
+ int result;
+ static of1275_canon_service s;
+ s.service = "canon";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of1275_server(&s);
+ *length = s.length;
+ return result;
+}
+
+int of1275_finddevice(const char *device_specifier, int *phandle)
+{
+ int result;
+ static of1275_finddevice_service s;
+ s.service = "finddevice";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ result = of1275_server(&s);
+ *phandle = s.phandle;
+ return result;
+}
+
+int
+of1275_instance_to_path(int ihandle, void *buf, int buflen, int *length)
+{
+ int result;
+ static of1275_instance_to_path_service s;
+ s.service = "instance-to-path";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of1275_server(&s);
+ *length = s.length;
+ return result;
+}
+
+int of1275_package_to_path(int phandle, void *buf, int buflen, int *length)
+{
+ int result;
+ static of1275_package_to_path_service s;
+ s.service = "package-to-path";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.phandle = phandle;
+ s.buf = buf;
+ s.buflen = buflen;
+ result = of1275_server(&s);
+ *length = s.length;
+ return result;
+}
+
+/* int of1275_call_method(const char *method, int ihandle, ...); */
+
+
+/* 6.3.2.3 Device I/O */
+
+
+int of1275_open(const char *device_specifier, int *ihandle)
+{
+ int result;
+ static of1275_open_service s;
+ s.service = "open";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.device_specifier = device_specifier;
+ result = of1275_server(&s);
+ *ihandle = s.ihandle;
+ return result;
+}
+
+int of1275_close(int ihandle)
+{
+ int result;
+ static of1275_close_service s;
+ s.service = "close";
+ s.n_args = 1;
+ s.n_returns = 0;
+ s.ihandle = ihandle;
+ result = of1275_server(&s);
+ return result;
+}
+
+int of1275_read(int ihandle, void *addr, int len, int *actual)
+{
+ int result;
+ static of1275_read_service s;
+ s.service = "read";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.addr = addr;
+ s.len = len;
+ result = of1275_server(&s);
+ *actual = s.actual;
+ return result;
+}
+
+int of1275_write(int ihandle, void *addr, int len, int *actual)
+{
+ int result;
+ static of1275_write_service s;
+ s.service = "write";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.addr = addr;
+ s.len = len;
+ result = of1275_server(&s);
+ *actual = s.actual;
+ return result;
+}
+
+int of1275_seek(int ihandle, int pos_hi, int pos_lo, int *status)
+{
+ int result;
+ static of1275_seek_service s;
+ s.service = "seek";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.ihandle = ihandle;
+ s.pos_hi = pos_hi;
+ s.pos_lo = pos_lo;
+ result = of1275_server(&s);
+ *status = s.status;
+ return result;
+}
+
+
+/* 6.3.2.4 Memory */
+
+
+int of1275_claim(void *virt, int size, int align, void **baseaddr)
+{
+ int result;
+ static of1275_claim_service s;
+ s.service = "claim";
+ s.n_args = 3;
+ s.n_returns = 1;
+ s.virt = virt;
+ s.size = size;
+ s.align = align;
+ result = of1275_server(&s);
+ *baseaddr = s.baseaddr;
+ return result;
+}
+
+int of1275_release(void *virt, int size)
+{
+ int result;
+ static of1275_release_service s;
+ s.service = "release";
+ s.n_args = 2;
+ s.n_returns = 0;
+ s.virt = virt;
+ s.size = size;
+ result = of1275_server(&s);
+ return result;
+}
+
+
+/* 6.3.2.5 Control transfer */
+
+
+int of1275_boot(const char *bootspec)
+{
+ int result;
+ static of1275_boot_service s;
+ s.service = "boot";
+ s.n_args = 1;
+ s.n_returns = 0;
+ s.bootspec = bootspec;
+ result = of1275_server(&s);
+ return result;
+}
+
+int of1275_enter(void)
+{
+ int result;
+ static of1275_enter_service s;
+ s.service = "enter";
+ s.n_args = 0;
+ s.n_returns = 0;
+ result = of1275_server(&s);
+ return result;
+}
+
+int of1275_exit(int status)
+{
+ int result;
+ static of1275_exit_service s;
+ s.service = "exit";
+ s.n_args = 1;
+ s.n_returns = 0;
+ s.status = status;
+ result = of1275_server(&s);
+ return result;
+}
+
+/* int of1275_chain(void *virt, int size, void *entry, void *args, int len); */
+
+
+/* 6.3.2.6 User interface */
+
+
+/* int of1275_interpret(const char *arg, ...); */
+
+int of1275_set_callback(void *newfunc, void **oldfunc)
+{
+ int result;
+ static of1275_set_callback_service s;
+ s.service = "set-callback";
+ s.n_args = 1;
+ s.n_returns = 1;
+ s.newfunc = newfunc;
+ result = of1275_server(&s);
+ *oldfunc = s.oldfunc;
+ return result;
+}
+
+int of1275_set_symbol_lookup(void *sym_to_value, void *value_to_sym)
+{
+ int result;
+ static of1275_set_symbol_lookup_service s;
+ s.service = "set-symbol-lookup";
+ s.n_args = 2;
+ s.n_returns = 0;
+ s.sym_to_value = sym_to_value;
+ s.value_to_sym = s.value_to_sym;
+ result = of1275_server(&s);
+ return result;
+}
+
+
+/* 6.3.2.7 Time */
+
+int of1275_milliseconds(int *ms)
+{
+ int result;
+ static of1275_milliseconds_service s;
+ s.service = "milliseconds";
+ s.n_args = 0;
+ s.n_returns = 1;
+ result = of1275_server(&s);
+ *ms = s.ms;
+ return result;
+}
+
+
+int of_find_integer_property(const char *device, const char *property)
+{
+ int phandle;
+ int integer;
+ int size;
+ /* find the device's phandle */
+ if (of1275_finddevice(device, &phandle) < 0) {
+ //printk("of1275: no such device '%s'\n", device);
+ exit(1);
+ }
+ /* find the device's property */
+ of1275_getprop(phandle, property, &integer,
+ sizeof(integer), &size);
+ if (size < sizeof(integer)) {
+ //printk("of1275: unknown integer property '%s'\n", property);
+ exit(1);
+ }
+ return ntohl(integer);
+}
+
+void
+of_find_string_property(const char *device,
+ const char *property,
+ char *string, int sizeof_string)
+{
+ int phandle;
+ int size;
+ /* find the device's phandle */
+ if (of1275_finddevice(device, &phandle) < 0) {
+ //printk("of1275: no such device '%s'\n", device);
+ exit(1);
+ }
+
+ /* find the device's property */
+ of1275_getprop(phandle, property, string, sizeof_string, &size);
+ if (size == 0 || size >= sizeof_string) {
+ //printk("of1275: unknown string property '%s'\n", property);
+ exit(1);
+ }
+}
diff --git a/roms/openbios/utils/ofclient/of1275.h b/roms/openbios/utils/ofclient/of1275.h
new file mode 100644
index 00000000..a73bb19a
--- /dev/null
+++ b/roms/openbios/utils/ofclient/of1275.h
@@ -0,0 +1,437 @@
+/* OpenFirmware interface */
+
+
+/* 6.3.2.1 Client interface */
+
+
+typedef struct _of1275_test_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *name;
+ /*out */
+ int missing;
+} of1275_test_service;
+
+int of1275_test(const char *name, int *missing);
+
+
+/* 6.3.2.2 Device tree */
+
+
+typedef struct _of1275_peer_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ /*out */
+ int sibling_phandle;
+} of1275_peer_service;
+
+int of1275_peer(int phandle, int *sibling_phandle);
+
+
+typedef struct _of1275_child_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ /*out */
+ int child_phandle;
+} of1275_child_service;
+
+int of1275_child(int phandle, int *child_phandle);
+
+
+typedef struct _of1275_parent_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ /*out */
+ int parent_phandle;
+} of1275_parent_service;
+
+int of1275_child(int phandle, int *parent_phandle);
+
+
+typedef struct _of1275_instance_to_package_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ /*out */
+ int phandle;
+} of1275_instance_to_package_service;
+
+int of1275_instance_to_package(int ihandle, int *phandle);
+
+
+typedef struct _of1275_getproplen_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ const char *name;
+ /*out */
+ int proplen;
+} of1275_getproplen_service;
+
+int of1275_getproplen(int phandle, const char *name, int *proplen);
+
+
+typedef struct _of1275_getprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ const char *name;
+ void *buf;
+ int buflen;
+ /*out */
+ int size;
+} of1275_getprop_service;
+
+int of1275_getprop(int phandle, const char *name, void *buf, int buflen,
+ int *size);
+
+
+typedef struct _of1275_nextprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ const char *previous;
+ void *buf;
+ /*out */
+ int flag;
+} of1275_nextprop_service;
+
+int of1275_nextprop(int phandle, const char *previous, void *buf,
+ int *flag);
+
+
+typedef struct _of1275_setprop_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ const char *name;
+ void *buf;
+ int len;
+ /*out */
+ int size;
+} of1275_setprop_service;
+
+int of1275_setprop(int phandle, const char *name, void *buf, int len,
+ int *size);
+
+
+typedef struct _of1275_canon_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *device_specifier;
+ void *buf;
+ int buflen;
+ /*out */
+ int length;
+} of1275_canon_service;
+
+int of1275_canon(const char *device_specifier, void *buf, int buflen,
+ int *length);
+
+
+typedef struct _of1275_finddevice_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *device_specifier;
+ /*out */
+ int phandle;
+} of1275_finddevice_service;
+
+int of1275_finddevice(const char *device_specifier, int *phandle);
+
+
+typedef struct _of1275_instance_to_path_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ void *buf;
+ int buflen;
+ /*out */
+ int length;
+} of1275_instance_to_path_service;
+
+int of1275_instance_to_path(int ihandle, void *buf, int buflen,
+ int *length);
+
+
+typedef struct _of1275_package_to_path_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int phandle;
+ void *buf;
+ int buflen;
+ /*out */
+ int length;
+} of1275_package_to_path_service;
+
+int of1275_package_to_path(int phandle, void *buf, int buflen,
+ int *length);
+
+
+typedef struct _of1275_call_method_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *method;
+ int ihandle;
+ /*... */
+ int args[0];
+} of1275_call_method_service;
+
+int of1275_call_method(const char *method, int ihandle, ...);
+
+
+/* 6.3.2.3 Device I/O */
+
+
+typedef struct _of1275_open_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *device_specifier;
+ /*out */
+ int ihandle;
+} of1275_open_service;
+
+int of1275_open(const char *device_specifier, int *ihandle);
+
+
+typedef struct _of1275_close_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ /*out */
+} of1275_close_service;
+
+int of1275_close(int ihandle);
+
+
+typedef struct _of1275_read_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ void *addr;
+ int len;
+ /*out */
+ int actual;
+} of1275_read_service;
+
+int of1275_read(int ihandle, void *addr, int len, int *actual);
+
+
+typedef struct _of1275_write_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ void *addr;
+ int len;
+ /*out */
+ int actual;
+} of1275_write_service;
+
+int of1275_write(int ihandle, void *addr, int len, int *actual);
+
+
+typedef struct _of1275_seek_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int ihandle;
+ int pos_hi;
+ int pos_lo;
+ /*out */
+ int status;
+} of1275_seek_service;
+
+int of1275_seek(int ihandle, int pos_hi, int pos_lo, int *status);
+
+
+/* 6.3.2.4 Memory */
+
+
+typedef struct _of1275_claim_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *virt;
+ int size;
+ int align;
+ /*out */
+ void *baseaddr;
+} of1275_claim_service;
+
+int of1275_claim(void *virt, int size, int align, void **baseaddr);
+
+
+typedef struct _of1275_release_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *virt;
+ int size;
+ int align;
+ /*out */
+} of1275_release_service;
+
+int of1275_release(void *virt, int size);
+
+
+/* 6.3.2.5 Control transfer */
+
+
+typedef struct _of1275_boot_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *bootspec;
+ /*out */
+} of1275_boot_service;
+
+int of1275_boot(const char *bootspec);
+
+
+typedef struct _of1275_enter_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ /*out */
+} of1275_enter_service;
+
+int of1275_enter(void);
+
+typedef struct _of1275_exit_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ int status;
+ /*out */
+} of1275_exit_service;
+
+int of1275_exit(int status);
+
+
+typedef struct _of1275_chain_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *virt;
+ int size;
+ void *entry;
+ void *args;
+ int len;
+ /*out */
+} of1275_chain_service;
+
+int of1275_chain(void *virt, int size, void *entry, void *args, int len);
+
+
+/* 6.3.2.6 User interface */
+
+
+typedef struct _of1275_interpret_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ const char *cmd;
+ int args[0];
+ /*... */
+ /*out */
+ /*... */
+} of1275_interpret_service;
+
+int of1275_interpret(const char *arg, ...);
+
+
+typedef struct _of1275_set_callback_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *newfunc;
+ /*out */
+ void *oldfunc;
+} of1275_set_callback_service;
+
+int of1275_set_callback(void *newfunc, void **oldfunc);
+
+
+typedef struct _of1275_set_symbol_lookup_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ void *sym_to_value;
+ void *value_to_sym;
+ /*out */
+} of1275_set_symbol_lookup_service;
+
+int of1275_set_symbol_lookup(void *sym_to_value, void *value_to_sym);
+
+
+/* 6.3.2.7 Time */
+
+
+typedef struct _of1275_milliseconds_service {
+ const char *service;
+ int n_args;
+ int n_returns;
+ /*in */
+ /*out */
+ int ms;
+} of1275_milliseconds_service;
+
+int of1275_milliseconds(int *ms);
+
+
+/* Common and useful utilities */
+
+
+int of_find_integer_property(const char *path, const char *property);
+
+void of_find_string_property(const char *path, const char *property,
+ char *string, int sizeof_string);
diff --git a/roms/openbios/utils/ofclient/of1275_io.c b/roms/openbios/utils/ofclient/of1275_io.c
new file mode 100644
index 00000000..25d1132c
--- /dev/null
+++ b/roms/openbios/utils/ofclient/of1275_io.c
@@ -0,0 +1,51 @@
+#include "of1275.h"
+
+static int of_write_initialized = 0;
+static int stdout_ihandle = 0;
+static int of_read_initialized = 0;
+static int stdin_ihandle = 0;
+
+int write(int fd, char *buf, int len)
+{
+ int actual;
+
+ if (fd != 1 && fd != 2) {
+ // printk("write: bad id %x\n", fd);
+ exit(1);
+ }
+
+ if (!of_write_initialized) {
+ stdout_ihandle =
+ of_find_integer_property("/chosen", "stdout");
+ // printk("stdout_ihandle: %x\n",stdout_ihandle);
+ of_write_initialized = 1;
+ }
+
+ of1275_write(stdout_ihandle, buf, len, &actual);
+ return actual;
+}
+
+int read(int fd, char *buf, int len)
+{
+ int actual;
+
+ if (fd != 0) {
+ // printk("write: bad id %x\n", fd);
+ exit(1);
+ }
+
+ if (!of_read_initialized) {
+ stdin_ihandle =
+ of_find_integer_property("/chosen", "stdin");
+ of_read_initialized = 1;
+ }
+
+ of1275_read(stdin_ihandle, buf, len, &actual);
+ return actual;
+}
+
+exit(int status)
+{
+ of1275_exit(status);
+ while (1);
+}
diff --git a/roms/openbios/utils/ofclient/ofclient.c b/roms/openbios/utils/ofclient/ofclient.c
new file mode 100644
index 00000000..94214c6c
--- /dev/null
+++ b/roms/openbios/utils/ofclient/ofclient.c
@@ -0,0 +1,9 @@
+#include "of1275.h"
+
+int write(int fd, char *buf, int len);
+
+int main(void)
+{
+ write(1, "Hello world!\n", 13 );
+ return 0;
+}