The Client Interface Open Firmware refers to operating systems as "client programs". So then, officially, the services which OF provides to OSes is called the "client interface". Bad Things: * Using memory which you didn't allocate. * Doing your own virtual-memory stuff. * Messing with devices that OF is using. * Modifying certain processor registers (processor-dependent). If you do any of these, the client interface services may stop working. So don't. Unless, of course, you are planning to take over completely. An Implementation Must: * provide the client interface services (listed below). * provide the "client execution environment" (also below). * implement the device-tree nodes * /openprom - describes the OF - kind of useless. * /options - configuration options - I don't have much use for these either. * /chosen - ihandles for useful things like stdin, stdout, etc. * the node described by /chosen's "memory" property ("describes the allocation status of physical memory"). Client Execution Environment When OF transfers control to your program's entry point, r1 is a valid stack pointer with at least 32KB of memory available for stack growth, and r5 contains the entry point of the OF client interface handler. There's more, but those are the important things. Calling conventions for the handler are similar to all other PPC calling conventions. Specifically, r3-r12 and all condition register fields except cr2-cr4 are volatile, all other registers are preserved. You pass the handler a pointer to an "argument array structure" in r3, and it returns a true/false (-1/0) value in r3, indicating whether OF successfully passed control to the requested service. Any values returned by the service are placed in the argument array structure, which looks like this: * Address of service name (zero-terminated string) * Number of arguments * Number of return values * Arguments * Return values (you're supposed to zero these before calling the handler) Useful Client Interface Services I'll stick with OF's organization of these...note that this is NOT all the required services, merely the ones you need to get started playing with OF. See the draft OF spec, pages 64-70, for the whole story. Client Interface * test ( name -- missing ) - returns 0 if service "name" exists, -1 if not. Device Tree * finddevice ( device-path -- phandle | -1 ) - find a device node by name. * getprop ( phandle name addr len -- ) - get a property of a device node (into buffer defined by addr, len). Device I/O * open ( device-path -- ihandle | 0 ) - open a device. * close ( ihandle -- ) * read ( ihandle addr len -- actual_len ) - read from a device. Note that, unlike Linux, an actual_len of 0 does *not* indicate end of "file". When reading a hard drive, the read method appears to return immediately, whether the drive has responded or not. So you just have to try several times until it works. Note also that actual_len may be -1 (if the device doesn't actually have a read method). * write ( ihandle addr len -- actual_len ) write to a device. * seek ( ihandle pos.hi pos.lo -- status ) seek to a certain position on a device. I don't remember what the status codes are. Again, -1 means no seek method. Memory * claim ( virt_addr, size, align -- base_addr ) - claim size bytes of memory. If align is zero, you get exactly virt_addr, size. Otherwise, virt_addr is ignored, and you get size bytes at some address aligned to the smallest power of two larger than align. * release ( virt_addr, size -- ) - release some memory that you got from claim. Control Transfer * exit ( -- ) - Exits to the OF prompt. On my OF (from Apple), once you exit, you must reboot before you can load and run another program. Time * milliseconds ( -- ms ) - Returns a number that increases periodically, in units of milliseconds. Granularity is system dependent, and I haven't tested mine.