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