Subject: OS/8 disk structure

From: [email-masked]
Date: Sat, 12 Nov 94 12:55:28 EST

>records 0001-0006 to see if it resembles a directory.
 
Can anyone tell me how to write an OS/8 directory?  I already know how to
read them, but I don't know how to pick such constants as the number of
dir blocks to write (is it always 6, or does it vary with the medium size
like in RT-11?).
 
How do you make a medium bootable?  I gather a boot disk keeps stuff in the
space between the end of the dir and the beginning of the file area;  how big
an area should I reserve there?  And what do I write there?  In RT-11 you
just pull the primary bootstrap out of the system driver file, and the
secondary bootstrap out of the monitor file, make a couple of patches, and
write them out as blocks 0 and 2-5.  But RT-11's disk structure is only
vaguely based on that of OS/8, so this may be totally different.  What are
the standard names for these files if it *is* similar?
 
John Wilson

---

From: Charles Lasner <[email-masked]>
Date: Sun, 13 Nov 1994 04:47:27 -0500 (EST)

> dir blocks to write (is it always 6, or does it vary with the medium size

OS/8 directories are essentially a sacred length of 6.  There is overhead 
in the structure to allow it to vary, but it never can due to other 
considerations.  In theory, variable size applies, but in practice, 
changing anything will definitely break certain programs!

For the record, please do not use the term "block" when referring to OS/8 
stuff.  PDP-8 equipment owns the prior title of "block" to mean physical 
block, as in 128 words in a DECtape block (if you ignore the 129th word!) 
while OS/8 was the first system to refer to logical *records* of 256 
words/record.  Thus, in the DECtape case, 1 OS/8 record = 2 DECtape blocks.

Note that in P?S/8 and several other systems, the terms are 
interchangeable because both sizes are 128 words, etc.

> the standard names for these files if it *is* similar?

Bootable systems require that record 0 be specially written.  Note that 
record 0 is wasted on a non-bootable device.  System heads come in two 
varieties, one that can run in 8K because the handler fits in 07600-07777 
completely, and another that requires 27600-27777 as well.  (Note: a 
small few words are reserved, so in practice, these small sizes are 
slightly exaggerated over their even smaller true sizes!)

When the system is bootable, the data starts in record 70, not in record 
7.  The directory indicates this either way.  The directory placement 
itself is unchanged.  All of the records 7-67 are reserved for a system.  
In particular, record 66 is reserved for the two-page 12K system handler 
itself.

In the 8K case, the entire handler resides in record 0 second half, 
essentially being an image of what belongs in 07600-07777.  In fact, it's 
a restriction of OS/8 build constraints that this indeed must be the 
case!  (See below.)  In said case, the first half is the code that is 
generally brought in by the primary boot code already in memory at the 
beginnning of the boot process, etc.  Additionally, some of the code in 
the first half of record 0 is reserved as the image of certain code 
skeletons that must be placed into 17600-17777.  Again, it's a 
restriction of the build program that merely loading the image of this 
first half of record 0 into 17600-17777 is sufficient to startup the 
system as a sort-of generic bootstrap.  (What actually happens is that 
build swaps around the contents of memory using the handler images loaded 
appropriately to perform the write-out of the new system from the current 
running system.  Build isn't interested in handler quirks/nuances, thus 
the requirement that mere image loading produces a functional handler for 
a short moment of system writing during the build copy process, etc.)

In the 12K two-page case, the record 0 first half code does participate 
in the boot process, but the image of 17600-17777, but the handler is not 
located in the second half of the record.  Instead, record 66 houses both 
halves of the extended handler, the first half being the image of 
07600-07777 and the second half being the image of 27600-27777.  (Note: 
build internal conventions are such that writing handlers imposes 
physical origin settings far removed from these actual loading 
considerations; those writing actual handlers must recognize this!  In 
general, build insists on an origin of *0000 in front of a header of info 
words that aren't in the handler code.  Said head ends with a pragmatic 
notion of the words that are to be written into the first half of record 
0 "next" to the skeleton words that must be present.  Then there is a 
*0200 for the next binary page and that is the code for the 07600-07777 
part.  Should there be an additional page, you follow that with an origin 
to *0400 followed by the code meant to execute in 27600-27777, etc.  
Again, note that indicating (in the header) that there are two pages to 
load causes both pages to be written instead of record 0 to record 66 
both halves, etc.

My design gripe about image loading stems from the following problem:

Certain existing boot conventions do not necessarily cause the boot code 
to come into memory in the most convenient way, sometimes causing 
additional fixup code to make the handler viable.  In some cases, it's 
difficult to get in enough boot code as it comes in for the purpose of 
secondary and/or tertiary loading of the rest of the handler, etc., 
especially in the case of multiple page handlers, etc.

In one notable case, someone created a byte-mode RX01 handler that 
requires an incredibly complicated boot code segment to satisfy build's 
constraints that the image of the code be able to function as loaded.  As 
a result, a long and incompatible boot sequence is required to get this 
system started, etc.  However, an after-the-fact program that uses the 
standard boot in 12-bit mode can be run that patches the system head to 
obey the normal conventions again.  But build cannot create this system 
directly!  (It cannot be used to write out an image of itself using the 
current image of itself merely loaded bodily and without initialization 
directly into 07600-07777 and if necessary 27600-27777, etc.)

A concept added to P?S/8 for the benefit of system build (still in a 
primitive but viable state!) is the notion that a handler needs once-only 
initialization of the image of the handler to make said image into a 
working handler strictly for the system generation time usage of the 
handler otherwise loaded into the normal 07600-0777 and whatever other 
locations required.  This allows handlers to be freed from having to be 
lame images of what needs to eventually be there, and instead can merely 
be the image of what can later be brought up to the required operational 
level as a consequence of the boot process, even though the initial 
loading of what's there is not in and of itself necessarily yet a handler!

Taking advantage of this, P?S/8 doesn't even bother to have a defined boot
block per se, rather block 0000 directly is an (almost if necessary!)
image of the handler itself cognizent of its (eventual) mission of getting
up a viable handler within 07600-07777.  As such, it's conceivable that 
this code is partially an image of the secondary boot code read in by the 
toggle-in primary boot code, later replaced by the intended contents of 
the corresponding relative region when the rest of the handler is located 
in 07600-07777, etc.

In the case of the P?S/8 RX01 handler, there is a large "hole" in the 
code that is responsible for continuing the loading process started by 
the primary boot code, where the code is being loaded into 00002 and 
following (even though relatively speaking, the code would be more 
functional if loaded into 07600 and up at the time, etc.!).  Once this 
loading code is in control, the rest of block 0 gets loaded into the 
proper places in 07600-07777, but the hole is still there (for the moment).

The boot process continues in a way that is quite different from OS/8 at 
this point:  P?S/8 reserves 8 additional blocks for handler code, and 2 
additional blocks for handler initialization code.  The "hole" code loads 
the two pages of once-only code into 05400-05600.  (These values were 
chosen to slightly simplify what follows, but are totally arbitrary, etc.)

The two pages of code then perform a dynamic memory test that runs on all 
models (avoiding known model-dependent quirks!) that establishes the 
highest memory field available.  Field 0 obviously exists, but now field 
1 must be discoved in order to proceed (up to field 7, the most 
preferable field if available, etc.)

Then the contents of the 8 pages of extended handler code are loaded into 
x6000-x7777 where x is the highest field discoved in the range of 1-7.  
The final initialization code moves the code from 00002 to 07600 where it 
is (nearly) executable, etc.

The final initialization is to call a routine (located within 
x6000-x7777) which "fills the hole" in the code in 07600-07777 to make it 
functional.  For system-generation usage, there is an analogous call to 
fill the hole, etc. in an image of the handler moved to 07600-07777 and 
16000-17777 that is then viable for writing out any and all system 
images, etc.  Whenever the system handler is reloaded (such as optionally 
after binary file loading, etc.) the hole-fill init routine is always 
available to make the merely loaded code into a viable image of the 
intended handler, etc.

What constitutes the OS/8 system head is the contents of the rest of the 
area in the range of record 0007-0067.  This is constant across all 
systems, and is written from one to another when build is used.  OS/8 PIP 
/Y option makes an image file of the entire system head so it can be 
easily restored to the intended device.  Note that the PIP head file 
contains copies of all of the system and non-system handlers, thus it 
becomes device-specific.  Additionally, it must be written to a 
media-compatible device by a handler of the current system being used to 
accomplish the PIP operation!  Thus, for example, a TD8E non-system 
handler could be used to perform the operation of writing out the monitor 
head of a TC08-specific system onto a DECtape.  Said tape could then be 
taken to a TC01/08-based machine and be booted directly, etc.

Because of the possible anomalies, certain systems take some defensive 
safeguards:  One of the later RX01 system boot code segments checks to 
see that the device really is capable of single density as written, i.e., 
it hasn't been accidentally written out onto a double-density media, 
since this would make the boot process fail, etc.  Similarly, the 
double-density RX02 system boot code checks to make sure the media and 
drive are actually double-density lest it actually be written to a 
single-density RX01-type drive/media where it wouldn't boot properly, etc.

> John Wilson

cjl