1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
*/
#include "bootloader.h"
/* this is the stupidest "file system" imaginable -- it applies an */
/* offset to the seek pointers and optionally checks against a length */
struct offsets {
int fd;
__u64 start;
__u64 length;
} ofd [MAX_FD];
static int offset_read(int fd, char *buf, unsigned count, __u64 devaddr)
{
struct offsets *o = &ofd[fd];
if (Debug) printf("offset_read(%d, 0x%p, %d, %lld)\r\n",
fd, buf, count, devaddr);
/* abort early if we reach firmware limit */
if (disk_2gb_limit && ((devaddr + count) >> 31)) {
printf("offset_read(%lld): block not reachable via firmware call\r\n",
devaddr + count);
return -1;
}
/* truncate 'count' according to max device/file size */
if (o->length > 0 && devaddr < o->length && devaddr + count > o->length)
count = o->length - devaddr;
else if (o->length > 0 && devaddr + count > o->length)
{
printf("offset_read(%d, 0x%p, %d, %lld) can't seek past %lld\r\n",
fd, buf, count, devaddr, o->length);
return -1;
}
return seekread(o->fd, buf, count, devaddr + o->start);
}
static void offset_describe(int fd, int *bufalign,
int *blocksize)
{
describe(ofd[fd].fd, bufalign, blocksize);
}
/* returns true if OK */
int offset_open(int otherfd, __u64 offset, __u64 length)
{
int fd = fileio_open(offset_describe, offset_read);
if (fd >= 0)
{
struct offsets *o = &ofd[fd];
o->fd = otherfd;
o->start = offset;
o->length = length;
}
if (Debug) printf("offset_open(%d, %lld, %lld) = %d\n",
otherfd, offset, length, fd);
return fd;
}
|