Beginning Open Firmware debugging techniques, Part I: The command line interface

Prerequisites:

"This operating system, that hardware," the introductory article to this series. (link goes here)

For readers not familiar with what Open Firmware is, a good qualititative primer would be Peter Seebach's "Standards and specs: Open Firmware -- the bridge between power-up and OS" at http://www-106.ibm.com/developerworks/library/pa-spec2.html. Peter lists several other qualititative references that can enhance the reader's understanding of the purpose of Open Firmware.

System Requirements:

An Open Firmware equipped computer. Included examples will use Apple hardware.

About this tutorial

This tutorial explores basic Open Firmware concepts in a quantitative manner, presented at a beginner's level, with examples. This tutorial and the next three will build basic debugging skills necessary to be able to use the firmware to load, execute and debug a bootloader. Reference material will be introduced within this tutorial as appropriate for the context of the concept being discussed. A comprehensive listing of the References is at the end of this tutorial, and as material is introduced it may be discussed or simply identified to indicate its relevance. Advanced Exercises will offer a chance for the reader to explore a concept independently, and for those exercises in which a quantitative answer is appropriate, the answers will appear in the next tutorial. The Advanced Exercises often introduce concepts that will be applied in later tutorials.

This tutorial does not explore the use of Open Firmware and Forth for on-board device driver development.

Reference Material

Open Firmware

The formal name for Open Firmware is IEEE 1275-1994, and the entire standard can be obtained through IEEE. Apple has additional information on obtaining this in Hardware Note 85: http://developer.apple.com/qa/hw/hw85.html. The primary Open Firmware web site is at http://playground.sun.com/1275/, but several mirrors exist.

Apple and Sun Documents

Peter Seebach's primer references three Apple technotes that contain information these tutorials will be using, but there are other Apple documents that are equally informative, perhaps more so for someone unfamiliar with Forth. http://developer.apple.com/devicedrivers/pci/downloads/Forth_PP.hqx is a package that contains two PowerPoint demonstrations on Forth, both of which are excellent. Apple used to have PDFs of the two demonstrations available at the developer.apple.com website, but unfortunately pulled them in late December 2004; the Powerpoint version is compressed with the Apple-centric .hqx format, adding to the inconvenience. http://bananajr6000.apple.com/OF/technotes.html is a slightly out-of-date compilation of Apple's Tech and Hardware Notes specific to Open Firmware. The few Technotes that are missing can be found at http://developer.apple.com/technicalnotes/Hardware/idxOpenFirmware-date.html. Be forewarned: Apple appears to be moving or removing some of their Open Firmware related documents, and the bananajr6000 server may be offline.

Sun uses a variant of IEEE 1275-1994 they call Open Boot. Except for their differences, Open Boot and Open Firmware are the same. Congruently, Sun's Writing FCode books are often useful, if only to provide a different perspective on the same concept. Sun makes the Writing FCode series available at http://docs.sun.com/app/docs/doc/801-7050

Open Firmware Bindings

Once a rudimentary grasp of Open Firmware and Forth is achieved, the next most important documents for debugging in Open Firmware will be the "Bindings." These documents specify the requirements hardware manufacturers must adhere to in order to be compliant with the Open Firmware specification. These can be found at http://playground.sun.com/1275/bindings/, but the ones of the most interest to readers of this series are

http://playground.sun.com/1275/bindings/ppc/release/ppc-2_1.html (PowerPC Binding, version 2.1)

http://playground.sun.com/1275/bindings/pci/pci2_1.pdf (PCI 2.0 Binding, version 2.1)

Both of the above bindings expect a strong understanding of Open Firmware. For beginners, it is useful to review the documents without a full understanding of the contents, in order to know where to look for answers to questions as yet unformulated. It is perfectly normal to read these repeatedly without comprehension while questioning one's own grasp of the English language.

Advanced Exercises, Qualititative

Supplementing the PowerPC Binding are the manufacturing specs from IBM and Motorola/Freescale, which are often relocated to archive sections as newer processors come online. A little bit of googling on terms like "MPC604e.pdf" and "MPC7400UM.pdf" will turn up the relevant documents for two of the CPUs used in this series (and often other reference material listed in this tutorial can be found through similar means when a link has not been supplied). The reader should obtain these as well as the manufacturer's documentation for the reader's computer.

