As a newbee in this space I got qemu-system-sparc[64] running on a linux machine.
Trying to find out how qemu and openbios work together I'm currently looking into building openbios-sparc64.
This goes with mixed success as https://www.openfirmware.info/OpenBIOS has nice description on how to build openbios, but there's a missing link as to how to harvest the openbios-sparc64 from this.
My build of openbios is done on an Ultra60(Sparc) machine that runs:
Linux ultra60 4.19.0-2-sparc64 #1 Debian 4.19.16-1 (2019-01-17) sparc64 GNU/Linux
with gcc --version
gcc (Debian 8.3.0-2) 8.3.0
It seems like the file openbios/obj-sparc64/openbios-builtin.elf may be the candidate to become openbios-sparc64??
When giving this a try, and moving openbios-builtin.elf to my x86 qemu machine, it crashes spectacularly with:
qemu: fatal: Trap 0x0064 while trap level (5) >= MAXTL (5), Error state
pc: 0000000000004c80 npc: 0000000000004c84
%g0-3: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%g4-7: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%o0-3: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%o4-7: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%l0-3: 00000000fff001e0 000001ff00000000 000001fff0080000 0000000000000000
%l4-7: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%i0-3: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%i4-7: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%f00: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%f08: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%f16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%f24: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%f32: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%f40: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%f48: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
%f56: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
pstate: 00000414 ccr: 44 (icc: -Z-- xcc: -Z--) asi: 00 tl: 5 pil: 0 gl: 2
tbr: 0000000000000000 hpstate: 0000000000000000 htba: 0000000000000000
cansave: 6 canrestore: 0 otherwin: 0 wstate: 0 cleanwin: 6 cwp: 7
fsr: 0000000000000000 y: 0000000000000000 fprs: 0000000000000000
On x86: Booting qemu with the provided openbios-sparc64 rom works flawless.
On the Ultra60: Running ./openbios-unix openbios-sparc64.dict seems to behave as expected:
Output device screen not found.
Input device keyboard not found.
Output device screen not found.
Type 'help' for detailed information
[unix] Booting default not supported.
Trying disk...
No valid state has been set by load or init-program
0 > help
To get openbios build, I had to make a small change in Makefile.target:
#CFLAGS+= -Werror
CFLAGS+= -Wno-error
To "fix":
Building OpenBIOS for sparc64
Building...
/usr/bin/xsltproc
error:
CC target/arch/unix/unix.o
CC target/arch/unix/boot.o
/sources/openbios/arch/unix/boot.c:101:6: error: redundant redeclaration of 'forth_fw_cfg_read_file' [-Werror=redundant-decls]
void forth_fw_cfg_read_file(void);
^~~~~~~~~~~~~~~~~~~~~~
In file included from ./target/include/asm/io.h:8,
from /sources/openbios/include/kernel/kernel.h:22,
from /sources/openbios/include/libopenbios/bindings.h:21,
from /sources/openbios/arch/unix/boot.c:6:
/sources/openbios/include/arch/common/fw_cfg.h:104:6: note: previous declaration of 'forth_fw_cfg_read_file' was here
void forth_fw_cfg_read_file(void);
^~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
Any pointers or suggestions to continue this journey are appreciated.
Signed-off-by: BALATON Zoltan <balaton(a)eik.bme.hu>
---
drivers/pci.c | 51 +++++++++++++++++++++++++++++++++++++--------------
drivers/pci.fs | 41 +++++++++++++++++++++++++++++++++++++++++
drivers/vga.fs | 4 ++--
forth/device/other.fs | 6 ++++++
4 files changed, 86 insertions(+), 16 deletions(-)
This is on top of Mark's previous patches from the openbios mailing
list applied to openbios master:
9a32ed9 Implement missing words for the ATI FCode ROM to test ati-vga emulation
b90ac41 virtio: use instance value to initialise C instance parameter
ac467a3 lsi: use instance value to hold sd_private_t pointer
177684a pc_kbd: use instance value to initialise C instance parameter
d5fdb98 pc_serial: remove separate init word
7c20840 pci: call set-args before configuring PCI device nodes
f37460e pci: remove explicit setting of my-self from PCI devices
b548924 pci: remove explicit find-device from PCI devices
b1ca78f x86: set active package and current instance to root device node before probe
6222a47 SPARC64: set active package and current instance to root device node before probe
5cd41e5 ppc: set active package and current instance to root device node before probe
e68504f ppc: move New World uninorth and nvram device node creation to the root device
86aa740 nvram: ensure that NVRAM configuration is separate from NVRAM node creation
e959bfd libopenbios: remove REGISTER_NAMED_NODE and REGISTER_NAMED_NODE_PHANDLE macros
abc4553 pci: remove ob_pci_initialize() and ob_pci_empty_node
0a63c74 pci: convert to use BIND_NODE_METHODS() macro
57ff6ea virtio: convert to use BIND_NODE_METHODS() macro
ea3a8eb lsi: convert to use BIND_NODE_METHODS() macro
32ff529 lsi: don't change active package when setting device alias
f63f5ee nvram: convert to use BIND_NODE_METHODS() macro
03c53be usbhid: convert to use BIND_NODE_METHODS() macro
365b2c1 pmu: convert to use BIND_NODE_METHODS() macro
60125f5 macio: convert to use BIND_NODE_METHODS() macro
7d23b31 cuda: convert to use BIND_NODE_METHODS() macro
305d629 escc: convert to use BIND_NODE_METHODS() macro
4a0aea1 adb: convert to use BIND_NODE_METHODS() macro
0081f71 ide: convert to use BIND_NODE_METHODS() macro
79a241c floppy: convert to use BIND_NODE_METHODS() macro
01ea2e4 pc_serial: convert to use BIND_NODE_METHODS() macro
9eb09a9 pc_kbd: convert to use BIND_NODE_METHODS() macro
8945ab4 libopenbios: introduce BIND_NODE_METHODS() macro
e9491ea admin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses propertyadmin/devices.fs: Format assigned-addresses property
c79e0ec (origin/master, origin/HEAD) SPARC64: use serial console when QEMU is launched with -vga none
admin/devices.fs: Format assigned-addresses property is
https://mail.coreboot.org/hyperkitty/list/openbios@openbios.org/thread/WHL7…
and additionally to the above I also have another patch from Mark that
I can't find now in the list archives even though I remember I've replyed
to it and had a discussion about having 3 or 2 cases if-else statement.
diff --git a/drivers/pci.c b/drivers/pci.c
index 4bc02c9..eb5f7d3 100644
--- a/drivers/pci.c
+++ b/drivers/pci.c
@@ -408,20 +408,32 @@ static void ob_pci_unmap(ucell virt, ucell size) {
static void
ob_pci_bus_map_in(int *idx)
{
- uint32_t ba;
- ucell size;
- ucell virt;
-
- PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx);
+ fword("pci-map-in");
+}
- size = POP();
- POP();
- POP();
- ba = POP();
+static void
+ob_pci_bus_map_out(int *idx)
+{
+ /* Should call pci-map-out but nothing to do in it yet */
+ fword("2drop");
+}
- virt = ob_pci_map(ba, size);
+static void
+ob_pci_config_read8(int *idx)
+{
+ cell hi = POP();
+ pci_addr addr = PCI_ADDR(PCI_BUS(hi), PCI_DEV(hi), PCI_FN(hi));
+ uint8_t val = pci_config_read8(addr, hi & 0xff);
+ PUSH(val);
+}
- PUSH(virt);
+static void
+ob_pci_config_write8(int *idx)
+{
+ cell hi = POP();
+ pci_addr addr = PCI_ADDR(PCI_BUS(hi), PCI_DEV(hi), PCI_FN(hi));
+ cell val = POP();
+ pci_config_write8(addr, hi & 0xff, val & 0xff);
}
static void
@@ -459,7 +471,10 @@ NODE_METHODS(ob_pci_bus_node) = {
{ "close", ob_pci_close },
{ "decode-unit", ob_pci_decode_unit },
{ "encode-unit", ob_pci_encode_unit },
- { "pci-map-in", ob_pci_bus_map_in },
+ { "map-in", ob_pci_bus_map_in },
+ { "map-out", ob_pci_bus_map_out },
+ { "config-b@", ob_pci_config_read8 },
+ { "config-b!", ob_pci_config_write8 },
{ "dma-alloc", ob_pci_dma_alloc },
{ "dma-free", ob_pci_dma_free },
{ "dma-map-in", ob_pci_dma_map_in },
@@ -473,7 +488,14 @@ static void
ob_pci_bridge_map_in(int *idx)
{
/* As per the IEEE-1275 PCI specification, chain up to the parent */
- call_parent_method("pci-map-in");
+ call_parent_method("map-in");
+}
+
+static void
+ob_pci_bridge_map_out(int *idx)
+{
+ /* As per the IEEE-1275 PCI specification, chain up to the parent */
+ call_parent_method("map-out");
}
NODE_METHODS(ob_pci_bridge_node) = {
@@ -481,7 +503,8 @@ NODE_METHODS(ob_pci_bridge_node) = {
{ "close", ob_pci_close },
{ "decode-unit", ob_pci_decode_unit },
{ "encode-unit", ob_pci_encode_unit },
- { "pci-map-in", ob_pci_bridge_map_in },
+ { "map-in", ob_pci_bridge_map_in },
+ { "map-out", ob_pci_bridge_map_out },
{ "dma-alloc", ob_pci_dma_alloc },
{ "dma-free", ob_pci_dma_free },
{ "dma-map-in", ob_pci_dma_map_in },
diff --git a/drivers/pci.fs b/drivers/pci.fs
index a7b56e1..327c9c9 100644
--- a/drivers/pci.fs
+++ b/drivers/pci.fs
@@ -37,4 +37,45 @@
then
;
+: pci-map-in ( addr.lo addr.mid addr.hi size -- virt )
+ \ Ignore everything but addr.hi and find assigned addr for BAR
+ drop nip nip
+ \ Save my-self and set it to same as active package because otherwise
+ \ decode-phys below seems to be confused. Maybe this should not be needed
+ my-self swap active-package ihandle>phandle to my-self
+ " assigned-addresses" active-package get-package-property 0= if
+ begin
+ decode-phys ( bar prop prop-len phys.lo phys.mid phys.hi )
+ dup 0fffffff and 6 pick 0fffffff and = if
+ 2drop -rot
+ decode-int drop decode-int drop 2drop
+ ( bar addr.lo )
+ \ Now translate addr.lo, This may be wrong
+ \ maybe we should look at parent's ranges instead?
+ over 18 rshift 3 and 1 = if
+ " reg" active-package parent get-package-property 0= if
+ ( bar addr.lo prop prop-len reg.addr reg.size )
+ decode-int -rot decode-int 3drop
+ +
+ then
+ then
+ nip swap to my-self
+ exit
+ else
+ 3drop \ no match, try next
+ then
+ \ Drop the size as we don't need it
+ decode-int drop decode-int drop
+ dup 0=
+ until
+ 3drop
+ to my-self
+ -1 \ not found
+ else
+ drop
+ to my-self
+ -1 \ could not find assigned-addresses
+ then
+ ;
+
[THEN]
diff --git a/drivers/vga.fs b/drivers/vga.fs
index 53dcff0..f3ffda7 100644
--- a/drivers/vga.fs
+++ b/drivers/vga.fs
@@ -146,14 +146,14 @@ defer vbe-iow!
: map-fb ( -- )
cfg-bar0 pci-bar>pci-addr if \ ( pci-addr.lo pci-addr.mid pci-addr.hi size )
- " pci-map-in" $call-parent
+ " map-in" $call-parent
to fb-addr
then
;
: map-mmio ( -- )
cfg-bar2 pci-bar>pci-addr if \ ( pci-addr.lo pci-addr.mid pci-addr.hi size )
- " pci-map-in" $call-parent
+ " map-in" $call-parent
to mmio-addr
then
;
diff --git a/forth/device/other.fs b/forth/device/other.fs
index 1bed9b8..0ff34b6 100644
--- a/forth/device/other.fs
+++ b/forth/device/other.fs
@@ -58,21 +58,27 @@ defer (poke)
\ 5.3.7.2 Device-register access
: rb@ ( addr -- byte )
+ ioc@
;
: rw@ ( waddr -- w )
+ iow@
;
: rl@ ( qaddr -- quad )
+ iol@
;
: rb! ( byte addr -- )
+ ioc!
;
: rw! ( w waddr -- )
+ iow!
;
: rl! ( quad qaddr -- )
+ iol!
;
: rx@ ( oaddr - o )
--
2.13.7
To help reading property listing also format assigned-addresses
property the same way as reg was already formatted.
Signed-off-by: BALATON Zoltan <balaton(a)eik.bme.hu>
---
Actually wanted to improve printing of ranges but I could not do that
this one is simpler though.
forth/admin/devices.fs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/forth/admin/devices.fs b/forth/admin/devices.fs
index 6f9e8ef..38f6ad6 100644
--- a/forth/admin/devices.fs
+++ b/forth/admin/devices.fs
@@ -417,7 +417,7 @@
\ This function hardwires data formats to particular node properties
: (.property-by-name) ( name-str name-len data len -- )
- 2over " reg" strcmp 0= if
+ 2over 2dup " reg" strcmp 0= -rot " assigned-addresses" strcmp 0= or if
my-#acells my-#scells 2swap .p-reg
2drop exit
then
--
2.13.7
Hello,
On Tue, 30 Jul 2019, BALATON Zoltan wrote:
> 3. Try to get some other OF implementation working like OpenFirmware. Based
> on previous work by Atar for the 40p this is possible although to do it
> cleanly may be more work and hindered by the need to do it in Forth
> completely. But Forth is needed to hack on OpenBIOS as well so once someone
> gets over that hurdle it does not matter. I've started looking at this
> posibility to find out how much work would this be that's why I was asking
> the question. I've compiled Atar's work which is now upstram in Mitch
> Bradley's tree and it worked well with 40p and even started with pegasos2 but
> of course it did not init the hardware correctly expecting to run on 40p
> (haven't tried with mac99 but I expect the same result). So OpenFirmware
> already works on PPC and has some QEMU specific drivers what we may need is
> porting drivers for mac specific and pegasos2 devices from OpenBIOS from C to
> Forth (or get equivalents from somewhere else) and think about how to pass
> the initial device tree similar to SLOF to avoid having to implement each
> board in OpenFirmware separately (although doing hardcoded board
> implementation like Atar's 40p might be a quick and dirty way to get it
> working with much less work).
I gave it a try playing with it for a few hours (without really knowing
what am I doing) just to get to know it better and see what's needed. So I
started by stripping down Atar's QEMU PReP port removing PReP specific
parts and just leaving a bare minimum to work on PowerPC and I actually
managed to build a ROM image that works with my pegasos2 emulation and
gets me an OF environment over diag serial port now:
$ qemu-system-ppc -M pegasos2 -bios ofw.rom -serial stdio
setup_mem_windows: Should enable region 14
Mapping pci1-io-win 0x0+0x2000000 @ 0xfe000000
setup_mem_windows: Should enable region 20
Type 'i' to interrupt stand-init sequence
First stand-init:
Calibrate
CIF buffers
DHCP init
memory node
Instruction cache on
Decrementer
Enable machine check exceptions
Set Memory Map
MMU
Root node
Data cache on
Fast CPU mode
PCI host bridge
CPU nodes
Keyboard overrides
Memory node
not found.
not found.
/pci/isa/serial@i2f8 not found.
/pci/isa/serial@i2f8 not found.
not found.
not found.
, Serial #0, 128 MiB memory installed
Open Firmware
Copyright (c) 1995-2000, FirmWorks.
Copyright (c) 2014,2017,2019 Artyom Tarasenko.
Type any key to interrupt automatic startup
6 5 4 3 2 1
Boot device: net Arguments:
Can't open boot device
ok show-devs
/dropin-fs
/null-nvram
/cpus
/<Unnamed>
/mmu
/memory@0
/aliases
/options
/openprom
/chosen
/packages
/cpus/PowerPC,603evARTHUR@0
/packages/ext2-file-system
/packages/disk-label
/packages/iso9660-file-system
/packages/fat-file-system
/packages/obp-tftp
/packages/deblocker
/packages/stringio
/packages/terminal-emulator
/packages/client-services
ok printenv
Variable Name Value Default Value
hrp-memmap? false false
virt-size 0x0 0xffffffff
virt-base 0x0 0xffffffff
real-size 0x0 0xffffffff
real-base 0x0 0xffffffff
real-mode? false false
diag-switch? false false
fcode-debug? false false
ip-address 255.255.255.255 255.255.255.255
ip-router
ip-domain
ip-netmask 255.255.255.0 255.255.255.0
ip-dns-server
local-mac-address? false false
oem-logo
oem-logo? false false
oem-banner
oem-banner? false false
output-device /pci/isa/serial@i2f8 /pci/isa/serial@i2f8
input-device /pci/isa/serial@i2f8 /pci/isa/serial@i2f8
load-base 4194304 4194304
boot-command boot boot
auto-boot? true true
watchdog-reboot? false false
diag-file
diag-device net net
boot-file
boot-device disk net disk net
ansi-terminal? true true
screen-#columns 80 80
screen-#rows 34 34
silent-mode? false false
use-nvramrc? false false
nvramrc
security-password
security-#badlogins 0
security-mode none
diag-switch? false false
ok dev /
ok .properties
#address-cells 00000001
ok dev openprom
ok .properties
model FirmWorks,3.0
aligned-allocator
relative-addressing
name openprom
ok dev /cpus/PowerPC,603evARTHUR
ok .properties
clock-frequency 05f5e100
reg 00000000
timebase-frequency 007de290
tlb-sets 00000080
tlb-size 00000100
d-cache-sets 00000080
d-cache-block-size 00000020
d-cache-size 00008000
i-cache-sets 00000080
i-cache-block-size 00000020
i-cache-size 00008000
device_type cpu
name PowerPC,603evARTHUR
ok
Of course it's only the start and has a lot of missing parts yet: does not
detect PCI bus and devices (I need to write a driver for the PCI host
similar to what Atar did for 40p), it misdetects the CPU (or it may be
hard coded somewhere), does not detect memory size (this is mentioned on
Atar's blog) and may have other defficiencies. But for a start it works
quite well and it was surprisingly easy to get it up thanks to previous
work. Given that the Pegasos2 is quite close to PReP and PC hardware most
of the drivers for PC like hardware are already there in OF, so maybe if I
can make a working driver for the system controller chip the rest would
just work or should be relatively easy to fix. So for the pegasos2 this
seems to be a viable alternative that may not be too hard to get working
if I limit the scope to just the pegasos2.
For Mac machines more drivers would need to be written as these are not
included in the open source OF version that was released for OLPC so only
those drivers are included which were needed for that. Therefore it would
be more work to write those missing drivers. We have USB driver (I've once
tried porting that to OpenBIOS[1]) so keyboard and mouse might work where
we have USB but we would still need drivers for uninorth and mac-io at
least to get something working but maybe others as well, I'm not sure.
For Sparc machines even CPU support is missing so it may be more difficult
to get that working. Or maybe not as this could be added based on some
other similar architecture: arm, mips and ppc are already there but these
do have a lot of Forth files so it may take a while to understand those. I
don't know Sparc hardware to tell what drivers may be needed.
But from Atar's blog on getting OF working for QEMU PReP/40p I got the
impression that Mitch Bradley (inventor of OpenFirmware and founder of
FirmWorks) did help him by releasing some additional drivers or sources
that he needed so maybe asking politely would not hurt and it may get
easier, unless there are legal hurdles in releasing additional sources.
Otherwise those need to be recreated but that may still be doable if
someone does not mind learning enough Forth to do it.
I'm not sure which is more work, getting OpenBIOS to the same level or
writing drivers for OpenFirmware but maybe for PPC machines it's not much
harder to rewrite the missing drivers. For Sparc I'm not sure, PPC support
was already there so I don't know what it takes to add a new cpu support.
Regards,
BALATON Zoltan
[1] One can follow the thread starting here:
https://mail.coreboot.org/pipermail/openbios/2014-May/008244.html
but basically the attempt to port OF driver to OpenBIOS ended with:
https://mail.coreboot.org/pipermail/openbios/2014-May/008281.html
some of those words are already there now but some are still missing.
I've ended up finishing the C driver which was finally added, even though
I only wanted to try qemu-system-ppc64 originally and did not plan to port
a USB driver. That's what I meant saying I end up having to do fixes
whenever I try something in OpenBIOS: like trying an FCode ROM the last
time. At least OpenFirmware implements the standard already perfectly so
we would only need to care about getting it to work with the machine and
not if it has everythung that might be needed by stuff using it (or at
least much less so than starting from scratch).