diff options
Diffstat (limited to 'qemu/roms/openbios/packages/pc-parts.c')
-rw-r--r-- | qemu/roms/openbios/packages/pc-parts.c | 393 |
1 files changed, 0 insertions, 393 deletions
diff --git a/qemu/roms/openbios/packages/pc-parts.c b/qemu/roms/openbios/packages/pc-parts.c deleted file mode 100644 index 771923efe..000000000 --- a/qemu/roms/openbios/packages/pc-parts.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * pc partition support - * - * Copyright (C) 2004 Stefan Reinauer - * - * This code is based (and copied in many places) from - * mac partition support by Samuel Rydh (samuel@ibrium.se) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 - * - */ - -#include "config.h" -#include "libopenbios/bindings.h" -#include "libopenbios/load.h" -#include "libc/byteorder.h" -#include "libc/vsprintf.h" -#include "packages.h" - -//#define DEBUG_PC_PARTS - -#ifdef DEBUG_PC_PARTS -#define DPRINTF(fmt, args...) \ - do { printk(fmt , ##args); } while (0) -#else -#define DPRINTF(fmt, args...) -#endif - -typedef struct { - xt_t seek_xt, read_xt; - ucell offs_hi, offs_lo; - ucell size_hi, size_lo; - phandle_t filesystem_ph; -} pcparts_info_t; - -DECLARE_NODE( pcparts, INSTALL_OPEN, sizeof(pcparts_info_t), "+/packages/pc-parts" ); - -#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); }) -#define READ( buf, size ) ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); }) - -/* three helper functions */ - -static inline int has_pc_valid_partition(unsigned char *sect) -{ - /* Make sure the partition table contains at least one valid entry */ - return (sect[0x1c2] != 0 || sect[0x1d2] != 0 || sect[0x1e2] != 0); -} - -static inline int has_pc_part_magic(unsigned char *sect) -{ - return sect[0x1fe]==0x55 && sect[0x1ff]==0xAA; -} - -static inline int is_pc_extended_part(unsigned char type) -{ - return type==5 || type==0xf || type==0x85; -} - -/* ( open -- flag ) */ -static void -pcparts_open( pcparts_info_t *di ) -{ - char *str = my_args_copy(); - char *argstr = strdup(""); - char *parstr = strdup(""); - int bs, parnum=-1; - int found = 0; - phandle_t ph; - ducell offs, size; - - /* Layout of PC partition table */ - struct pc_partition { - unsigned char boot; - unsigned char head; - unsigned char sector; - unsigned char cyl; - unsigned char type; - unsigned char e_head; - unsigned char e_sector; - unsigned char e_cyl; - u32 start_sect; /* unaligned little endian */ - u32 nr_sects; /* ditto */ - } *p, *partition; - - unsigned char buf[512]; - - DPRINTF("pcparts_open '%s'\n", str ); - - /* - Arguments that we accept: - id: [0-7] - [(id)][,][filespec] - */ - - if ( strlen(str) ) { - /* Detect the arguments */ - if ((*str >= '0' && *str <= '7') || (*str == ',')) { - push_str(str); - PUSH(','); - fword("left-parse-string"); - parstr = pop_fstr_copy(); - argstr = pop_fstr_copy(); - } else { - argstr = str; - } - - /* Convert the id to a partition number */ - if (parstr && strlen(parstr)) - parnum = atol(parstr); - } - - /* Make sure argstr is not null */ - if (argstr == NULL) - argstr = strdup(""); - - DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum); - free(parstr); - - if( parnum < 0 ) - parnum = 0; - - di->filesystem_ph = 0; - di->read_xt = find_parent_method("read"); - di->seek_xt = find_parent_method("seek"); - - SEEK( 0 ); - if( READ(buf, 512) != 512 ) - RET(0); - - /* Check Magic */ - if (!has_pc_part_magic(buf)) { - DPRINTF("pc partition magic not found.\n"); - RET(0); - } - - /* Actual partition data */ - partition = (struct pc_partition *) (buf + 0x1be); - - /* Make sure we use a copy accessible from an aligned pointer (some archs - e.g. SPARC will crash otherwise) */ - p = malloc(sizeof(struct pc_partition)); - - bs = 512; - - if (parnum < 4) { - /* primary partition */ - partition += parnum; - memcpy(p, partition, sizeof(struct pc_partition)); - - if (p->type == 0 || is_pc_extended_part(p->type)) { - DPRINTF("partition %d does not exist\n", parnum+1 ); - RET( 0 ); - } - - offs = (long long)(__le32_to_cpu(p->start_sect)) * bs; - di->offs_hi = offs >> BITS; - di->offs_lo = offs & (ucell) -1; - - size = (long long)(__le32_to_cpu(p->nr_sects)) * bs; - di->size_hi = size >> BITS; - di->size_lo = size & (ucell) -1; - - DPRINTF("Primary partition at sector %x\n", __le32_to_cpu(p->start_sect)); - - found = 1; - } else { - /* Extended partition */ - int i, cur_part; - unsigned long ext_start, cur_table; - - /* Search for the extended partition - * which contains logical partitions */ - for (i = 0; i < 4; i++) { - if (is_pc_extended_part(p[i].type)) - break; - } - - if (i >= 4) { - DPRINTF("Extended partition not found\n"); - RET( 0 ); - } - - DPRINTF("Extended partition at %d\n", i+1); - - /* Visit each logical partition labels */ - ext_start = __le32_to_cpu(p[i].start_sect); - cur_table = ext_start; - cur_part = 4; - - while (cur_part <= parnum) { - DPRINTF("cur_part=%d at %lx\n", cur_part, cur_table); - - SEEK( cur_table * bs ); - if( READ(buf, sizeof(512)) != sizeof(512) ) - RET( 0 ); - - if (!has_pc_part_magic(buf)) { - DPRINTF("Extended partition has no magic\n"); - break; - } - - /* Read the extended partition, making sure we are aligned again */ - partition = (struct pc_partition *) (buf + 0x1be); - memcpy(p, partition, sizeof(struct pc_partition)); - - /* First entry is the logical partition */ - if (cur_part == parnum) { - if (p->type == 0) { - DPRINTF("Partition %d is empty\n", parnum+1); - RET( 0 ); - } - - offs = (long long)(cur_table+__le32_to_cpu(p->start_sect)) * bs; - di->offs_hi = offs >> BITS; - di->offs_lo = offs & (ucell) -1; - - size = (long long)__le32_to_cpu(p->nr_sects) * bs; - di->size_hi = size >> BITS; - di->size_lo = size & (ucell) -1; - - found = 1; - break; - } - - /* Second entry is link to next partition */ - if (!is_pc_extended_part(p[1].type)) { - DPRINTF("no link\n"); - break; - } - - cur_table = ext_start + __le32_to_cpu(p[1].start_sect); - cur_part++; - } - - if (!found) { - DPRINTF("Logical partition %d does not exist\n", parnum+1); - RET( 0 ); - } - } - - free(p); - - if (found) { - /* We have a valid partition - so probe for a filesystem at the current offset */ - DPRINTF("pc-parts: about to probe for fs\n"); - DPUSH( offs ); - PUSH_ih( my_parent() ); - parword("find-filesystem"); - DPRINTF("pc-parts: done fs probe\n"); - - ph = POP_ph(); - if( ph ) { - DPRINTF("pc-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr); - di->filesystem_ph = ph; - - /* If we have been asked to open a particular file, interpose the filesystem package with - the passed filename as an argument */ - if (strlen(argstr)) { - push_str( argstr ); - PUSH_ph( ph ); - fword("interpose"); - } - } else { - DPRINTF("pc-parts: no filesystem found; bypassing misc-files interpose\n"); - } - - free( str ); - RET( -1 ); - } else { - DPRINTF("pc-parts: unable to locate partition\n"); - - free( str ); - RET( 0 ); - } -} - -/* ( block0 -- flag? ) */ -static void -pcparts_probe( pcparts_info_t *dummy ) -{ - unsigned char *buf = (unsigned char *)cell2pointer(POP()); - - DPRINTF("probing for PC partitions\n"); - - /* We also check that at least one valid partition exists; this is because - some CDs seem broken in that they have a partition table but it is empty - e.g. MorphOS. */ - RET ( has_pc_part_magic(buf) && has_pc_valid_partition(buf) ); -} - -/* ( -- type offset.d size.d ) */ -static void -pcparts_get_info( pcparts_info_t *di ) -{ - DPRINTF("PC get_info\n"); - PUSH( -1 ); /* no type */ - PUSH( di->offs_lo ); - PUSH( di->offs_hi ); - PUSH( di->size_lo ); - PUSH( di->size_hi ); -} - -static void -pcparts_block_size( __attribute__((unused))pcparts_info_t *di ) -{ - PUSH(512); -} - -static void -pcparts_initialize( pcparts_info_t *di ) -{ - fword("register-partition-package"); -} - -/* ( pos.d -- status ) */ -static void -pcparts_seek(pcparts_info_t *di ) -{ - long long pos = DPOP(); - long long offs, size; - - DPRINTF("pcparts_seek %llx:\n", pos); - - /* Seek is invalid if we reach the end of the device */ - size = ((ducell)di->size_hi << BITS) | di->size_lo; - if (pos > size) - RET( -1 ); - - /* Calculate the seek offset for the parent */ - offs = ((ducell)di->offs_hi << BITS) | di->offs_lo; - offs += pos; - DPUSH(offs); - - DPRINTF("pcparts_seek parent offset %llx:\n", offs); - - call_package(di->seek_xt, my_parent()); -} - -/* ( buf len -- actlen ) */ -static void -pcparts_read(pcparts_info_t *di ) -{ - DPRINTF("pcparts_read\n"); - - /* Pass the read back up to the parent */ - call_package(di->read_xt, my_parent()); -} - -/* ( addr -- size ) */ -static void -pcparts_load( __attribute__((unused))pcparts_info_t *di ) -{ - /* Invoke the loader */ - load(my_self()); -} - -/* ( pathstr len -- ) */ -static void -pcparts_dir( pcparts_info_t *di ) -{ - if ( di->filesystem_ph ) { - PUSH( my_self() ); - push_str("dir"); - PUSH( di->filesystem_ph ); - fword("find-method"); - POP(); - fword("execute"); - } else { - forth_printf("pc-parts: Unable to determine filesystem\n"); - POP(); - POP(); - } -} - -NODE_METHODS( pcparts ) = { - { "probe", pcparts_probe }, - { "open", pcparts_open }, - { "seek", pcparts_seek }, - { "read", pcparts_read }, - { "load", pcparts_load }, - { "dir", pcparts_dir }, - { "get-info", pcparts_get_info }, - { "block-size", pcparts_block_size }, - { NULL, pcparts_initialize }, -}; - -void -pcparts_init( void ) -{ - REGISTER_NODE( pcparts ); -} |