Additionally, the reader should obtain a copy of PowerPC Processor Family: The Programming Environments, which covers both 64 and 32 bit PowerPC. There is a 32 bit edition that is a subset of the full edition, and will also suffice. Both are freely available over the web.

Entering Open Firmware

Keystroke combination

Often just getting into Open Firmware (refered to hereafter as "OF") is a challenge to users unfamiliar with it. On almost all PCI PowerMacs, holding down the Apple-Option-O-F keys immediately after the boot chord will invoke the user interface to OF. However, finding the output from the user interface is not automatic, if this is the first time invoking OF. For early models such as a serial port equipped PowerMac 7300, the default output is the modem port, also referred to as ttya. This will require a serial connection. The settings for that connection are 38,400 baud, 8 bits, 1 stop bit, no parity, XOn/XOff enabled (see Apple's Technote 1061 http://developer.apple.com/technotes/tn/tn1061.html). For later models, the output will usually be the monitor for easy use, but the "easy use" part is not always true. For example, on an AGP G4 used in this series, the author has never successfully invoked the OF user interface from a cold boot or after booting into MacOS 9.x. Instead, booting into OS X and then rebooting while holding down the magic keystroke will bring the output to the monitor. This may be dependent on the model and monitor combination.

User command line

Upon the user invoking the user interface, OF will bring up a prompt such as (from a PowerMac 7300):

Open Firmware, 1.0.5
To continue booting the MacOS type:
BYE<return>
To continue booting from the default boot device type:
BOOT<return>
 ok
0 > _
The output gives the version of OF and a couple quick tips to remind the user how to return to normal operation, ideally before the user has rendered the machine unbootable.

To further clarify what was entered by the user and what was returned by OF, this tutorial will adopt a formatting for display. In the above exercise, everything up to an including the

0 > _
was returned by OF. The prompt is normally a blinking underscore, which can not be displayed in static text, so a static underscore will suffice to denote where user entered keystrokes will appear. Additionally, consistent with the text returned by OF above, this tutorial will show a at the end of the user entered command. It is important to note that Forth is very particular about "whitespace," as sometimes this whitespace is actually part of the parameters to the Forth command. In the user interface, commands are executed after the return key is pressed. In the event of successful execution of a user entered command, OF will return an ok; otherwise OF will return an error indication. OF will then return to the prompt.

It should be noted that there can be variations in output with different versions of OF, but backwards or forwards extrapolation by the reader should be possible.

Disclaimer

Yes, it is possible to render an Apple computer unbootable through interaction with the firmware, so when one has decided to pull the curtain back to reveal the machine it is wise to tread lightly and with caution. Failure to do so can result in enough damage that the computer will need to be brought to an Apple authorized repair shop for replacement parts. Thankfully this level of damage is not true for all models, and some early Macs like the PowerMac 7300 can be leaned on pretty hard in ways that would render an AGP G4 an expensive environmental particulate decontaminator.

Advanced Exercises, Qualitative

The reader should obtain information on how to reset the firmware in the reader's computer.

Basic Forth operation

Forth in Open Firmware

As was discussed in the qualitative article referenced in the introduction, OF is the push that gets the wheel turning during the booting process. It does a lot of the ground work for device discovery and quite a bit of initial configuring of those devices, when possible. It does this by executing Forth-based FCode. Forth can operate as an interpreted language, a byte code compiled language, and as a front end to CPU specific opcodes (compiled executable code). It is extremely versatile, and in addition to having its own song (as mentioned in the qualititative article), it has been used to write an entire operating system (see http://www.forthos.org). One might suggest that Forth is the promise of Java realized, before Java was conceived of. The Forth Interest Group (FIG) has a web page at http://www.forth.org/ which contains several tutorials on Forth, and it is well worth the reader's time to look at these as well as other links at the site.

For a device to be considered Open Firmware compatible, it must contain ROM that contains basic driver code written in Forth that meets several criteria. Apple details the criteria in Technote 1044: http://developer.apple.com/technotes/tn/tn1044.html.

Two aspects of Forth

Two aspects fundamental to Forth are its stack based operation and the use of words, which are executable methods. In using Forth, under most circumstances arguments will be placed onto the stack before a word is called (by pushing it onto the stack as well) and return arguments will be placed on the stack at the point the arguments passed to the word began. For example, if the stack contains three values, and the word requires two of these and returns one value, there will be two values remaining on the stack after execution of the word, the one remaining value from the original three and the one returned by the word.

It is common to chain word execution together, where in the process of setting up values for one word another word will be called to prepare parameters properly. For example, many words take device path names, but not as human readable strings. Instead, they require the string to be formatted as a memory address with a length, for a total of two values. An intermediate word will be placed between the human readable string and the Forth word that needs the device path. A qualitative example would be the process of baking a cake. One usually sets up and organizes all of the ingredients, but proper preparation of the dry ingredients includes mixing them thoroughly before adding liquid ingredients. For example, one might place flour, baking powder and sugar on the stack (bowl), then mix thoroughly.

dry ingredients

The resulting mix remains on the stack and eggs and milk are added to the stack, with mixing repeated. The combined batter can then be put into a pan for baking. Obviously just adding the ingredients together into the pan will not yield an edible cake.

image of delicious chocolate cake

There is a logical flow to passing arguments to a stack. Consider the phrase "two aspects of Forth." "Two" is placed on the stack before calling the noun "aspect." The resulting concept is followed by the connecting adverb "of" and then "Forth" is called. Linguistically Forth is no different from Germanic and Romantic languages, but for those used to C and Pascal style argument passing (or the grammar of Mandarin Chinese), it might take a moment or two to feel comfortable.

Global words

What follows is an oversimplification, at the risk of omitting some details in order to convey the concepts to beginners.

There are two types of words, global and local. Global words come with the version of Open Firmware present on the computer. Some of these are placeholders that get overwritten by device specific local words. Local words are restricted in scope to the device that contains the word. The available global and local commands can be listed with the command words:

0 > words<return>
boot-command    nvramrc         oem-logo        oem-banner      output-device  
input-device
diag-file       diag-device     boot-file       boot-device     selftest-#megs 
screen-#rows
screen-#columns pci-probe-list  load-base       virt-size       virt-base      
real-size
real-base       use-nvramrc?    oem-logo?       oem-banner?     fcode-debug?   
diag-switch?
auto-boot?      real-mode?      little-endian?  make-cpu-properties            
nvunalias
$nvunalias      nvalias         $nvalias        nvrecover       nvrun          
nvstore
nvquit          nvedit          set-defaults    set-default     nodefault-bytes
setenv
$setenv         printenv        nv-free         assign-addresses               
make-properties
probe-pci       probing-pci?    eject           dir             boot            $boot
reload          load            go              init-program    loadmapsize    
loadsize
loadaddr        +dis            dis             (dis1           dis1           
dis_ptr
see             (see)           release-virt    claim-virt      release-real   
claim-real
release-mem     claim-mem       (is-user-word)  is-remove       is-install     
fb8-install
io              output          input           $open-package   find-package   
end-package
begin-package   unselect-dev    select-dev      devalias        show-devs       dev
find-device     interpose       open-dev        apply           execute-device-method
ihandle>phandle pop-package     push-package    close-dev       close-package  
open-package
mac-address     free-virtual    dump-device-tree                .properties     ls
pwd             finish-device   new-device      set-args        peer            child
More [<space>,<cr>,q] ? q<return>
ok
0 > _

There are over one hundred global words contained in OF 1.0.5, and each successive version of OF contained more.

Local words

As mentioned earlier, for a device to be properly attached to the Open Firmware tree, the device must contain built in FCode for initialization. Some or all of that will be made public. An example of device specific words would be those contained in the video controller chip, which contains both video in and and video out, from a 7300:

0 > words<return>
encode-unit     decode-unit     dma-sync        dma-map-out     dma-map-in     
dma-free
dma-alloc       map-out         map-in          close           open           
probe-slots
req-io-addr     alloc-io-addr   align-io-addr   req-mem-addr    alloc-mem-addr 
align-mem-addr
map-range       add-range       make-assigned-addresses         allocate-addresses
add-package     init-packages   config-l!       config-l@       config-w!      
config-w@
config-b!       config-b@
ok
0 > _

The video out has a completely different set of local words:

0 > words<return>
close           restore         draw-logo       write           open           
read-rectangle
fill-rectangle  draw-rectangle  get-colors      set-colors      color!         
color@
control#
ok
0 > _

Navigation within Open Firmware to the above devices has been omitted but will be discussed in the next tutorial.

"see"ing words

When a word has a user visible name, it can be viewed with the see command. The see command requires arguments after the command, instead of before, one of the few that do require this. With the open word the video out device above, one "sees" how compact Forth words can be (with a de rigueur bad pun, no less).

0 > see open<return>
: open
  -7BF628 ^-7E0950
  ; ok
0 > _

The : begins the definition of open, there are two objects to evaluate, denoted by - and ^-, and the ; closes the definition. When the open word is executed, the ; causes the execution to occur. This is different than the user interface, where the key causes the Forth code to be executed.

Completeness thereom

In case the reader is wondering - yes, see is itself a word:

0 > see see<return>
: see
  ' (see)
  ; ok
0 > _

(see)

If there is no user visible name, the value given is most often a memory location, displayed as either a signed or unsigned long integer. The FCode can often still be viewed with a slightly different version of see, as inferred in the tangent, by using (see). In order to look at -7BF628 contained in the open word, provide the address on the stack and call (see):

0 > -7BF628 (see)<return>
: ^-7BF628
  ^-7F0478  get-my-property if
    "no REG property" type abort
    then
  begin
    dup 0> while/if
      decode-int ^-7F3860  and >r decode-int drop decode-int >r 8 - swap
      8 + swap r> r> case
        14 of
          to ^-7C0068
          endof
        18 of
          800000 + to ^-7C0050
          endof
        swap drop
        endcase
      repeat
    2drop ^-7C0070  dup ^-7F0BE0  _i_g do-map ^-7BF770  ^-7BFBC8  dup ^-7BFC28
    ! ^-7BFC50
    begin
      2dup @ <> while/if
        8 +
        repeat
      nip cell+ @ ^-7BF720  ^-7BF9C0  ^-7BF740  ^-7C0058  dup ^-7C0040  ^-7C0028
      * ^-7F0CB8  do-map default-font set-font ^-7C0040  ^-7C0028  over 14
      - char-width / over 14 - char-height / fb8-install ^-7C0040  #columns
      char-width * - 2/ to window-left ^-7C0028  #lines char-height * - 2/
      to window-top ^-7C0058  to frame-buffer-adr
      ; ok
0 > _

Obviously, driver FCode can get somewhat complex. However, as this tutorial is focused on learning enough OF to handle basic debugging and not in writing driver FCode, there is no need to examine this rigorously at this time. It should be noted that (see) required the argument to be placed onto the stack before the (see) word.

Forth math and showstack

Readers familiar with Hewlitt-Packard calculators may recognize Forth's approach to math:

0 > 2 2 +  ok
1 > _

The two parameters were placed onto the stack before the addition command. Note the difference in the prompt returned by OF. It is indicating that one value remains on the stack. Logically, this is the result of the addition. Due to the nature of Forth, values stay resident on the stack until removed. Additionally, manipulating values on the stack does not remove the other ones already resident. Those values just move their relative location in the stack calling chain (down if more are added, up if values above are removed). Additionally, the completion of a Forth word will not remove values on the stack except as documented in the Forth language specification for that word. If there are four values on the stack before calling a word that requires three arguments to be passed to it, and the word is expected to return a single value, there will be two values on the stack upon completion of the word (assuming there was not an error, which will always clear the stack). This is an important aspect to Forth that will be built upon repeatedly in the future. In the user command line interface, there are two ways to give feedback to the user. The first is to state how many values were returned, as above. The other is to show the values returned. To enter this mode, use the word showstack.

1 > showstack<return>  ok
4
_

The change in mode has altered the output from OF, as there is no more ">" before the prompt and the value on the stack is visible. Consistent with how OF will display the output, this article will use "_" to denote the prompt, and this is the location at which entered text will appear after being typed. In an attempt to clarify the flow of steps, for the remainder of this tutorial, the line before the prompt from the previous snippet will be shown at the beginning of each snippet, and the text entered will appear on the line below the "_" prompt, although in OF the text will appear at the prompt.

stack manipulation

Values on the stack can be manipulated:

4
_
2 +<return>  ok
6
_

Values on the stack can be chained:

6
_
2 2 + 2 + 2 + 4  ok
6 8 4
_

There are now three values on the stack. The left value is from the previous operation. The middle value is the result of the three addition instructions (adding four twos together). The right value is the result of placing a four on the stack without a subsequent operation.

image of Forth math

To remove values from the stack, use the drop word (and its siblings 2drop and 3drop, no relation to dewdrop)

6 8 4
_
3drop ok
Empty
_

Subtraction, multiplication, and division follow similar rules, and use -, *, and /, respectively.

Division and converting number bases

The default mode of displaying number is hexidecimal. Changing between bases uses decimal and hex. A calculation of how many megabytes the hexidecimal value 0x8000000 is might look like:

Empty
_
8000000 100000 /<return>  ok
80
decimal<return>  ok
128
_

0x100000 is the hexidecimal equivalent to 1M, so the above snippet put the 8000000 value on the stack, put 1M on the stack, and then told OF to divide with the / character. The resulting value 0x80 converts to 128, so 0x8000000 is 128M. Who needs a calculator when one can use the firmware?

To check for adherence to order of operations:

128
_
drop 100000 8000000 /<return>  ok
0
_

The number 0 is not the same as an empty stack, but 0 is the same in both hex and decimal. An example of converting from decimal to hex could be CPU MHz speeds:

0
_
drop 200000000 hex  ok
BEBC200

Forth syntax in documentation

Documentation of the Forth language, and by extension the commands available within Open Firmware, uses a specific syntax to denote how the word should be used. If the word is expecting arguments to be placed on the stack before being called, the documentation will have the syntax

(arg1 arg2 -- return1 return2)
where the number of arguments and results will be dependent on the word. arg1 must be placed on the stack before arg2. return1 will be below return2 on the stack, and the stack location will be after return2. The -- construct denotes the demarcation between before execution and after execution. To the left of -- is before execution; to the right is after execution.

For example, the syntax on + is

(nu1 nu2 -- sum)

Two values are placed on the stack and after execution their sum is on the stack.

Order of operation is preserved by the location of the parameter on the stack. For example, the syntax on - is:

(nu1 nu2 -- diff)

Diff is nu2 subtracted from nu1.

3 - 2 = 1

Words that require input to follow the word on the stack have the syntax

([arg1< >arg2< >] -- result1 result2)

where the < > construct indicates white space demarcation between arguments. For example, the syntax on d#, which is used to treat the following number as a decimal, is:

([number< >] -- n)

d# is useful when having to do calculations that mix decimal and hexidecimal bases. There are tutorials at the Forth SIG web site linked earlier that go more into details on the use of Forth.

Two dupes walk into a Forth bar...

2 dupes walk into a bar

Introduction to string manipulation

Examination of some string manipulation routines is important because it provides one example of how Open Firmware handles memory (but is by no means comprehensive). To create a string for use with Forth routines, the string must be "encoded." The easiest way to do this in the user interface is with the "(space) word. The (space) construct denotes the space character. This also reiterates how precise Forth is with white space. For example:

BEBC200
_
"testing"<return> "testing", unknown word
 ok
Empty
_
" testing"<return>
-7F1710 7
_

The first approach, which resulted in the unknown word error (and empty stack), failed because it did not include the space character. The second approach did include the space character, and a (signed virtual) memory address and the size of the string were returned on the stack. To examine the string in raw memory, use the dump word, which has a syntax of address size (two values) and so the encoded string returned from " can be passed to dump as the bottom parameter on the stack is the address -7F1710 and the top parameter is how many characters:

-7F1710 7
_
dump<return>
FF80E8F0: 74 65 73 74 69 6E 67 ok
Empty
_

The above output is from OF 1.0.5. Readers following along with more recent versions of OF will already know the values in memory are ASCII, as the output from more recent firmware sometimes/often includes the actual text. In cases where the ASCII is not automatically displayed, the string can be retrieved using the type word:

Empty
_
-7F1710 7 type<return> testing ok
Empty
_

Displaying C-style strings

It may occasionally be necessary to examine C-strings in memory. This requires decoding them in a different manner, but here again the " word will be used. To set up the string so that it gets loaded into memory and then displayed with type, use the second form of " which has the syntax

" "(ASCII)"

As an example, here is a C-string in OF associated with the keyboard device (cut and pasted into the prompt):

Empty
_
" "(2F62616E 6469742F 67632F76 69612D63 7564612F 6164622F 6B657962 6F617264 00)"
type /bandit/gc/via-cuda/adb/keyboard
Empty
_

" ignored the white space breaks, and formatted the C-string in a manner that type could use to display the string, transparently.

Advanced Exercises, Quantitative

How does 3drop work?

It is often useful to display opcodes around an instruction at a known offset from the start of a file. If dis displays PowerPC instructions starting from an address passed to it, the executable file starts in memory at 0x600000, and the target instruction offset is 0x200, formulate a Forth chain that will display the four instructions before the target address.

Answers will be provided in the next tutorial.

Configuration Variables

printenv

The first place to poke around in Open Firmware itself is the configuration variables. Apple very briefly discusses configuration variables in a Hardware Note at http://developer.apple.com/qa/hw/hw38.html. The PowerPC Processor Binding for 1275-1994 discussed at the beginning of this tutorial has some information about a few of the variables.

For simplicity, this part of the discussion will use OF 1.0.5, but this aspect does not change much with other versions. At the prompt, type

Empty
_
printenv<return>

little-endian?      false               false
real-mode?          false               false
auto-boot?          true                true
diag-switch?        false               false
fcode-debug?        false               false
oem-banner?         false               false
oem-logo?           false               false
use-nvramrc?        false               false
real-base           -1                  -1
real-size           100000              100000
virt-base           -1                  -1
virt-size           100000              100000
load-base           600000              4000
pci-probe-list      -1                  -1
screen-#columns     64                  64
screen-#rows        28                  28
selftest-#megs      0                   0
boot-device         /AAPL,ROM           /AAPL,ROM
boot-file
diag-device         fd:diags            fd:diags
diag-file
input-device        ttya                ttya
output-device       ttya                ttya
oem-banner
oem-logo
nvramrc
boot-command        boot                boot
 ok
Empty
_

The three columns indicate the name of the configuration variable, the current value for the variable, and the default value for the configuration variable. Some default values can be reset by resetting the PRAM, in the event the computer has been rendered unable to enter the OF prompt, but some values require further efforts, as mentioned earlier. For future reference, in the event the computer is still in the OF user interface, the default values can be restored through the use of the command "set-defaults." Unsubstantiated rumor has it that the author did recover from having (rather ineptly) rendered his AGP G4 unbootable by following instructions found on an unnamed mailing list that said to hold down the recessed firmware button on the front panel upon booting until an extended tone is heard, but this is just a rumor and the author will deny having confirmed this.

setenv

Of the configuration variables, three are of interest at this moment: auto-boot?, output-device, and input-device. To set a configuration variable, the syntax is straightforward, as noted in Apple's Hardware Note 40 at http://developer.apple.com/qa/hw/hw40.html:

setenv (variable name) (value)<return>

For this tutorial, there are only three configuration variables of interest: auto-boot?, input-device, and output-device. Several of the other variables will be examined in later tutorials.

auto-boot?

This variable tells OF whether to invoke the user interface prior to booting an operating system. While doing testing and exploration, this value should be false, so that each time the computer is booted OF invokes the user interface, rather than relying on the user to hold down the correct keys. auto-boot? to false, as had already been done in the readout above:

Empty
_
setenv auto-boot? false<return> ok
Empty
_
printenv<return>

little-endian?      false               false
real-mode?          false               false
auto-boot?          false                true
diag-switch?        false               false
fcode-debug?        false               false
oem-banner?         false               false
oem-logo?           false               false
use-nvramrc?        false               false
real-base           -1                  -1
real-size           100000              100000
virt-base           -1                  -1
virt-size           100000              100000
load-base           600000              4000
pci-probe-list      -1                  -1
screen-#columns     64                  64
screen-#rows        28                  28
selftest-#megs      0                   0
boot-device         /AAPL,ROM           /AAPL,ROM
boot-file
diag-device         fd:diags            fd:diags
diag-file
input-device        ttya                ttya
output-device       ttya                ttya
oem-banner
oem-logo
nvramrc
boot-command        boot                boot
 ok
Empty
_

The command reset-all will store the new value and reboot, with the new value. The use of the new value can occur without rebooting, unless the value is critical to getting to the firmware itself.

input-device/output-device

The next two values of interest, input-device and output-device, tell OF where to expect user input to come from and where to send output to. The default ttya, which is the modem port, remain for both. Consider the implication: all pre-OS X versions of the MacOS are Graphical User Interface-only operating systems, and have no output on the modem port for user interaction. The importance here is that there are times that a layer between the operating system and the hardware is extremely useful for debugging both. In order to communicate with the layer, there has to be some mechanism that can be invoked and that mechanism has requirements in order to be used as either an input device or an output device. Not all video devices can be used as an output device for Open Firmware. Some OF equipped systems, like the IBM JS20 models available at the time of this writing, have no video subsystem at all. The only option is a serial connection.

Another aspect to the user interface is session capture. When debugging aspects of the operating system or bootstrapping process on a new hardware platform, it is imperative to have the ability to log the results, whether successful or not, in getting to the next step in the booting process. A pure video out/keyboard in arrangement does not offer this.

With the introduction of the "New World" models, serial ports became deprecated. However, those same models have the ability to do remote sessions, via telnet. A good tutorial on how to do this is at http://developer.apple.com/technotes/tn/tn2004.html. This is useful for session capture, but not necessary for basic debugging and exploration. There is also a part II to the note, at http://developer.apple.com/technotes/tn/tn2023.html.

Normally one might expect a discussion of what appropriate input and output devices would be, but instead there is a very good discussion of this at http://www.netbsd.org/Ports/macppc/faq.html

If the reader was only interested in setting these values for the purpose of using an operating system such as NetBSD on an already supported model, further discussion would be redundant. However, this series is concerned with the process of porting an operating system to a new platform, so there are different questions that need to be asked and answered. In the next tutorial, which focuses on hardware, some details of the requirements of input and output devices will be discussed, in addition to navigation through the device tree to find those devices.

Completeness thereom

Empty
_
see setenv<return>
: setenv
  bl word count ^-7DA580  pack drop carret word count ^-7DA550  pack drop
  ^-7DA550  count ^-7DA580  count $setenv
  ; ok
Empty
_

Epilogue

In conclusion

This tutorial covered some of the fundamentals of debugging with Open Firmware, using the proverbial "learning to crawl before walking" method. In the context of porting an operating system to new hardware, the first step is learning about the firmware present. This involves not just learning the standard, but also how to apply the standard. It goes beyond this, of course, because it is not just a matter of learning the specifics of one port, but learning how to port.

The math examples provided are obviously so rudimentary as to be useless, but the idea of using a known numerical reference to locate other information is absolutely essential. The observation that open and setenv are just Forth words isn't really useful. Grasping that it is possible to look at what the firmware is doing and reproduce that behavior to overcome obstacles is absolutely essential. Learning how to learn is absolutely essential.

This is Part I of a four part section of the series. The Part II looks at hardware from Open Firmware's perspective, discuss the answers to the quantitative Advanced Exercises, and of course, discuss errata contained in this piece that will undoubtably get pointed out after publication.

About the author

Gregory T. (tim) Kelly has read the Open Firmware Bindings repeatedly without comprehension and questions daily his grasp of the English language. He can be reached at gtkelly at this domain (dialectronics.com).

Resources, organized by topic

Open Firmware specification:

http://developer.apple.com/qa/hw/hw85.html - Obtaining the IEEE 1275-1994 Standard

http://playground.sun.com/1275/ - Open Firmware Working Group homepage

http://www-106.ibm.com/developerworks/library/pa-spec2.html - Peter Seebach's qualitative primer on Open Firmware

http://bananajr6000.apple.com/OF/technotes.html - incomplete compilation of Open Firmware Technotes from Apple (possibly gone offline)

http://developer.apple.com/technicalnotes/Hardware/idxOpenFirmware-date.html - the Technotes not found at the above

Bindings:

http://playground.sun.com/1275/bindings - IEEE 1275-1994 hardware requirements

http://playground.sun.com/1275/bindings/ppc/release/ppc-2_1.html - PowerPC CPU Binding

http://playground.sun.com/1275/bindings/pci/pci2_1.pdf - PCI Binding

Forth:

http://www.forth.org/ - Forth Special Interest Group (SIG)

http://www.forthos.org/ - an operating system written in Forth

http://developer.apple.com/devicedrivers/pci/downloads/Forth_PP.hqx - Apple's presentation of basic Forth operations

http://docs.sun.com/app/docs/doc/801-7050 - Writing FCode for Open Boot

http://developer.apple.com/technotes/tn/tn1061.html - User Interface Fundamentals, Part I Technote from Apple

Open Firmware configuration variables:

http://developer.apple.com/qa/hw/hw38.html

http://developer.apple.com/qa/hw/hw40.html

http://www.netbsd.org/Ports/macppc/faq.html#ofw