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