Annotation of qemu/roms/SLOF/slof/fs/packages/disk-label.fs, revision 1.1.1.2

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: ;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.