diff options
author | Helge Deller <deller@gmx.de> | 2022-08-04 16:11:27 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2022-08-04 16:35:04 +0200 |
commit | c6d95074c7f6f1c873f515b700060408d7a6761f (patch) | |
tree | 5cbb4d5caf318377b84fa6da69e726fccf051184 | |
parent | 3859f95ffe7aa4bbc824de54cd871046115f358e (diff) | |
download | palo-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.h | 14 | ||||
-rw-r--r-- | ipl/byteio.c | 31 | ||||
-rw-r--r-- | ipl/ext2.c | 25 | ||||
-rw-r--r-- | ipl/fileio.c | 4 | ||||
-rw-r--r-- | ipl/ipl.c | 10 | ||||
-rw-r--r-- | ipl/lib.c | 4 | ||||
-rw-r--r-- | ipl/offset.c | 14 | ||||
-rw-r--r-- | ipl/pdc_bootio.c | 33 | ||||
-rw-r--r-- | ipl/pdc_misc.c | 54 | ||||
-rw-r--r-- | ipl/vsprintf.c | 19 | ||||
-rw-r--r-- | lib/common.h | 5 | ||||
-rw-r--r-- | lib/diskpart.c | 38 | ||||
-rw-r--r-- | palo/palo.c | 2 | ||||
-rw-r--r-- | palo/palo.h | 4 | ||||
-rw-r--r-- | palo/paloio.c | 18 |
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)) @@ -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); @@ -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", @@ -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) { |