|
|
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 SADR,0 # r0 -- overwritten with start addr
28: .set SR1,1*4 # offsets in save area
29: .set SR3,3*4
30: .set SFLGS,4*4 # boot flags -- r5
31: .set DRIVER,5*4 # where device driver addr gets saved -- r6
32: .set SVSIZE,7*4
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: tstw (r9) # empty entry?
164: beql 1f # yes, skip it
165: cmpc3 $DIRSIZ,2(r9),bootname # desired name?
166: beql diryes # yep
167: 1: acbw $FSBSIZE-1,$DIRSIZ+2,r9,0b
168: incl r12 # get next block
169: brb dirblk
170:
171: berr: brb stask
172:
173: #
174: # subroutines placed here, out of sequence, to save space
175: #
176: # copy/convert block numbers
177: # out of an i-node
178: # r10 points to where we want them
179: # r0 points to the i-node
180: # for now, only the direct blocks
181: #
182: # r0 is destroyed
183: #
184:
185: addrcpy:
186: movl r10,r1 # make a volatile copy
187: addl2 $I_ADDR,r0 # point to addresses
188: clrl r2
189: 0:
190: movw (r0)+,(r1)+
191: movb (r0)+,(r1)+
192: clrb (r1)+
193: aoblss $NDIREC+1,r2,0b
194: rsb
195:
196: #
197: # fetch an i-node
198: # r0 has the i-number
199: # on exit, r0 points to the i-node in core
200: # address 0 is used as a buffer
201: #
202:
203: iget:
204: decl r0 # i-numbers are 1 based
205: clrl r1 # make a quadword
206: ediv $INOPB,r0,r8,-(sp) # r8 == block; (sp) == offset
207: addl2 $ILBLK*FSBSIZE/BSIZE,r8
208: clrl r5 # into address 0
209: bsbb bread
210: ashl $ISHIFT,(sp)+,r0 # point to i-node
211: rsb
212:
213: #
214: # read a BSIZE block from the disk
215: # using the rom subroutine
216: # block number in r8;
217: # buffer address in r5
218: # no return if it failed
219: #
220: # hack: if we would read atop the boot roms, don't;
221: # read into a safe place instead, and remember
222: # for the purposes of the hack, it's assumed that
223: # reads are aligned in memory conveniently
224: #
225:
226: bread:
227: subl3 bufaddr,r5,r0
228: blss 0f
229: cmpl r0,$BUFSIZE
230: bgeq 0f
231: movab savedata,r5
232: addl2 r0,r5
233: movb $1,didsave
234: 0:
235: pushl r5 # save real addr
236: movl bufaddr,r5 # get buffer loc
237: movq SR1(r11),r1 # device address stuff
238: movl SR3(r11),r3 # unit number
239: pushl r5 # duplicate address for driver routine
240: jsb *DRIVER(r11) # and call driver
241: blbc r0,berr # disk error, start over
242: tstl (sp)+ # fixup stack
243: movc3 $BSIZE,*bufaddr,*(sp)+ # copy data to final resting place
244: rsb
245:
246: #
247: # back to the main path:
248: # found the file
249: # fetch its i-node and read it in
250: #
251:
252: diryes:
253: movzwl (r9),r0 # i-number
254: bsbb iget
255: ##### check i-node?
256: bsbb addrcpy
257: #
258: # indirect blocks
259: # only the first 1024 bytes of the first indirect block examined
260: #
261: mull3 NDIREC*4(r10),$FSBSIZE/BSIZE,r12 # pick up one indirect block
262: beql noind
263: movl r12,r8
264: moval NDIREC*4(r10),r5
265: bsbb bread
266: addl3 r12,$1,r8 # 2 sectors == 256 indirections
267: moval NDIREC*4+BSIZE(r10),r5
268: bsbb bread
269: noind:
270: clrl r5
271: clrl r12
272: rdloop:
273: ashl $FSSHIFT,r12,r5
274: bsbb lread
275: bneq eof
276: incl r12
277: brb rdloop
278: #
279: # whole file read in
280: # check for a.out header and relocate
281: #
282: eof:
283: blbc didsave,1f
284: movc3 $BUFSIZE,savedata,*bufaddr
285: 1: clrl r12
286: movq A_TEXT(r12),r7 # r7 = text size; r8 = data size
287: extzv $0,$30,A_ENTRY(r12),SADR(r11) # starting address
288: 2: casel A_MAGIC(r12),$0407,$1
289: 0: .word m0407-0b
290: .word m0410-0b
291: clrl SADR(r11) # no a.out, start at the top
292: brb done
293: m0407:
294: addl2 r8,r7 # text = text + data; no data
295: clrl r8
296: #
297: # do copies by longword: simpler and smaller than movc3,
298: # which would need to loop anyway
299: # longword not quadword because ld rounds sizes to long
300: #
301: # really should beql after the second div, else when there's no data
302: # we copy one extra word to a nonsense place.
303: # too bad; we can't spare the code space
304: #
305: m0410:
306: clrl r0
307: movzbl $32,r1
308: addl3 r7,r8,r2
309: divl2 $4,r2
310: 1: movl (r1)+,(r0)+ # copy down over a.out header
311: sobgtr r2,1b
312: divl3 $4,r8,r2
313: addl3 r8,r7,r1 # from t + d
314: extzv $0,$PGSHIFT,r7,r0
315: beql 0f # don't overround
316: subw3 r0,$PGSIZE,r0
317: 0: addl2 r1,r0 # to t + d + round
318: 2: movl -(r1),-(r0) # copy data to start at page boundary
319: sobgtr r2,2b
320: #
321: # reset registers and start
322: #
323:
324: done:
325: movl r11,sp
326: popr $REGMASK
327: movl r5,r11 # put boot flags in stupid bky place
328: jmp 2(r0) # skip register mask & start it
329:
330: #
331: # read a (filesystem) block from a file
332: # (filesystem) block number in r12
333: # buffer address in r5
334: # r10 points to the addresses
335: # returns status in psw:
336: # zero flag set if read a block
337: # clear if error or block doesn't exist
338: #
339:
340: lread:
341: cmpl r12,$NINDBLK
342: blss 0f
343: lerr:
344: bicpsw $4 # clear zero flag
345: rsb
346: 0:
347: movl (r10)[r12],r8
348: beql lerr
349: pushl $FSBSIZE/BSIZE # count of disk blocks within fs block
350: mull3 $FSBSIZE/BSIZE,r8,-(sp) # fs block to disk block
351: 1:
352: movl (sp),r8
353: movl r5,r6 # safe place
354: bsbw bread
355: movab BSIZE(r6),r5
356: incl (sp)
357: sobgtr 4(sp),1b
358: clrq (sp)+ # addl2 $8,sp; set zero bit
359: rsb
360: #
361: # last address that needs saving
362: #
363: .globl end
364: end:
365:
366: #
367: # put uninitialized (not 0) data here
368: #
369: .align 2
370: savedata:
371: # .space ROMSIZE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.