|
|
1.1 root 1: \ *****************************************************************************
2: \ * Copyright (c) 2004, 2008 IBM Corporation
3: \ * All rights reserved.
4: \ * This program and the accompanying materials
5: \ * are made available under the terms of the BSD License
6: \ * which accompanies this distribution, and is available at
7: \ * http://www.opensource.org/licenses/bsd-license.php
8: \ *
9: \ * Contributors:
10: \ * IBM Corporation - initial implementation
11: \ ****************************************************************************/
12:
13:
14: \ Set debug-disk-label? to true to get debug messages for the disk-label code.
15: false VALUE debug-disk-label?
16:
17: \ This value defines the maximum number of blocks (512b) to load from a PREP
18: \ partition. This is required to keep the load time in reasonable limits if the
19: \ PREP partition becomes big.
20: \ If we ever want to put a large kernel with initramfs from a PREP partition
21: \ we might need to increase this value. The default value is 16384 blocks (8MB)
22: d# 16384 value max-prep-partition-blocks
23:
24: s" disk-label" device-name
25:
26: 0 INSTANCE VALUE partition
27: 0 INSTANCE VALUE part-offset
28:
29: 0 INSTANCE VALUE part-start
30: 0 INSTANCE VALUE lpart-start
31: 0 INSTANCE VALUE part-size
32: 0 INSTANCE VALUE dos-logical-partitions
33:
34: 0 INSTANCE VALUE block-size
35: 0 INSTANCE VALUE block
36:
37: 0 INSTANCE VALUE args
38: 0 INSTANCE VALUE args-len
39:
40:
41: INSTANCE VARIABLE block# \ variable to store logical sector#
42: INSTANCE VARIABLE hit# \ partition counter
43: INSTANCE VARIABLE success-flag
44:
45: \ ISO9660 specific information
46: 0ff constant END-OF-DESC
47: 3 constant PARTITION-ID
48: 48 constant VOL-PART-LOC
49:
50:
51: \ DOS partition label (MBR) specific structures
52:
53: STRUCT
54: 1b8 field mbr>boot-loader
55: /l field mbr>disk-signature
56: /w field mbr>null
57: 40 field mbr>partition-table
58: /w field mbr>magic
59:
60: CONSTANT /mbr
61:
62: STRUCT
63: /c field part-entry>active
64: /c field part-entry>start-head
65: /c field part-entry>start-sect
66: /c field part-entry>start-cyl
67: /c field part-entry>id
68: /c field part-entry>end-head
69: /c field part-entry>end-sect
70: /c field part-entry>end-cyl
71: /l field part-entry>sector-offset
72: /l field part-entry>sector-count
73:
74: CONSTANT /partition-entry
75:
76:
77: \ Defined by IEEE 1275-1994 (3.8.1)
78:
79: : offset ( d.rel -- d.abs )
80: part-offset 0 d+
81: ;
82:
83: : seek ( pos.lo pos.hi -- status )
84: offset
85: debug-disk-label? IF 2dup ." seek-parent: pos.hi=0x" u. ." pos.lo=0x" u. THEN
86: s" seek" $call-parent
87: debug-disk-label? IF dup ." status=" . cr THEN
88: ;
89:
90: : read ( addr len -- actual )
91: debug-disk-label? IF 2dup swap ." read-parent: addr=0x" u. ." len=" .d THEN
92: s" read" $call-parent
93: debug-disk-label? IF dup ." actual=" .d cr THEN
94: ;
95:
96:
97: \ read sector to array "block"
98: : read-sector ( sector-number -- )
99: \ block-size is 0x200 on disks, 0x800 on cdrom drives
100: block-size * 0 seek drop \ seek to sector
101: block block-size read drop \ read sector
102: ;
103:
104: : (.part-entry) ( part-entry )
105: cr ." part-entry>active: " dup part-entry>active c@ .d
106: cr ." part-entry>start-head: " dup part-entry>start-head c@ .d
107: cr ." part-entry>start-sect: " dup part-entry>start-sect c@ .d
108: cr ." part-entry>start-cyl: " dup part-entry>start-cyl c@ .d
109: cr ." part-entry>id: " dup part-entry>id c@ .d
110: cr ." part-entry>end-head: " dup part-entry>end-head c@ .d
111: cr ." part-entry>end-sect: " dup part-entry>end-sect c@ .d
112: cr ." part-entry>end-cyl: " dup part-entry>end-cyl c@ .d
113: cr ." part-entry>sector-offset: " dup part-entry>sector-offset l@-le .d
114: cr ." part-entry>sector-count: " dup part-entry>sector-count l@-le .d
115: cr
116: ;
117:
118: : (.name) r@ begin cell - dup @ <colon> = UNTIL xt>name cr type space ;
119:
120: : init-block ( -- )
121: s" block-size" ['] $call-parent CATCH IF ABORT" parent has no block-size." THEN
122: to block-size
123: d# 2048 alloc-mem
124: dup d# 2048 erase
125: to block
126: debug-disk-label? IF
127: ." init-block: block-size=" block-size .d ." block=0x" block u. cr
128: THEN
129: ;
130:
131:
132: \ This word returns true if the currently loaded block has _NO_ MBR magic
133: : no-mbr? ( -- true|false )
134: 0 read-sector block mbr>magic w@-le aa55 <>
135: ;
136:
137: : pc-extended-partition? ( part-entry-addr -- true|false )
138: part-entry>id c@ ( id )
139: dup 5 = swap ( true|false id )
140: dup f = swap ( true|false true|false id )
141: 85 = ( true|false true|false true|false )
142: or or ( true|false )
143: ;
144:
145: : partition>part-entry ( partition -- part-entry )
146: 1- /partition-entry * block mbr>partition-table +
147: ;
148:
149: : partition>start-sector ( partition -- sector-offset )
150: partition>part-entry part-entry>sector-offset l@-le
151: ;
152:
153: : count-dos-logical-partitions ( -- #logical-partitions )
154: no-mbr? IF 0 EXIT THEN
155: 0 5 1 DO ( current )
156: i partition>part-entry ( current part-entry )
157: dup pc-extended-partition? IF
158: part-entry>sector-offset l@-le ( current sector )
159: dup to part-start to lpart-start ( current )
160: BEGIN
161: part-start read-sector \ read EBR
162: 1 partition>start-sector IF
163: \ ." Logical Partition found at " part-start .d cr
164: 1+
165: THEN \ another logical partition
166: 2 partition>start-sector
167: ( current relative-sector )
168: ?dup IF lpart-start + to part-start false ELSE true THEN
169: UNTIL
170: ELSE
171: drop
172: THEN
173: LOOP
174: ;
175:
176: : (get-dos-partition-params) ( ext-part-start part-entry -- offset count active? id )
177: dup part-entry>sector-offset l@-le rot + swap ( offset part-entry )
178: dup part-entry>sector-count l@-le swap ( offset count part-entry )
179: dup part-entry>active c@ 80 = swap ( offset count active? part-entry )
180: part-entry>id c@ ( offset count active? id )
181: ;
182:
183: : find-dos-partition ( partition# -- false | offset count active? id true )
184: to partition 0 to part-start 0 to part-offset
185:
186: \ no negative partitions
187: partition 0<= IF 0 to partition false EXIT THEN
188:
189: \ load MBR and check it
190: no-mbr? IF 0 to partition false EXIT THEN
191:
192: partition 4 <= IF \ Is this a primary partition?
193: 0 partition partition>part-entry
194: (get-dos-partition-params)
195: \ FIXME sanity checks?
196: true EXIT
197: ELSE
198: partition 4 - 0 5 1 DO ( logical-partition current )
199: i partition>part-entry ( log-part current part-entry )
200: dup pc-extended-partition? IF
201: part-entry>sector-offset l@-le ( log-part current sector )
202: dup to part-start to lpart-start ( log-part current )
203: BEGIN
204: part-start read-sector \ read EBR
205: 1 partition>start-sector IF \ first partition entry
206: 1+ 2dup = IF ( log-part current )
207: 2drop
208: part-start 1 partition>part-entry
209: (get-dos-partition-params)
210: true UNLOOP EXIT
211: THEN
212: 2 partition>start-sector
213: ( log-part current relative-sector )
214:
215: ?dup IF lpart-start + to part-start false ELSE true THEN
216: ELSE
217: true
218: THEN
219: UNTIL
220: ELSE
221: drop
222: THEN
223: LOOP
224: 2drop false
225: THEN
226: ;
227:
228: : try-dos-partition ( -- okay? )
229: \ Read partition table and check magic.
230: no-mbr? IF cr ." No DOS disk-label found." cr false EXIT THEN
231:
232: count-dos-logical-partitions TO dos-logical-partitions
233:
234: debug-disk-label? IF
235: ." Found " dos-logical-partitions .d ." logical partitions" cr
236: ." Partition = " partition .d cr
237: THEN
238:
239: partition 1 5 dos-logical-partitions +
240: within 0= IF
241: cr ." Partition # not 1-" 4 dos-logical-partitions + . cr false EXIT
242: THEN
243:
244: \ Could/should check for valid partition here... the magic is not enough really.
245:
246: \ Get the partition offset.
247:
248: partition find-dos-partition IF
249: ( offset count active? id )
250: 2drop drop
251: block-size * to part-offset
252: true
253: ELSE
254: false
255: THEN
256: ;
257:
258: \ Check for an ISO-9660 filesystem on the disk
259: \ : try-iso9660-partition ( -- true|false )
260: \ implement me if you can ;-)
261: \ ;
262:
263:
264: \ Check for an ISO-9660 filesystem on the disk
265: \ (cf. CHRP IEEE 1275 spec., chapter 11.1.2.3)
266: : has-iso9660-filesystem ( -- TRUE|FALSE )
267: \ Seek to the begining of logical 2048-byte sector 16
268: \ refer to Chapter C.11.1 in PAPR 2.0 Spec
269: \ was: 10 read-sector, but this might cause trouble if you
270: \ try booting an ISO image from a device with 512b sectors.
271: 10 800 * 0 seek drop \ seek to sector
272: block 800 read drop \ read sector
273: \ Check for CD-ROM volume magic:
274: block c@ 1 =
275: block 1+ 5 s" CD001" str=
276: and
277: dup IF 800 to block-size THEN
278: ;
279:
280:
281: \ Load from first active DOS boot partition.
282:
283: \ NOTE: block-size is always 512 bytes for DOS partition tables.
284:
285: : load-from-dos-boot-partition ( addr -- size )
286: no-mbr? IF FALSE EXIT THEN \ read MBR and check for DOS disk-label magic
287:
288: count-dos-logical-partitions TO dos-logical-partitions
289:
290: debug-disk-label? IF
291: ." Found " dos-logical-partitions .d ." logical partitions" cr
292: ." Partition = " partition .d cr
293: THEN
294:
295: \ Now walk through the partitions:
296: 5 dos-logical-partitions + 1 DO
297: \ ." checking partition " i .
298: i find-dos-partition IF ( addr offset count active? id )
299: 41 = and ( addr offset count prep-boot-part? )
300: IF ( addr offset count )
301: max-prep-partition-blocks min \ reduce load size
302: swap ( addr count offset )
303: block-size * to part-offset
304: 0 0 seek drop ( addr offset )
305: block-size * read ( size )
306: UNLOOP EXIT
307: ELSE
308: 2drop ( addr )
309: THEN
310: THEN
311: LOOP
312: drop 0
313: ;
314:
315:
316: \ load from a bootable partition
317:
318: : load-from-boot-partition ( addr -- size )
319: load-from-dos-boot-partition
320: \ More boot partition formats ...
321: ;
322:
323:
324:
325: \ Extract the boot loader path from a bootinfo.txt file
326: \ In: address and length of buffer where the bootinfo.txt has been loaded to.
327: \ Out: string address and length of the boot loader (within the input buffer)
328: \ or a string with length = 0 when parsing failed.
329:
330: \ Here is a sample bootinfo file:
331: \ <chrp-boot>
332: \ <description>Linux Distribution</description>
333: \ <os-name>Linux</os-name>
334: \ <boot-script>boot &device;:1,\boot\yaboot.ibm</boot-script>
335: \ <icon size=64,64 color-space=3,3,2>
336: \ <bitmap>[..]</bitmap>
337: \ </icon>
338: \ </chrp-boot>
339:
340: : parse-bootinfo-txt ( addr len -- str len )
341: 2dup s" <boot-script>" find-substr ( addr len pos1 )
342: 2dup = IF
343: \ String not found
344: 3drop 0 0 EXIT
345: THEN
346: dup >r - swap r> + swap ( addr1 len1 )
347: 2dup [char] \ findchar drop ( addr1 len1 pos2 )
348: dup >r - swap r> + swap ( addr2 len2 )
349: 2dup s" </boot-script>" find-substr nip ( addr2 len3 )
350: ;
351:
352: \ Try to load \ppc\bootinfo.txt from the disk (used mainly on CD-ROMs), and if
353: \ available, get the boot loader path from this file and load it.
354: \ See the "CHRP system binding to IEEE 1275" specification for more information
355: \ about bootinfo.txt. An example file can be found in the comment of
356: \ parse-bootinfo-txt ( addr len -- str len )
357:
358: : load-chrp-boot-file ( addr -- size )
359: \ Create bootinfo.txt path name and load that file:
360: my-self parent ihandle>phandle node>path
361: s" :\ppc\bootinfo.txt" $cat strdup ( addr str len )
362: open-dev dup 0= IF 2drop 0 EXIT THEN
363: >r dup ( addr addr R:ihandle )
364: dup s" load" r@ $call-method ( addr addr size R:ihandle )
365: r> close-dev ( addr addr size )
366:
367: \ Now parse the information from bootinfo.txt:
368: parse-bootinfo-txt ( addr fnstr fnlen )
369: dup 0= IF 3drop 0 EXIT THEN
370: \ Create the full path to the boot loader:
371: my-self parent ihandle>phandle node>path ( addr fnstr fnlen nstr nlen )
372: s" :" $cat 2swap $cat strdup ( addr str len )
373: \ Update the bootpath:
374: 2dup encode-string s" bootpath" set-chosen
375: \ And finally load the boot loader itself:
376: open-dev dup 0= IF ." failed to load CHRP boot loader." 2drop 0 EXIT THEN
377: >r s" load" r@ $call-method ( size R:ihandle )
378: r> close-dev ( size )
379: ;
380:
381: \ parse partition number from my-args
382:
383: \ my-args has the following format
384: \ [<partition>[,<path>]]
385:
386: \ | example my-args | example boot command |
387: \ +------------------+---------------------------+
388: \ | 1,\boot\vmlinuz | boot disk:1,\boot\vmlinuz |
389: \ | 2 | boot disk:2 |
390:
391: \ 0 means the whole disk, this is the same behavior
392: \ as if no partition is specified (yaboot wants this).
393:
394: : parse-partition ( -- okay? )
395: 0 to partition
396: 0 to part-offset
397:
398: my-args to args-len to args
399:
400: \ Fix up the "0" thing yaboot does.
401: args-len 1 = IF args c@ [char] 0 = IF 0 to args-len THEN THEN
402:
403: \ Check for "full disk" arguments.
404: my-args [char] , findchar 0= IF true EXIT THEN drop \ no comma
405: my-args [char] , split to args-len to args
406: dup 0= IF 2drop true EXIT THEN \ no first argument
407:
408: \ Check partition #.
409: base @ >r decimal $number r> base !
410: IF cr ." Not a partition #" false EXIT THEN
411:
412: \ Store part #, done.
413: to partition
414: true
415: ;
416:
417:
418: \ try-files and try-partitions
419:
420: : (interpose-filesystem) ( str len -- )
421: find-package IF args args-len rot interpose THEN
422: ;
423:
424: : try-dos-files ( -- found? )
425: no-mbr? IF false EXIT THEN
426:
427: \ block 0 byte 0-2 is a jump instruction in all FAT
428: \ filesystems.
429: \ e9 and eb are jump instructions in x86 assembler.
430: block c@ e9 <> IF
431: block c@ eb <>
432: block 2+ c@ 90 <> or
433: IF false EXIT THEN
434: THEN
435: s" fat-files" (interpose-filesystem)
436: true
437: ;
438:
439: : try-ext2-files ( -- found? )
440: 2 read-sector \ read first superblock
441: block d# 56 + w@-le \ fetch s_magic
442: ef53 <> IF false EXIT THEN \ s_magic found?
443: s" ext2-files" (interpose-filesystem)
444: true
445: ;
446:
447:
448: : try-iso9660-files
449: has-iso9660-filesystem 0= IF false exit THEN
450: s" iso-9660" (interpose-filesystem)
451: true
452: ;
453:
454: : try-files ( -- found? )
455: \ If no path, then full disk.
456: args-len 0= IF true EXIT THEN
457:
458: try-dos-files IF true EXIT THEN
459: try-ext2-files IF true EXIT THEN
460: try-iso9660-files IF true EXIT THEN
461:
462: \ ... more filesystem types here ...
463:
464: false
465: ;
466:
467: : try-partitions ( -- found? )
468: try-dos-partition IF try-files EXIT THEN
469: \ try-iso9660-partition IF try-files EXIT THEN
470: \ ... more partition types here...
471: false
472: ;
473:
474: \ Interface functions for disk-label package
475: \ as defined by IEEE 1275-1994 3.8.1
476:
477: : close ( -- )
478: debug-disk-label? IF ." Closing disk-label: block=0x" block u. ." block-size=" block-size .d cr THEN
479: block d# 2048 free-mem
480: ;
481:
482:
483: : open ( -- true|false )
484: init-block
485:
486: parse-partition 0= IF
487: close
488: false EXIT
489: THEN
490:
491: partition IF
492: try-partitions
493: ELSE
494: try-files
495: THEN
496: dup 0= IF debug-disk-label? IF ." not found." cr THEN close THEN \ free memory again
497: ;
498:
499:
500: \ Boot & Load w/o arguments is assumed to be boot from boot partition
501:
502: : load ( addr -- size )
503: debug-disk-label? IF
504: ." load: " dup u. cr
505: THEN
506:
507: args-len IF
508: TRUE ABORT" Load done w/o filesystem"
509: ELSE
510: partition IF
511: 0 0 seek drop
512: 200000 read
513: ELSE
514: has-iso9660-filesystem IF
515: dup load-chrp-boot-file ?dup 0 > IF nip EXIT THEN
516: THEN
517: load-from-boot-partition
518: dup 0= ABORT" No boot partition found"
519: THEN
520: THEN
521: ;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.