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