Contents
Q: What is OpenBoot?
When you turn on a Sun workstation, the firmware in the boot PROM (programmable read-only memory) is executed immediately. The main function of a boot PROM is to load a standalone program to the core memory and start its execution. Standalone programs can be operating systems, diagnostic software, and others. The firmware in Sun's boot PROM is called OpenBoot. Other than initial program loading and invocation, OpenBoot provides debugging features to assist kernel debugging and board bring-up.
Q: What is the main advantage of OpenBoot?
Sun offers many different machine architectures (e.g., sun4d, sun4m, etc.) and boot devices (e.g., different types of disks). Instead of having different versions of the boot PROM firmware to support all combinations, OpenBoot supports plug-in device drivers. The drivers are written in a dialect of the interpreted language Forth (OpenBoot implements a Forth interpreter). The code for the driver may reside on the device PROM itself or in empty space on the system board PROM. This plug-in feature allows Sun or any third-party vendors to develop new boot devices but without recompiling or relinking the boot PROM.
Another nice thing about OpenBoot is that it behaves the same across platforms. The newer revisions provide new commands, but generally OpenBoot is stable. Sun hasn't released a major revision in more than a year.
Q: Why do application developers need to care about OpenBoot?
When the network connected to your workstation is down, and you have nothing else to do, you can always go to OpenBoot to write a Forth program to entertain yourself for a few hours. Besides that, there are many practical things you can do with OpenBoot, such as security and device diagnostics.
Q: How do I access OpenBoot?
Pressing the keys L1 and A at the same time will bring you to the OpenBoot system. You will see the display
Type b (boot), c (continued), or n (new command mode)
>
You are now interacting with the restricted monitor that allows you to do three things. Typing b
boots a standalone program (most likely the operating system). Typing c
resumes the execution of a halted program. Typing n
gets you to the Forth monitor, and the prompt will change to ok
. Most of the Forth language syntax is accepted at the Forth monitor, a.k.a., the ok
prompt.
ok
Now you are ready and able to do many interesting things. To continue executing (e.g., return to the OS), type
ok go
Q: What is Forth doing in OpenBoot?
OpenBoot contains a command interpreter (something like the shell).Instead of providing a new command language syntax, it incorporates a dialect of the programming language Forth. Forth is a popular language used in many embedded systems. Because the language is simple and its interpreter small, Forth systems take up very little space. They fit perfectly into PROM.
Q: What does a Forth program look like?
Forth programming is interactive, much like BASIC programming. You see the result immediately. Forth commands are also called words. In addition to accepting arguments, Forth words rely heavily on values in the Forth stack, which is a last-in, first-out (LIFO) buffer for temporarily holding information. The word showstack
shows the current content of the stack. Forth uses postfix notation rather than infix. For example, in Forth, you write "3 4 +" instead of "3 + 4".
You can define your own Forth word. The syntax is weird. A colon starts the definition, and semicolon ends it. (There is a space between the colon and the name of the word.)
In the following example, we define a new Forth word double
, which doubles the value of the top stack item.
dup
and +
are built-in Forth words. dup
duplicates the top stack item. +
adds the topmost two stack items and pushes the result on top of the stack. The built-in command . (yes, it's a period) pops the top stack item and displays it. You can see the source code of any Forth word by the command see
.
ok : double dup + . ;
ok 4 double
8
ok see double
: double dup + . ;
Q: How do I change the OpenBoot settings?
There are OpenBoot configuration parameters that you can set. They are stored in the non-volatile RAM (NVRAM) that keeps the values of the parameters even after a power cycle. To display all current values, type
ok printenv
To display just the current value of a named parameter, type
ok printenv parameter
where parameter is the name of the object you want to see.
To set the named parameter to the given value, type
ok setenv parameter value
To reset all parameters or the named parameter to the factory default, type
ok set-defaults
or
ok set-default parameter
to reset just one specific parameter.
Some of the valid parameters are boot-device, boot-file, screen-#columns, screen-#rows, and security-mode.
Q: How do I stop people from rebooting my workstation?
OpenBoot can provide security on reboot. Security parameters control what actions users can perform in OpenBoot. Remember, users interact with OpenBoot through either the restricted monitor or the Forth Monitor. Security parameter security-mode
places restrictions on how the boot process works. The default value of security-mode is none
; therefore, anybody can reboot the machine.
With security-mode
set to command
, a password is required to boot with parameters (the b
command), or execute the n
command in the restricted monitor. This prevents illegal users executing illegal programs. For example,
>b stand_alone_program_virus
PROM Password:
>n
PROM Password:
For the examples above, a password is required for both the command b
and n
, and is not echoed as it is typed.
Note: A password is not required to reboot with default parameters. If you set security-mode
to full
, then a password is required to perform any kind of reboot. For example,
>b
PROM Password:
You can set the password with the command password
in the Forth monitor. For example,
ok password
New Password (only first 8 chars are used);
Retype new password:
You can reset security back to none
by issuing the command setenv security-mode none
.
One thing you have to remember -- if you enable the password and forget it, you will have to call Sun's support to remove the password and make your machine bootable again.
Q: How do I change the Power-on Banner?
First, you can display the system banner by executing the command banner
. It displays Sun's power-on logo and message. To let the OEM partners have a little bit of freedom, Sun (or OpenBoot) lets you set your own power-on logo and message. For example, type
ok setenv oem-banner power-on-message
ok setenv oem-banner? True
This will set your own power-on message. To set the power-on logo, you do the same thing with the parameters oem-logo
and oem-logo?
. However it is a little bit more complicated to set oem-logo
, since a logo is a bit-mapped icon. It is better to do this with OS utility eeprom
. eeprom
can be used to access OpenBoot settings. First, at the OS level, run iconedit
to create the power-on icon, then use eeprom
to convert the icon to the internal format oem-logo
uses.
Q: How do I boot a different kernel?
At the Forth monitor, the command to boot a standalone program (e.g., OS kernel) is :
ok boot [boot-device] [stand-alone-program] [flag(s)-for-the-stand-alone-program]
If you execute boot
without any arguments, defaults are used. The defaults are stored in the configuration parameters boot-device
and boot-file
. To display their contents, type
ok printenv boot-device
boot-device disk0 disk
ok printenv bootfile
boot-file
In the above example, current and default values of boot-device
are disk0
and disk
. And the values of boot-file
are empty strings. disk0
and disk
are device aliases. To see the real device, type
ok devalias disk0
disk0 /sbus/esp@0,800000/sd@3,0
As you can see from the output, disk0
is a SCSI disk sd
. An empty string in boot-file
means to let the secondary booter choose the default, usually kernel/unix
.
The commands devalias
and printenv
with no argument list all the device aliases and NVRAMRC configuration parameters in the OpenBoot firmware, respectively.
Q: What exactly happens during the boot process?
A lot. First, at the Forth monitor, the command boot
locates the boot device. boot
loads the fixed-size block bootblock
from a fixed location in the boot device.
Second, bootblock
loads the secondary booter from the device. The location of the secondary booter is recorded in the bootblock
. bootblock
is prepared by the Solaris utility installboot
. If the boot device is a UFS file system, the secondary booter is ufsboot
.
Third, the secondary booter locates and loads the standalone program. If the name of the standalone program was not specified in boot
, ufsboot
loads its default kernel/unix
.
At last the standalone program is executed.
A different secondary booter is needed for each different type of file system installed in the boot device. This is because the secondary booter needs to understand the protocol of that particular file system in order to locate and load the standalone program. For example, if you specify the standalone program as /home/mary/test/version10/kernel/unix
, the secondary booter has to be able to locate the file from the file system in the boot device.
Q: Can I boot from any device?
Officially, Sun only supports booting from a hard disk, CD-ROM, floppy disk, and Ethernet. A floppy disk typically does not have the capacity to boot a kernel, given their usual size. However you can use it to boot other standalone programs (assuming that they would fit in a single floppy disk).
When booting from the network, OpenBoot broadcasts a reverse ARP request to the network, and a boot server will reply. Then OpenBoot establishes a TFTP connection to the boot server to retrieve the secondary booter inetboot
. inetboot
uses the bootparams protocol to obtain the root file system, and then it uses the NFS protocol to fetch the kernel over the Ethernet. The boot server needs to set up its boot parameter database properly in order for this boot process to work.
Q: What are the option parameters available in booting Solaris kernels?
A Solaris kernel takes a few standard flags at the Forth monitor. They are
ok boot kernel/unix [-a | -r | -s | -v ]
-a
asks you interactively for configuration information. You use this flag if you want to specify a different system configuration file (not /etc/system), a different root file system, a different search path for dynamic load modules (DLMs), etc.
-r
reconfigures your device tree at both /dev and /devices. You would boot the kernel with this flag on after you add a new device to the system. The system probes all attached hardware devices and rebuilds the device tree from scratch. -s
boots the kernel to the single-user mode. Many times when you fail to complete a full kernel boot, you would prefer to at least boot to the single-user mode and then perform troubleshooting there.
-v
turns on the verbose mode. This means system boot messages are not just going to the system log file (usually /var/adm/messages
) but also simultaneously to the console display.
Q: What other standalone programs are available for OpenBoot?
Ninety-nine percent of the time, the standalone program is the Solaris kernel. The rest of the time you probably run the kernel debugger kadb
and some hardware diagnostic tools from the hardware vendors.
kadb
is based on the debugger adb
and includes many pre-defined macros which understand kernel data structures. Sorry, you cannot define your own macros. They are compiled together with kadb
. The syntax to run kadb
is
ok boot [boot-device] kadb [-d] [kernel-flags]
With -d
, kadb
prompts you for the kernel you want to debug; otherwise the default kernel/unix
is used. Kernel flags are simply passed to the kernel by kadb
.
Q: What is a device tree?
Sun hardware uses the concept of the device tree to organize devices attached to the system. To see the entire device tree, use show-devs
.
ok show-devs
/io-unit@f,e1200000
/io-unit@f,e0200000
/mem-unit@f,e1100000
/mem-unit@f,e0100000
/cpu-unit@f,e1800000
/cpu-unit@f,e1000000
/cpu-unit@f,e0800000
/cpu-unit@f,e0000000
/boards
/openprom
/virtual-memory@0,0
/memory@0,0
/aliases
/options
/packages
/io-unit@f,e1200000/sbi@0,0
/io-unit@f,e1200000/sbi@0,0/SBUSDKHS@3,2000
/io-unit@f,e1200000/sbi@0,0/lebuffer@0,40000
/io-unit@f,e1200000/sbi@0,0/dma@0,81000
/io-unit@f,e1200000/sbi@0,0/lebuffer@0,40000/le@0,60000
/io-unit@f,e1200000/sbi@0,0/dma@0,81000/esp@0,80000
Each entry of the output represents a device. At the Solaris OS level, you can see the same tree under /devices
. In addition, the Forth Monitor provides Unix-like commands to manipulate the
devices. For example,
ok cd /io-unit@f,e0200000/sbi@0.0
The command cd
makes the device /io-unit@f,e0200000/sbi@0.0 the current node.
ok ls
ffda2b3c qec@3,20000
ffda093c lebuffer@1,40000
ffd9baec dma@1,81000
ffd998ec lebuffer@0,40000
ffd946c4 dma@0,81000
The command ls
lists the nodes under the current nodes. The second column of the output lists the names of the nodes. The first column lists the physical addresses associated with the nodes.
The command pwd
displays the pathname of the current node.
ok pwd
/io-unit@f,e0200000/sbi@0,0
Q: How do I interpret a device tree?
Each node in the device tree represents a device. Nodes with children usually represent buses and their associated controllers. Their children are devices connected to the buses or controllers.
A full device path begins with a /. It is the root of the tree and represents the machine node. Each node name has the form name@address:arguments. Other than name, the rest are optional and the format is device-dependent. If the system can identify the device without ambiguity, you can ignore that portion of the device path name. I usually write the complete path.
address represents a physical address associated with the device. arguments is used to pass additional information to the device's software.
Let's look at a simple example. The root file system of my IPX system is /dev/dsk/c0t3d0s0, which is equivalent to the device node
/sbus@1,f8000000/esp@0,800000/sd@3,0:a
Let's see how we interpret the path. From sd@3,0:a
, we know the device is a SCSI disk sd
attached to the SCSI bus at target 3 and logical unit 0. The a
at the end represents the first partition of the disk. From esp@0,800000
, we know the SCSI bus is implemented as a SCSI host adapter esp
residing in the SBus slot 0 at offset 800,000. Finally from sbus@1,f8000000
, we know the SBus interface is attached to the system bus at address 1,f8000000
.
Q: How do I create device aliases?
As you can see, each device path is quite long. It would be nice to be able to make aliases for devices. OpenBoot provides the command devalias
for this purpose.
ok devalias [alias]
The command devalias
displays the current values of all device aliases (if no parameter is given) or the named alias.
ok devalias alias device-path
devalias
with two arguments defines a device alias alias to the value device-path.
Q: What can I do with a device node?
Each device node has attributes and methods associated with it. Use the Forth Monitor commands .attributes
and words
to display the values for the current node. For example,
ok cd /io-unit@f,e0200000/sbi@0,0/dma@0,81000/esp@0,80000/sd
ok .attributes
device_type block
name sd
ok words
selftest reset load write read
seek sd-selftest close open
write-blocks read-blocks dma-free dma-alloc
max-transfer block-size spin-up
The above example shows a SCSI disk sd
and it is a block
device. Methods are provided to open, close, read and write the device. The cd
command is needed to make the named device the current node. .attributes
and words
only work on the current node.
Q: How do I perform device
diagnostics?
There are a few commands that come very handy for device diagnostics.
probe-scsi-all
identifies all SCSI devices attached to the
system.
(Note: probe-scsi-all
is not supported until OpenBoot
revision 2.6. The output of the command banner will indicate
the current OpenBoot revision number for your machine.)
ok probe-scsi-all
/io-unit@f,e1200000/sbi@0,0/dma@0,81000/esp@0,80000
Target 0
Unit 0 Disk CONNER CP30548 SUN0535AEBX9308288P
Target 1
Unit 0 Disk CONNER CP30548 SUN0535AEBX93082PA7
Target 2
Unit 0 Disk CONNER CP30548 SUN0535AEBX9308280V
Target 3
Unit 0 Disk CONNER CP30548 SUN0535AEBX93082PMC
/io-unit@f,e0200000/sbi@0,0/dma@1,81000/esp@1,80000
Target 0
Unit 0 Disk SEAGATE ST42400N SUN2.1G0417705457 Copyright (c)
1992 Seagate All rights reserved
ok
probe-scsi
identifies SCSI devices attached to only the
built-in SCSI bus.
ok probe-scsi
Target 0
Unit 0 Disk SEAGATE ST31200N SUN1.05872200147810Copyright (c)
1994 Seaga
te All rights reserved 0000
Target 1
Unit 0 Disk SEAGATE ST31200N SUN1.05872200137389Copyright (c)
1994 Seaga
te All rights reserved 0000
Target 2
Unit 0 Disk SEAGATE ST31200N SUN1.05872200150421Copyright (c)
1994 Seaga
te All rights reserved 0000
Target 3
Unit 0 Disk SEAGATE ST31200N SUN1.058722001494te All rights
reserved 000078Copyright (c) 1994 Seaga
te All rights reserved 0000
Target 5
Unit 0 Removable Tape ARCHIVE Python 28454-XXX4ASB
Target 6
Unit 0 Removable Read Only device SONY CDU 561 SUNMSCD1.9k
ok
test
executes the named device's method selftest
.
In other words, if words
lists the method, selftest
,
test
will work.
ok test /io-unit@f,e0200000/sbi@0,0
No selftest method for /io-unit@f,e0200000/sbi@0,0
ok test disk
In the example, the device /io-unit@f,e0200000/sbi@0,0 does not have the method selftest
; therefore test
would not work. The device disk
has the method; therefore, test
works. If selftest
succeeds, it outputs nothing.
test-all
tests all the devices in the system.
ok test-all
Testing /memory@0,0
Testing /io-unit@f,e1200000/sbi@0,0/lebuffer@0,40000
Testing /io-unit@f,e1200000/sbi@0,0/lebuffer@0,40000/le@0,60000
Internal loopback test -- succeeded.
External loopback test -- succeeded.
Testing /io-unit@f,e1200000/sbi@0,0/dma@0,81000/esp@0,80000
Testing /io-unit@f,e0200000/sbi@0,0/qec@3,20000
Testing /io-unit@f,e0200000/sbi@0,0/lebuffer@1,40000
Testing /io-unit@f,e0200000/sbi@0,0/lebuffer@0,40000
Testing /io-unit@f,e0200000/sbi@0,0/qec@3,20000/qe@3,0
Internal loopback test -- succeeded.
Internal (including Mendec) loopback test -- succeeded.
Link state check -- failed, transceiver cable problem? or check the
hub.
Selftest failed. Return code = -1
watch-clock
tests the clock function. The system responds by incrementing a number (starting at zero) by one each second.
ok watch-clock
Watching the 'seconds' register of the real time clock chip.
It should be 'ticking' once a second.
Type any key to stop.
49
ok
watch-net
monitors the network traffic. It displays a dot (.) each time it receives a error-free packet. The external loopback test will fail if the system is not connected to Ethernet.
ok watch-net
Internal loopback test -- succeeded.
External loopback test -- succeeded.
Looking for Ethernet packets.
'.' is a good packet. 'X' is a bad packet.
Type any key to stop.
................................................................................
...................................
ok
show-bus
displays all the installed and probed SBus devices.
ok show-sbus
Board# 0 SBus slot 0 lebuffer le dma esp
Board# 0 SBus slot 1 lebuffer le dma esp
Board# 0 SBus slot 2
Board# 0 SBus slot 3 qec qe qe qe qe
Board# 1 SBus slot 0 lebuffer le dma esp
Board# 1 SBus slot 1
Board# 1 SBus slot 2
Board# 1 SBus slot 3 SBUSDKHS
ok
Q: How do I make permanent changes in OpenBoot settings?
A portion of the NVRAM called NVRAMRC is reserved for storing user-defined commands and device aliases. User-defined commands are written in Forth. You can look at it as those Unix rc files in which commands are executed during start-up. Those commands are stored in ASCII text format. Almost all Forth monitor commands can be used. Exceptions are banner, boot, go, nvedit, password, reset,
and setenv security-mode
. Some useful commands to operate NVRAMRC are:
ok nvalias alias device-path
The effect of nvalias
is to store the command "devalias
alias device-path" in the NVRAMRC. Or you can use the NVRAMRC editor nvedit
to directly edit the NVRAMRC buffer. nvedit
has its own editing commands, a little bit like Emacs, e.g., CTRL-P to move forward one character and CTRL-B to move backward. nvedit
only operates on a temporary buffer. To make permanent changes to NVRAMRC, execute the command nvstore after you quit nvedit
. To test the changes in the buffer, try nvrun
, which executes the contents of the temporary buffer. Also
ok nvunalias alias
deletes the named alias from NVRAMRC.
Q: How do I do program debugging with
OpenBoot?
OpenBoot provides register-display commands, breakpoint commands, a disassembler, and symbolic debugging ability. However they are intended for assisting device bring-up's. They are not general-purpose facilities for the general public. For OS- and applications-level debugging, kadb
is the preferred choice.
OpenBoot debugging commands normally display addresses in hexadecimal. However, if you load the standalone program through the command dload
(which is another way to perform program loading in OpenBoot), OpenBoot will keep the symbol table information, and memory addresses are displayed symbolically whenever possible. The OS is usually not loaded with dload
but through some intermediate booter (like the ufsboot
used withboot
); therefore symbol information included in the kernel's a.out file is not available to the OpenBoot debugging facility. It is really not much use for the average users if the symbol information is
not available.
Here are some useful commands if you have to debug at the OpenBoot level (for example, if kadb
was not started at the boot time, and the system crashes):
.fregisters
displays values in registers %f0
through %f31
.
ok .fregisters
0 1 2 3 4 5 6
7
+0: 0 0 ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff
+8: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff
+16: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff
+24: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff
fsr: 0 fq:address: 0 fq:instruction: 81a00000
.registers
displays values in registers %g0
through %g7
, plus %pc
, %npc
, %psr
, %y
, %wim
, %tbr
.
ok .registers
%g0 %g1 %g2 %g3 %g4 %g5 %g6 %g7
0 e00511f0 e3781ec0 e0069fb8 570 0 1 e3781ec0
PC nPC Y PSR WIM TBR
ffd72210 ffd72214 0 40400ce6 10 e0040050
.locals
displays the values in %i
, %L
, and %o
registers. In SPARC terminology, %i
, %L
, and %o
are input, local and output registers respectively.
ok .locals
0 1 2 3 4 5 6 7
IN: 2 ffd418a0 e e01a54e2 0 1 e379fdb0
e006ca04
LOC: 40800cc6 f0 e006c518 40 0 e0069fb8 7
ffffffc0
OUT: e0040050 ffeff000 0 1f00506 0 f00 e379fd50
ffd418ac
%f0
and etc. return the value of the individual register respectively. The value is pushed onto the Forth monitor stack. The command . is used to pop the value off the stack and display it.
ok %g1 .
e00511f0
ok %pc .
ffd72210
w
sets the current active window for displaying %i
, %L
, and %o
registers. By changing the current register window, you can examine different set of local registers. SPARC has the concept of register sliding windows. Each window has its own set of local resisters for faster context switch. 1 w .locals
advances one window and executes .locals
.
ok 1 w .locals
IN: 2e0000 6e 2e0000 4 1 6e e379fe10
e004c878
LOC: 60 e00e48a0 f 10 1 e01b88c8 1
e01c4f10
OUT: 2 ffd418a0 e e01a54e2 0 1 e379fdb0
e006ca04
ctrace
displays the return stack showing C functions.
ok ctrace
PC: ffd72210
Last leaf: call ffd721ec from ffd418ac
0 w %o0-%o5: ( e0040050 ffeff000 0 1f00506 0 f00 )
jmpl ffd418a0 from e006ca04
1 w %o0-%o5: ( 2 ffd418a0 e01b8800 f c 1 )
call e006c9a4 from e004c878
2 w %o0-%o5: ( 2e0000 63 2e0000 e01b88dc c 63 )
call e004c764 from e004c748
3 w %o0-%o5: ( 0 740000 74 0 e01c497c e01c497c )
ok
dis
starts disassembling at the given address. +dis
continues disassembling where the last disassembly left off. In the following example, it starts the disassembling at the current program counter. The command %pc
places the current value of the program counter on the Forth monitor stack. dis
pops the value off the top of the stack and takes it as the argument.
ok %pc
ok dis
ffd72210 ta %g0, 7f
ffd72214 wrtbr %o0, 0
ffd72218 sethi 0, %g0
ffd7221c sethi 0, %g0
ffd72220 sethi 0, %g0
ffd72224 jmp %o7, 8, %g0
ffd72228 sethi 0, %g0
ok +dis
ffd7222c call ffd48ecc
ffd72230 sub %g7, 4, %g7
ok
Q: At OpenBoot, can I mount file systems and access files?
No, in practice you cannot. OpenBoot understands neither Solaris file systems nor files. It is a very primitive system that mainly deals with hardware devices and not high-level objects like file systems and files.
But yes, theoretically, you can. You can write a Forth program to interface with the methods of a device like a hard disk. For example a hard disk device would have the methods to read and write disk blocks. You can then map the file system related data structures to the disk blocks and locate the individual files. The whole process is definitely not trivial.
Q: How do I reset reboot the system?
ok reset
The command reset
resets the complete system and is similar to a power cycle. It initializes the memory to zeros. If auto-boot?
is set to true
, the system will also re-boot. Alternately you can use the command sync
to reboot the system. sync
synchronizes all the mounted file systems and flushes out all the dirty pages to the disks before the reboot.
ok sync
The command sync
returns to the OS which then synchronizes (sync
) all the mounted file systems, and saves a core image of the kernel. You can hit L1-A to stop the core dump. Sync always reboots the machine automatically at the end.
Q: Where can I find more literature on OpenBoot and related topics?
At the Forth Monitor, you can type help
to get more information. In addition each command is a Forth word, and you can type see
command to view the Forth source code for a particular command.
There are also manual pages. Try man pages: monitor(1M), boot(1M), eeprom(1M), kernel(1M), kadb(1M), iconedit(1), system(4), installboot(1M).
There are reference manuals and users' guides too. Try Writing FCode Programs, by Sun Microsystems, published by SunSoft Press, 1994, ISBN 0-13-107236-6. Details and ordering info on this book are available at
http://www.sun.com/smi/ssoftpress/books/WritingFCode/WritingFCode.html.
To learn more on Forth 83 programming, read: Starting Forth, second edition by Leo Brodie, Prentice-Hall.