#include "fs.h"
#include "errors.h"
#include "debug.h"
+#include "bootinfo.h"
#define FAST_VERSION
#define MAX_READ_RANGE 256
#include "ext2fs/ext2fs.h"
static int ext2_open( struct boot_file_t* file,
- const char* dev_name,
struct partition_t* part,
- const char* file_name);
+ struct boot_fspec_t* fspec);
static int ext2_read( struct boot_file_t* file,
unsigned int size,
void* buffer);
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);
struct fs_t ext2_filesystem =
{
ext2_open,
ext2_read,
ext2_seek,
- ext2_close
+ ext2_close,
+ ext2_ino_size,
};
/* IO manager structure for the ext2 library */
static int opened = 0; /* We can't open twice ! */
static unsigned int bs; /* Blocksize */
static unsigned long long doff; /* Byte offset where partition starts */
+static unsigned long long dend; /* Byte offset where partition ends */
static ino_t root,cwd;
static ext2_filsys fs = 0;
static struct boot_file_t* cur_file;
static int
ext2_open( struct boot_file_t* file,
- const char* dev_name,
struct partition_t* part,
- const char* file_name)
+ struct boot_fspec_t* fspec)
{
int result = 0;
int error = FILE_ERR_NOTFOUND;
static char buffer[1024];
int ofopened = 0;
+ char *dev_name = fspec->dev;
+ char *file_name = fspec->file;
DEBUG_ENTER;
DEBUG_OPEN;
DEBUG_LEAVE(FILE_ERR_FSBUSY);
return FILE_ERR_FSBUSY;
}
- if (file->device_kind != FILE_DEVICE_BLOCK) {
+ if (file->device_kind != FILE_DEVICE_BLOCK
+ && file->device_kind != FILE_DEVICE_ISCSI) {
DEBUG_LEAVE(FILE_ERR_BADDEV);
return FILE_ERR_BADDEV;
}
* compatible with older versions of OF
*/
bs = 1024;
- doff = 0;
- if (part)
+
+ /*
+ * On the other hand, we do care about the actual size of the
+ * partition, reads or seeks past the end may cause undefined
+ * behavior on some devices. A netapp that tries to seek and
+ * read past the end of the lun takes ~30 secs to recover per
+ * attempt.
+ */
+ doff = dend = 0;
+ if (part) {
doff = (unsigned long long)(part->part_start) * part->blocksize;
+ dend = doff + (unsigned long long)part->part_size * part->blocksize;
+ }
cur_file = file;
- DEBUG_F("partition offset: %Lu\n", doff);
+ DEBUG_F("partition offset: %Lx, end: %Lx\n", doff, dend);
/* Open the OF device for the entire disk */
strncpy(buffer, dev_name, 1020);
- strcat(buffer, ":0");
+ if (_machine != _MACH_bplan)
+ strcat(buffer, ":0");
DEBUG_F("<%s>\n", buffer);
return 0;
}
+static unsigned int ext2_ino_size(struct boot_file_t *file)
+{
+ struct ext2_inode ei;
+
+ if (ext2fs_read_inode(fs, file->inode, &ei))
+ return 0;
+
+ return ei.i_size;
+}
+
static errcode_t linux_open (const char *name, int flags, io_channel * channel)
{
io_channel io;
static errcode_t linux_set_blksize (io_channel channel, int blksize)
{
+ DEBUG_F("bs set to 0x%x\n", blksize);
channel->block_size = bs = blksize;
if (block_buffer) {
free(block_buffer);
tempb = (((unsigned long long) block) *
((unsigned long long)bs)) + (unsigned long long)doff;
+ /*
+ * Only test tempb exceeding dend if dend is set to allow things
+ * like boot: hd:0,\xxxx
+ */
+ if (dend && tempb > dend) {
+ DEBUG_F("\nSeek error on block %lx, tempb=%Lx\n", block, tempb >> 9);
+ return EXT2_ET_LLSEEK_FAILED;
+ }
+
size = (count < 0) ? -count : count * bs;
prom_lseek(cur_file->of_device, tempb);
if (prom_read(cur_file->of_device, data, size) != size) {