The NitrOS-9 Boot Process Explained

Disclaimer: NitrOS-9 is one of the most unorganized yet rewarding operating systems for the CoCo. There are literally 200 versions or revisions of every kernel, module, driver, command, source file, and the chances of you getting it all together properly so it works with Your hardware greatly depends on Your deep knowledge of the system or the ability to get quick help before you throw your CoCo out a window.

One of the most asked questions is why do I get “BOOT FAILED”. Really, guys… while you can throw a disk in DOS and type DIR and nothing bad happens, with OS-9 there’s a 50/50 chance these days that an OS-9 boot disk isn’t going to boot. Does it have to be this way? Maybe so. Maybe not.

So you might find yourself here wondering what those stupid cryptic codes are on the Boot Failed screen, if you were lucky to even get that. 🙂 Well, as of 2006, maybe a few years later, a post or two was found on the web with a list of codes being used at that time. I copied the text and added it to my little collection of OS-9 references in case it vanished from the web.

The NitrOS-9 boot process involves 2 binary lumps. The first is named (in the makefile target) KERNELFILE_xxx and the second is named BOOTFILE_yyy – where xxx and yyy identify variants targeting different hardware configurations. In this description they will be called KERNELFILE and BOOTFILE respectively.

In each case, the lump is created by concatenating multiple NitrOS-9 binary modules. This works because each module is relocatable code and because there is a header on each module which allows the modules to be treated as a linked list that is searchable by module name.

KERNELFILE is written to track 34 of the boot disk and is the first part of NitrOS-9 to be loaded and executed. BOOTFILE is stored with the name OS9Boot in the filesystem of the boot disk just like any other file. However, the LSN (the Logical Sector Number) at which the BOOTFILE starts on the disk is coded into the LSN0, which is a data structure stored at the first block on the disk.

Coding the start address into the LSN0 makes the process of reading BOOTFILE from disk into memory simpler — the driver that performs this task does not need to include code that understands the file-system. However, it does impose a couple of restrictions:

  • (At least on some systems) BOOTFILE must use contiguous blocks on the disk — it must not be fragmented.
  • In order to use a modified BOOTFILE on a disk, the LSN0 must be re-written. If you forget to re-write the LSN0 data you can end up in the confusing situation where the actual BOOTFILE being used is not the one that you expect. Keep in mind that BOOT (the driver module which loads the BOOTFILE) finds the file through the LSN0 pointer and does not care about which name it has in the file system.

When creating disk images on a non-NitrOS-9 host system, the Toolshed os9 tool’s “gen” command is used to set up LSN0 as part of the build process. For example, from level1/mc09/makefile:

        $(OS9FORMAT_DS80) -q $@ -n"NitrOS-9/$(CPU) Level $(LEVEL)"
        $(OS9GEN) $@ -b=$(BOOTFILE_COVDG_SD80) -t=$(KERNELFILE_COCOSDC)
  • The -t argument specifies the KERNELFILE; the file to be written to track 34 (the “boot track”)
  • The -b argument specifies the BOOTFILE; the file whose start LSN must be written into LSN0.

In order to start the boot process, some command must be issued on the system to load and execute track 34.

On a CoCo this is typically done from the Disk Extended Color BASIC (DECB) ‘OK’ prompt. Typing ‘DOS’ at the prompt loads track 34 from the disk into memory at $2600 and jumps to address $2602. At this point, control has passed to NitrOS-9.

Track 34 consists of 18 sectors of 256 bytes each; a total of 4,608 ($1200) bytes. The first 2 bytes of KERNELFILE are ‘O’ and ‘S’; executable code starts at offset 2 (the 3rd byte) and is a BRA to the entry point of the REL module.

See: More about the NitrOS-9 Kernel file, More about the NitrOS-9 Boot file.

