// IfsBootInstall.bcpl -- boot file installation
// Copyright Xerox Corporation 1979, 1980, 1981, 1982
// Last modified December 12, 1982 11:22 AM by Taft
get "Pup0.decl"
get "Pup1.decl"
get "Ifs.decl"
get "IfsRs.decl"
get "IfsBootServ.decl"
get "IfsFiles.decl"
get "IfsDirs.decl"
external
[
// outgoing procedures
CreateBootServ; InstallBootFiles
// incoming procedures
BootServEvent; FindBFE; InsertBFE; BFTCompareKey; BFTEntryLength
CreateEvent
LookupIFSFile; NextFD; DestroyFD; GetBufferForFD
OpenIFSStream; CloseIFSStream; DeleteFileFromFD; IFSOpenFile; StreamsFD
ReadBlock; WriteBlock; Closes; FileLength; SetFilePos; PositionPage
ReadLeaderPage; WriteLeaderPage
OpenIFSTree; CloseBTree; @VWRP; VirtualPage
ExtractSubstring; CopyString
SysAllocate; SysAllocateZero; SysFree; MoveBlock; IFSError
// incoming statics
@bs; primaryIFS
]
//----------------------------------------------------------------------------
let CreateBootServ() be
//----------------------------------------------------------------------------
[
bs = SysAllocateZero(lenBS)
bs>>BS.stats.version = bootStatsVersion
bs>>BS.internalLock = true // until BFT B-tree is built
CreateEvent(BootServEvent)
]
//----------------------------------------------------------------------------
and InstallBootFiles() be
//----------------------------------------------------------------------------
// Install all boot files currently residing in <System>Boot>.
// Caller is responsible for write-locking the BFT.
[
if bs>>BS.tree ne 0 then CloseBTree(bs>>BS.tree)
// (Re)create the B-tree file with all appropriate attributes
let stream = IFSOpenFile("Boot>BootDirectory.tree", 0, modeReadWrite)
if stream eq 0 then IFSError(ecCreateEssentialFile)
let ld = GetBufferForFD(StreamsFD(stream))
ReadLeaderPage(stream, ld)
ld>>ILD.type = ftBinary
ld>>ILD.byteSize = 8
ld>>ILD.noBackup = true
ld>>ILD.undeletable = true
WriteLeaderPage(stream, ld)
PositionPage(stream, bootTreePages)
bs>>BS.tree = OpenIFSTree(lv StreamsFD(stream)>>FD.dr>>DR.fp, primaryIFS,
BFTCompareKey, BFTEntryLength, true, bootTreePages)
SysFree(ld)
Closes(stream)
// InstallBootFiles (cont'd)
// Enumerate all files with names of the form "<System>Boot>bfn-name.boot",
// reformat them if necessary, and insert them into the BFT.
let fd = LookupIFSFile("Boot>**-**", lcVHighest+lcMultiple)
if fd ne 0 then
[ // repeat
let bootFile = OpenIFSStream(fd) // modeRead
if bootFile eq 0 loop
// pick apart the file name and build BFD for it
let bfd = vec (offset BFD.name/16 + 127)
bfd>>BFD.bfn = 0
let i = fd>>FD.lenSubDirString+1
let char = nil
while i ls fd>>FD.lenBodyString do
[
char = fd>>FD.dr>>DR.pathName.char↑i
if (char-$0) ugr 7 break
bfd>>BFD.bfn = bfd>>BFD.bfn lshift 3 + char - $0
i = i+1
]
if char ne $- % // improper filename, bypass
FindBFE(bfd>>BFD.bfn) ne 0 then // duplicate bfn, bypass
[ CloseIFSStream(bootFile); loop ]
let bootName = ExtractSubstring(lv fd>>FD.dr>>DR.pathName,
i+1, fd>>FD.lenBodyString-1)
CopyString(lv bfd>>BFD.name, bootName)
SysFree(bootName)
// There are two kinds of boot file.
// For more on boot files see the BuildBoot documentation
// B-Files produced by BuildBoot.run:
// File page 1: DiskBoot loader
// File page 2: locations 0-377b
// File page 3: locations 1000b - 1377b
// File page 4: locations 1400b - 1777b
// ...
// File page n: locations (n-1)*400b - (n-1)*400b+377b
// B-Files have 0 in word 1 of the first page.
// B-Files are started by jmp @0 when loading is complete.
// S-Files produced by Swat OutLd:
// File page 1: InOutLd loader
// File page 2: locations 1000b - 1377b
// File page 3: locations 1400 - 1777b
// ...
// File page 253: locations 176400b-176777b
// File page 254: locations 400b - 777b
// File page 255: locations 0 - 377b
// S-Files have a nonzero value in [1..377B] in word 1 of the first page.
// Some S-Files can be started by jmp @0.
// This is the kind we use, but we re-format them first.
// There are other kinds of boot files as well (e.g., microcode files,
// Sun boot files, etc.) These are identified by word 1 not in [1..377B].
// We use these as-is and do not attempt to reformat them.
// InstallBootFiles (cont'd)
let buffer = SysAllocate(256)
ReadBlock(bootFile, buffer, 256)
MoveBlock(lv bfd>>BFD.date, buffer+3, 2)
let newFile = valof
[ // this block returns a disk stream iff the file should be reformatted
if (buffer!1)-1 uge 377B then // not in [1..377B]?
resultis 0 // B-file or file of unknown type
// S-files are always exactly 377000B bytes long. If this file
// is not the correct length then do not try to reformat it.
let fileLength = vec 1
FileLength(bootFile, fileLength)
unless fileLength!0 eq 1 & fileLength!1 eq 177000B do resultis 0
let newName = ExtractSubstring(lv fd>>FD.dr>>DR.pathName,
1, fd>>FD.lenBodyString-1)
let s = IFSOpenFile(newName, 0, modeWrite)
SysFree(newName)
resultis s
]
test newFile eq 0
ifso CloseIFSStream(bootFile)
ifnot // S-file - make it B-format
[
buffer!1 = 0 // mark it as a B-format file
WriteBlock(newFile, buffer, 256) //useless swat InLdr
// read page containing loc 0-#377
SetFilePos(bootFile, 1, 254 lshift 9) // last page of file (255)
WriteBlock(newFile, buffer, ReadBlock(bootFile, buffer, 256))
// now copy the rest of the file.
// stop on page count not end of file.
// note that file page 254 (core page 1) is discarded
SetFilePos(bootFile, 0, 512) // set up to read page 2
// S-Format files are guaranteed to be at least 255 pages long
for i = 2 to 253 do
WriteBlock(newFile, buffer, ReadBlock(bootFile, buffer, 256))
Closes(newFile)
CloseIFSStream(bootFile)
DeleteFileFromFD(fd) // delete the old one
]
SysFree(buffer)
// Now insert the entry into the bft
let bfe = InsertBFE(bfd)
bfe>>BFE.exists = true
VWRP(VirtualPage(bfe rshift 8)) // mark BFE dirty
] repeatwhile NextFD(fd)
if fd ne 0 then DestroyFD(fd)
bs>>BS.internalLock = false
]