|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.