The boot process proceeds like this:

  1. REL copies the boot track ($2600 to $3800) to address $ED00, and jumps to another routine inside of REL at the new address
  2. REL then jumps to module KRN (OS9P1), which sets up system variables, the system memory map, system call tables, IRQ and SWI setup, and calls module BOOT.
  3. BOOT reads sector $000000 off of a disk, and finds out where the OS9Boot file is.
  4. BOOT requests system memory for the size of OS9Boot, seeks to where OS9Boot is, and loads it directly into RAM.
  5. BOOT then returns to KRN (OS9P1), after setting up pointers in low memory to the OS9Boot file.
  6. KRN (OS9P1) links to module KRNP2 (OS9P2), and jumps into its execution entry point.
  7. KRNP2 (OS9P2) sets up more system calls, links to the CLOCK module, and calls it.
  8. CLOCK sets up some more system calls, starts multitasking, and returns to KRNP2.
  9. KRNP2 attempts to locate and link a module named KRNP3 See: More about KRNP3.
  10. KRNP3 need not exist. If it does exist, it should initialise then return control to KRNP2.
  11. KRNP2 inspects the Init module to find the name of the default program — usually SYSGO.
  12. KRNP2 does a F$Chain of SYSGO (CC3GO). This prints a start up banner, and runs your ‘startup’ file through a shell.

An annotated boot

When a NitrOS-9 Level 2 system boots, code at D.BtBug can be configured to provide debug information. Code in rel.asm loads D.BtBug either with a RTS ($39) or with a JMP ($7E) — the jump destination is code fragment BtDebug. By default, it is set to JMP, and provides progress messages through the boot. Here is an example, with decoder.

NITROS9 BOOTKREL Boot Krn tb0...........................................................................................bKrnP2 IOMan Init RBF mc09sd DD D0 D1 D2 D3 SCF mc6850 Term T0 T1 PipeMan Piper Pipe Clock Clock2 Shell Date DeIniz Echo Iniz Link Load Save Unlink i2xoCNitrOS-9/6809 Level 2 V3.3.0
Multicomp09
(C) 2014 The NitrOS-9 Project
**   DEVELOPMENT BUILD   **
** NOT FOR DISTRIBUTION! **
Fri May 19 20:55:49 2017
http://www.nitros9.org

* Welcome to NitrOS-9 Level 2 on the Multicomp09 *

       yyyy/mm/dd hh:mm:ss
Time ?  
May 19, 2017  20:57:55

Shell+ v2.2a 17/05/19 20:58:11

{Term|02}/DD:

Decoder (old list from 2006):

  • NITROS9 BOOT – This is the BootMsg text from rel.asm. It indicates that the Kernel file has been loaded and started successfully.
  • K – This is from krn.asm. It indicates that REL branched to and started the Kernel successfully.
  • REL Boot Krn – This is the list of modules found in the Kernel file. Your mileage may vary.
  • t – in the kernel F$Boot call; tried to boot.
  • b – found the Boot module successfully; calling Boot.
  • 0 – loaded LSN0 successfully (LSN0 contains, amongst other things, the location of the Boot file).
  • . – one period each time a sector of the Boot file is loaded from disk
  • b – Boot returned successfully.
  • KrnP2 IOMan Init RBF mc09sd DD D0 D1 D2 D3 SCF mc6850 Term T0 T1 PipeMan Piper Pipe Clock Clock2 Shell Date DeIniz Echo Iniz Link Load Save Unlink – This is the list of modules found in the Boot file. Your mileage may vary.
  • i – found the Init module.
  • 2 – This is from krnp2.asm. It indicates that KrnP2 started successfully.
  • x – Tried to change-directory to the default directory.
  • o – Tried opening an output window.
  • (if KRNP3 exists, this is where it will be initialised)
  • C – Tried to go to SysGo (previously, SysGo was called CC3GO which explains why this is a C and not an S).
  • NitrOS-9/6809 Level 2 V3.3.0 – This is the OSStr text from the Init module. It is referenced as OSName (defined in os9.d) and printed by SysGo using an I$Write system call.
  • Multicomp09 – This is the InstStr text from the Init module. It is referenced as InstallName (defined in os9.d) and printed by SysGo using an I$Write system call.
  • (C) 2014 The NitrOS-9 Project .. nitros9.org – This is the Banner text from the SysGo module.
  • * Welcome to NitrOS-9 Level 2 on the Multicomp09 * – The /DD/startup script is being executed. This message is produced by an ‘echo’ command in that script.
  • yyyy/mm/dd hh:mm:ss .. Time ? – This message is produced by a ‘setime </1’ command in the startup file.
  • May 19, 2017 20:57:55 – This message is produced by a ‘date -t’ command in the startup file. If you simply pressed <Return> in response to the ‘Time ?’ prompt, the default system time is the time at which the boot disk was build.
  • Shell+ v2.2a 17/05/19 20:58:11 – A startup message printed by the shell.
  • {Term|02}/DD: – the shell prompt. Boot is complete.
