ino_t inode;
__u64 pos;
unsigned char* buffer;
+ char* devspec_cache;
__u64 len;
// unsigned int dev_blk_size;
// unsigned int part_start;
int (*close)( struct boot_file_t* file);
- unsigned int (*ino_size)(struct boot_file_t *file);
+ int (*ino_size)(struct boot_file_t *file, unsigned int *size);
};
extern const struct fs_t *fs_of;
static int ext2_seek( struct boot_file_t* file,
unsigned int newpos);
static int ext2_close( struct boot_file_t* file);
-static unsigned int ext2_ino_size(struct boot_file_t *file);
+static int ext2_ino_size(struct boot_file_t *file, unsigned int *size);
struct fs_t ext2_filesystem =
{
return 0;
}
-static unsigned int ext2_ino_size(struct boot_file_t *file)
+static int ext2_ino_size(struct boot_file_t *file, unsigned int *size)
{
struct ext2_inode ei;
if (ext2fs_read_inode(fs, file->inode, &ei))
- return 0;
+ return FILE_IOERR;
- return ei.i_size;
+ *size = ei.i_size;
+ return FILE_ERR_OK;
}
static errcode_t linux_open (const char *name, int flags, io_channel * channel)
static int of_read(struct boot_file_t* file, unsigned int size, void* buffer);
static int of_seek(struct boot_file_t* file, unsigned int newpos);
static int of_close(struct boot_file_t* file);
+static int of_ino_size(struct boot_file_t* file, unsigned int *size);
static int of_net_open(struct boot_file_t* file,
struct partition_t* part, struct boot_fspec_t* fspec);
static int of_net_read(struct boot_file_t* file, unsigned int size, void* buffer);
static int of_net_seek(struct boot_file_t* file, unsigned int newpos);
-static unsigned int of_net_ino_size(struct boot_file_t* file);
+static int of_net_ino_size(struct boot_file_t* file, unsigned int *size);
struct fs_t of_filesystem =
of_open,
of_read,
of_seek,
- of_close
+ of_close,
+ of_ino_size,
};
struct fs_t of_net_filesystem =
file->pos = 0;
file->buffer = NULL;
+ file->devspec_cache = strdup(buffer);
+
if ((file->of_device == PROM_INVALID_HANDLE) || (file->of_device == 0))
{
DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
return 0;
}
-static unsigned int
-of_net_ino_size(struct boot_file_t* file)
+static int
+of_ino_size(struct boot_file_t* file, unsigned int *size)
+{
+ static char buffer[1<<20];
+ int read_count = 0;
+
+ if (file->len == 0) {
+ DEBUG_F("Estimating size of: %p\n", file->of_device);
+ while (prom_read(file->of_device, (void *)&buffer, sizeof(buffer))
+ != 0) {
+ read_count++;
+ DEBUG_F("read_count == %d\n", read_count);
+ }
+ file->pos = 0;
+ file->len = read_count * sizeof(buffer);
+ /* sigh:
+ * prom_seek(file->of_device, file->pos);
+ * doen't work */
+ prom_close(file->of_device);
+ DEBUG_F("Re-Opening: \"%s\"\n", file->devspec_cache);
+ file->of_device = prom_open(file->devspec_cache);
+ DEBUG_F("file->of_device = %p\n", file->of_device);
+ if (file->of_device == 0) {
+ file->len = 0;
+ return FILE_IOERR;
+ }
+ }
+
+ DEBUG_F("Estimated size is: %Lu(%d)\n", (unsigned long long)file->len,
+ read_count);
+ *size = file->len;
+ return FILE_ERR_OK;
+}
+
+static int
+of_net_ino_size(struct boot_file_t* file, unsigned int *size)
{
- return file->len;
+ *size = file->len;
+ return FILE_ERR_OK;
}
/*
#define KERNEL_LINK_ADDR_PPC32 0xC0000000UL
#define KERNEL_LINK_ADDR_PPC64 0xC000000000000000ULL
+#define INITRD_CHUNKSIZE 0x100000
+
typedef struct {
union {
Elf32_Ehdr elf32hdr;
loadinfo_t loadinfo;
void *initrd_more,*initrd_want;
unsigned long initrd_read;
+ unsigned int len = INITRD_CHUNKSIZE;
loadinfo.load_loc = 0;
}
prom_printf("Loading ramdisk...\n");
result = open_file(¶ms.rd, &file);
+ if (result == FILE_ERR_OK && file.fs->ino_size) {
+ result = file.fs->ino_size(&file, &len);
+ }
if (result != FILE_ERR_OK) {
prom_printf("%s:%d,", params.rd.dev, params.rd.part);
prom_perror(result, params.rd.file);
}
else {
-#define INITRD_CHUNKSIZE 0x100000
- unsigned int len = INITRD_CHUNKSIZE;
-
- /* We add a bit to the actual size so the loop below doesn't think
- * there is more to load.
+ /* We add a bit to the actual size so the loop below
+ * doesn't think there is more to load.
*/
- if (file.fs->ino_size && file.fs->ino_size(&file) > 0)
- len = file.fs->ino_size(&file) + 0x1000;
+ len += 0x1000;
initrd_base = prom_claim_chunk(loadinfo.base+loadinfo.memsize, len, 0);
if (initrd_base == (void *)-1) {