Annotation of qemu/roms/openbios/packages/mac-parts.c, revision 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.