NitrOS-9 Level 2 Booting screen and what it means
=================================================
by Chris Hawks.  12 May 2006
Updated by L. Curtis Boyle June 23, 2019.

The 1st part ("WHAT THE BOOT SCREEN MEANS") explains what all the characters on
the boot screen means, in the order that they appear, to help you figure out where
things are going wrong. The 2nd part of this document ("THE BOOT PROCESS
EXPLAINED") is the technical explanation. 

                            WHAT THE BOOT SCREEN MEANS
                            --------------------------
The first thing that should appear, after you type DOS, is that the screen will
clear (whether it is 32, 40 or 80 column will depend on which version of REL you
have used) and it will print NITROS9 BOOT in the center. This indicates that the
kernal track (usually track 34) has been loaded, and at least the REL module in
that appears to be working. After that, things print from the upper left corner
of the screen:
K - Indicates the KRN module was found (in the boot track) and jumped into
REL - REL (RELocate) module is found and had it's CRC verified
Boot - BOOT module is found and had it's CRC verified
Krn - (formerly OS9P1) module is found and had it's CRC verified
t - the F$Boot system call has been installed
b - the F$Boot system call is now running. This loads in track 0/sector 0 from the
    boot drive
0 - LSN0 (sector 0 on the boot drive) has been successfully read (this sector,
    amongst other things, tells F$Boot where to find your OS9Boot file)
. - Each '.' indicates 1 sector (256 bytes) of the OS9Boot file has been read.
b - the F$Boot is now validating the OS9boot and all the modules it contains
[modulenames] - Each module name will be printed, as it is found and CRC verified
    in the OS9boot file. Usually starts with KrnP2, and the rest depends on what
    hardware/software options you installed in your boot.
i - Linked to the INIT module (which contains some system defaults/strings, etc.)
2 - Now in KRNP2 module (kernal part 2)
x - About to try CHD to default data directory specified in INIT module (usually /dd)
o - About to try to open default terminal device specified in INIT module (usually /term)
G - (NEW TO EOU, ONLY SHOWN IF DEFAULT TERMINAL DEVICE USES CoGrf OR CoWin) - About to
   try and load GRFDRV outside of system task (solves some boot problems when system task
   memory is low)
C - About to launch startup module specified in INIT module (usually SysGo; formerly CC3Go)

If the screen clears and it prints a NitrOS-9 splash screen, then SysGo is running. SysGo
will also make a "dummy" call to the Set the Time, which is used to kickstart multi-tasking
by initializing the Clock module and clock IRQ. If it freezes here, you may have the wrong
Clock/Clock2 module.

ERROR CODE LIST (numbers that are blank or not listed should NOT appear on the NitrOS9 BOOT
screen, as they are not legitimate errors at that point):
CHAR is the character that appears after the '*'			
Char	ASCII	Error #	NitrOS-9 Error message
7	55	183	Illegal window type
8	56	184	Window already defined
9	57	185	Font Not found
:	58	186	Stack Overflow
;	59	187	Illegal Argument
<	60	188	
=	61	189	Illegal Coordinates
>	62	190	Internal Integrity check
?	63	191	Buffer size is too small
@	64	192	Illegal Command
A	65	193	Screen or Window Table is Full
B	66	194	Bad/Undefined buffer number
C	67	195	Illegal window definition
D	68	196	Window undefined
E	69	197	
F	70	198	
G	71	199	
H	72	200	Path Table Full
I	73	201	Illegal Path Number
J	74	202	Interrupt Polling Table Full
K	75	203	Illegal Mode
L	76	204	Device Table Full
M	77	205	Illegal Module Header
N	78	206	Module Directory Full
O	79	207	Memory Full
P	80	208	Illegal Service Request
Q	81	209	Module Busy
R	82	210	Boundary Error
S	83	211	End of File
T	84	212	Returning non-allocated memory
U	85	213	Non-existing Segment
V	86	214	No Permission
W	87	215	Bad Path Name
X	88	216	Path Name Not Found
Y	89	217	Segment List Full
Z	90	218	File Already Exists
[	91	219	Illegal Block Address
\	92	220	Phone Hangup-Data Carrier Detect lost
]	93	221	Module Not Found
^	94	222	
_	95	223	Suicide Attempt
`	96	224	Illegal Process Number
a	97	225	
b	98	226	No Children
c	99	227	Illegal SWI Code
d	100	228	Process Aborted
e	101	229	Process Table Full
f	102	230	Illegal Parameter Area
g	103	231	Known module
h	104	232	Incorrect Module CRC
i	105	233	Signal Error
j	106	234	Non-existent Module
k	107	235	Bad Name
l	108	236	Bad Module Header
m	109	237	RAM Full
n	110	238	Unknown Process ID
o	111	239	No task number available
p	112	240	Unit Error
q	113	241	Sector Error
r	114	242	Write Protect
s	115	243	CRC Error
t	116	244	Read Error
u	117	245	Write Error
v	118	246	Not Ready
w	119	247	Seek Error
x	120	248	Media Full
y	121	249	Wrong Type
z	122	250	Device Busy
{	123	251	Disk ID Change
|	124	252	Record is locked-out
}	125	253	Non-sharable file busy
~	126	254	I/O Deadlock Error



                     THE BOOT PROCESS EXPLAINED
                     --------------------------
	One of our local Coco-nuts was having a problem with NitrOS-9 on
his Coco3. It had recently stopped booting NitrOS-9 from HDB-DOS in
his SuperIDE. We got together at the monthly Glenside Color Computer Club
meeting to see if we could resolve the problem. He brought his system
and I brought a sub-set of my system to the meeting. We were the 
'presentation' for that meeting. I booted my system from HDB-DOS and
my SuperIDE adapter with his compactflash card in a compactflash to
IDE adapter as the slave drive. After my systems booted, I looked at
the root directory of his compactflash card. It looked OK to me, but,
he did have some odd files there. I shut down my system and swapped the
compactflash cards.  (His as mastr and mine as slave. The boot process
started and loaded track 34 and the OS9boot and then just stopped. From
the debugging clues posted to the screen during the boot process, I was
able to determine the the boot process was unable to find the 'sysgo'
module. I re-booted with my compactflash as master and his as slave,
and copied 'sysgo' from my root directory to his. We swapped the
compactflash cards once again and his compact flash was able to boot!

	I was asked to write-up our adventure as a article for the GCCC
newsletter (Coco 1 2 3). I had not been able to find any information on
debugging the boot process in NitrOS-9 (except from the source code) so
here it is.

STEP 1
	The modules 'rel', 'boot', and 'krn' are loaded into memory from
track 34 by the 'dos' command. 'Rel' ensures that it is located in the
correct part of memory, sets up some of the hardware, clears the screen,
and installs the debugging 'print' routine. It prints 'NITROS9 BOOT' in
the center of the screen and jumps to the execution address of the
module 'krn'.

STEP 2
	The module 'krn' uses the debug 'print' routine to put a 'K' on the
startup screen. It validates the modules in memory ('rel', boot, and
'krn') which prints their names on the startup screen and makes a system
call (F$Boot) which puts a 't' on the startup screen and links the module
'boot'. It puts a 'b' on the startup screen and calls 'boot'. 'Boot' reads
LSN0 to find OS9boot and puts a '0' on the startup screen. 'Boot' then
loads OS9boot and puts a '.' on the startup screen for each sector read.
'$F$Boot' validates all modules in OS9boot which prints their names to the
screen, and puts a second 'b' on the startup screen. Next 'krn' links to
the 'init' module and puts 'i' on the startup screen. Following this it
links to and executes 'krnp2' the second part of the kernel.

STEP 3
	'Krnp2' puts a '2' on the startup screen, and puts an 'x' on the
startup screen. Then 'krnp2' tries to 'chd' to the system device named in
'init' (usually '/dd'). Next 'krnp2' puts a 'o' on the startup screen and
tries to open the output console named in 'init' (usually '/term'). 'Krnp2'
checks for 'krnp3' and runs it if available. Then 'krnp2' puts a 'C' on
the startup screen and tries to run the startup module named in init
usually 'sysgo'.

STEP 4
	'Sysgo' opens the output console, prints the NitrOS-9 startup banner
and sets the data and exec directories. 'Sysgo' will execute 'startup' and
'autoexec' if available (unless you hold the 'shift' key) and finally
starts a 'shell' on the console.

	If something goes wrong during the boot, the module will call the
'crash' routine which will put a '*' and single character on the startup
screen.  The '*' indicates that an error occured and the character's ascii
value plus 128 is the error number. For instance '*X' would indicate a
'Path Name Not Found' error. 'X' is ascii 88, and 88 + 128 = 216, the
error code for 'Path Name Not Found'. This is the error we saw when sysgo
was missing from the root directory of the disk.

	So, the start up messages look something like this:
Krel boot krn tb0...................................................
......... bkrnp2 dd d0 rbf rb1773 term w w1 w2 w3 w4 scf cowin clock 
clock2 init i2xoC

	Of course, YMMV (Your Modules May Vary)

	This should give you some insight into what goes on during a NitrOS-9
boot, and perhaps some debugging assistance when something goes wrong.
NitrOS-9 Level 2 Booting and (trouble)Shooting.

by Chris Hawks.  12 May 2006

	One of our local Coco-nuts was having a problem with NitrOS-9 on
his Coco3. It had recently stopped booting NitrOS-9 from HDB-DOS in
his SuperIDE. We got together at the monthly Glenside Color Computer Club
meeting to see if we could resolve the problem. He brought his system
and I brought a sub-set of my system to the meeting. We were the 
'presentation' for that meeting. I booted my system from HDB-DOS and
my SuperIDE adapter with his compactflash card in a compactflash to
IDE adapter as the slave drive. After my systems booted, I looked at
the root directory of his compactflash card. It looked OK to me, but,
he did have some odd files there. I shut down my system and swapped the
compactflash cards.  (His as mastr and mine as slave. The boot process
started and loaded track 34 and the OS9boot and then just stopped. From
the debugging clues posted to the screen during the boot process, I was
able to determine the the boot process was unable to find the 'sysgo'
module. I re-booted with my compactflash as master and his as slave,
and copied 'sysgo' from my root directory to his. We swapped the
compactflash cards once again and his compact flash was able to boot!

	I was asked to write-up our adventure as a article for the GCCC
newsletter (Coco 1 2 3). I had not been able to find any information on
debugging the boot process in NitrOS-9 (except from the source code) so
here it is.

STEP 1
	The modules 'rel', 'boot', and 'krn' are loaded into memory from
track 34 by the 'dos' command. 'Rel' ensures that it is located in the
correct part of memory, sets up some of the hardware, clears the screen,
and installs the debugging 'print' routine. It prints 'NITROS9 BOOT' in
the center of the screen and jumps to the execution address of the
module 'krn'.

STEP 2
	The module 'krn' uses the debug 'print' routine to put a 'K' on the
startup screen. It validates the modules in memory ('rel', boot, and
'krn') which prints their names on the startup screen and makes a system
call (F$Boot) which puts a 't' on the startup screen and links the module
'boot'. It puts a 'b' on the startup screen and calls 'boot'. 'Boot' reads
LSN0 to find OS9boot and puts a '0' on the startup screen. 'Boot' then
loads OS9boot and puts a '.' on the startup screen for each sector read.
'$F$Boot' validates all modules in OS9boot which prints their names to the
screen, and puts a second 'b' on the startup screen. Next 'krn' links to
the 'init' module and puts 'i' on the startup screen. Following this it
links to and executes 'krnp2' the second part of the kernel.

STEP 3
	'Krnp2' puts a '2' on the startup screen, and puts an 'x' on the
startup screen. Then 'krnp2' tries to 'chd' to the system device named in
'init' (usually '/dd'). Next 'krnp2' puts a 'o' on the startup screen and
tries to open the output console named in 'init' (usually '/term'). 'Krnp2'
checks for 'krnp3' and runs it if available. Then 'krnp2' puts a 'C' on
the startup screen and tries to run the startup module named in init
usually 'sysgo'.

STEP 4
	'Sysgo' opens the output console, prints the NitrOS-9 startup banner
and sets the data and exec directories. 'Sysgo' will execute 'startup' and
'autoexec' if available (unless you hold the 'shift' key) and finally
starts a 'shell' on the console.

	If something goes wrong during the boot, the module will call the
'crash' routine which will put a '*' and single character on the startup
screen.  The '*' indicates that an error occured and the character's ascii
value plus 128 is the error number. For instance '*X' would indicate a
'Path Name Not Found' error. 'X' is ascii 88, and 88 + 128 = 216, the
error code for 'Path Name Not Found'. This is the error we saw when sysgo
was missing from the root directory of the disk.

	So, the start up messages look something like this:
Krel boot krn tb0...................................................
......... bkrnp2 dd d0 rbf rb1773 term w w1 w2 w3 w4 scf cowin clock 
clock2 init i2xoC

	Of course, YMMV (Your Modules May Vary)

	This should give you some insight into what goes on during a NitrOS-9
boot, and berhaps some debugging assistance when something goes wrong.

Author: Roger Taylor