|
|
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 )
1.1.1.2 ! root 80: part-offset xlsplit d+
1.1 root 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 )
1.1.1.2 ! root 250: 2drop
! 251: to part-size
1.1 root 252: block-size * to part-offset
253: true
254: ELSE
255: false
256: THEN
257: ;
258:
259: \ Check for an ISO-9660 filesystem on the disk
260: \ : try-iso9660-partition ( -- true|false )
261: \ implement me if you can ;-)
262: \ ;
263:
264:
265: \ Check for an ISO-9660 filesystem on the disk
266: \ (cf. CHRP IEEE 1275 spec., chapter 11.1.2.3)
267: : has-iso9660-filesystem ( -- TRUE|FALSE )
268: \ Seek to the begining of logical 2048-byte sector 16
269: \ refer to Chapter C.11.1 in PAPR 2.0 Spec
270: \ was: 10 read-sector, but this might cause trouble if you
271: \ try booting an ISO image from a device with 512b sectors.
272: 10 800 * 0 seek drop \ seek to sector
273: block 800 read drop \ read sector
274: \ Check for CD-ROM volume magic:
275: block c@ 1 =
276: block 1+ 5 s" CD001" str=
277: and
278: dup IF 800 to block-size THEN
279: ;
280:
281:
282: \ Load from first active DOS boot partition.
283:
284: \ NOTE: block-size is always 512 bytes for DOS partition tables.
285:
286: : load-from-dos-boot-partition ( addr -- size )
287: no-mbr? IF FALSE EXIT THEN \ read MBR and check for DOS disk-label magic
288:
289: count-dos-logical-partitions TO dos-logical-partitions
290:
291: debug-disk-label? IF
292: ." Found " dos-logical-partitions .d ." logical partitions" cr
293: ." Partition = " partition .d cr
294: THEN
295:
296: \ Now walk through the partitions:
297: 5 dos-logical-partitions + 1 DO
298: \ ." checking partition " i .
299: i find-dos-partition IF ( addr offset count active? id )
300: 41 = and ( addr offset count prep-boot-part? )
301: IF ( addr offset count )
302: max-prep-partition-blocks min \ reduce load size
303: swap ( addr count offset )
304: block-size * to part-offset
305: 0 0 seek drop ( addr offset )
306: block-size * read ( size )
307: UNLOOP EXIT
308: ELSE
309: 2drop ( addr )
310: THEN
311: THEN
312: LOOP
313: drop 0
314: ;
315:
316:
317: \ load from a bootable partition
318:
319: : load-from-boot-partition ( addr -- size )
320: load-from-dos-boot-partition
321: \ More boot partition formats ...
322: ;
323:
324:
325:
326: \ Extract the boot loader path from a bootinfo.txt file
327: \ In: address and length of buffer where the bootinfo.txt has been loaded to.
328: \ Out: string address and length of the boot loader (within the input buffer)
329: \ or a string with length = 0 when parsing failed.
330:
331: \ Here is a sample bootinfo file:
332: \ <chrp-boot>
333: \ <description>Linux Distribution</description>
334: \ <os-name>Linux</os-name>
335: \ <boot-script>boot &device;:1,\boot\yaboot.ibm</boot-script>
336: \ <icon size=64,64 color-space=3,3,2>
337: \ <bitmap>[..]</bitmap>
338: \ </icon>
339: \ </chrp-boot>
340:
341: : parse-bootinfo-txt ( addr len -- str len )
342: 2dup s" <boot-script>" find-substr ( addr len pos1 )
343: 2dup = IF
344: \ String not found
345: 3drop 0 0 EXIT
346: THEN
347: dup >r - swap r> + swap ( addr1 len1 )
348: 2dup [char] \ findchar drop ( addr1 len1 pos2 )
349: dup >r - swap r> + swap ( addr2 len2 )
350: 2dup s" </boot-script>" find-substr nip ( addr2 len3 )
351: ;
352:
353: \ Try to load \ppc\bootinfo.txt from the disk (used mainly on CD-ROMs), and if
354: \ available, get the boot loader path from this file and load it.
355: \ See the "CHRP system binding to IEEE 1275" specification for more information
356: \ about bootinfo.txt. An example file can be found in the comment of
357: \ parse-bootinfo-txt ( addr len -- str len )
358:
359: : load-chrp-boot-file ( addr -- size )
360: \ Create bootinfo.txt path name and load that file:
361: my-self parent ihandle>phandle node>path
362: s" :\ppc\bootinfo.txt" $cat strdup ( addr str len )
363: open-dev dup 0= IF 2drop 0 EXIT THEN
364: >r dup ( addr addr R:ihandle )
365: dup s" load" r@ $call-method ( addr addr size R:ihandle )
366: r> close-dev ( addr addr size )
367:
368: \ Now parse the information from bootinfo.txt:
369: parse-bootinfo-txt ( addr fnstr fnlen )
370: dup 0= IF 3drop 0 EXIT THEN
371: \ Create the full path to the boot loader:
372: my-self parent ihandle>phandle node>path ( addr fnstr fnlen nstr nlen )
373: s" :" $cat 2swap $cat strdup ( addr str len )
374: \ Update the bootpath:
375: 2dup encode-string s" bootpath" set-chosen
376: \ And finally load the boot loader itself:
377: open-dev dup 0= IF ." failed to load CHRP boot loader." 2drop 0 EXIT THEN
378: >r s" load" r@ $call-method ( size R:ihandle )
379: r> close-dev ( size )
380: ;
381:
382: \ parse partition number from my-args
383:
384: \ my-args has the following format
385: \ [<partition>[,<path>]]
386:
387: \ | example my-args | example boot command |
388: \ +------------------+---------------------------+
389: \ | 1,\boot\vmlinuz | boot disk:1,\boot\vmlinuz |
390: \ | 2 | boot disk:2 |
391:
392: \ 0 means the whole disk, this is the same behavior
393: \ as if no partition is specified (yaboot wants this).
394:
395: : parse-partition ( -- okay? )
396: 0 to partition
397: 0 to part-offset
1.1.1.2 ! root 398: 0 to part-size
1.1 root 399:
400: my-args to args-len to args
401:
1.1.1.2 ! root 402: debug-disk-label? IF
! 403: cr ." disk-label parse-partition: my-args=" my-args type cr
! 404: THEN
! 405:
! 406: \ Called without arguments?
! 407: args-len 0 = IF true EXIT THEN
1.1 root 408:
409: \ Check for "full disk" arguments.
1.1.1.2 ! root 410: my-args [char] , findchar 0= IF \ no comma?
! 411: args c@ isdigit not IF \ ... and not a partition number?
! 412: true EXIT \ ... then it's not a partition we can parse
! 413: THEN
! 414: ELSE
! 415: drop
! 416: THEN
1.1 root 417: my-args [char] , split to args-len to args
418: dup 0= IF 2drop true EXIT THEN \ no first argument
419:
420: \ Check partition #.
421: base @ >r decimal $number r> base !
422: IF cr ." Not a partition #" false EXIT THEN
423:
424: \ Store part #, done.
425: to partition
426: true
427: ;
428:
429:
430: \ try-files and try-partitions
431:
432: : (interpose-filesystem) ( str len -- )
433: find-package IF args args-len rot interpose THEN
434: ;
435:
436: : try-dos-files ( -- found? )
437: no-mbr? IF false EXIT THEN
438:
439: \ block 0 byte 0-2 is a jump instruction in all FAT
440: \ filesystems.
441: \ e9 and eb are jump instructions in x86 assembler.
442: block c@ e9 <> IF
443: block c@ eb <>
444: block 2+ c@ 90 <> or
445: IF false EXIT THEN
446: THEN
447: s" fat-files" (interpose-filesystem)
448: true
449: ;
450:
451: : try-ext2-files ( -- found? )
452: 2 read-sector \ read first superblock
453: block d# 56 + w@-le \ fetch s_magic
454: ef53 <> IF false EXIT THEN \ s_magic found?
455: s" ext2-files" (interpose-filesystem)
456: true
457: ;
458:
459:
460: : try-iso9660-files
461: has-iso9660-filesystem 0= IF false exit THEN
462: s" iso-9660" (interpose-filesystem)
463: true
464: ;
465:
466: : try-files ( -- found? )
467: \ If no path, then full disk.
468: args-len 0= IF true EXIT THEN
469:
470: try-dos-files IF true EXIT THEN
471: try-ext2-files IF true EXIT THEN
472: try-iso9660-files IF true EXIT THEN
473:
474: \ ... more filesystem types here ...
475:
476: false
477: ;
478:
479: : try-partitions ( -- found? )
480: try-dos-partition IF try-files EXIT THEN
481: \ try-iso9660-partition IF try-files EXIT THEN
482: \ ... more partition types here...
483: false
484: ;
485:
486: \ Interface functions for disk-label package
487: \ as defined by IEEE 1275-1994 3.8.1
488:
489: : close ( -- )
490: debug-disk-label? IF ." Closing disk-label: block=0x" block u. ." block-size=" block-size .d cr THEN
491: block d# 2048 free-mem
492: ;
493:
494:
495: : open ( -- true|false )
496: init-block
497:
498: parse-partition 0= IF
499: close
500: false EXIT
501: THEN
502:
503: partition IF
504: try-partitions
505: ELSE
506: try-files
507: THEN
508: dup 0= IF debug-disk-label? IF ." not found." cr THEN close THEN \ free memory again
509: ;
510:
511:
512: \ Boot & Load w/o arguments is assumed to be boot from boot partition
513:
514: : load ( addr -- size )
515: debug-disk-label? IF
516: ." load: " dup u. cr
517: THEN
518:
519: args-len IF
520: TRUE ABORT" Load done w/o filesystem"
521: ELSE
522: partition IF
523: 0 0 seek drop
1.1.1.2 ! root 524: part-size IF
! 525: part-size max-prep-partition-blocks min \ Load size
! 526: ELSE
! 527: max-prep-partition-blocks
! 528: THEN
! 529: 200 * read
1.1 root 530: ELSE
531: has-iso9660-filesystem IF
532: dup load-chrp-boot-file ?dup 0 > IF nip EXIT THEN
533: THEN
534: load-from-boot-partition
535: dup 0= ABORT" No boot partition found"
536: THEN
537: THEN
538: ;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.