From 26fef18cb877b94853231b225c284e230b4a67f8 Mon Sep 17 00:00:00 2001 From: gord Date: Wed, 19 Apr 2000 20:34:28 +0000 Subject: [PATCH] Added Jochen's sector alignment checking patch. --- ChangeLog | 12 +++++++++ stage2/builtins.c | 64 +++++++++++++++++++++++++++++++++++++---------- stage2/common.c | 1 + stage2/disk_io.c | 31 +++++++++++++++-------- stage2/shared.h | 5 ++-- 5 files changed, 87 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0837ab28..0fa6e9fc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2000-02-29 Jochen Hoenicke + + * stage2/common.c (err_list): Added message for ERR_UNALIGNED. + * stage2/shared.h [!STAGE1_5] (disk_read_hook,disk_read_func): New + parameters offset and length. + (ERR_UNALIGNED): New error code. + * stage2/disk_io.c (rawread) [!STAGE1_5]: Call disk_read_func with + offset and length. + * stage2/builtin.c (disk_read_print_func): Print offset and length. + (blocklist_func): Print detailed byte ranges for partial sectors. + (install_func): Detect partial sectors and print error message. + 2000-04-18 Pavel Roskin * util/grub-install.in: Don't use `!' in `test' for more diff --git a/stage2/builtins.c b/stage2/builtins.c index 64dc482ca..2400e6b11 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -77,9 +77,9 @@ init_config (void) /* Print which sector is read when loading a file. */ static void -disk_read_print_func (int sector) +disk_read_print_func (int sector, int offset, int length) { - grub_printf ("[%d]", sector); + grub_printf ("[%d,%d,%d]", sector, offset, length); } @@ -91,30 +91,50 @@ blocklist_func (char *arg, int flags) int start_sector; int num_sectors = 0; int num_entries = 0; + int last_length = 0; /* Collect contiguous blocks into one entry as many as possible, and print the blocklist notation on the screen. */ - static void disk_read_blocklist_func (int sector) + static void disk_read_blocklist_func (int sector, int offset, int length) { - if (debug) - grub_printf ("[%d]", sector); - if (num_sectors > 0) { - if (start_sector + num_sectors == sector) - num_sectors++; + if (start_sector + num_sectors == sector + && offset == 0 && last_length == SECTOR_SIZE) + { + num_sectors++; + last_length = length; + return; + } else { - grub_printf ("%s%d+%d", num_entries ? "," : "", - start_sector - part_start, num_sectors); + if (last_length == SECTOR_SIZE) + grub_printf ("%s%d+%d", num_entries ? "," : "", + start_sector - part_start, num_sectors); + else if (num_sectors > 1) + grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "", + start_sector - part_start, num_sectors-1, + start_sector + num_sectors-1 - part_start, + last_length); + else + grub_printf ("%s%d[0-%d]", num_entries ? "," : "", + start_sector - part_start, last_length); num_entries++; num_sectors = 0; } } + + if (offset > 0) + { + grub_printf("%s%d[%d-%d]", num_entries ? "," : "", + sector-part_start, offset, offset+length); + num_entries++; + } else { start_sector = sector; num_sectors = 1; + last_length = length; } } @@ -140,7 +160,8 @@ blocklist_func (char *arg, int flags) if (! grub_read (dummy, -1)) goto fail; - /* The last entry may not be printed yet. */ + /* The last entry may not be printed yet. Don't check if it is a + * full sector, since it doesn't matter if we read too much. */ if (num_sectors > 0) grub_printf ("%s%d+%d", num_entries ? "," : "", start_sector - part_start, num_sectors); @@ -1389,23 +1410,40 @@ install_func (char *arg, int flags) int is_open = 0; /* If LBA is forced? */ int is_force_lba = 0; + /* Was the last sector full? */ + int last_length = SECTOR_SIZE; /* Save the first sector of Stage2 in STAGE2_SECT. */ - static void disk_read_savesect_func (int sector) + static void disk_read_savesect_func (int sector, int offset, int length) { if (debug) printf ("[%d]", sector); + /* ReiserFS has files which sometimes contain data not aligned + on sector boundaries. Returning an error is better than + silently failing. */ + if (offset != 0 || length != SECTOR_SIZE) + errnum = ERR_UNALIGNED; + saved_sector = sector; } /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and INSTALLSECT. */ - static void disk_read_blocklist_func (int sector) + static void disk_read_blocklist_func (int sector, int offset, int length) { if (debug) printf("[%d]", sector); + if (offset != 0 || last_length != SECTOR_SIZE) + { + /* We found a non-sector-aligned data block. */ + errnum = ERR_UNALIGNED; + return; + } + + last_length = length; + if (*((unsigned long *) (installlist - 4)) + *((unsigned short *) installlist) != sector || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4) diff --git a/stage2/common.c b/stage2/common.c index 5bb39f59e..081c32fcc 100644 --- a/stage2/common.c +++ b/stage2/common.c @@ -75,6 +75,7 @@ char *err_list[] = [ERR_WONT_FIT] = "Selected item cannot fit into memory", [ERR_WRITE] = "Disk write error", [ERR_BAD_ARGUMENT] = "Invaild argument specified", + [ERR_UNALIGNED] = "File is not sector aligned", }; diff --git a/stage2/disk_io.c b/stage2/disk_io.c index ae543e0c1..edc33c993 100644 --- a/stage2/disk_io.c +++ b/stage2/disk_io.c @@ -26,8 +26,8 @@ #ifndef STAGE1_5 /* instrumentation variables */ -void (*disk_read_hook) (int) = NULL; -void (*disk_read_func) (int) = NULL; +void (*disk_read_hook) (int, int, int) = NULL; +void (*disk_read_func) (int, int, int) = NULL; int print_possibilities; @@ -182,23 +182,32 @@ rawread (int drive, int sector, int byte_offset, int byte_len, char *buf) buf_track = track; } + if (size > ((num_sect * SECTOR_SIZE) - byte_offset)) + size = (num_sect * SECTOR_SIZE) - byte_offset; + #ifndef STAGE1_5 /* * Instrumentation to tell which sectors were read and used. */ - if (disk_read_hook && disk_read_func) + if (disk_read_func) { - int sector_end = sector + ((num_sect < slen) ? num_sect : slen); int sector_num = sector; - - while (sector_num < sector_end) - (*disk_read_func) (sector_num++); + int length = SECTOR_SIZE - byte_offset; + if (length > size) + length = size; + (*disk_read_func) (sector_num++, byte_offset, length); + length = size - length; + if (length > 0) + { + while (length > SECTOR_SIZE) + { + (*disk_read_func) (sector_num++, 0, SECTOR_SIZE); + length -= SECTOR_SIZE; + } + (*disk_read_func) (sector_num, 0, length); + } } #endif /* STAGE1_5 */ - - if (size > ((num_sect * SECTOR_SIZE) - byte_offset)) - size = (num_sect * SECTOR_SIZE) - byte_offset; - memmove (buf, (char *) bufaddr, size); buf += size; diff --git a/stage2/shared.h b/stage2/shared.h index c07c7f3b3..9efa324c5 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -416,6 +416,7 @@ typedef enum ERR_WONT_FIT, ERR_WRITE, ERR_BAD_ARGUMENT, + ERR_UNALIGNED, MAX_ERR_NUM } grub_error_t; @@ -470,8 +471,8 @@ extern int compressed_file; #ifndef STAGE1_5 /* instrumentation variables */ -extern void (*disk_read_hook) (int); -extern void (*disk_read_func) (int); +extern void (*disk_read_hook) (int, int, int); +extern void (*disk_read_func) (int, int, int); /* The flag for debug mode. */ extern int debug; /* Color settings */