As documented on the mailing lists, change the interposition order of the disk packages from:

cdrom -> deblocker -> disk-label -> (misc-files | sun-parts | pc-parts | mac-parts) 

to:

cdrom -> deblocker -> disk-label -> (sun-parts | pc-parts | mac-parts) -> misc-files 

This makes the overall code much simpler, since instead of passing get-info structures between the different layers to work out 
the current device offset, each package can simply maintain its own offsets and bubble them back up to the parent.

There are also many, many bugfixes present is patch, some of which are given below:

- Add debugging in /packages/misc-files, augment debugging in all other disk packages
- Fix alignment issue in /packages/pc-parts so it works correctly on strictly align archs, e.g. SPARC64
- Fix parsing of [<id>,][filename] arguments to load (in preparation for next patch set)
- Fix byte-swapping issues in /packages/mac-parts (in theory it should now work regardless of endian)




git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@791 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
cdrom - deblocker - disk-label - (misc-files | sun-parts | pc-parts | mac-parts)
2010-06-08 20:59:08 +00:00
committed by Mark Cave-Ayland
parent 1e5c4a8173
commit 7fc4e304c3
9 changed files with 777 additions and 342 deletions

View File

@@ -17,6 +17,7 @@
#include "config.h"
#include "libopenbios/bindings.h"
#include "libc/diskio.h"
#include "libc/vsprintf.h"
#include "packages.h"
//#define DEBUG_DISK_LABEL
@@ -29,7 +30,9 @@ do { printk("DISK-LABEL - %s: " fmt, __func__ , ##args); } while (0)
#endif
typedef struct {
int fd;
xt_t parent_seek_xt;
xt_t parent_tell_xt;
xt_t parent_read_xt;
ucell offs_hi, offs_lo;
ucell size_hi, size_lo;
@@ -44,117 +47,81 @@ DECLARE_NODE( dlabel, 0, sizeof(dlabel_info_t), "/packages/disk-label" );
/* ( -- ) */
static void
dlabel_close( dlabel_info_t *di )
dlabel_close( __attribute__((unused))dlabel_info_t *di )
{
if( di->part_ih )
close_package( di->part_ih );
if( di->fd )
close_io( di->fd );
}
/* ( -- success? ) */
static void
dlabel_open( dlabel_info_t *di )
{
const char *s, *filename;
char *path;
char block0[512];
phandle_t ph;
int fd, success=0;
xt_t xt;
int success=0;
cell status;
path = my_args_copy();
if (!path) {
path = strdup("");
}
if (!path) {
goto out;
}
DPRINTF("dlabel-open '%s'\n", path );
/* open disk interface */
/* Find parent methods */
di->parent_seek_xt = find_parent_method("seek");
di->parent_tell_xt = find_parent_method("tell");
di->parent_read_xt = find_parent_method("read");
if( (fd=open_ih(my_parent())) == -1 )
/* Read first block from parent device */
DPUSH(0);
call_package(di->parent_seek_xt, my_parent());
POP();
PUSH((ucell)block0);
PUSH(sizeof(block0));
call_package(di->parent_read_xt, my_parent());
status = POP();
if (status != sizeof(block0))
goto out;
di->fd = fd;
/* argument format: parnum,filename */
s = path;
filename = "";
if( *s == '-' || isdigit(*s) ||
(*s >= 'a' && *s < ('a' + 8)
&& (*(s + 1) == ',' || *(s + 1) == '\0'))) {
if( (s=strpbrk(path,",")) ) {
filename = s+1;
}
} else {
filename = s;
if( *s == ',' )
filename++;
}
DPRINTF("filename %s\n", filename);
/* find partition handler */
seek_io( fd, 0 );
if( read_io(fd, block0, sizeof(block0)) != sizeof(block0) )
goto out;
/* Find partition handler */
PUSH( (ucell)block0 );
selfword("find-part-handler");
ph = POP_ph();
/* open partition package */
if( ph ) {
if( !(di->part_ih=open_package(path, ph)) )
goto out;
if( !(xt=find_ih_method("get-info", di->part_ih)) )
goto out;
call_package( xt , di->part_ih );
di->size_hi = POP();
di->size_lo = POP();
di->offs_hi = POP();
di->offs_lo = POP();
di->type = POP();
di->block_size = 512;
xt = find_ih_method("block-size", di->part_ih);
if (xt) {
call_package(xt, di->part_ih);
di->block_size = POP();
}
/* We found a suitable partition handler, so interpose it */
DPRINTF("Partition found on disk - scheduling interpose with ph " FMT_ucellx "\n", ph);
push_str(path);
PUSH_ph(ph);
fword("interpose");
success = 1;
} else {
/* unknown (or missing) partition map,
* try the whole disk
*/
di->offs_hi = 0;
di->offs_lo = 0;
di->size_hi = 0;
di->size_lo = 0;
di->part_ih = 0;
di->type = -1;
di->block_size = 512;
xt = find_parent_method("block-size");
if (xt) {
call_parent(xt);
di->block_size = POP();
DPRINTF("Unknown or missing partition map; trying whole disk\n");
/* Probe for filesystem from start of device */
DPUSH ( 0 );
PUSH_ih( my_self() );
selfword("find-filesystem");
ph = POP_ph();
if( ph ) {
push_str( path );
PUSH_ph( ph );
fword("interpose");
} else if (*path && strcmp(path, "%BOOT") != 0) {
goto out;
}
success = 1;
}
/* probe for filesystem */
PUSH_ih( my_self() );
selfword("find-filesystem");
ph = POP_ph();
if( ph ) {
push_str( filename );
PUSH_ph( ph );
fword("interpose");
} else if (*filename && strcmp(filename, "%BOOT") != 0) {
goto out;
}
success = 1;
out:
out:
if( path )
free( path );
if( !success ) {
@@ -168,61 +135,26 @@ dlabel_open( dlabel_info_t *di )
static void
dlabel_read( dlabel_info_t *di )
{
int ret, len = POP();
char *buf = (char*)POP();
llong pos = tell( di->fd );
ducell offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
ducell size = ((ducell)di->size_hi << BITS) | di->size_lo;
if (size && len > pos - offs + size) {
len = size - (pos - offs);
}
ret = read_io( di->fd, buf, len );
PUSH( ret );
/* Call back up to parent */
call_package(di->parent_read_xt, my_parent());
}
/* ( pos.d -- status ) */
static void
dlabel_seek( dlabel_info_t *di )
{
llong pos = DPOP();
int ret;
ducell offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
ducell size = ((ducell)di->size_hi << BITS) | di->size_lo;
DPRINTF("dlabel_seek %llx [%llx, %llx]\n", pos, offs, size);
if( pos != -1 )
pos += offs;
else if( size ) {
DPRINTF("Seek EOF\n");
pos = offs + size;
} else {
/* let parent handle the EOF seek. */
}
DPRINTF("dlabel_seek: 0x%llx\n", pos );
if (size && (pos - offs >= size )) {
PUSH(-1);
return;
}
ret = seek_io( di->fd, pos );
PUSH( ret );
/* Call back up to parent */
call_package(di->parent_seek_xt, my_parent());
}
/* ( -- filepos.d ) */
static void
dlabel_tell( dlabel_info_t *di )
{
llong pos = tell( di->fd );
ducell offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
if( pos != -1 )
pos -= offs;
DPUSH( pos );
/* Call back up to parent */
call_package(di->parent_tell_xt, my_parent());
}
/* ( addr len -- actual ) */
static void
dlabel_write( __attribute__((unused)) dlabel_info_t *di )
@@ -231,39 +163,32 @@ dlabel_write( __attribute__((unused)) dlabel_info_t *di )
PUSH( -1 );
}
/* ( rel.d -- abs.d ) */
static void
dlabel_offset( dlabel_info_t *di )
{
ullong rel = DPOP();
ducell offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
rel += offs;
DPUSH( rel );
}
/* ( addr -- size ) */
static void
dlabel_load( __attribute__((unused)) dlabel_info_t *di )
{
/* XXX: try the load method of the part package */
/* Try the load method of the part package */
char *buf;
xt_t xt;
printk("Can't load from this device!\n");
POP();
PUSH(0);
}
buf = (char *)POP();
static void
dlabel_block_size( dlabel_info_t *di )
{
PUSH(di->block_size);
DPRINTF("load invoked with address %p\n", buf);
xt = find_ih_method("load", di->part_ih);
if (!xt) {
forth_printf("load currently not implemented for /packages/disk-label\n");
PUSH(0);
return;
}
call_package(xt, di->part_ih);
}
NODE_METHODS( dlabel ) = {
{ "open", dlabel_open },
{ "close", dlabel_close },
{ "offset", dlabel_offset },
{ "load", dlabel_load },
{ "block-size", dlabel_block_size },
{ "read", dlabel_read },
{ "write", dlabel_write },
{ "seek", dlabel_seek },

View File

@@ -36,19 +36,32 @@ new-device
r> drop 0
;
: find-filesystem ( ih -- ph | 0 )
>r fs-handlers
: find-filesystem ( offs.d ih -- ph | 0 )
>r fs-handlers ( offs.d listhead )
begin list-get while
( nextlist dictptr )
r@ over @ execute if
( nextlist dictptr )
na1+ @ r> rot 2drop exit
then
drop
2over ( offs.d nextlist dictptr offs.d )
r@ ( offs.d nextlist dictptr offs.d ih )
3 pick ( offs.d nextlist dictptr offs.d ih dictptr )
@ ( offs.d nextlist dictptr offs.d ih probe-xt )
execute ( offs.d nextlist dictptr flag? )
if
( offs.d nextlist dictptr )
na1+ ( offs.d nextlist dictptr+1 )
@ ( offs.d nextlist phandle )
r> ( offs.d nextlist phandle ih )
rot ( offs.d phandle ih nextlist )
2drop ( offs.d phandle )
-rot ( phandle offs.d )
2drop ( phandle )
exit
then
drop ( offs.d nextlist )
repeat
2drop ( offs.d )
r> drop 0
;
: register-part-handler ( handler-ph -- )
dup " probe" rot find-method
0= abort" Missing probe method!"

View File

@@ -17,8 +17,12 @@
#include "config.h"
#include "libopenbios/bindings.h"
#include "mac-parts.h"
#include "libc/byteorder.h"
#include "libc/vsprintf.h"
#include "packages.h"
//#define CONFIG_DEBUG_MAC_PARTS
#ifdef CONFIG_DEBUG_MAC_PARTS
#define DPRINTF(fmt, args...) \
do { printk("MAC-PARTS: " fmt , ##args); } while (0)
@@ -27,54 +31,77 @@ do { printk("MAC-PARTS: " fmt , ##args); } while (0)
#endif
typedef struct {
ullong offs;
ullong size;
xt_t seek_xt, read_xt;
ucell offs_hi, offs_lo;
ucell size_hi, size_lo;
uint blocksize;
} macparts_info_t;
DECLARE_NODE( macparts, INSTALL_OPEN, sizeof(macparts_info_t), "+/packages/mac-parts" );
#define SEEK( pos ) ({ DPUSH(pos); call_parent(seek_xt); POP(); })
#define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(read_xt); POP(); })
#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
#define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(di->read_xt); POP(); })
/* ( open -- flag ) */
static void
macparts_open( macparts_info_t *di )
{
char *str = my_args_copy();
xt_t seek_xt = find_parent_method("seek");
xt_t read_xt = find_parent_method("read");
int bs, parnum=0;
char *argstr = strdup("");
char *parstr = strdup("");
int bs, parnum=-1;
desc_map_t dmap;
part_entry_t par;
int ret = 0;
int want_bootcode = 0;
phandle_t ph;
ducell offs, size;
DPRINTF("macparts_open '%s'\n", str );
/*
Arguments that we accept:
id: [0-7]
[(id,)][filespec]
*/
DPRINTF("partition %s\n", str);
if( str ) {
char *tmp;
char *comma = strchr(str, ',');
parnum = atol(str);
if( *str == 0 || *str == ',' )
if ( !strlen(str) )
parnum = -1;
if (comma) {
tmp = comma + 1;
} else {
if (*str >= '0' && *str <= '9') {
tmp = (char*)"";
else {
/* If end of string, we just have a partition id */
if (str[1] == '\0') {
parstr = str;
} else {
tmp = str;
parnum = -1;
/* If a comma, then we have a partition id plus argument */
if (str[1] == ',') {
str[1] = '\0';
parstr = str;
argstr = &str[2];
} else {
/* Otherwise we have just an argument */
argstr = str;
}
}
/* Convert the id to a partition number */
if (strlen(parstr))
parnum = atol(parstr);
/* Detect if we are looking for the bootcode */
if (strcmp(argstr, "%BOOT") == 0)
want_bootcode = 1;
}
if (strcmp(tmp, "%BOOT") == 0)
want_bootcode = 1;
free(str);
}
DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
DPRINTF("want_bootcode %d\n", want_bootcode);
DPRINTF("macparts_open %d\n", parnum);
di->read_xt = find_parent_method("read");
di->seek_xt = find_parent_method("seek");
SEEK( 0 );
if( READ(&dmap, sizeof(dmap)) != sizeof(dmap) )
goto out;
@@ -82,17 +109,17 @@ macparts_open( macparts_info_t *di )
/* partition maps might support multiple block sizes; in this case,
* pmPyPartStart is typically given in terms of 512 byte blocks.
*/
bs = dmap.sbBlockSize;
bs = __be16_to_cpu(dmap.sbBlockSize);
if( bs != 512 ) {
SEEK( 512 );
READ( &par, sizeof(par) );
if( par.pmSig == DESC_PART_SIGNATURE )
if( __be16_to_cpu(par.pmSig) == DESC_PART_SIGNATURE )
bs = 512;
}
SEEK( bs );
if( READ(&par, sizeof(par)) != sizeof(par) )
goto out;
if (par.pmSig != DESC_PART_SIGNATURE)
if (__be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE)
goto out;
if (parnum == -1) {
@@ -101,28 +128,42 @@ macparts_open( macparts_info_t *di )
/* see PowerPC Microprocessor CHRP bindings */
parnum = 1;
while (parnum <= par.pmMapBlkCnt) {
while (parnum <= __be32_to_cpu(par.pmMapBlkCnt)) {
SEEK( (bs * parnum) );
READ( &par, sizeof(par) );
if( par.pmSig != DESC_PART_SIGNATURE ||
!par.pmPartBlkCnt )
if( __be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE ||
!__be16_to_cpu(par.pmPartBlkCnt) )
goto out;
DPRINTF("found partition type: %s\n", par.pmPartType);
if (firstHFS == -1 &&
strcmp(par.pmPartType, "Apple_HFS") == 0)
firstHFS = parnum;
if( (par.pmPartStatus & kPartitionAUXIsBootValid) &&
(par.pmPartStatus & kPartitionAUXIsValid) &&
(par.pmPartStatus & kPartitionAUXIsAllocated) &&
(par.pmPartStatus & kPartitionAUXIsReadable) &&
if( (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsBootValid) &&
(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) &&
(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) &&
(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) &&
(strcmp(par.pmProcessor, "PowerPC") == 0) ) {
di->blocksize =(uint)bs;
di->offs = (llong)par.pmPyPartStart * bs;
di->size = (llong)par.pmPartBlkCnt * bs;
offs = (llong)(__be32_to_cpu(par.pmPyPartStart)) * bs;
di->offs_hi = offs >> BITS;
di->offs_lo = offs & (ucell) -1;
size = (llong)(__be32_to_cpu(par.pmPartBlkCnt)) * bs;
di->size_hi = size >> BITS;
di->size_lo = size & (ucell) -1;
if (want_bootcode) {
di->offs += (llong)par.pmLgBootStart*bs;
di->size = (llong)par.pmBootSize;
offs = (llong)(__be32_to_cpu(par.pmLgBootStart)) * bs;
di->offs_hi = offs >> BITS;
di->offs_lo = offs & (ucell) -1;
size = (llong)(__be32_to_cpu(par.pmBootSize)) * bs;
di->size_hi = size >> BITS;
di->size_lo = size & (ucell) -1;
}
ret = -1;
goto out;
@@ -141,37 +182,70 @@ macparts_open( macparts_info_t *di )
if (parnum == 0) {
di->blocksize =(uint)bs;
di->offs = (llong)0;
di->size = (llong)dmap.sbBlkCount * bs;
offs = (llong)0;
di->offs_hi = offs >> BITS;
di->offs_lo = offs & (ucell) -1;
size = (llong)__be32_to_cpu(dmap.sbBlkCount) * bs;
di->size_hi = size >> BITS;
di->size_lo = size & (ucell) -1;
ret = -1;
goto out;
}
if( parnum > par.pmMapBlkCnt)
if( parnum > __be32_to_cpu(par.pmMapBlkCnt))
goto out;
found:
SEEK( (bs * parnum) );
READ( &par, sizeof(par) );
if( par.pmSig != DESC_PART_SIGNATURE || !par.pmPartBlkCnt )
if( __be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE || !__be32_to_cpu(par.pmPartBlkCnt) )
goto out;
if( !(par.pmPartStatus & kPartitionAUXIsValid) ||
!(par.pmPartStatus & kPartitionAUXIsAllocated) ||
!(par.pmPartStatus & kPartitionAUXIsReadable) )
if( !(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) ||
!(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) ||
!(__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) )
goto out;
ret = -1;
di->blocksize =(uint)bs;
di->offs = (llong)par.pmPyPartStart * bs;
di->size = (llong)par.pmPartBlkCnt * bs;
di->blocksize = (uint)bs;
offs = (llong)__be32_to_cpu(par.pmPyPartStart) * bs;
size = (llong)__be32_to_cpu(par.pmPartBlkCnt) * bs;
if (want_bootcode) {
di->offs += (llong)par.pmLgBootStart * bs;
di->size = (llong)par.pmBootSize;
offs += (llong)__be32_to_cpu(par.pmLgBootStart) * bs;
size = (llong)__be32_to_cpu(par.pmBootSize);
}
di->offs_hi = offs >> BITS;
di->offs_lo = offs & (ucell) -1;
di->size_hi = size >> BITS;
di->size_lo = size & (ucell) -1;
/* We have a valid partition - so probe for a filesystem at the current offset */
DPRINTF("mac-parts: about to probe for fs\n");
DPUSH( offs );
PUSH_ih( my_parent() );
parword("find-filesystem");
DPRINTF("mac-parts: done fs probe\n");
ph = POP_ph();
if( ph ) {
DPRINTF("mac-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, str);
push_str( argstr );
PUSH_ph( ph );
fword("interpose");
} else {
DPRINTF("mac-parts: no filesystem found; bypassing misc-files interpose\n");
}
free( str );
out:
DPRINTF("offset 0x%llx size 0x%llx\n", di->offs, di->size);
PUSH( ret);
PUSH( ret );
}
/* ( block0 -- flag? ) */
@@ -181,7 +255,7 @@ macparts_probe( macparts_info_t *dummy )
desc_map_t *dmap = (desc_map_t*)POP();
DPRINTF("macparts_probe %x ?= %x\n", dmap->sbSig, DESC_MAP_SIGNATURE);
if( dmap->sbSig != DESC_MAP_SIGNATURE )
if( __be16_to_cpu(dmap->sbSig) != DESC_MAP_SIGNATURE )
RET(0);
RET(-1);
}
@@ -190,10 +264,13 @@ macparts_probe( macparts_info_t *dummy )
static void
macparts_get_info( macparts_info_t *di )
{
DPRINTF("macparts_get_info");
PUSH( -1 ); /* no type */
DPUSH( di->offs );
DPUSH( di->size );
DPRINTF("macparts_get_info %lld %lld\n", di->offs, di->size);
PUSH( di->offs_lo );
PUSH( di->offs_hi );
PUSH( di->size_lo );
PUSH( di->size_hi );
}
static void
@@ -209,9 +286,49 @@ macparts_initialize( macparts_info_t *di )
fword("register-partition-package");
}
/* ( pos.d -- status ) */
static void
macparts_seek(macparts_info_t *di )
{
llong pos = DPOP();
llong offs;
DPRINTF("macparts_seek %llx:\n", pos);
/* Calculate the seek offset for the parent */
offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
offs += pos;
DPUSH(offs);
DPRINTF("macparts_seek parent offset %llx:\n", offs);
call_package(di->seek_xt, my_parent());
}
/* ( buf len -- actlen ) */
static void
macparts_read(macparts_info_t *di )
{
DPRINTF("macparts_read\n");
/* Pass the read back up to the parent */
call_package(di->read_xt, my_parent());
}
/* ( addr -- size ) */
static void
macparts_load( __attribute__((unused))macparts_info_t *di )
{
forth_printf("load currently not implemented for /packages/mac-parts\n");
PUSH(0);
}
NODE_METHODS( macparts ) = {
{ "probe", macparts_probe },
{ "open", macparts_open },
{ "seek", macparts_seek },
{ "read", macparts_read },
{ "load", macparts_load },
{ "get-info", macparts_get_info },
{ "block-size", macparts_block_size },
{ NULL, macparts_initialize },

View File

@@ -38,47 +38,47 @@ enum {
};
typedef struct {
long ddBlock; /* first block of driver */
short ddSize; /* driver size in blocks */
short ddType; /* 1 & -1 for SCSI */
u32 ddBlock; /* first block of driver */
u16 ddSize; /* driver size in blocks */
s16 ddType; /* 1 & -1 for SCSI */
} driver_entry_t;
typedef struct { /* Block 0 of a device */
short sbSig; /* always 0x4552 */
short sbBlockSize; /* 512 */
long sbBlkCount; /* #blocks on device */
short sbDevType; /* 0 */
short sbDevID; /* 0 */
long sbData; /* 0 */
short sbDrvrCount; /* #driver descriptors */
u16 sbSig; /* always 0x4552 */
u16 sbBlockSize; /* 512 */
s32 sbBlkCount; /* #blocks on device */
u16 sbDevType; /* 0 */
u16 sbDevID; /* 0 */
u32 sbData; /* 0 */
s16 sbDrvrCount; /* #driver descriptors */
/* driver entries goes here */
driver_entry_t drivers[61] __attribute__ ((packed));
short filler1;
long filler2;
u16 filler1;
u32 filler2;
} desc_map_t;
typedef struct { /* Partition descriptor */
short pmSig; /* always 0x504d 'PM' */
short pmSigPad; /* 0 */
ulong pmMapBlkCnt; /* #blocks in partition map */
ulong pmPyPartStart; /* first physical block of part. */
ulong pmPartBlkCnt; /* #blocks in partition */
u16 pmSig; /* always 0x504d 'PM' */
u16 pmSigPad; /* 0 */
u32 pmMapBlkCnt; /* #blocks in partition map */
u32 pmPyPartStart; /* first physical block of part. */
u32 pmPartBlkCnt; /* #blocks in partition */
char pmPartName[32]; /* partition name */
char pmPartType[32]; /* partition type */
/* these fields may or may not be used */
ulong pmLgDataStart;
ulong pmDataCnt;
ulong pmPartStatus;
ulong pmLgBootStart;
ulong pmBootSize;
ulong pmBootLoad;
ulong pmBootLoad2;
ulong pmBootEntry;
ulong pmBootEntry2;
ulong pmBootCksum;
u32 pmLgDataStart;
u32 pmDataCnt;
u32 pmPartStatus;
u32 pmLgBootStart;
u32 pmBootSize;
u32 pmBootLoad;
u32 pmBootLoad2;
u32 pmBootEntry;
u32 pmBootEntry2;
u32 pmBootCksum;
char pmProcessor[16];
char filler[376]; /* might contain extra information */

View File

@@ -19,8 +19,18 @@
#include "libopenbios/bindings.h"
#include "fs/fs.h"
#include "libc/diskio.h"
#include "libc/vsprintf.h"
#include "packages.h"
//#define CONFIG_DEBUG_MISC_FILES
#ifdef CONFIG_DEBUG_MISC_FILES
#define DPRINTF(fmt, args...) \
do { printk(fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...)
#endif
#define PATHBUF_SIZE 256
#define VOLNAME_SIZE 64
@@ -42,17 +52,36 @@ do_open( ihandle_t ih )
fs_ops_t *fs = malloc( sizeof(*fs) );
int err, fd;
err = (fd=open_ih(ih)) == -1;
DPRINTF("misc-files doing open with ih " FMT_ucellX "\n", ih);
err = (fd = open_ih(ih)) == -1;
if( !err ) {
err=fs_hfsp_open(fd, fs);
if( err ) err = fs_hfs_open(fd, fs);
if( err ) err = fs_iso9660_open(fd, fs);
if( err ) err = fs_ext2_open(fd, fs);
if( err ) err = fs_grubfs_open(fd, fs);
}
err = fs_hfsp_open(fd, fs);
DPRINTF("--- HFSP returned %d\n", err);
fs->fd = fd;
if( err ) {
err = fs_hfs_open(fd, fs);
DPRINTF("--- HFS returned %d\n", err);
}
if( err ) {
err = fs_iso9660_open(fd, fs);
DPRINTF("--- ISO9660 returned %d\n", err);
}
if( err ) {
err = fs_ext2_open(fd, fs);
DPRINTF("--- ext2 returned %d\n", err);
}
if( err ) {
err = fs_grubfs_open(fd, fs);
DPRINTF("--- grubfs returned %d\n", err);
}
fs->fd = fd;
}
if( err ) {
if( fd != -1 )
@@ -61,6 +90,8 @@ do_open( ihandle_t ih )
return NULL;
}
DPRINTF("misc-files open returns %p\n", fs);
return fs;
}
@@ -83,15 +114,29 @@ files_open( files_info_t *mi )
RET( 0 );
name = my_args_copy();
mi->fs = fs;
DPRINTF("misc-files open arguments: %s\n", name);
/* If we have been passed a specific file, open it */
if( name ) {
if( !(mi->file=fs_open_path(fs, name)) ) {
if( !(mi->file = fs_open_path(fs, name)) ) {
forth_printf("Unable to open path %s\n", name);
free( name );
do_close( fs );
RET(0);
}
/* printk("PATH: %s\n", fs->get_path(mi->file, mi->pathbuf, PATHBUF_SIZE) ); */
DPRINTF("Successfully opened %s\n", name);
// printk("PATH: %s\n", fs->get_path(mi->file, mi->pathbuf, PATHBUF_SIZE) );
} else {
/* No file was specified, but return success so that we can read
the filesystem. If mi->file is not set, routines simply call their
parent which in this case is the partition handler. */
RET(-1);
}
mi->fs = fs;
if( name )
free( name );
@@ -183,17 +228,23 @@ files_close( files_info_t *mi )
static void
files_read( files_info_t *mi )
{
int len = POP();
char *buf = (char*)POP();
int len;
char *buf;
int ret;
if( mi->file ) {
len = POP();
buf = (char*)POP();
ret = mi->fs->read( mi->file, buf, len );
mi->filepos += ret;
PUSH( ret );
} else {
ret = read_io( mi->fs->fd, buf, len );
DPRINTF("misc-files read: no valid FS so calling parent\n");
call_parent_method("read");
}
PUSH( ret );
}
/* ( buf len -- actlen ) */
@@ -208,23 +259,27 @@ files_write( files_info_t *mi )
static void
files_seek( files_info_t *mi )
{
llong pos = DPOP();
cell ret;
if( mi->file ) {
llong pos = DPOP();
cell ret;
int offs = (int)pos;
int whence = SEEK_SET;
DPRINTF("misc-files seek: using FS handle\n");
if( offs == -1 ) {
offs = 0;
whence = SEEK_END;
}
mi->filepos = mi->fs->lseek( mi->file, offs, whence );
ret = (mi->filepos < 0)? -1 : 0;
PUSH( ret );
} else {
ret = seek_io( mi->fs->fd, pos );
DPRINTF("misc-files seek: no valid FS so calling parent\n");
call_parent_method("seek");
}
PUSH( ret );
}
/* ( -- filepos.d ) */
@@ -250,42 +305,89 @@ files_get_fstype( files_info_t *mi )
static void
files_load( files_info_t *mi)
{
char *buf = (char*)POP();
char *buf;
int ret, size;
if (!mi->file) {
PUSH(0);
return;
}
if (mi->file) {
buf = (char*)POP();
size = 0;
size = 0;
while(1) {
ret = mi->fs->read( mi->file, buf, 512 );
if (ret <= 0)
break;
buf += ret;
mi->filepos += ret;
size += ret;
if (ret != 512)
break;
DPRINTF("misc-files load at address %p\n", buf);
while (1) {
ret = mi->fs->read( mi->file, buf, 8192 );
if (ret <= 0)
break;
buf += ret;
mi->filepos += ret;
size += ret;
if (size % 0x100000 == 0)
DPRINTF("----> size is %dM\n", size / 0x100000);
if (ret != 8192)
break;
}
DPRINTF("load complete with size: %d\n", size);
PUSH( size );
} else {
DPRINTF("misc-files load: no valid FS so calling parent\n");
call_parent_method("load");
}
PUSH( size );
}
/* static method, ( ih -- flag? ) */
/* static method, ( pos.d ih -- flag? ) */
static void
files_probe( files_info_t *dummy )
files_probe( files_info_t *mi )
{
ihandle_t ih = POP_ih();
fs_ops_t *fs;
int ret = 0;
llong offs = DPOP();
int fd, err = 0;
if( (fs=do_open(ih)) != NULL ) {
/* printk("HFS[+] filesystem found\n"); */
do_close( fs );
ret = -1;
DPRINTF("misc-files probe with offset %llx\n", offs);
err = (fd = open_ih(ih)) == -1;
if( !err ) {
/*
err = fs_hfsp_open(fd, fs);
DPRINTF("--- HFSP returned %d\n", err);
if( err ) {
err = fs_hfs_open(fd, fs);
DPRINTF("--- HFS returned %d\n", err);
}
if( err ) {
err = fs_iso9660_open(fd, fs);
DPRINTF("--- ISO9660 returned %d\n", err);
}
if( err ) {
err = fs_ext2_open(fd, fs);
DPRINTF("--- ext2 returned %d\n", err);
}
*/
if( err ) {
err = fs_grubfs_probe(fd, offs);
DPRINTF("--- grubfs returned %d\n", err);
}
}
if (fd)
close_io(fd);
/* If no errors occurred, indicate success */
if (!err) {
DPRINTF("misc-files probe found filesystem\n");
PUSH(-1);
} else {
DPRINTF("misc-files probe could not find filesystem\n");
PUSH(0);
}
PUSH( ret );
}
static void

View File

@@ -15,24 +15,40 @@
#include "config.h"
#include "libopenbios/bindings.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 {
ullong offs;
ullong size;
xt_t seek_xt, read_xt;
ucell offs_hi, offs_lo;
ucell size_hi, size_lo;
} 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((ucell)buf); PUSH(size); call_parent(di->read_xt); POP(); })
#define SEEK( pos ) ({ DPUSH(pos); call_parent(seek_xt); POP(); })
#define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(read_xt); POP(); })
/* three helper functions */
/* two 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[510]==0x55 && sect[511]==0xAA;
return sect[0x1fe]==0x55 && sect[0x1ff]==0xAA;
}
static inline int is_pc_extended_part(unsigned char type)
@@ -45,9 +61,13 @@ static void
pcparts_open( pcparts_info_t *di )
{
char *str = my_args_copy();
xt_t seek_xt = find_parent_method("seek");
xt_t read_xt = find_parent_method("read");
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;
@@ -60,19 +80,50 @@ pcparts_open( pcparts_info_t *di )
unsigned char e_cyl;
u32 start_sect; /* unaligned little endian */
u32 nr_sects; /* ditto */
} *p;
} *p, *partition;
unsigned char buf[512];
/* printk("pcparts_open '%s'\n", str ); */
DPRINTF("pcparts_open '%s'\n", str );
/*
Arguments that we accept:
id: [0-7]
[(id,)][filespec]
*/
if( str ) {
parnum = atol(str);
if( !strlen(str) )
parnum = 1;
free( str );
if ( !strlen(str) )
parnum = -1;
else {
/* If end of string, we just have a partition id */
if (str[1] == '\0') {
parstr = str;
} else {
/* If a comma, then we have a partition id plus argument */
if (str[1] == ',') {
str[1] = '\0';
parstr = str;
argstr = &str[2];
} else {
/* Otherwise we have just an argument */
argstr = str;
}
}
/* Convert the id to a partition number */
if (strlen(parstr))
parnum = atol(parstr);
}
}
DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
if( parnum < 0 )
parnum = 1;
parnum = 0;
di->read_xt = find_parent_method("read");
di->seek_xt = find_parent_method("seek");
SEEK( 0 );
if( READ(buf, 512) != 512 )
@@ -80,29 +131,40 @@ pcparts_open( pcparts_info_t *di )
/* Check Magic */
if (!has_pc_part_magic(buf)) {
printk("pc partition magic not found.\n");
DPRINTF("pc partition magic not found.\n");
RET(0);
}
/* get partition data */
p = (struct pc_partition *) (buf + 0x1be);
/* Actual partition data */
partition = (struct pc_partition *) (buf + 0x1be);
bs=512;
/* 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 */
p += parnum;
if (p->type==0 || is_pc_extended_part(p->type)) {
printk("partition %d does not exist\n", parnum+1 );
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 );
}
di->offs = (llong)(__le32_to_cpu(p->start_sect)) * bs;
di->size = (llong)(__le32_to_cpu(p->nr_sects)) * bs;
/* printk("Primary partition at sector %x\n",
__le32_to_cpu(p->start_sect)); */
offs = (llong)(__le32_to_cpu(p->start_sect)) * bs;
di->offs_hi = offs >> BITS;
di->offs_lo = offs & (ucell) -1;
RET( -1 );
size = (llong)(__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;
@@ -116,55 +178,96 @@ pcparts_open( pcparts_info_t *di )
}
if (i >= 4) {
printk("Extended partition not found\n");
DPRINTF("Extended partition not found\n");
RET( 0 );
}
printk("Extended partition at %d\n", i+1);
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;
for (;;) {
/* printk("cur_part=%d at %x\n", cur_part, cur_table); */
while (cur_part <= parnum) {
DPRINTF("cur_part=%d at %lx\n", cur_part, cur_table);
SEEK( cur_table*bs );
SEEK( cur_table * bs );
if( READ(buf, sizeof(512)) != sizeof(512) )
RET( 0 );
if (!has_pc_part_magic(buf)) {
printk("Extended partition has no magic\n");
DPRINTF("Extended partition has no magic\n");
break;
}
p = (struct pc_partition *) (buf + 0x1be);
/* 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) {
printk("Partition %d is empty\n", parnum+1);
if (p->type == 0) {
DPRINTF("Partition %d is empty\n", parnum+1);
RET( 0 );
}
di->offs =
(llong)(cur_table+__le32_to_cpu(p->start_sect)) * bs;
di->size = (llong)__le32_to_cpu(p->nr_sects) * bs;
RET ( -1 );
offs = (llong)(cur_table+__le32_to_cpu(p->start_sect)) * bs;
di->offs_hi = offs >> BITS;
di->offs_lo = offs & (ucell) -1;
size = (llong)__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)) {
printk("no link\n");
DPRINTF("no link\n");
break;
}
cur_table = ext_start + __le32_to_cpu(p[1].start_sect);
cur_table = ext_start + __le32_to_cpu(p[1].start_sect);
cur_part++;
}
printk("Logical partition %d does not exist\n", parnum+1);
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, str);
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 );
}
/* we should never reach this point */
}
/* ( block0 -- flag? ) */
@@ -173,16 +276,24 @@ pcparts_probe( pcparts_info_t *dummy )
{
unsigned char *buf = (unsigned char *)POP();
RET ( has_pc_part_magic(buf) );
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 */
DPUSH( di->offs );
DPUSH( di->size );
PUSH( di->offs_lo );
PUSH( di->offs_hi );
PUSH( di->size_lo );
PUSH( di->size_hi );
}
static void
@@ -197,9 +308,50 @@ pcparts_initialize( pcparts_info_t *di )
fword("register-partition-package");
}
/* ( pos.d -- status ) */
static void
pcparts_seek(pcparts_info_t *di )
{
llong pos = DPOP();
llong offs;
DPRINTF("pcparts_seek %llx:\n", pos);
/* 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 )
{
forth_printf("load currently not implemented for /packages/pc-parts\n");
PUSH(0);
}
NODE_METHODS( pcparts ) = {
{ "probe", pcparts_probe },
{ "open", pcparts_open },
{ "seek", pcparts_seek },
{ "read", pcparts_read },
{ "load", pcparts_load },
{ "get-info", pcparts_get_info },
{ "block-size", pcparts_block_size },
{ NULL, pcparts_initialize },

View File

@@ -15,9 +15,12 @@
#include "config.h"
#include "libopenbios/bindings.h"
#include "libc/byteorder.h"
#include "libc/vsprintf.h"
#include "packages.h"
#ifdef CONFIG_DEBUG_SUN_PARTS
//#define DEBUG_SUN_PARTS
#ifdef DEBUG_SUN_PARTS
#define DPRINTF(fmt, args...) \
do { printk(fmt , ##args); } while (0)
#else
@@ -25,6 +28,7 @@
#endif
typedef struct {
xt_t seek_xt, read_xt;
ucell offs_hi, offs_lo;
ucell size_hi, size_lo;
int type;
@@ -32,9 +36,8 @@ typedef struct {
DECLARE_NODE( sunparts, INSTALL_OPEN, sizeof(sunparts_info_t), "+/packages/sun-parts" );
#define SEEK( pos ) ({ DPUSH(pos); call_parent(seek_xt); POP(); })
#define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(read_xt); POP(); })
#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
#define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(di->read_xt); POP(); })
/* Layout of SUN partition table */
struct sun_disklabel {
@@ -89,27 +92,57 @@ static void
sunparts_open( sunparts_info_t *di )
{
char *str = my_args_copy();
xt_t seek_xt = find_parent_method("seek");
xt_t read_xt = find_parent_method("read");
char *argstr = strdup("");
char *parstr = strdup("");
int parnum = -1;
unsigned char buf[512];
struct sun_disklabel *p;
unsigned int i, bs;
ducell offs, size;
phandle_t ph;
DPRINTF("sunparts_open '%s'\n", str );
if( str ) {
if( !strlen(str) )
parnum = -1;
else if (str[0] >= 'a' && str[0] < ('a' + 8))
parnum = str[0] - 'a';
else
parnum = atol(str);
/*
Arguments that we accept:
id: [0-7] | [a-h]
[(id,)][filespec]
*/
free( str );
if( str ) {
if ( !strlen(str) )
parnum = -1;
else {
/* If end of string, we just have a partition id */
if (str[1] == '\0') {
parstr = str;
} else {
/* If a comma, then we have a partition id plus argument */
if (str[1] == ',') {
str[1] = '\0';
parstr = str;
argstr = &str[2];
} else {
/* Otherwise we have just an argument */
argstr = str;
}
}
/* Convert the id to a partition number */
if (strlen(parstr)) {
if (parstr[0] >= 'a' && parstr[0] < ('a' + 8))
parnum = parstr[0] - 'a';
else
parnum = atol(parstr);
}
}
}
DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
di->read_xt = find_parent_method("read");
di->seek_xt = find_parent_method("seek");
SEEK( 0 );
if( READ(buf, 512) != 512 )
RET(0);
@@ -137,6 +170,7 @@ sunparts_open( sunparts_info_t *di )
parnum = 0;
DPRINTF("Selected partition %d\n", parnum);
offs = (llong)__be32_to_cpu(p->partitions[parnum].start_cylinder) *
__be16_to_cpu(p->ntrks) * __be16_to_cpu(p->nsect) * bs;
@@ -146,9 +180,28 @@ sunparts_open( sunparts_info_t *di )
di->size_hi = size >> BITS;
di->size_lo = size & (ucell) -1;
di->type = __be32_to_cpu(p->infos[parnum].id);
DPRINTF("Found Sun partition table, offs %lld size %lld\n",
DPRINTF("Found Sun partition, offs %lld size %lld\n",
(llong)offs, (llong)size);
/* Probe for filesystem at current offset */
DPRINTF("sun-parts: about to probe for fs\n");
DPUSH( offs );
PUSH_ih( my_parent() );
parword("find-filesystem");
DPRINTF("sun-parts: done fs probe\n");
ph = POP_ph();
if( ph ) {
DPRINTF("sun-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, str);
push_str( argstr );
PUSH_ph( ph );
fword("interpose");
} else {
DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n");
}
free( str );
RET( -1 );
}
@@ -158,6 +211,8 @@ sunparts_probe( __attribute__((unused))sunparts_info_t *dummy )
{
unsigned char *buf = (unsigned char *)POP();
DPRINTF("probing for Sun partitions\n");
RET ( has_sun_part_magic(buf) );
}
@@ -185,11 +240,52 @@ sunparts_initialize( __attribute__((unused))sunparts_info_t *di )
fword("register-partition-package");
}
/* ( pos.d -- status ) */
static void
sunparts_seek(sunparts_info_t *di )
{
llong pos = DPOP();
llong offs;
DPRINTF("sunparts_seek %llx:\n", pos);
/* Calculate the seek offset for the parent */
offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
offs += pos;
DPUSH(offs);
DPRINTF("sunparts_seek parent offset %llx:\n", offs);
call_package(di->seek_xt, my_parent());
}
/* ( buf len -- actlen ) */
static void
sunparts_read(sunparts_info_t *di )
{
DPRINTF("sunparts_read\n");
/* Pass the read back up to the parent */
call_package(di->read_xt, my_parent());
}
/* ( addr -- size ) */
static void
sunparts_load( __attribute__((unused))sunparts_info_t *di )
{
forth_printf("load currently not implemented for /packages/sun-parts\n");
PUSH(0);
}
NODE_METHODS( sunparts ) = {
{ "probe", sunparts_probe },
{ "open", sunparts_open },
{ "get-info", sunparts_get_info },
{ "block-size", sunparts_block_size },
{ "seek", sunparts_seek },
{ "read", sunparts_read },
{ "load", sunparts_load },
{ NULL, sunparts_initialize },
};