|
|
1.1 root 1: #
2: # device-independent boot block
3: # uses the rom device driver
4: # reads an already-de-headered, small file with predetermined name
5: # into the beginning of memory
6: # and executes it
7: #
8: # buffering:
9: # the ROM driver will only write into the bottom 64K of memory
10: # to make things simple, we always read to a fixed place,
11: # then copy to the desired place.
12: # if we would have read to the fixed place,
13: # we copy to a safe buffer, and copy back when we're all done.
14: # the same subterfuge is needed to avoid overwriting the in-RAM copy
15: # of the boot ROMs, where our device driver lives,
16: # so we use the memory just below the ROM copy for the buffer
17: #
18: .set BSIZE,512 # size of a disk block, according to rom driver
19: .set BSHIFT,9
20: .set BUFADDR,0xfa00-BSIZE # where to read stuff
21: .set BUFSIZE,1024+BSIZE # sizeof(buffer) + sizeof(roms)
22:
23: .set NAMELEN,14 # number of chars in name; one element for now
24: .set HIADDR,0x70000 # high address at which we run
25:
26: .set REGMASK,0xef # registers to save for second boot
27: .set SVSIZE,7*4
28: .set SADR,0 # r0 -- overwritten with start addr
29: .set SR1,(1*4) # offsets in save area
30: .set SR3,(3*4)
31: .set SFLGS,(4*4) # boot flags -- r5
32: .set DRIVER,(5*4) # where device driver addr gets saved -- r6
33:
34: .set A_MAGIC,0 # offset in exec hdr: magic number
35: .set A_TEXT,4 # text size
36: .set A_DATA,8 # data size
37: .set A_ENTRY,20 # start address
38:
39: .set ISIZE,64 # size of an i-node
40: .set ISHIFT,6 # same as a shift
41: .set INOPB,BSIZE/ISIZE
42: .set ROOTINO,2 # i-number of the root
43: .set ILBLK,2 # first block of i-list
44: .set NDIREC,10 # number of direct blocks
45: .set NINDIR,256 # number of (interesting) indirect blocks
46: .set NINDBLK,NDIREC+NINDIR
47: .set I_ADDR,12 # offset to addresses in inode
48: .set DIRSIZ,14 # chars in filename
49:
50: .set PGSIZE,1024 # ld's idea of page size -- for 0410 a.out
51: .set PGSHIFT,10
52:
53: .set RXCS,32 # console rcv csr
54: .set RXDB,33 # console rcv data buffer
55: .set RRDY_B,7 # bit number of ready bit in RXCS
56: .set TXCS,34 # console xmt csr
57: .set TXDB,35 # console xmt data buffer
58: .set TRDY_B,7 # bit number of ready bit in TXCS
59:
60: #
61: # main code
62: # relocate ourselves to high memory
63: # read the root directory, and search it for
64: # the desired file
65: # read that file in
66: #
67: # start must be at addr 0xc
68: #
69:
70: beg:
71: brb start;brb start # 0, 2 valid start addresses
72: hiaddr: .long HIADDR
73: .set didsave,hiaddr+3 # a byte which is 0 when we start
74: bufaddr: .long BUFADDR # handy constant reference
75: start:
76: movl hiaddr,sp # set up new stack
77: pushr $REGMASK # save important boot registers
78: movl sp,r11 # remember where they are
79: movc3 $end,beg,SVSIZE(sp) # copy us up
80: jmp strel+SVSIZE(sp)
81:
82: bootname:
83: .byte 'u,'n,'i,'x,0,0,0,0,0,0,0,0,0,0
84:
85:
86: #
87: # print a character on the console from r1
88: #
89:
90: putc:
91: mfpr $TXCS,r2
92: bbc $TRDY_B,r2,putc
93: mtpr r1,$TXDB
94: rsb
95:
96: #
97: # jump here after relocation
98: #
99:
100: strel:
101: blbs SFLGS(r11),stask # boot flag 1 == prompt for filename
102: movab bootname,r0
103: 0: movzbl (r0)+,r1
104: beql prnl
105: bsbb putc
106: brb 0b
107:
108: stask:
109: movl r11,sp # in case we loop back
110:
111: #
112: # read a string from the console into bootname
113: # terminated by newline
114: #
115:
116: getpr:
117: movzbl $'*,r1 # prompt
118: bsbb putc
119:
120: getname:
121: movab bootname,r3
122: movzbl $NAMELEN-1,r0
123: 0: mfpr $RXCS,r1
124: bbc $RRDY_B,r1,0b
125: mfpr $RXDB,r1
126: bicb2 $0200,r1
127: bsbb putc
128: cmpb $015,r1
129: beql 8f
130: cmpb $040,r1 # ignore control chars; thanks, nautilus
131: bgtr 0b
132: decl r0
133: blss 0b
134: movb r1,(r3)+
135: brb 0b
136: 8: clrb (r3)+
137: sobgtr r0,8b
138: prnl: movzbl $015,r1
139: bsbb putc
140: movzbl $012,r1
141: bsbb putc # and return
142: 2:
143: #
144: # get the root i-node
145: #
146: movl $ROOTINO,r0
147: bsbb iget
148: #### check is directory?
149: movab -NINDBLK*4(sp),sp
150: movl sp,r10
151: bsbb addrcpy
152: #
153: # search the root directory
154: #
155:
156: clrl r12 # init block pointer
157: dirblk:
158: clrl r5 # use beginning of mem as buffer
159: bsbw lread
160: bneq stask # eof, try another file
161: clrl r9
162: 0:
163: movzwl (r9)+,r0 # empty entry?
164: beql 2f # yes, skip it
165: clrl r1
166: 1: cmpb (r9)[r1],bootname[r1] # MicroVAX II doesn't have cmpc
167: bneq 2f
168: aoblss $DIRSIZ,r1,1b
169: brb diryes # the name we want
170:
171: 2: acbw $FSBSIZE-1,$DIRSIZ,r9,0b
172: incl r12 # get next block
173: brb dirblk
174:
175: berr: brb stask
176:
177: #
178: # subroutines placed here, out of sequence, to save space
179: #
180: # copy/convert block numbers
181: # out of an i-node
182: # r10 points to where we want them
183: # r0 points to the i-node
184: # for now, only the direct blocks
185: #
186: # r0 is destroyed
187: #
188:
189: addrcpy:
190: movl r10,r1 # make a volatile copy
191: addl2 $I_ADDR,r0 # point to addresses
192: clrl r2
193: 0:
194: movw (r0)+,(r1)+
195: movzbw (r0)+,(r1)+
196: aoblss $NDIREC+1,r2,0b
197: rsb
198:
199: #
200: # fetch an i-node
201: # r0 has the i-number
202: # on exit, r0 points to the i-node in core
203: # address 0 is used as a buffer
204: #
205:
206: iget:
207: decl r0 # i-numbers are 1 based
208: clrl r1 # make a quadword
209: ediv $INOPB,r0,r8,-(sp) # r8 == block; (sp) == offset
210: addl2 $ILBLK*FSBSIZE/BSIZE,r8
211: clrl r5 # into address 0
212: bsbb bread
213: ashl $ISHIFT,(sp)+,r0 # point to i-node
214: rsb
215:
216: #
217: # read a BSIZE block from the disk
218: # using the rom subroutine
219: # block number in r8;
220: # buffer address in r5
221: # no return if it failed
222: #
223: # hack: if we would read atop the boot roms, don't;
224: # read into a safe place instead, and remember
225: # for the purposes of the hack, it's assumed that
226: # reads are aligned in memory conveniently
227: #
228:
229: bread:
230: subl3 bufaddr,r5,r0
231: blss 0f
232: cmpl r0,$BUFSIZE
233: bgeq 0f
234: movab savedata,r5
235: addl2 r0,r5
236: movb $1,didsave
237: 0:
238: pushl r5 # save real addr
239: movl bufaddr,r5 # get buffer loc
240: movq SR1(r11),r1 # device address stuff
241: movl SR3(r11),r3 # unit number
242: pushl r5 # duplicate address for driver routine
243: jsb *DRIVER(r11) # and call driver
244: blbc r0,berr # disk error, start over
245: tstl (sp)+ # fixup stack
246: movc3 $BSIZE,*bufaddr,*(sp)+ # copy data to final resting place
247: rsb
248:
249: #
250: # back to the main path:
251: # found the file
252: # fetch its i-node and read it in
253: # i-number left in r0 for us
254: #
255:
256: diryes:
257: bsbb iget
258: ##### check i-node?
259: bsbb addrcpy
260: #
261: # indirect blocks
262: # only the first 1024 bytes of the first indirect block examined
263: #
264: mull3 NDIREC*4(r10),$FSBSIZE/BSIZE,r12 # pick up one indirect block
265: beql noind
266: movl r12,r8
267: moval NDIREC*4(r10),r5
268: bsbb bread
269: addl3 r12,$1,r8 # 2 sectors == 256 indirections
270: moval NDIREC*4+BSIZE(r10),r5
271: bsbb bread
272: noind:
273: clrl r5
274: clrl r12
275: rdloop:
276: ashl $FSSHIFT,r12,r5
277: bsbb lread
278: bneq eof
279: incl r12
280: brb rdloop
281: #
282: # whole file read in
283: # check for a.out header and relocate
284: #
285: eof:
286: blbc didsave,1f
287: movc3 $BUFSIZE,savedata,*bufaddr
288: 1: clrl r12
289: movq A_TEXT(r12),r7 # r7 = text size; r8 = data size
290: movl A_ENTRY(r12),SADR(r11) # starting address
291: 2: casel A_MAGIC(r12),$0407,$1
292: 0: .word m0407-0b
293: .word m0410-0b
294: clrl SADR(r11) # no a.out, start at the top
295: brb done
296: m0407:
297: addl2 r8,r7 # text = text + data; no data
298: clrl r8
299: #
300: # do copies by longword: simpler and smaller than movc3,
301: # which would need to loop anyway
302: # longword not quadword because ld rounds sizes to long
303: #
304: # really should beql after the second div, else when there's no data
305: # we copy one extra word to a nonsense place.
306: # too bad; we can't spare the code space
307: #
308: m0410:
309: clrl r0
310: movzbl $32,r1
311: addl3 r7,r8,r2
312: divl2 $4,r2
313: 1: movl (r1)+,(r0)+ # copy down over a.out header
314: sobgtr r2,1b
315: divl3 $4,r8,r2
316: addl3 r8,r7,r1 # from t + d
317: extzv $0,$PGSHIFT,r7,r0
318: beql 0f # don't overround
319: subw3 r0,$PGSIZE,r0
320: 0: addl2 r1,r0 # to t + d + round
321: 2: movl -(r1),-(r0) # copy data to start at page boundary
322: sobgtr r2,2b
323: #
324: # reset registers and start
325: #
326:
327: done:
328: movl r11,sp
329: popr $REGMASK
330: movl r5,r11 # put boot flags in stupid bky place
331: jmp 2(r0) # skip register mask & start it
332:
333: #
334: # read a (filesystem) block from a file
335: # (filesystem) block number in r12
336: # buffer address in r5
337: # r10 points to the addresses
338: # returns status in psw:
339: # zero flag set if read a block
340: # clear if error or block doesn't exist
341: #
342:
343: lread:
344: cmpw r12,$NINDBLK
345: blss 0f
346: lerr:
347: bicpsw $4 # clear zero flag
348: rsb
349: 0:
350: movl (r10)[r12],r8
351: beql lerr
352: pushl $FSBSIZE/BSIZE # count of disk blocks within fs block
353: mull3 $FSBSIZE/BSIZE,r8,-(sp) # fs block to disk block
354: 1:
355: movl (sp),r8
356: movl r5,r6 # safe place
357: bsbw bread
358: movab BSIZE(r6),r5
359: incl (sp)
360: sobgtr 4(sp),1b
361: clrq (sp)+ # addl2 $8,sp; set zero bit
362: rsb
363: #
364: # last address that needs saving
365: #
366: .globl end
367: end:
368:
369: #
370: # put uninitialized (not 0) data here
371: #
372: .align 2
373: savedata:
374: # .space ROMSIZE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.