// 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 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 "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 ]