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

1.1       root        1: /*
                      2:  *   pc partition support
                      3:  *
                      4:  *   Copyright (C) 2004 Stefan Reinauer
                      5:  *
                      6:  *   This code is based (and copied in many places) from
                      7:  *   mac partition support by Samuel Rydh ([email protected])
                      8:  *
                      9:  *   This program is free software; you can redistribute it and/or
                     10:  *   modify it under the terms of the GNU General Public License
                     11:  *   version 2
                     12:  *
                     13:  */
                     14: 
                     15: #include "config.h"
                     16: #include "libopenbios/bindings.h"
                     17: #include "libopenbios/load.h"
                     18: #include "libc/byteorder.h"
                     19: #include "libc/vsprintf.h"
                     20: #include "packages.h"
                     21: 
                     22: //#define DEBUG_PC_PARTS
                     23: 
                     24: #ifdef DEBUG_PC_PARTS
                     25: #define DPRINTF(fmt, args...)                   \
                     26:     do { printk(fmt , ##args); } while (0)
                     27: #else
                     28: #define DPRINTF(fmt, args...)
                     29: #endif
                     30: 
                     31: typedef struct {
                     32:        xt_t            seek_xt, read_xt;
                     33:        ucell           offs_hi, offs_lo;
                     34:         ucell          size_hi, size_lo;
                     35:        phandle_t       filesystem_ph;
                     36: } pcparts_info_t;
                     37: 
                     38: DECLARE_NODE( pcparts, INSTALL_OPEN, sizeof(pcparts_info_t), "+/packages/pc-parts" );
                     39: 
                     40: #define SEEK( pos )            ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
                     41: #define READ( buf, size )      ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); })
                     42: 
                     43: /* three helper functions */
                     44: 
                     45: static inline int has_pc_valid_partition(unsigned char *sect)
                     46: {
                     47:        /* Make sure the partition table contains at least one valid entry */
                     48:        return (sect[0x1c2] != 0 || sect[0x1d2] != 0 || sect[0x1e2] != 0);
                     49: }
                     50: 
                     51: static inline int has_pc_part_magic(unsigned char *sect)
                     52: {
                     53:        return sect[0x1fe]==0x55 && sect[0x1ff]==0xAA;
                     54: }
                     55: 
                     56: static inline int is_pc_extended_part(unsigned char type)
                     57: {
                     58:        return type==5 || type==0xf || type==0x85;
                     59: }
                     60: 
                     61: /* ( open -- flag ) */
                     62: static void
                     63: pcparts_open( pcparts_info_t *di )
                     64: {
                     65:        char *str = my_args_copy();
                     66:        char *argstr = strdup("");
                     67:        char *parstr = strdup("");
                     68:        int bs, parnum=-1;
                     69:        int found = 0;
                     70:        phandle_t ph;
                     71:        ducell offs, size;
                     72: 
                     73:        /* Layout of PC partition table */
                     74:        struct pc_partition {
                     75:                unsigned char boot;
                     76:                unsigned char head;
                     77:                unsigned char sector;
                     78:                unsigned char cyl;
                     79:                unsigned char type;
                     80:                unsigned char e_head;
                     81:                unsigned char e_sector;
                     82:                unsigned char e_cyl;
                     83:                u32 start_sect; /* unaligned little endian */
                     84:                u32 nr_sects; /* ditto */
                     85:        } *p, *partition;
                     86: 
                     87:        unsigned char buf[512];
                     88: 
                     89:        DPRINTF("pcparts_open '%s'\n", str );
                     90: 
                     91:        /* 
                     92:                Arguments that we accept:
                     93:                id: [0-7]
                     94:                [(id)][,][filespec]
                     95:        */
                     96: 
                     97:        if( str ) {
                     98:                if ( !strlen(str) )
                     99:                        parnum = -1;
                    100:                else {
                    101:                        /* Detect the boot parameters */
                    102:                        char *ptr;
                    103:                        ptr = str;
                    104: 
                    105:                        /* <id>,<file> */
                    106:                        if (*ptr >= '0' && *ptr <= '9' && *(ptr + 1) == ',') {
                    107:                                parstr = ptr;
                    108:                                *(ptr + 1) = '\0';
                    109:                                argstr = ptr + 2;
                    110:                        }
                    111: 
                    112:                        /* <id> */
                    113:                        else if (*ptr >= '0' && *ptr <='9' && *(ptr + 1) == '\0') {
                    114:                                parstr = ptr;
                    115:                        }
                    116: 
                    117:                        /* ,<file> */
                    118:                        else if (*ptr == ',') {
                    119:                                argstr = ptr + 1;
                    120:                        }       
                    121: 
                    122:                        /* <file> */
                    123:                        else {
                    124:                                argstr = str;
                    125:                        }
                    126:                
                    127:                        /* Convert the id to a partition number */
                    128:                        if (strlen(parstr))
                    129:                                parnum = atol(parstr);
                    130:                }
                    131:        }
                    132: 
                    133:        DPRINTF("parstr: %s  argstr: %s  parnum: %d\n", parstr, argstr, parnum);
                    134:         free(parstr);
                    135: 
                    136:        if( parnum < 0 )
                    137:                parnum = 0;
                    138: 
                    139:        di->filesystem_ph = 0;
                    140:        di->read_xt = find_parent_method("read");
                    141:        di->seek_xt = find_parent_method("seek");
                    142: 
                    143:        SEEK( 0 );
                    144:        if( READ(buf, 512) != 512 )
                    145:                RET(0);
                    146: 
                    147:        /* Check Magic */
                    148:        if (!has_pc_part_magic(buf)) {
                    149:                DPRINTF("pc partition magic not found.\n");
                    150:                RET(0);
                    151:        }
                    152: 
                    153:        /* Actual partition data */
                    154:        partition = (struct pc_partition *) (buf + 0x1be);
                    155: 
                    156:        /* Make sure we use a copy accessible from an aligned pointer (some archs
                    157:           e.g. SPARC will crash otherwise) */
                    158:        p = malloc(sizeof(struct pc_partition));
                    159: 
                    160:        bs = 512;
                    161: 
                    162:        if (parnum < 4) {
                    163:                /* primary partition */
                    164:                partition += parnum;
                    165:                memcpy(p, partition, sizeof(struct pc_partition));
                    166: 
                    167:                if (p->type == 0 || is_pc_extended_part(p->type)) {
                    168:                        DPRINTF("partition %d does not exist\n", parnum+1 );
                    169:                        RET( 0 );
                    170:                }
                    171: 
                    172:                offs = (long long)(__le32_to_cpu(p->start_sect)) * bs;
                    173:                di->offs_hi = offs >> BITS;
                    174:                di->offs_lo = offs & (ucell) -1;
                    175: 
                    176:                size = (long long)(__le32_to_cpu(p->nr_sects)) * bs;
                    177:                di->size_hi = size >> BITS;
                    178:                di->size_lo = size & (ucell) -1;
                    179: 
                    180:                DPRINTF("Primary partition at sector %x\n", __le32_to_cpu(p->start_sect));
                    181: 
                    182:                found = 1;
                    183:        } else {
                    184:                /* Extended partition */
                    185:                int i, cur_part;
                    186:                unsigned long ext_start, cur_table;
                    187: 
                    188:                /* Search for the extended partition
                    189:                 * which contains logical partitions */
                    190:                for (i = 0; i < 4; i++) {
                    191:                        if (is_pc_extended_part(p[i].type))
                    192:                                break;
                    193:                }
                    194: 
                    195:                if (i >= 4) {
                    196:                        DPRINTF("Extended partition not found\n");
                    197:                        RET( 0 );
                    198:                }
                    199: 
                    200:                DPRINTF("Extended partition at %d\n", i+1);
                    201: 
                    202:                /* Visit each logical partition labels */
                    203:                ext_start = __le32_to_cpu(p[i].start_sect);
                    204:                cur_table = ext_start;
                    205:                cur_part = 4;
                    206: 
                    207:                while (cur_part <= parnum) {
                    208:                        DPRINTF("cur_part=%d at %lx\n", cur_part, cur_table);
                    209: 
                    210:                        SEEK( cur_table * bs );
                    211:                        if( READ(buf, sizeof(512)) != sizeof(512) )
                    212:                                RET( 0 );
                    213: 
                    214:                        if (!has_pc_part_magic(buf)) {
                    215:                                DPRINTF("Extended partition has no magic\n");
                    216:                                break;
                    217:                        }
                    218: 
                    219:                        /* Read the extended partition, making sure we are aligned again */
                    220:                        partition = (struct pc_partition *) (buf + 0x1be);
                    221:                        memcpy(p, partition, sizeof(struct pc_partition));
                    222: 
                    223:                        /* First entry is the logical partition */
                    224:                        if (cur_part == parnum) {
                    225:                                if (p->type == 0) {
                    226:                                        DPRINTF("Partition %d is empty\n", parnum+1);
                    227:                                        RET( 0 );
                    228:                                }
                    229: 
                    230:                                offs = (long long)(cur_table+__le32_to_cpu(p->start_sect)) * bs;
                    231:                                di->offs_hi = offs >> BITS;
                    232:                                di->offs_lo = offs & (ucell) -1;
                    233: 
                    234:                                size = (long long)__le32_to_cpu(p->nr_sects) * bs;
                    235:                                di->size_hi = size >> BITS;
                    236:                                di->size_lo = size & (ucell) -1;
                    237: 
                    238:                                found = 1;
                    239:                                break;
                    240:                        }
                    241: 
                    242:                        /* Second entry is link to next partition */
                    243:                        if (!is_pc_extended_part(p[1].type)) {
                    244:                                DPRINTF("no link\n");
                    245:                                break;
                    246:                        }
                    247: 
                    248:                        cur_table = ext_start + __le32_to_cpu(p[1].start_sect);
                    249:                        cur_part++;
                    250:                }
                    251: 
                    252:                if (!found) {
                    253:                        DPRINTF("Logical partition %d does not exist\n", parnum+1);
                    254:                        RET( 0 );
                    255:                }
                    256:        }
                    257:        
                    258:        free(p);
                    259: 
                    260:        if (found) {
                    261:                /* We have a valid partition - so probe for a filesystem at the current offset */
                    262:                DPRINTF("pc-parts: about to probe for fs\n");
                    263:                DPUSH( offs );
                    264:                PUSH_ih( my_parent() );
                    265:                parword("find-filesystem");
                    266:                DPRINTF("pc-parts: done fs probe\n");
                    267:        
                    268:                ph = POP_ph();
                    269:                if( ph ) {
                    270:                        DPRINTF("pc-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
                    271:                        di->filesystem_ph = ph;
                    272: 
                    273:                        /* If we have been asked to open a particular file, interpose the filesystem package with 
                    274:                        the passed filename as an argument */
                    275:                        if (strlen(argstr)) {
                    276:                                push_str( argstr );
                    277:                                PUSH_ph( ph );
                    278:                                fword("interpose");
                    279:                        }
                    280:                } else {
                    281:                        DPRINTF("pc-parts: no filesystem found; bypassing misc-files interpose\n");
                    282:                }
                    283:        
                    284:                free( str );
                    285:                RET( -1 );
                    286:        } else {
                    287:                DPRINTF("pc-parts: unable to locate partition\n");
                    288: 
                    289:                free( str );
                    290:                RET( 0 );
                    291:        }
                    292: }
                    293: 
                    294: /* ( block0 -- flag? ) */
                    295: static void
                    296: pcparts_probe( pcparts_info_t *dummy )
                    297: {
                    298:        unsigned char *buf = (unsigned char *)cell2pointer(POP());
                    299: 
                    300:        DPRINTF("probing for PC partitions\n");
                    301: 
                    302:        /* We also check that at least one valid partition exists; this is because
                    303:        some CDs seem broken in that they have a partition table but it is empty
                    304:        e.g. MorphOS. */
                    305:        RET ( has_pc_part_magic(buf) && has_pc_valid_partition(buf) );
                    306: }
                    307: 
                    308: /* ( -- type offset.d size.d ) */
                    309: static void
                    310: pcparts_get_info( pcparts_info_t *di )
                    311: {
                    312:        DPRINTF("PC get_info\n");
                    313:        PUSH( -1 );             /* no type */
                    314:        PUSH( di->offs_lo );
                    315:        PUSH( di->offs_hi );
                    316:        PUSH( di->size_lo );
                    317:        PUSH( di->size_hi );
                    318: }
                    319: 
                    320: static void
                    321: pcparts_block_size( __attribute__((unused))pcparts_info_t *di )
                    322: {
                    323:        PUSH(512);
                    324: }
                    325: 
                    326: static void
                    327: pcparts_initialize( pcparts_info_t *di )
                    328: {
                    329:        fword("register-partition-package");
                    330: }
                    331: 
                    332: /* ( pos.d -- status ) */
                    333: static void
                    334: pcparts_seek(pcparts_info_t *di )
                    335: {
                    336:        long long pos = DPOP();
                    337:        long long offs, size;
                    338: 
                    339:        DPRINTF("pcparts_seek %llx:\n", pos);
                    340: 
                    341:        /* Seek is invalid if we reach the end of the device */
                    342:        size = ((ducell)di->size_hi << BITS) | di->size_lo;
                    343:        if (pos > size)
                    344:                RET( -1 );
                    345: 
                    346:        /* Calculate the seek offset for the parent */
                    347:        offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
                    348:        offs += pos;
                    349:        DPUSH(offs);
                    350: 
                    351:        DPRINTF("pcparts_seek parent offset %llx:\n", offs);
                    352: 
                    353:        call_package(di->seek_xt, my_parent());
                    354: }
                    355: 
                    356: /* ( buf len -- actlen ) */
                    357: static void
                    358: pcparts_read(pcparts_info_t *di )
                    359: {
                    360:        DPRINTF("pcparts_read\n");
                    361: 
                    362:        /* Pass the read back up to the parent */
                    363:        call_package(di->read_xt, my_parent());
                    364: }
                    365: 
                    366: /* ( addr -- size ) */
                    367: static void
                    368: pcparts_load( __attribute__((unused))pcparts_info_t *di )
                    369: {
                    370:        /* Invoke the loader */
                    371:        load(my_self());
                    372: }
                    373: 
                    374: /* ( pathstr len -- ) */
                    375: static void
                    376: pcparts_dir( pcparts_info_t *di )
                    377: {
                    378:        if ( di->filesystem_ph ) {
                    379:                PUSH( my_self() );
                    380:                push_str("dir");
                    381:                PUSH( di->filesystem_ph );
                    382:                fword("find-method");
                    383:                POP();
                    384:                fword("execute");
                    385:        } else {
                    386:                forth_printf("pc-parts: Unable to determine filesystem\n");
                    387:                POP();
                    388:                POP();
                    389:        }
                    390: }
                    391: 
                    392: NODE_METHODS( pcparts ) = {
                    393:        { "probe",      pcparts_probe           },
                    394:        { "open",       pcparts_open            },
                    395:        { "seek",       pcparts_seek            },
                    396:        { "read",       pcparts_read            },
                    397:        { "load",       pcparts_load            },
                    398:        { "dir",        pcparts_dir             },
                    399:        { "get-info",   pcparts_get_info        },
                    400:        { "block-size", pcparts_block_size      },
                    401:        { NULL,         pcparts_initialize      },
                    402: };
                    403: 
                    404: void
                    405: pcparts_init( void )
                    406: {
                    407:        REGISTER_NODE( pcparts );
                    408: }

unix.superglobalmegacorp.com

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