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

1.1       root        1: /*
                      2:  *   Sun (Sparc32/64) 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_SUN_PARTS
                     23: 
                     24: #ifdef DEBUG_SUN_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:        int             type;
                     36:        phandle_t       filesystem_ph;
                     37: } sunparts_info_t;
                     38: 
                     39: DECLARE_NODE( sunparts, INSTALL_OPEN, sizeof(sunparts_info_t), "+/packages/sun-parts" );
                     40: 
                     41: #define SEEK( pos )            ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
                     42: #define READ( buf, size )      ({ PUSH((ucell)buf); PUSH(size); call_parent(di->read_xt); POP(); })
                     43: 
                     44: /* Layout of SUN partition table */
                     45: struct sun_disklabel {
                     46:     uint8_t info[128];   /* Informative text string */
                     47:     uint8_t spare0[14];
                     48:     struct sun_info {
                     49:         uint16_t id;
                     50:         uint16_t flags;
                     51:     } infos[8];
                     52:     uint8_t spare[246];  /* Boot information etc. */
                     53:     uint16_t rspeed;     /* Disk rotational speed */
                     54:     uint16_t pcylcount;  /* Physical cylinder count */
                     55:     uint16_t sparecyl;   /* extra sects per cylinder */
                     56:     uint8_t spare2[4];   /* More magic... */
                     57:     uint16_t ilfact;     /* Interleave factor */
                     58:     uint16_t ncyl;       /* Data cylinder count */
                     59:     uint16_t nacyl;      /* Alt. cylinder count */
                     60:     uint16_t ntrks;      /* Tracks per cylinder */
                     61:     uint16_t nsect;      /* Sectors per track */
                     62:     uint8_t spare3[4];   /* Even more magic... */
                     63:     struct sun_partition {
                     64:         uint32_t start_cylinder;
                     65:         uint32_t num_sectors;
                     66:     } partitions[8];
                     67:     uint16_t magic;      /* Magic number */
                     68:     uint16_t csum;       /* Label xor'd checksum */
                     69: };
                     70: 
                     71: /* two helper functions */
                     72: 
                     73: static inline int
                     74: has_sun_part_magic(unsigned char *sect)
                     75: {
                     76:     struct sun_disklabel *p = (struct sun_disklabel *)sect;
                     77:     uint16_t csum, *ush, tmp16;
                     78: 
                     79:     if (__be16_to_cpu(p->magic) != 0xDABE)
                     80:         return 0;
                     81: 
                     82:     csum = 0;
                     83:     for (ush = (uint16_t *)p; ush < (uint16_t *)(p + 1); ush++) {
                     84:         tmp16 = __be16_to_cpu(*ush);
                     85:        csum ^= tmp16;
                     86:     }
                     87:     return csum == 0;
                     88: }
                     89: 
                     90: /* ( open -- flag ) */
                     91: static void
                     92: sunparts_open( sunparts_info_t *di )
                     93: {
                     94:        char *str = my_args_copy();
                     95:         char *argstr = NULL;
                     96:         char *parstr = NULL;
                     97:        int parnum = -1;
                     98:        unsigned char buf[512];
                     99:         struct sun_disklabel *p;
                    100:         unsigned int i, bs;
                    101:         ducell offs, size;
                    102:        phandle_t ph;
                    103: 
                    104:        DPRINTF("sunparts_open '%s'\n", str );
                    105: 
                    106:        /* 
                    107:                Arguments that we accept:
                    108:                id: [0-7] | [a-h]
                    109:                [(id)][,][filespec]
                    110:        */
                    111: 
                    112:        if( str ) {
                    113:                if ( !strlen(str) )
                    114:                        parnum = -1;
                    115:                else {
                    116:                        /* Detect the boot parameters */
                    117:                        char *ptr;
                    118:                        ptr = str;
                    119: 
                    120:                        /* <id>,<file> */
                    121:                        if (((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'a' + 8)) && *(ptr + 1) == ',') {
                    122:                                parstr = ptr;
                    123:                                *(ptr + 1) = '\0';
                    124:                                argstr = ptr + 2;
                    125:                        }
                    126: 
                    127:                        /* <id> */
                    128:                        else if (((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'a' + 8)) && *(ptr + 1) == '\0') {
                    129:                                parstr = ptr;
                    130:                        }
                    131: 
                    132:                        /* ,<file> */
                    133:                        else if (*ptr == ',') {
                    134:                                argstr = ptr + 1;
                    135:                        }       
                    136: 
                    137:                        /* <file> */
                    138:                        else {
                    139:                                argstr = str;
                    140:                        }
                    141:                
                    142:                        /* Convert the id to a partition number */
                    143:                         if (parstr && strlen(parstr)) {
                    144:                                if (parstr[0] >= 'a' && parstr[0] < ('a' + 8))
                    145:                                        parnum = parstr[0] - 'a';
                    146:                                else
                    147:                                        parnum = atol(parstr);
                    148:                        }
                    149:                }
                    150:        }
                    151: 
                    152:        DPRINTF("parstr: %s  argstr: %s  parnum: %d\n", parstr, argstr, parnum);
                    153: 
                    154:        di->filesystem_ph = 0;
                    155:        di->read_xt = find_parent_method("read");
                    156:        di->seek_xt = find_parent_method("seek");
                    157: 
                    158:        SEEK( 0 );
                    159:         if (READ(buf, 512) != 512) {
                    160:                 free(str);
                    161:                RET(0);
                    162:         }
                    163: 
                    164:        /* Check Magic */
                    165:        if (!has_sun_part_magic(buf)) {
                    166:                DPRINTF("Sun partition magic not found.\n");
                    167:                 free(str);
                    168:                RET(0);
                    169:        }
                    170: 
                    171:        bs = 512;
                    172:        /* get partition data */
                    173:        p = (struct sun_disklabel *)buf;
                    174: 
                    175:         for (i = 0; i < 8; i++) {
                    176:             DPRINTF("%c: %d + %d, id %x, flags %x\n", 'a' + i,
                    177:                     __be32_to_cpu(p->partitions[i].start_cylinder),
                    178:                     __be32_to_cpu(p->partitions[i].num_sectors),
                    179:                     __be16_to_cpu(p->infos[i].id),
                    180:                     __be16_to_cpu(p->infos[i].flags));
                    181:         }
                    182: 
                    183:         if (parnum < 0)
                    184:             parnum = 0;
                    185: 
                    186:        DPRINTF("Selected partition %d\n", parnum);
                    187: 
                    188:         offs = (long long)__be32_to_cpu(p->partitions[parnum].start_cylinder) *
                    189:             __be16_to_cpu(p->ntrks) * __be16_to_cpu(p->nsect) * bs;
                    190: 
                    191:         di->offs_hi = offs >> BITS;
                    192:         di->offs_lo = offs & (ucell) -1;
                    193:         size = (long long)__be32_to_cpu(p->partitions[parnum].num_sectors) * bs;
                    194:         if (size == 0) {
                    195:                 DPRINTF("Partition size is 0, exiting\n");
                    196:                 free(str);
                    197:                 RET(0);
                    198:         }
                    199:         di->size_hi = size >> BITS;
                    200:         di->size_lo = size & (ucell) -1;
                    201:         di->type = __be16_to_cpu(p->infos[parnum].id);
                    202: 
                    203:         DPRINTF("Found Sun partition, offs %lld size %lld\n",
                    204:                 (long long)offs, (long long)size);
                    205: 
                    206:        /* Probe for filesystem at current offset */
                    207:        DPRINTF("sun-parts: about to probe for fs\n");
                    208:        DPUSH( offs );
                    209:        PUSH_ih( my_parent() );
                    210:        parword("find-filesystem");
                    211:        DPRINTF("sun-parts: done fs probe\n");
                    212: 
                    213:        ph = POP_ph();
                    214:        if( ph ) {
                    215:                DPRINTF("sun-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
                    216:                di->filesystem_ph = ph;
                    217: 
                    218:                /* If we have been asked to open a particular file, interpose the filesystem package with 
                    219:                   the passed filename as an argument */
                    220:                 if (argstr && strlen(argstr)) {
                    221:                        push_str( argstr );
                    222:                        PUSH_ph( ph );
                    223:                        fword("interpose");
                    224:                }
                    225:        } else {
                    226:                DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n");
                    227: 
                    228:                /* Solaris Fcode boot blocks assume that the disk-label package will always
                    229:                   automatically interpose the "ufs-file-system" package if it exists! We
                    230:                   need to mimic this behaviour in order for the boot to work. */
                    231:                push_str("ufs-file-system");
                    232:                feval("find-package");
                    233:                ph = POP_ph();
                    234: 
                    235:                 if (argstr && ph) {
                    236:                        ph = POP_ph();
                    237:                        push_str(argstr);
                    238:                        PUSH_ph(ph);
                    239:                        fword("interpose");
                    240:                }
                    241:        }
                    242: 
                    243:        free( str );
                    244:         RET( -1 );
                    245: }
                    246: 
                    247: /* ( block0 -- flag? ) */
                    248: static void
                    249: sunparts_probe( __attribute__((unused))sunparts_info_t *dummy )
                    250: {
                    251:        unsigned char *buf = (unsigned char *)POP();
                    252: 
                    253:        DPRINTF("probing for Sun partitions\n");
                    254: 
                    255:        RET ( has_sun_part_magic(buf) );
                    256: }
                    257: 
                    258: /* ( -- type offset.d size.d ) */
                    259: static void
                    260: sunparts_get_info( sunparts_info_t *di )
                    261: {
                    262:        DPRINTF("Sun get_info\n");
                    263:        PUSH( di->type );
                    264:        PUSH( di->offs_lo );
                    265:        PUSH( di->offs_hi );
                    266:        PUSH( di->size_lo );
                    267:        PUSH( di->size_hi );
                    268: }
                    269: 
                    270: static void
                    271: sunparts_block_size( __attribute__((unused))sunparts_info_t *di )
                    272: {
                    273:        PUSH(512);
                    274: }
                    275: 
                    276: static void
                    277: sunparts_initialize( __attribute__((unused))sunparts_info_t *di )
                    278: {
                    279:        fword("register-partition-package");
                    280: }
                    281: 
                    282: /* ( pos.d -- status ) */
                    283: static void
                    284: sunparts_seek(sunparts_info_t *di )
                    285: {
                    286:        long long pos = DPOP();
                    287:        long long offs, size;;
                    288: 
                    289:        DPRINTF("sunparts_seek %llx:\n", pos);
                    290: 
                    291:        /* Seek is invalid if we reach the end of the device */
                    292:        size = ((ducell)di->size_hi << BITS) | di->size_lo;
                    293:        if (pos > size)
                    294:                RET( -1 );
                    295: 
                    296:        /* Calculate the seek offset for the parent */
                    297:        offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
                    298:        offs += pos;
                    299:        DPUSH(offs);
                    300: 
                    301:        DPRINTF("sunparts_seek parent offset %llx:\n", offs);
                    302: 
                    303:        call_package(di->seek_xt, my_parent());
                    304: }
                    305: 
                    306: /* ( buf len -- actlen ) */
                    307: static void
                    308: sunparts_read(sunparts_info_t *di )
                    309: {
                    310:        DPRINTF("sunparts_read\n");
                    311: 
                    312:        /* Pass the read back up to the parent */
                    313:        call_package(di->read_xt, my_parent());
                    314: }
                    315: 
                    316: /* ( addr -- size ) */
                    317: static void
                    318: sunparts_load( __attribute__((unused))sunparts_info_t *di )
                    319: {
                    320:        /* Invoke the loader */
                    321:        load(my_self());
                    322: }
                    323: 
                    324: /* ( pathstr len -- ) */
                    325: static void
                    326: sunparts_dir( sunparts_info_t *di )
                    327: {
                    328:        if ( di->filesystem_ph) {
                    329:                PUSH( my_self() );
                    330:                push_str("dir");
                    331:                PUSH( di->filesystem_ph );
                    332:                fword("find-method");
                    333:                POP();
                    334:                fword("execute");
                    335:        } else {
                    336:                forth_printf("sun-parts: Unable to determine filesystem\n");
                    337:                POP();
                    338:                POP();
                    339:        }
                    340: }
                    341: 
                    342: NODE_METHODS( sunparts ) = {
                    343:        { "probe",      sunparts_probe          },
                    344:        { "open",       sunparts_open           },
                    345:        { "get-info",   sunparts_get_info       },
                    346:        { "block-size", sunparts_block_size     },
                    347:        { "seek",       sunparts_seek           },
                    348:        { "read",       sunparts_read           },
                    349:        { "load",       sunparts_load           },
                    350:        { "dir",        sunparts_dir            },
                    351:        { NULL,         sunparts_initialize     },
                    352: };
                    353: 
                    354: void
                    355: sunparts_init( void )
                    356: {
                    357:        REGISTER_NODE( sunparts );
                    358: }

unix.superglobalmegacorp.com

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