Annotation of qemu/roms/openbios/packages/mac-parts.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *   Creation Date: <2003/12/04 17:07:05 samuel>
                      3:  *   Time-stamp: <2004/01/07 19:36:09 samuel>
                      4:  *
                      5:  *     <mac-parts.c>
                      6:  *
                      7:  *     macintosh partition support
                      8:  *
                      9:  *   Copyright (C) 2003, 2004 Samuel Rydh ([email protected])
                     10:  *
                     11:  *   This program is free software; you can redistribute it and/or
                     12:  *   modify it under the terms of the GNU General Public License
                     13:  *   version 2
                     14:  *
                     15:  */
                     16: 
                     17: #include "config.h"
                     18: #include "libopenbios/bindings.h"
                     19: #include "libopenbios/load.h"
                     20: #include "mac-parts.h"
                     21: #include "libc/byteorder.h"
                     22: #include "libc/vsprintf.h"
                     23: #include "packages.h"
                     24: 
                     25: //#define CONFIG_DEBUG_MAC_PARTS
                     26: 
                     27: #ifdef CONFIG_DEBUG_MAC_PARTS
                     28: #define DPRINTF(fmt, args...) \
                     29: do { printk("MAC-PARTS: " fmt , ##args); } while (0)
                     30: #else
                     31: #define DPRINTF(fmt, args...) do {} while(0)
                     32: #endif
                     33: 
                     34: typedef struct {
                     35:        xt_t            seek_xt, read_xt;
                     36:        ucell           offs_hi, offs_lo;
                     37:         ucell          size_hi, size_lo;
                     38:        unsigned int    blocksize;
                     39:        phandle_t       filesystem_ph;
                     40: } macparts_info_t;
                     41: 
                     42: DECLARE_NODE( macparts, INSTALL_OPEN, sizeof(macparts_info_t), "+/packages/mac-parts" );
                     43: 
                     44: #define SEEK( pos )            ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
                     45: #define READ( buf, size )      ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); })
                     46: 
                     47: /* ( open -- flag ) */
                     48: static void
                     49: macparts_open( macparts_info_t *di )
                     50: {
                     51:        char *str = my_args_copy();
                     52:        char *argstr = strdup("");
                     53:        char *parstr = strdup("");
                     54:        int bs, parnum=-1;
                     55:        desc_map_t dmap;
                     56:        part_entry_t par;
                     57:        int ret = 0;
                     58:        int want_bootcode = 0;
                     59:        phandle_t ph;
                     60:        ducell offs = 0, size = -1;
                     61: 
                     62:        DPRINTF("macparts_open '%s'\n", str );
                     63: 
                     64:        /* 
                     65:                Arguments that we accept:
                     66:                id: [0-7]
                     67:                [(id)][,][filespec]
                     68:        */
                     69: 
                     70:        if( str ) {
                     71:                if ( !strlen(str) )
                     72:                        parnum = -1;
                     73:                else {
                     74:                        /* Detect the boot parameters */
                     75:                        char *ptr;
                     76:                        ptr = str;
                     77: 
                     78:                        /* <id>,<file> */
                     79:                        if (*ptr >= '0' && *ptr <= '9' && *(ptr + 1) == ',') {
                     80:                                parstr = ptr;
                     81:                                *(ptr + 1) = '\0';
                     82:                                argstr = ptr + 2;
                     83:                        }
                     84: 
                     85:                        /* <id> */
                     86:                        else if (*ptr >= '0' && *ptr <='9' && *(ptr + 1) == '\0') {
                     87:                                parstr = ptr;
                     88:                        }
                     89: 
                     90:                        /* ,<file> */
                     91:                        else if (*ptr == ',') {
                     92:                                argstr = ptr + 1;
                     93:                        }       
                     94: 
                     95:                        /* <file> */
                     96:                        else {
                     97:                                argstr = str;
                     98:                        }
                     99:                
                    100:                        /* Convert the id to a partition number */
                    101:                        if (strlen(parstr))
                    102:                                parnum = atol(parstr);
                    103: 
                    104:                        /* Detect if we are looking for the bootcode */
                    105:                        if (strcmp(argstr, "%BOOT") == 0)
                    106:                                want_bootcode = 1;
                    107:                }
                    108:        }
                    109: 
                    110:        DPRINTF("parstr: %s  argstr: %s  parnum: %d\n", parstr, argstr, parnum);
                    111: 
                    112:        DPRINTF("want_bootcode %d\n", want_bootcode);
                    113:        DPRINTF("macparts_open %d\n", parnum);
                    114: 
                    115:        di->filesystem_ph = 0;
                    116:        di->read_xt = find_parent_method("read");
                    117:        di->seek_xt = find_parent_method("seek");
                    118: 
                    119:        SEEK( 0 );
                    120:        if( READ(&dmap, sizeof(dmap)) != sizeof(dmap) )
                    121:                goto out;
                    122: 
                    123:        /* partition maps might support multiple block sizes; in this case,
                    124:         * pmPyPartStart is typically given in terms of 512 byte blocks.
                    125:         */
                    126:        bs = __be16_to_cpu(dmap.sbBlockSize);
                    127:        if( bs != 512 ) {
                    128:                SEEK( 512 );
                    129:                READ( &par, sizeof(par) );
                    130:                if( __be16_to_cpu(par.pmSig) == DESC_PART_SIGNATURE )
                    131:                        bs = 512;
                    132:        }
                    133:        SEEK( bs );
                    134:        if( READ(&par, sizeof(par)) != sizeof(par) )
                    135:                goto out;
                    136:         if (__be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE)
                    137:                goto out;
                    138: 
                    139:        /*
                    140:         * Implement partition selection as per the PowerPC Microprocessor CHRP bindings
                    141:         */
                    142: 
                    143:        if (str == NULL || parnum == 0) {
                    144:                /* According to the spec, partition 0 as well as no arguments means the whole disk */
                    145:                offs = (long long)0;
                    146:                size = (long long)__be32_to_cpu(dmap.sbBlkCount) * bs;
                    147: 
                    148:                di->blocksize = (unsigned int)bs;
                    149: 
                    150:                di->offs_hi = offs >> BITS;
                    151:                di->offs_lo = offs & (ucell) -1;
                    152:        
                    153:                di->size_hi = size >> BITS;
                    154:                di->size_lo = size & (ucell) -1;
                    155: 
                    156:                ret = -1;
                    157:                goto out;
                    158: 
                    159:        } else if (parnum == -1 && strlen(argstr)) {
                    160: 
                    161:                DPRINTF("mac-parts: counted %d partitions\n", __be32_to_cpu(par.pmMapBlkCnt));
                    162: 
                    163:                /* No partition was explicitly requested, but an argstr was passed in.
                    164:                   So let's find a suitable partition... */
                    165:                for (parnum = 1; parnum <= __be32_to_cpu(par.pmMapBlkCnt); parnum++) {
                    166:                        SEEK( bs * parnum );
                    167:                        READ( &par, sizeof(par) );
                    168:                        if( __be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE ||
                    169:                             !__be32_to_cpu(par.pmPartBlkCnt) )
                    170:                                break;
                    171: 
                    172:                        DPRINTF("found partition type: %s with status %x\n", par.pmPartType, __be32_to_cpu(par.pmPartStatus));
                    173: 
                    174:                        /* If we have a valid, allocated and readable partition... */
                    175:                        if( (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
                    176:                        (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
                    177:                        (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) ) {
                    178:                                offs = (long long)__be32_to_cpu(par.pmPyPartStart) * bs;
                    179:                                size = (long long)__be32_to_cpu(par.pmPartBlkCnt) * bs;
                    180: 
                    181:                                /* If the filename was set to %BOOT, we actually want the bootcode */
                    182:                                if (want_bootcode && (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsBootValid)) {
                    183:                                        offs += (long long)__be32_to_cpu(par.pmLgBootStart) * bs;
                    184:                                        size = (long long)__be32_to_cpu(par.pmBootSize);
                    185: 
                    186:                                        goto found;
                    187:                                } else {
                    188:                                        /* Otherwise we were passed a filename and path. So let's
                    189:                                           choose the first partition with a valid filesystem */
                    190:                                        DPUSH( offs );
                    191:                                        PUSH_ih( my_parent() );
                    192:                                        parword("find-filesystem");
                    193:                                
                    194:                                        ph = POP_ph();
                    195:                                        if (ph)
                    196:                                                goto found;
                    197:                                }
                    198:                        }
                    199:                }
                    200: 
                    201:        } else {
                    202:                /* Another partition was explicitly requested */
                    203:                SEEK( bs * parnum );
                    204:                READ( &par, sizeof(par) );
                    205: 
                    206:                if( (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
                    207:                            (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
                    208:                            (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) ) {
                    209: 
                    210:                        offs = (long long)__be32_to_cpu(par.pmPyPartStart) * bs;
                    211:                        size = (long long)__be32_to_cpu(par.pmPartBlkCnt) * bs;
                    212:                }
                    213:        }
                    214: 
                    215:        /* If we couldn't find a partition, exit */
                    216:        if (size == -1) {
                    217:                DPRINTF("Unable to automatically find partition!\n");
                    218:                goto out;
                    219:        }
                    220: 
                    221: found:
                    222: 
                    223:        ret = -1;
                    224:        di->blocksize = (unsigned int)bs;
                    225: 
                    226:        di->offs_hi = offs >> BITS;
                    227:        di->offs_lo = offs & (ucell) -1;
                    228: 
                    229:        di->size_hi = size >> BITS;
                    230:        di->size_lo = size & (ucell) -1;
                    231: 
                    232:        /* We have a valid partition - so probe for a filesystem at the current offset */
                    233:        DPRINTF("mac-parts: about to probe for fs\n");
                    234:        DPUSH( offs );
                    235:        PUSH_ih( my_parent() );
                    236:        parword("find-filesystem");
                    237:        DPRINTF("mac-parts: done fs probe\n");
                    238: 
                    239:        ph = POP_ph();
                    240:        if( ph ) {
                    241:                DPRINTF("mac-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
                    242:                di->filesystem_ph = ph;
                    243: 
                    244:                /* If the filename was %BOOT then it's not a real filename, so clear argstr before
                    245:                   attempting interpose */
                    246:                if (want_bootcode)
                    247:                        argstr = strdup("");
                    248: 
                    249:                /* If we have been asked to open a particular file, interpose the filesystem package with 
                    250:                   the passed filename as an argument */
                    251:                if (strlen(argstr)) {
                    252:                        push_str( argstr );
                    253:                        PUSH_ph( ph );
                    254:                        fword("interpose");
                    255:                }
                    256:        } else {
                    257:                DPRINTF("mac-parts: no filesystem found; bypassing misc-files interpose\n");
                    258:        }
                    259: 
                    260:        free( str );
                    261: 
                    262: out:
                    263:        PUSH( ret );
                    264: }
                    265: 
                    266: /* ( block0 -- flag? ) */
                    267: static void
                    268: macparts_probe( macparts_info_t *dummy )
                    269: {
                    270:        desc_map_t *dmap = (desc_map_t*)cell2pointer(POP());
                    271: 
                    272:        DPRINTF("macparts_probe %x ?= %x\n", dmap->sbSig, DESC_MAP_SIGNATURE);
                    273:        if( __be16_to_cpu(dmap->sbSig) != DESC_MAP_SIGNATURE )
                    274:                RET(0);
                    275:        RET(-1);
                    276: }
                    277: 
                    278: /* ( -- type offset.d size.d ) */
                    279: static void
                    280: macparts_get_info( macparts_info_t *di )
                    281: {
                    282:        DPRINTF("macparts_get_info");
                    283: 
                    284:        PUSH( -1 );             /* no type */
                    285:        PUSH( di->offs_lo );
                    286:        PUSH( di->offs_hi );
                    287:        PUSH( di->size_lo );
                    288:        PUSH( di->size_hi );
                    289: }
                    290: 
                    291: static void
                    292: macparts_block_size( macparts_info_t *di )
                    293: {
                    294:        DPRINTF("macparts_block_size = %x\n", di->blocksize);
                    295:        PUSH(di->blocksize);
                    296: }
                    297: 
                    298: static void
                    299: macparts_initialize( macparts_info_t *di )
                    300: {
                    301:        fword("register-partition-package");
                    302: }
                    303: 
                    304: /* ( pos.d -- status ) */
                    305: static void
                    306: macparts_seek(macparts_info_t *di )
                    307: {
                    308:        long long pos = DPOP();
                    309:        long long offs, size;
                    310: 
                    311:        DPRINTF("macparts_seek %llx:\n", pos);
                    312: 
                    313:        /* Seek is invalid if we reach the end of the device */
                    314:        size = ((ducell)di->size_hi << BITS) | di->size_lo;
                    315:        if (pos > size)
                    316:                RET( -1 );
                    317: 
                    318:        /* Calculate the seek offset for the parent */
                    319:        offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
                    320:        offs += pos;
                    321:        DPUSH(offs);
                    322: 
                    323:        DPRINTF("macparts_seek parent offset %llx:\n", offs);
                    324: 
                    325:        call_package(di->seek_xt, my_parent());
                    326: }
                    327: 
                    328: /* ( buf len -- actlen ) */
                    329: static void
                    330: macparts_read(macparts_info_t *di )
                    331: {
                    332:        DPRINTF("macparts_read\n");
                    333: 
                    334:        /* Pass the read back up to the parent */
                    335:        call_package(di->read_xt, my_parent());
                    336: }
                    337: 
                    338: /* ( addr -- size ) */
                    339: static void
                    340: macparts_load( __attribute__((unused))macparts_info_t *di )
                    341: {
                    342:        /* Invoke the loader */
                    343:        load(my_self());
                    344: }
                    345: 
                    346: /* ( pathstr len -- ) */
                    347: static void
                    348: macparts_dir( macparts_info_t *di )
                    349: {
                    350:        /* On PPC Mac, the first partition chosen according to the CHRP boot
                    351:        specification (i.e. marked as bootable) may not necessarily contain 
                    352:        a valid FS */
                    353:        if ( di->filesystem_ph ) {
                    354:                PUSH( my_self() );
                    355:                push_str("dir");
                    356:                PUSH( di->filesystem_ph );
                    357:                fword("find-method");
                    358:                POP();
                    359:                fword("execute");
                    360:        } else {
                    361:                forth_printf("mac-parts: Unable to determine filesystem\n");
                    362:                POP();
                    363:                POP();
                    364:        }
                    365: }
                    366: 
                    367: NODE_METHODS( macparts ) = {
                    368:        { "probe",      macparts_probe          },
                    369:        { "open",       macparts_open           },
                    370:        { "seek",       macparts_seek           },
                    371:        { "read",       macparts_read           },
                    372:        { "load",       macparts_load           },
                    373:        { "dir",        macparts_dir            },
                    374:        { "get-info",   macparts_get_info       },
                    375:        { "block-size", macparts_block_size     },
                    376:        { NULL,         macparts_initialize     },
                    377: };
                    378: 
                    379: void
                    380: macparts_init( void )
                    381: {
                    382:        REGISTER_NODE( macparts );
                    383: }

unix.superglobalmegacorp.com

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