Showing posts with label 3400c. Show all posts
Showing posts with label 3400c. Show all posts

Thursday, October 3, 2013

iQUIK updates

iQUIK (my fork of QUIK, the OldWorld Linux bootloader) has seen a few enhancements.
  • Better 3400c support. Now that I have a CD drive, I verified that the media bay ATA only needs to be hidden when there's nothing attached to it. CD booting is still at large (but will probably work just fine).
  • PDQ/Wallstreet documentation. This includes patches to get booting via PCMCIA/CF and via internal IDE, as well as kernel options needed. CD booting is still untested (and will likely cause the nvramrc patches needed to grow).
  • Bug fixes around large disk access that was preventing from correctly reading partitions larger than 4GB. There's still a problem with partitions on large disks, so you should probably create a '/boot' partition. I wonder if certain ATA packages on old OF have issues... Needs investigation.
  • !cat to display short files
  • Bug fixes to path handling and compatibility with yaboot.conf used by debian installer.
  • Turn on shallow setprop support for OF 1.0.5 (pending testing to see if it's needed)
The current to-do list:
  • Clean-up command parsing/handling a-la U-Boot
  • Investigate partition access on large disks
  • Automatic nvramrc patching to ease deployment
  • Janitorial:
    • malloc/printf replacements
    • claim() load area and prom_exit() path should close all opened handles, release all claimed memory (end goal is being able to quit and load again)
  • Add !parts to scan and display partition/fs info for devices
  • Rewrite shallow setprop support to work for all props, not just initrd-base/initrd-size
  • BSD kernel loading
  • Partition-less device support
  • FAT support
  • ISO9660 support
  • EXT4 support
  • FCode loading
  • Forth loading
Current test plans:
  • OF 1.0.5
  • CD booting
  • More machines (anyone?), maybe try some different CPU modules on my PDQ
It's actually sort of interesting that there's no guarantee that the same OpenFirmware release (i.e. 2.0.1) will have the same bugs. And I'm not just talking about device support, because that's fairly obvious (different I/O chipsets need different drivers). For example, the 3400c has 'setprop' issues that need to be worked around, but the Wallstreet doesn't. The Wallstreet is obviously newer, but there's no way to draw a line between support without trying it on every model (so might as well always use the work-around).

As usual, everything is at https://github.com/andreiw/quik

A

Sunday, September 15, 2013

Working around OFW and kernel bugs on OldWorlds

Trying to boot up a 2.6 kernel with initrd on the 3400c I ran into a couple of bugs that were show stoppers. One resulted in the kernel not finding it's initrd image ("VFS panic"), the second in a hard hang probing a non-existing media bay ATA.

To understand the first bug (and the workaround for both) we need to see how the OFW structures are used in kernel bootup.

On PowerPC, the Linux kernel can be called anywhere. The early boot code is capable of running at any address (it is reloc-safe), but the kernel needs to be moved to its linked address before it can be run. Of course, the linked address might conflict with OFW mappings, hence the early boot code needs to exit the firmware services before relocating and jumping to the rest of the kernel. Of course, the rest of the kernel needs the device tree information to initialize the platform, and because OFW has been already quiesced, the early boot code needs to make a copy of the device tree structures, thereby "flattening" it. This early OFW-handling code is called from kernel/head_32.S and is in arch/powerpc/kernel/prom_init.c(prom_init).

Before flattening the device tree, prom_init first queries various bits and pieces and uses the OF setprop call to store them inside the /chosen node. The /chosen node represents information passed from OFW to the OS, and Linux sets properties in that node for itself to find later. For example, the initrd information (base and size), which is passed in registers to the kernel from the bootloader, is then stored in /chosen/linux,initrd-start and /chosen/linux,initrd-end. This information is then copied using the OFW getprop call when the dt is flattened later inside prom_init.

The problem on the 3400c with OFW 2.0.1 is that the setprop client call doesn't actually make a copy of the data, but just stashes the passed pointer away. Because the values set during calls from prom_init are built on the stack, the later getprop calls during dt flattening return garbage.

So how can we deal with it? Because we know the kernel only makes calls to the PROM before it trashes the memory map, we can "shim away" the real client interface with a filter inside the bootloader, that can
feed the kernel the right values and fix up any broken OF behavior. In case of the "shallow" setprop problem above, I simply feed the correct initrd base and end addresses when I detect accesses to /chosen/linux,initrd-start and /chosen/linux,initrd-end. Of course, a much better and generic way would be to make deep copies of any setprop-ed field onto the bootloader heap...

Come to think of it, it's highly likely older OF versions (like the infamous 1.0.5) have the same bug.

The second bug involved a hard hang scanning the media bay ATA controller on the 3400c. I don't have a CD drive, so I have no idea if this only happens with the bay empty. There are no kernel parameters to black list devices. Since we already have a shim to intercept and transform OF client interface results, I simply have hidden /bandit/ohare/media-bay/ata away from the kernel.