summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2022-08-04 16:11:27 +0200
committerHelge Deller <deller@gmx.de>2022-08-04 16:35:04 +0200
commitc6d95074c7f6f1c873f515b700060408d7a6761f (patch)
tree5cbb4d5caf318377b84fa6da69e726fccf051184
parent3859f95ffe7aa4bbc824de54cd871046115f358e (diff)
downloadpalo-c6d95074c7f6f1c873f515b700060408d7a6761f.tar.gz
ipl: Allow to boot beyond the 2GB disk limit (on most machines)
Most newer-generation PA-RISC machines provide firmware support for the ENTRY_IO_BBLOCK_IN (ARG=16) PDC option which addresses sectors in terms of 2048 byte blocks. This feature overcomes the limitations of the old ENTRY_IO_BOOTIN (ARG=0) PDC option, which uses byte offsets and thus requires that boot files are located inside the first 2GB of the drive. This palo patch checks the IODC_FEATURES (byte 10) of the IODC block of the boot device, and if the rightmost bit is set, it will use the ENTRY_IO boot block input support. Palo will output at startup if the machines has the 2GB limitation: -> Boot limited to sectors below 2GB: YES/NO Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--ipl/bootloader.h14
-rw-r--r--ipl/byteio.c31
-rw-r--r--ipl/ext2.c25
-rw-r--r--ipl/fileio.c4
-rw-r--r--ipl/ipl.c10
-rw-r--r--ipl/lib.c4
-rw-r--r--ipl/offset.c14
-rw-r--r--ipl/pdc_bootio.c33
-rw-r--r--ipl/pdc_misc.c54
-rw-r--r--ipl/vsprintf.c19
-rw-r--r--lib/common.h5
-rw-r--r--lib/diskpart.c38
-rw-r--r--palo/palo.c2
-rw-r--r--palo/palo.h4
-rw-r--r--palo/paloio.c18
15 files changed, 150 insertions, 125 deletions
diff --git a/ipl/bootloader.h b/ipl/bootloader.h
index 0c0116d..8871d87 100644
--- a/ipl/bootloader.h
+++ b/ipl/bootloader.h
@@ -12,24 +12,28 @@
#define MAX_FD 20
+#define __u64 unsigned long long
+
/* pdc_misc.c */
void die(const char *);
void firmware_init(int started_wide);
int pdc_default_width(int wide);
+int pdc_bootdisk_2GB_limit(void);
int pdc_cons_duplex();
int pdc_cons_mux(int *is_mux);
int pdc_iodc_cin(char *buf, int size);
void pdc_iodc_cout(const char *c, int size);
int pdc_os_bits();
-int pdc_iodc_bootin(unsigned devaddr, char *memaddr, unsigned size);
+int pdc_iodc_bootin(__u64 devaddr, char *memaddr, unsigned size);
int pdc_read_conspath(unsigned char *memaddr);
int pdc_do_reset(void);
int pdc_model_sysmodel(char *name);
typedef void (*describe_t)(int fd, int *bufalign, int *blocksize);
-typedef int (*read_t)(int fd, char *buf, unsigned nbytes, unsigned devaddr);
+typedef int (*read_t)(int fd, char *buf, unsigned nbytes, __u64 devaddr);
extern int Debug;
+extern int disk_2gb_limit;
extern const char bld_info[];
@@ -41,7 +45,7 @@ int byteio_open(int otherfd);
/* fileio.c */
int fileio_open(describe_t describef, read_t readf);
-int seekread(int fd, char *buf, unsigned nbytes, unsigned devaddr);
+int seekread(int fd, char *buf, unsigned nbytes, __u64 devaddr);
void describe(int fd, int *bufalign, int *blocksize);
/* ext2.c */
@@ -54,7 +58,7 @@ const char * ext2_readdir(int fd, int rewind, unsigned char *file_type);
void ext2_close(int fd);
/* lib.c */
-void blockprint(int zero_offset, char *buf, int nbytes);
+void blockprint(__u64 zero_offset, char *buf, int nbytes);
char *malloc_aligned(int nbytes, int align);
void *malloc(size_t nbytes);
void mark(void **ptr);
@@ -89,7 +93,7 @@ int putchar(int c);
int printf(const char *fmt, ...);
/* offset.c */
-int offset_open(int otherfd, int offset, int length);
+int offset_open(int otherfd, __u64 offset, __u64 length);
/* crt0.S */
typedef struct { unsigned save[32]; } jmp_buf;
diff --git a/ipl/byteio.c b/ipl/byteio.c
index ce1e597..07b34cd 100644
--- a/ipl/byteio.c
+++ b/ipl/byteio.c
@@ -31,10 +31,7 @@ struct bs
int align;
/* data in 'bd_readbuf' was seekread from boot device offset 'bd_bufoffset' */
- int devoffset;
-
- /* offset of next byte to be seekread from device */
- int devnextptr;
+ __u64 devoffset;
/* pointer to the properly-aligned 'blocksize' buffer */
char *readbuf;
@@ -43,9 +40,9 @@ struct bs
static struct bs *blockio = 0;
static int
-delivercache(struct bs *b, char **buf, unsigned *devaddr, unsigned endaddr)
+delivercache(struct bs *b, char **buf, __u64 *devaddr, __u64 endaddr)
{
- unsigned block = *devaddr & ~(b->blocksize - 1);
+ __u64 block = *devaddr & ~((__u64)b->blocksize - 1);
int offset = *devaddr - block;
int n = 0;
@@ -57,7 +54,7 @@ delivercache(struct bs *b, char **buf, unsigned *devaddr, unsigned endaddr)
/* copy into user's buffer */
memcpy(*buf, b->readbuf + offset, n);
- if (0 && Debug) printf("delivercache: %d bytes from devaddr 0x%x to 0x%p\r\n",
+ if (0 && Debug) printf("delivercache: %d bytes from devaddr 0x%llx to 0x%p\r\n",
n, *devaddr, *buf);
*devaddr += n;
@@ -68,10 +65,10 @@ delivercache(struct bs *b, char **buf, unsigned *devaddr, unsigned endaddr)
}
static int
-cacheblock(struct bs *b, unsigned devaddr)
+cacheblock(struct bs *b, __u64 devaddr)
{
int n;
- unsigned block = devaddr & ~(b->blocksize - 1);
+ __u64 block = devaddr & ~((__u64)b->blocksize - 1);
if ((n = seekread(b->fd, b->readbuf, b->blocksize, block)) != b->blocksize)
{
@@ -81,17 +78,17 @@ cacheblock(struct bs *b, unsigned devaddr)
return 0;
}
b->devoffset = block;
- if (0 && Debug) printf("cacheblock: cached block at devaddr 0x%x\r\n", devaddr);
+ if (0 && Debug) printf("cacheblock: cached block at devaddr 0x%llx\r\n", devaddr);
return 1;
}
-static int byteio_read(int fd, char *buf, unsigned count, unsigned devaddr)
+static int byteio_read(int fd, char *buf, unsigned count, __u64 devaddr)
{
struct bs *b = &blockio[fd];
- unsigned endaddr = devaddr + count;
- unsigned remember = devaddr;
+ __u64 endaddr = devaddr + count;
+ __u64 remember = devaddr;
- if (Debug) printf("byteio_read(fd:%d, buf:%p, count:%u, devaddr:0x%x)\r\n",
+ if (Debug) printf("byteio_read(fd:%d, buf:%p, count:%u, devaddr:0x%llx)\r\n",
fd, buf, count, devaddr);
while (devaddr < endaddr)
@@ -99,7 +96,7 @@ static int byteio_read(int fd, char *buf, unsigned count, unsigned devaddr)
int n, bigread;
char *alignedbuf;
- if (0 && Debug) printf("b_r: buf:0x%p devaddr 0x%x %s endaddr 0x%x\r\n",
+ if (0 && Debug) printf("b_r: buf:0x%p devaddr 0x%llx %s endaddr 0x%llx\r\n",
buf, devaddr,
(devaddr & (b->blocksize - 1)) == 0 ? "aligned" : "unaligned",
endaddr);
@@ -134,9 +131,9 @@ static int byteio_read(int fd, char *buf, unsigned count, unsigned devaddr)
bigread -= alignedbuf - buf;
/* must be a multiple of blocksize */
- bigread &= ~(b->blocksize - 1);
+ bigread &= ~((__u64)b->blocksize - 1);
- if (Debug) printf("reading %u bytes from dev %x to ubuf %p\r\n",
+ if (Debug) printf("reading %u bytes from dev 0x%llx to ubuf %p\r\n",
bigread, devaddr, alignedbuf);
/* read the blocks into user's buf */
if ((n = seekread(b->fd, alignedbuf, bigread, devaddr))
diff --git a/ipl/ext2.c b/ipl/ext2.c
index 9b46a37..a468790 100644
--- a/ipl/ext2.c
+++ b/ipl/ext2.c
@@ -338,7 +338,7 @@ static struct ext2_inode *ext2_iget(int ino)
struct ext2_inode *ip;
struct inode_table_entry *itp = 0;
int group;
- long offset;
+ __u64 offset;
ip = 0;
@@ -363,11 +363,11 @@ static struct ext2_inode *ext2_iget(int ino)
printf("group is %d\n", group);
#endif
offset = partition_offset
- + ((long) ext2_gds(group)->bg_inode_table * (long)ext2_blocksize)
+ + ((__u64) ext2_gds(group)->bg_inode_table * ext2_blocksize)
+ (((ino - 1) % EXT2_INODES_PER_GROUP(&sb))
* EXT2_INODE_SIZE(&sb));
#ifdef DEBUG
- printf("ext2_iget: reading %ld bytes at offset %ld "
+ printf("ext2_iget: reading %ld bytes at offset %lld "
"(%ld + (%d * %d) + ((%d) %% %d) * %d) "
"(inode %d -> table %d)\n",
sizeof(struct ext2_inode), offset, partition_offset,
@@ -560,7 +560,7 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff)
int blkno;
int iblkno;
int diblkno;
- unsigned long offset;
+ __u64 offset;
if (ip->i_flags & EXT3_EXTENTS_FL)
return ext3_extent_blkno(ip, blkoff);
@@ -583,7 +583,7 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff)
/* Read the indirect block */
if (cached_iblkno != iblkno) {
- offset = partition_offset + (long)iblkno * (long)ext2_blocksize;
+ offset = partition_offset + (__u64)iblkno * ext2_blocksize;
if (cons_read(dev, iblkbuf, ext2_blocksize, offset)
!= ext2_blocksize)
{
@@ -610,7 +610,7 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff)
/* Read in the double-indirect block */
if (cached_diblkno != diblkno) {
- offset = partition_offset + (long) diblkno * (long) ext2_blocksize;
+ offset = partition_offset + (__u64) diblkno * ext2_blocksize;
if (cons_read(dev, diblkbuf, ext2_blocksize, offset)
!= ext2_blocksize)
{
@@ -631,7 +631,7 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff)
/* Read the indirect block */
if (cached_iblkno != iblkno) {
- offset = partition_offset + (long) iblkno * (long) ext2_blocksize;
+ offset = partition_offset + (__u64) iblkno * ext2_blocksize;
if (cons_read(dev, iblkbuf, ext2_blocksize, offset)
!= ext2_blocksize)
{
@@ -667,7 +667,8 @@ static int print_ext2_blkno(struct ext2_inode *ip, int blkoff)
static int ext2_breadi(struct ext2_inode *ip, long blkno, long nblks,
char *buffer)
{
- long dev_blkno, ncontig, offset, nbytes, tot_bytes;
+ long dev_blkno, ncontig, nbytes, tot_bytes;
+ __u64 offset;
if (Debug) printf("ext2_breadi(%p, %ld, %ld, %p)\n",
ip, blkno, nblks, buffer);
@@ -698,9 +699,9 @@ static int ext2_breadi(struct ext2_inode *ip, long blkno, long nblks,
memset(buffer, 0, nbytes);
} else {
/* Read it for real */
- offset = partition_offset + (long) dev_blkno* (long) ext2_blocksize;
+ offset = partition_offset + (__u64) dev_blkno * ext2_blocksize;
#ifdef DEBUG
- printf("ext2_bread: reading %ld bytes at offset %ld\n",
+ printf("ext2_bread: reading %ld bytes at offset %lld\n",
nbytes, offset);
#endif
if (cons_read(dev, buffer, nbytes, offset)
@@ -960,12 +961,12 @@ static struct ext2_inode * ext2_follow_link(struct ext2_inode * from,
}
}
-static int ext2_read(int fd, char *buf, unsigned count, unsigned devaddr)
+static int ext2_read(int fd, char *buf, unsigned count, __u64 devaddr)
{
struct ext2_inode * ip;
ip = fd2inode[fd];
- if (Debug) printf("ext2_read(%d, 0x%p, %d, %d)\n",
+ if (Debug) printf("ext2_read(%d, 0x%p, %d, %lld)\n",
fd, buf, count, devaddr);
return ext2_breadi(ip,
diff --git a/ipl/fileio.c b/ipl/fileio.c
index 3788afd..7b31a69 100644
--- a/ipl/fileio.c
+++ b/ipl/fileio.c
@@ -44,11 +44,11 @@ int fileio_open(describe_t describef, read_t readf)
return d;
}
-int seekread(int fd, char *buf, unsigned nbytes, unsigned devaddr)
+int seekread(int fd, char *buf, unsigned nbytes, __u64 devaddr)
{
int r = -1;
- if (0) printf("seekread(%d, 0x%p, %d, %d)\r\n", fd, buf, nbytes, devaddr);
+ if (0) printf("seekread(%d, 0x%p, %d, 0x%llx)\r\n", fd, buf, nbytes, devaddr);
if (fileio[fd].readf != 0)
r = (*fileio[fd].readf)(fd, buf, nbytes, devaddr);
diff --git a/ipl/ipl.c b/ipl/ipl.c
index ffa4112..ef422d3 100644
--- a/ipl/ipl.c
+++ b/ipl/ipl.c
@@ -19,6 +19,7 @@ extern char _end, _start, _edata;
int Debug = 0;
int interactive = 0;
+int disk_2gb_limit;
/*
* Beware: pdc_model_sysmodel() may return a machine name which has trailing
@@ -328,8 +329,8 @@ ls(char *path)
partition_transform(&part, NULL);
/* partition table starts from zero */
- part_fd = offset_open(bootdev, 512 * partition[part - 1].start,
- 512 * partition[part - 1].length);
+ part_fd = offset_open(bootdev, 512ULL * partition[part - 1].start,
+ 512ULL * partition[part - 1].length);
if(ext2_mount(part_fd, 0, 0) == -1) {
printf("Failed to mount partition %d\n", part);
return;
@@ -535,6 +536,9 @@ iplmain(int is_interactive, char *initialstackptr, int started_wide)
printf("palo loaded at %p-%p.\n", &_start, &_end);
}
+ disk_2gb_limit = pdc_bootdisk_2GB_limit();
+ printf("Boot limited to sectors below 2GB: %s\n", disk_2gb_limit ? "YES":"NO");
+
restart:
blocked_bootdev = pdc_bootdev_open();
@@ -809,7 +813,7 @@ iplmain(int is_interactive, char *initialstackptr, int started_wide)
pp = &partition[kern_part - 1];
- part_fd = offset_open(bootdev, 512 * pp->start, 512 * pp->length);
+ part_fd = offset_open(bootdev, 512ULL * pp->start, 512ULL * pp->length);
mount_fd = ext2_mount(part_fd, 0, 0);
if (0) printf("ext2_mount(partition %d) returns %d\n",
diff --git a/ipl/lib.c b/ipl/lib.c
index de7ad6d..3a39727 100644
--- a/ipl/lib.c
+++ b/ipl/lib.c
@@ -8,13 +8,13 @@
#include "bootloader.h"
void
-blockprint(int zero_offset, char *buf, int nbytes)
+blockprint(__u64 zero_offset, char *buf, int nbytes)
{
int i;
for (i = 0; i < nbytes; i += 16)
{
int j;
- printf("%d:", zero_offset + i);
+ printf("%lld:", zero_offset + i);
for (j = 0; j < 16; j++)
{
printf(" %02x", buf[i + j] & 0xff);
diff --git a/ipl/offset.c b/ipl/offset.c
index 8441091..c048461 100644
--- a/ipl/offset.c
+++ b/ipl/offset.c
@@ -12,15 +12,15 @@
struct offsets {
int fd;
- int start;
- int length;
+ __u64 start;
+ __u64 length;
} ofd [MAX_FD];
-static int offset_read(int fd, char *buf, unsigned count, unsigned devaddr)
+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, %d)\r\n",
+ if (Debug) printf("offset_read(%d, 0x%p, %d, %lld)\r\n",
fd, buf, count, devaddr);
/* truncate 'count' according to max device/file size */
@@ -28,7 +28,7 @@ static int offset_read(int fd, char *buf, unsigned count, unsigned devaddr)
count = o->length - devaddr;
else if (o->length > 0 && devaddr + count > o->length)
{
- printf("offset_read(%d, 0x%p, %d, %d) can't seek past %d\r\n",
+ printf("offset_read(%d, 0x%p, %d, %lld) can't seek past %lld\r\n",
fd, buf, count, devaddr, o->length);
return -1;
}
@@ -43,7 +43,7 @@ static void offset_describe(int fd, int *bufalign,
}
/* returns true if OK */
-int offset_open(int otherfd, int offset, int length)
+int offset_open(int otherfd, __u64 offset, __u64 length)
{
int fd = fileio_open(offset_describe, offset_read);
@@ -56,7 +56,7 @@ int offset_open(int otherfd, int offset, int length)
o->length = length;
}
- if (Debug) printf("offset_open(%d, %d, %d) = %d\n",
+ if (Debug) printf("offset_open(%d, %lld, %lld) = %d\n",
otherfd, offset, length, fd);
return fd;
diff --git a/ipl/pdc_bootio.c b/ipl/pdc_bootio.c
index 3810fb4..c23e0b2 100644
--- a/ipl/pdc_bootio.c
+++ b/ipl/pdc_bootio.c
@@ -18,24 +18,20 @@
static int pdc_bootdev_read(int fd,
char *dest,
unsigned int n,
- unsigned int seek)
+ __u64 seek)
{
- int nbytes = 0;
- static unsigned devaddr = 0;
+ unsigned long nbytes = 0;
+ static __u64 devaddr = 0;
- if (0 && Debug) printf("pdc_bootdev_read(fd:%d, dest:0x%p, n:%u, seek:0x%x) 0x%x\n",
- fd, dest, n, seek, devaddr);
+ if (1 && Debug) printf("pdc_bootdev_read(fd:%d, dest:0x%p, n:%u, seek:0x%llx)\n",
+ fd, dest, n, seek);
if ((unsigned int)dest & 0x3f) {
printf("\nERROR: Boot device I/O buffer not properly aligned.\n");
return -1;
- } else if (n % 2048) {
+ } else if (n % FW_BLOCKSIZE) {
printf("\nERROR: Boot device read size not a multiple of 2048.\n");
return -1;
- } else if (seek & 0x80000000) {
- /* an unreliable test */
- printf("Information: Boot device can't seek past 2Gb (ignore next error).\n");
- return -1;
}
if (PAGE0->mem_boot.cl_class == CL_RANDOM)
@@ -48,14 +44,14 @@ static int pdc_bootdev_read(int fd,
/* check for rewind semantic */
if (seek < devaddr)
{
- printf("NOTE: pdc_bootdev_read() asked to seek to 0x%x from 0x%x, rewinding...\n", seek, devaddr);
+ printf("NOTE: pdc_bootdev_read() asked to seek to 0x%llx from 0x%llx, rewinding...\n", seek, devaddr);
/* IODC needs devaddr 0 to do a rewind */
devaddr = 0;
}
while (devaddr < seek)
{
- unsigned nseek = seek - devaddr;
+ __u64 nseek = seek - devaddr;
int count;
if (nseek > n)
nseek = n;
@@ -80,7 +76,7 @@ abort_with_warning:
/* how many bytes should be read? */
count = n - nbytes;
- if (Debug) printf("pdc_iodc_bootin(dev:0x%x, buf:0x%p, count:%u) = ",
+ if (Debug) printf("pdc_iodc_bootin(dev:0x%llx, buf:0x%p, count:%u) = ",
devaddr, dest+nbytes, count);
count = pdc_iodc_bootin(devaddr, dest + nbytes, count);
@@ -89,12 +85,9 @@ abort_with_warning:
if (0 && Debug)
{
- printf("%d@0x%x ", count, devaddr);
- {
- int i;
- for (i = 0; i < 16; i++)
- printf(" %02x", dest[nbytes + i] & 0xff);
- }
+ int i;
+ for (i = 0; i < 16; i++)
+ printf(" %02x", dest[nbytes + i] & 0xff);
printf("\n");
}
@@ -130,7 +123,7 @@ static void pdc_bootdev_describe(int fd, int *bufalign,
int *blocksize)
{
if (bufalign != 0)
- *bufalign = 64;
+ *bufalign = disk_2gb_limit ? 64 : FW_BLOCKSIZE;
if (blocksize != 0)
*blocksize = FW_BLOCKSIZE;
diff --git a/ipl/pdc_misc.c b/ipl/pdc_misc.c
index f2231ab..b2296da 100644
--- a/ipl/pdc_misc.c
+++ b/ipl/pdc_misc.c
@@ -237,6 +237,31 @@ pdc_model_sysmodel(char *name)
return r;
}
+/*
+ See https://parisc.wiki.kernel.org/images-parisc/9/9c/Pdc11-v0.96-Ch3-IODC.pdf The
+ IODC_FEATURES (byte 10) byte specifies which optional IODC feature are
+ supported by this module. The rightmost bit (block field) specifies whether
+ ENTRY_IO support block input (ARG1=16) and Boot block output (ARG1=17) are
+ supported.
+ */
+int
+pdc_bootdisk_2GB_limit(void)
+{
+ int r;
+ struct pdc_iodc iodc __attribute__ ((aligned (8)));
+
+ iodc.features = 0;
+ r = firmware_call(mem_pdc, PDC_IODC, PDC_IODC_READ,
+ pdc_result, PAGE0->mem_boot.hpa,
+ PDC_IODC_INDEX_DATA, &iodc, sizeof(iodc));
+
+ /* check boot block feature */
+ if (r >= 0)
+ return (iodc.features & 1) == 0;
+
+ return 1;
+}
+
int
pdc_cons_duplex()
{
@@ -331,14 +356,35 @@ pdc_iodc_cout(const char *s, int size)
}
int
-pdc_iodc_bootin(unsigned devaddr, char *memaddr, unsigned size)
+pdc_iodc_bootin(__u64 devaddr, char *memaddr, unsigned size)
{
- int r;
+ int r = -1;
- r = firmware_call(PAGE0->mem_boot.iodc_io,
+ if (!disk_2gb_limit) {
+ unsigned long a = devaddr / FW_BLOCKSIZE;
+ unsigned long s = (size + FW_BLOCKSIZE - 1) / FW_BLOCKSIZE;
+ r = firmware_call(PAGE0->mem_boot.iodc_io,
+ PAGE0->mem_boot.hpa, ENTRY_IO_BBLOCK_IN,
+ PAGE0->mem_boot.spa, PAGE0->mem_boot.dp.layers,
+ pdc_result, a, memaddr, s, s);
+ if (r >= 0)
+ {
+ convert_from_wide(pdc_result);
+ /* ENTRY_IO_BBLOCK_IN returns blocks, not bytes */
+ return pdc_result[0] * FW_BLOCKSIZE; /* return count in bytes */
+ }
+ }
+
+ if (r < 0) {
+ /* check for overflow - ENTRY_IO_BOOTIN allows up to 2GB only */
+ if (devaddr >> 31)
+ r = PDC_INVALID_ARG;
+ else
+ r = firmware_call(PAGE0->mem_boot.iodc_io,
PAGE0->mem_boot.hpa, ENTRY_IO_BOOTIN,
PAGE0->mem_boot.spa, PAGE0->mem_boot.dp.layers,
- pdc_result, devaddr, memaddr, size, size);
+ pdc_result, (unsigned long)devaddr, memaddr, size, size);
+ }
if (r == 3) /* EOF */
{
diff --git a/ipl/vsprintf.c b/ipl/vsprintf.c
index 797272f..4a7a060 100644
--- a/ipl/vsprintf.c
+++ b/ipl/vsprintf.c
@@ -38,11 +38,11 @@ static int skip_atoi(const char **s)
#define do_div(n,base) ({ \
int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
+__res = ((unsigned long long) n) % (unsigned) base; \
+n = ((unsigned long long) n) / (unsigned) base; \
__res; })
-static char * number(char * str, long num, int base, int size, int precision
+static char * number(char * str, unsigned long long num, int base, int size, int precision
,int type)
{
char c,sign,tmp[66];
@@ -115,7 +115,7 @@ int sprintf(char * buf, const char *fmt, ...);
int vsprintf(char *buf, const char *fmt, va_list args)
{
int len;
- unsigned long num;
+ unsigned long long num;
int i, base;
char * str;
const char *s;
@@ -183,7 +183,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
/* default base */
base = 10;
-
+again:
switch (*fmt) {
case 'c':
if (!(flags & LEFT))
@@ -246,6 +246,11 @@ int vsprintf(char *buf, const char *fmt, va_list args)
base = 16;
break;
+ case 'l':
+ qualifier = 'L';
+ fmt++;
+ goto again;
+
case 'd':
case 'i':
flags |= SIGN;
@@ -260,7 +265,9 @@ int vsprintf(char *buf, const char *fmt, va_list args)
--fmt;
continue;
}
- if (qualifier == 'l')
+ if (qualifier == 'L')
+ num = va_arg(args, unsigned long long);
+ else if (qualifier == 'l')
num = va_arg(args, unsigned long);
else if (qualifier == 'h') {
num = (unsigned short) va_arg(args, int);
diff --git a/lib/common.h b/lib/common.h
index cec873c..d755a0a 100644
--- a/lib/common.h
+++ b/lib/common.h
@@ -143,7 +143,9 @@ struct diskpartition
#define MAXPARTS 16
-int seekread(int fd, char *buf, unsigned nbytes, unsigned devaddr);
+extern int disk_2gb_limit;
+
+int seekread(int fd, char *buf, unsigned nbytes, __u64 devaddr);
#define STRUCTWRITE(f, data, where) seekwrite((f), (char *)&data, sizeof data, (where))
#define STRUCTREAD(f, data, where) seekread((f), (char *)&data, sizeof data, (where))
#define GZIP_STRUCTREAD(loadable, f, data, where) \
@@ -155,7 +157,6 @@ int seekread(int fd, char *buf, unsigned nbytes, unsigned devaddr);
/* diskpart.c */
extern int is_extended(int id);
extern int load_partitions(int bootdev, struct diskpartition *mptab, int maxparts);
-extern void print_ptab(struct diskpartition *mptab, int maxparts);
extern void print_ptab_pretty(struct diskpartition *mptab, int maxparts);
#endif /* __ASSEMBLY__ */
diff --git a/lib/diskpart.c b/lib/diskpart.c
index dd3982c..5fae1b9 100644
--- a/lib/diskpart.c
+++ b/lib/diskpart.c
@@ -52,37 +52,31 @@ load_partitions(int bootdev, struct diskpartition *mptab, int maxparts)
offset = mptab[ex].start;
while (extnum < maxparts)
{
- /* we're currently using 32-bit file seeks which is ok since
- * the IPL is also limited to 2G right now. On disks > 4GB
- * this next read may fail. Handle that gracefully.
- * Yes, we know newer IODC can read/write > 2GB but
- * it would confuse too many people if the docs attempted
- * to explain for no tangible benefit. And moving boot disks
- * between systems will always work (assuming a useable
- * kernel is present).
- */
- if (offset >= (2 * (GB / 512))) { /* weird () to quiet compiler */
- printf("Skipping extended partition %d - beyond reach of IPL\n\r",
+ if (disk_2gb_limit && offset >= (2 * (GB / 512))) { /* weird () to quiet compiler */
+ printf("NOTE: Extended partition %d might be beyond reach of IPL\r\n",
extnum + 1);
- break;
}
- if (seekread(bootdev, (char *)&fb, sizeof fb, 512 * offset) == -1) {
+
+ fb.dosmagic[0] = 0; // wipe dosmagic flag just to be on the safe side
+ if (seekread(bootdev, (char *)&fb, sizeof fb, 512ULL * offset) == -1) {
printf("seekread(bootdev,..., 512 * 0x%x) failed!\n\r", offset);
break;
}
if (fb.dosmagic[0] != 0x55 || fb.dosmagic[1] != 0xaa)
{
- printf("Bad DOS magic in extended partition\n\r");
+ // Seems to not be an extended partition, so exit.
break;
}
mptab[extnum].start = __le32_to_cpu(ptab[0].start_sect) + offset;
mptab[extnum].length = __le32_to_cpu(ptab[0].nr_sects);
mptab[extnum].id = ptab[0].sys_ind;
+
+ offset = mptab[extnum].start + __le32_to_cpu(ptab[1].start_sect);
+
extnum++;
if (!is_extended(ptab[1].sys_ind))
break;
- offset = mptab[ex].start + __le32_to_cpu(ptab[1].start_sect);
}
}
@@ -90,20 +84,6 @@ load_partitions(int bootdev, struct diskpartition *mptab, int maxparts)
}
void
-print_ptab(struct diskpartition *mptab, int maxparts)
-{
- int i;
- for (i = 0; i < maxparts; i++)
- {
- if (mptab[i].id != 0)
- printf("/dev/ida%-2d %02x %10u %10u\n\r",
- i + 1, mptab[i].id,
- mptab[i].start,
- mptab[i].length);
- }
-}
-
-void
print_ptab_pretty(struct diskpartition *mptab, int maxparts)
{
int i;
diff --git a/palo/palo.c b/palo/palo.c
index a68cef7..23fbc80 100644
--- a/palo/palo.c
+++ b/palo/palo.c
@@ -38,6 +38,8 @@
static int Install = 0;
int verbose = 0;
+int disk_2gb_limit = 0;
+
/* compute the sum of words in an 4-byte aligned region */
int
checksum(void *p, size_t len)
diff --git a/palo/palo.h b/palo/palo.h
index 38d662b..c6ea3fd 100644
--- a/palo/palo.h
+++ b/palo/palo.h
@@ -11,7 +11,7 @@
extern void error(int number, ...);
/* paloio.c */
-extern int seekwrite(int fd, char *buf, unsigned size, unsigned where);
-extern int seekread(int fd, char *buf, unsigned size, unsigned where);
+extern int seekwrite(int fd, char *buf, unsigned size, __u64 where);
+extern int seekread(int fd, char *buf, unsigned size, __u64 where);
extern int cat(int out, int in);
extern int fsize(int fd);
diff --git a/palo/paloio.c b/palo/paloio.c
index 0e3dba1..a925e17 100644
--- a/palo/paloio.c
+++ b/palo/paloio.c
@@ -14,19 +14,14 @@
#include "palo.h"
int
-seekwrite(int fd, char *buf, unsigned size, unsigned where)
+seekwrite(int fd, char *buf, unsigned size, __u64 where)
{
char check[1024];
int n = size < sizeof check ? size : sizeof check;
int r = 0;
off_t off;
- if (0) printf("seekwrite(%d, %p, %u, %u)\n", fd, buf, size, where);
-
- if (where & 0x80000000)
- {
- r = -1;
- }
+ if (1) printf("seekwrite(%d, %p, %u, %llu)\n", fd, buf, size, where);
fsync(fd);
if (r != -1 && lseek(fd, where, SEEK_SET) != where)
@@ -79,16 +74,11 @@ seekwrite(int fd, char *buf, unsigned size, unsigned where)
}
int
-seekread(int fd, char *buf, unsigned size, unsigned where)
+seekread(int fd, char *buf, unsigned size, __u64 where)
{
off_t off;
int r = 0;
- if (0) printf("seekread(%d, %p, %x, %d)\n", fd, buf, size, where);
-
- if (where & 0x80000000)
- {
- r = -1;
- }
+ if (1) printf("seekread(%d, %p, %x, %lld)\n", fd, buf, size, where);
if (r != -1 && lseek(fd, where, SEEK_SET) != where)
{