Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 58421 Details for
Bug 91959
grub-0.97 released
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
grub-0.97-nxstack.patch
grub-0.97-nxstack.patch (text/plain), 18.68 KB, created by
Ryan Hill (RETIRED)
on 2005-05-08 20:30:47 UTC
(
hide
)
Description:
grub-0.97-nxstack.patch
Filename:
MIME Type:
Creator:
Ryan Hill (RETIRED)
Created:
2005-05-08 20:30:47 UTC
Size:
18.68 KB
patch
obsolete
>diff -ru grub-0.97-orig/grub/asmstub.c grub-0.97/grub/asmstub.c >--- grub-0.97-orig/grub/asmstub.c 2005-05-08 20:29:59.000000000 -0600 >+++ grub-0.97/grub/asmstub.c 2005-05-08 21:00:52.000000000 -0600 >@@ -42,6 +42,7 @@ > #include <sys/time.h> > #include <termios.h> > #include <signal.h> >+#include <sys/mman.h> > > #ifdef __linux__ > # include <sys/ioctl.h> /* ioctl */ >@@ -79,7 +80,7 @@ > struct apm_info apm_bios_info; > > /* Emulation requirements. */ >-char *grub_scratch_mem = 0; >+void *grub_scratch_mem = 0; > > struct geometry *disks = 0; > >@@ -103,14 +104,62 @@ > static unsigned int serial_speed; > #endif /* SIMULATE_SLOWNESS_OF_SERIAL */ > >+/* This allocates page-aligned storage of the specified size, which must be >+ * a multiple of the page size as determined by calling sysconf(_SC_PAGESIZE) >+ */ >+#ifdef __linux__ >+static void * >+grub_mmap_alloc(size_t len) >+{ >+ int mmap_flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_EXECUTABLE; >+ >+#ifdef MAP_32BIT >+ mmap_flags |= MAP_32BIT; >+#endif >+ /* Mark the simulated stack executable, as GCC uses stack trampolines >+ * to implement nested functions. */ >+ return mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, mmap_flags, -1, 0); >+} >+#else /* !defined(__linux__) */ >+static void * >+grub_mmap_alloc(size_t len) >+{ >+ int fd = 0, offset = 0, ret = 0; >+ void *pa = MAP_FAILED; >+ char template[] = "/tmp/grub_mmap_alloc_XXXXXX"; >+ errno_t e; >+ >+ fd = mkstemp(template); >+ if (fd < 0) >+ return pa; >+ >+ unlink(template); >+ >+ ret = ftruncate(fd, len); >+ if (ret < 0) >+ return pa; >+ >+ /* Mark the simulated stack executable, as GCC uses stack trampolines >+ * to implement nested functions. */ >+ pa = mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, >+ MAP_PRIVATE|MAP_EXECUTABLE, fd, offset); >+ >+ e = errno; >+ close(fd); >+ errno = e; >+ return pa; >+} >+#endif /* defined(__linux__) */ >+ > /* The main entry point into this mess. */ > int > grub_stage2 (void) > { > /* These need to be static, because they survive our stack transitions. */ > static int status = 0; >- static char *realstack; >- char *scratch, *simstack; >+ static void *realstack; >+ void *simstack_alloc_base, *simstack; >+ size_t simstack_size, page_size; > int i; > > auto void doit (void); >@@ -142,10 +191,35 @@ > } > > assert (grub_scratch_mem == 0); >- scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15); >- assert (scratch); >- grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4); >+ /* Allocate enough pages for 0x100000 + EXTENDED_SIZE + 15, and >+ * make sure the memory is aligned to a multiple of the system's >+ * page size */ >+ page_size = sysconf (_SC_PAGESIZE); >+ simstack_size = ( 0x100000 + EXTENDED_MEMSIZE + 15); >+ if (simstack_size % page_size) >+ { >+ /* If we're not on a page_size boundary, round up to the next one */ >+ simstack_size &= ~(page_size-1); >+ simstack_size += page_size; >+ } >+ >+ /* Add one for a PROT_NONE boundary page at each end. */ >+ simstack_size += 2 * page_size; >+ >+ simstack_alloc_base = grub_mmap_alloc(simstack_size); >+ assert (simstack_alloc_base != MAP_FAILED); >+ >+ /* mark pages above and below our simstack area as innaccessable. >+ * If the implementation we're using doesn't support that, then the >+ * new protection modes are undefined. It's safe to just ignore >+ * them, though. It'd be nice if we knew that we'd get a SEGV for >+ * touching the area, but that's all. it'd be nice to have. */ >+ mprotect (simstack_alloc_base, page_size, PROT_NONE); >+ mprotect ((void *)((unsigned long)simstack_alloc_base + >+ simstack_size - page_size), page_size, PROT_NONE); > >+ grub_scratch_mem = (void *)((unsigned long)simstack_alloc_base + page_size); >+ > /* FIXME: simulate the memory holes using mprot, if available. */ > > assert (disks == 0); >@@ -217,7 +291,7 @@ > device_map = 0; > free (disks); > disks = 0; >- free (scratch); >+ munmap(simstack_alloc_base, simstack_size); > grub_scratch_mem = 0; > > if (serial_device) >diff -ru grub-0.97-orig/stage2/builtins.c grub-0.97/stage2/builtins.c >--- grub-0.97-orig/stage2/builtins.c 2005-05-08 20:29:59.000000000 -0600 >+++ grub-0.97/stage2/builtins.c 2005-05-08 21:22:26.000000000 -0600 >@@ -131,62 +131,96 @@ > } > > >-/* blocklist */ >-static int >-blocklist_func (char *arg, int flags) >+/* blocklist_read_helper nee disk_read_blocklist_func was a nested >+ * function, to which pointers were taken and exposed globally. Even >+ * in the GNU-C nested functions extension, they have local linkage, >+ * and aren't guaranteed to be accessable *at all* outside of their >+ * containing scope. >+ * >+ * Above and beyond all of that, the variables within blocklist_func_context >+ * are originally local variables, with local (not even static) linkage, >+ * from within blocklist_func. These were each referenced by >+ * disk_read_blocklist_func, which is only called from other functions >+ * through a globally scoped pointer. >+ * >+ * The documentation in GCC actually uses the words "all hell will break >+ * loose" to describe this scenario. >+ * >+ * Also, "start_sector" was also used uninitialized, but gcc doesn't warn >+ * about it (possibly because of the scoping madness?) >+ */ >+ >+static struct { >+ int start_sector; >+ int num_sectors; >+ int num_entries; >+ int last_length; >+} blocklist_func_context = { >+ .start_sector = 0, >+ .num_sectors = 0, >+ .num_entries = 0, >+ .last_length = 0 >+}; >+ >+/* Collect contiguous blocks into one entry as many as possible, >+ and print the blocklist notation on the screen. */ >+static void >+blocklist_read_helper (int sector, int offset, int length) > { >- char *dummy = (char *) RAW_ADDR (0x100000); >- int start_sector; >- int num_sectors = 0; >- int num_entries = 0; >- int last_length = 0; >+ int *start_sector = &blocklist_func_context.start_sector; >+ int *num_sectors = &blocklist_func_context.num_sectors; >+ int *num_entries = &blocklist_func_context.num_entries; >+ int *last_length = &blocklist_func_context.last_length; > >- auto void disk_read_blocklist_func (int sector, int offset, int length); >- >- /* Collect contiguous blocks into one entry as many as possible, >- and print the blocklist notation on the screen. */ >- auto void disk_read_blocklist_func (int sector, int offset, int length) >+ if (*num_sectors > 0) >+ { >+ if (*start_sector + *num_sectors == sector >+ && offset == 0 && *last_length == SECTOR_SIZE) > { >- if (num_sectors > 0) >- { >- if (start_sector + num_sectors == sector >- && offset == 0 && last_length == SECTOR_SIZE) >- { >- num_sectors++; >- last_length = length; >- return; >- } >- else >- { >- 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++; >- } >+ *num_sectors++; >+ *last_length = length; >+ return; >+ } >+ else >+ { >+ 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 >- { >- start_sector = sector; >- num_sectors = 1; >- last_length = length; >- } >+ 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; >+ } >+} >+ >+/* blocklist */ >+static int >+blocklist_func (char *arg, int flags) >+{ >+ char *dummy = (char *) RAW_ADDR (0x100000); >+ int *start_sector = &blocklist_func_context.start_sector; >+ int *num_sectors = &blocklist_func_context.num_sectors; >+ int *num_entries = &blocklist_func_context.num_entries; > > /* Open the file. */ > if (! grub_open (arg)) >@@ -206,15 +240,15 @@ > grub_printf (")"); > > /* Read in the whole file to DUMMY. */ >- disk_read_hook = disk_read_blocklist_func; >+ disk_read_hook = blocklist_read_helper; > if (! grub_read (dummy, -1)) > goto fail; > > /* 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); >+ if (*num_sectors > 0) >+ grub_printf ("%s%d+%d", *num_entries ? "," : "", >+ *start_sector - part_start, *num_sectors); > > grub_printf ("\n"); > >@@ -1740,6 +1774,77 @@ > > > /* install */ >+static struct { >+ int saved_sector; >+ int installaddr; >+ int installlist; >+ char *stage2_first_buffer; >+} install_func_context = { >+ .saved_sector = 0, >+ .installaddr = 0, >+ .installlist = 0, >+ .stage2_first_buffer = NULL, >+}; >+ >+/* Save the first sector of Stage2 in STAGE2_SECT. */ >+/* Formerly disk_read_savesect_func with local scope inside install_func */ >+static void >+install_savesect_helper(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; >+ >+ install_func_context.saved_sector = sector; >+} >+ >+/* Write SECTOR to INSTALLLIST, and update INSTALLADDR and INSTALLSECT. */ >+/* Formerly disk_read_blocklist_func with local scope inside install_func */ >+static void >+install_blocklist_helper (int sector, int offset, int length) >+{ >+ int *installaddr = &install_func_context.installaddr; >+ int *installlist = &install_func_context.installlist; >+ char **stage2_first_buffer = &install_func_context.stage2_first_buffer; >+ /* Was the last sector full? */ >+ static int last_length = SECTOR_SIZE; >+ >+ 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) >+ { >+ *installlist -= 8; >+ >+ if (*((unsigned long *) (*installlist - 8))) >+ errnum = ERR_WONT_FIT; >+ else >+ { >+ *((unsigned short *) (*installlist + 2)) = (*installaddr >> 4); >+ *((unsigned long *) (*installlist - 4)) = sector; >+ } >+ } >+ >+ *((unsigned short *) *installlist) += 1; >+ *installaddr += 512; >+} >+ > static int > install_func (char *arg, int flags) > { >@@ -1747,8 +1852,12 @@ > char *stage1_buffer = (char *) RAW_ADDR (0x100000); > char *stage2_buffer = stage1_buffer + SECTOR_SIZE; > char *old_sect = stage2_buffer + SECTOR_SIZE; >- char *stage2_first_buffer = old_sect + SECTOR_SIZE; >- char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; >+ /* stage2_first_buffer used to be defined as: >+ * char *stage2_first_buffer = old_sect + SECTOR_SIZE; */ >+ char **stage2_first_buffer = &install_func_context.stage2_first_buffer; >+ /* and stage2_second_buffer was: >+ * char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; */ >+ char *stage2_second_buffer = old_sect + SECTOR_SIZE + SECTOR_SIZE; > /* XXX: Probably SECTOR_SIZE is reasonable. */ > char *config_filename = stage2_second_buffer + SECTOR_SIZE; > char *dummy = config_filename + SECTOR_SIZE; >@@ -1757,10 +1866,11 @@ > int src_drive, src_partition, src_part_start; > int i; > struct geometry dest_geom, src_geom; >- int saved_sector; >+ int *saved_sector = &install_func_context.saved_sector; > int stage2_first_sector, stage2_second_sector; > char *ptr; >- int installaddr, installlist; >+ int *installaddr = &install_func_context.installaddr; >+ int *installlist = &install_func_context.installlist; > /* Point to the location of the name of a configuration file in Stage 2. */ > char *config_file_location; > /* If FILE is a Stage 1.5? */ >@@ -1769,8 +1879,7 @@ > int is_open = 0; > /* If LBA is forced? */ > int is_force_lba = 0; >- /* Was the last sector full? */ >- int last_length = SECTOR_SIZE; >+ *stage2_first_buffer = old_sect + SECTOR_SIZE; > > #ifdef GRUB_UTIL > /* If the Stage 2 is in a partition mounted by an OS, this will store >@@ -1778,59 +1887,6 @@ > char *stage2_os_file = 0; > #endif /* GRUB_UTIL */ > >- auto void disk_read_savesect_func (int sector, int offset, int length); >- auto void disk_read_blocklist_func (int sector, int offset, int length); >- >- /* Save the first sector of Stage2 in STAGE2_SECT. */ >- auto 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. */ >- auto 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) >- { >- installlist -= 8; >- >- if (*((unsigned long *) (installlist - 8))) >- errnum = ERR_WONT_FIT; >- else >- { >- *((unsigned short *) (installlist + 2)) = (installaddr >> 4); >- *((unsigned long *) (installlist - 4)) = sector; >- } >- } >- >- *((unsigned short *) installlist) += 1; >- installaddr += 512; >- } >- > /* First, check the GNU-style long option. */ > while (1) > { >@@ -1862,10 +1918,10 @@ > addr = skip_to (0, file); > > /* Get the installation address. */ >- if (! safe_parse_maxint (&addr, &installaddr)) >+ if (! safe_parse_maxint (&addr, installaddr)) > { > /* ADDR is not specified. */ >- installaddr = 0; >+ *installaddr = 0; > ptr = addr; > errnum = 0; > } >@@ -1961,17 +2017,17 @@ > = 0x9090; > > /* Read the first sector of Stage 2. */ >- disk_read_hook = disk_read_savesect_func; >- if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE) >+ disk_read_hook = install_savesect_helper; >+ if (grub_read (*stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE) > goto fail; > >- stage2_first_sector = saved_sector; >+ stage2_first_sector = *saved_sector; > > /* Read the second sector of Stage 2. */ > if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE) > goto fail; > >- stage2_second_sector = saved_sector; >+ stage2_second_sector = *saved_sector; > > /* Check for the version of Stage 2. */ > if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS)) >@@ -1987,27 +2043,27 @@ > > /* If INSTALLADDR is not specified explicitly in the command-line, > determine it by the Stage 2 id. */ >- if (! installaddr) >+ if (! *installaddr) > { > if (! is_stage1_5) > /* Stage 2. */ >- installaddr = 0x8000; >+ *installaddr = 0x8000; > else > /* Stage 1.5. */ >- installaddr = 0x2000; >+ *installaddr = 0x2000; > } > > *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR)) > = stage2_first_sector; > *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS)) >- = installaddr; >+ = *installaddr; > *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT)) >- = installaddr >> 4; >+ = *installaddr >> 4; > >- i = (int) stage2_first_buffer + SECTOR_SIZE - 4; >+ i = (int) *stage2_first_buffer + SECTOR_SIZE - 4; > while (*((unsigned long *) i)) > { >- if (i < (int) stage2_first_buffer >+ if (i < (int) *stage2_first_buffer > || (*((int *) (i - 4)) & 0x80000000) > || *((unsigned short *) i) >= 0xA00 > || *((short *) (i + 2)) == 0) >@@ -2021,13 +2077,13 @@ > i -= 8; > } > >- installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4; >- installaddr += SECTOR_SIZE; >+ *installlist = (int) *stage2_first_buffer + SECTOR_SIZE + 4; >+ *installaddr += SECTOR_SIZE; > > /* Read the whole of Stage2 except for the first sector. */ > grub_seek (SECTOR_SIZE); > >- disk_read_hook = disk_read_blocklist_func; >+ disk_read_hook = install_blocklist_helper; > if (! grub_read (dummy, -1)) > goto fail; > >@@ -2110,7 +2166,7 @@ > /* Skip the first sector. */ > grub_seek (SECTOR_SIZE); > >- disk_read_hook = disk_read_savesect_func; >+ disk_read_hook = install_savesect_helper; > if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE) > goto fail; > >@@ -2180,7 +2236,7 @@ > else > #endif /* GRUB_UTIL */ > { >- if (! devwrite (saved_sector - part_start, 1, stage2_buffer)) >+ if (! devwrite (*saved_sector - part_start, 1, stage2_buffer)) > goto fail; > } > } >@@ -2202,7 +2258,7 @@ > goto fail; > } > >- if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) >+ if (fwrite (*stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) > { > fclose (fp); > errnum = ERR_WRITE; >@@ -2229,7 +2285,7 @@ > goto fail; > > if (! devwrite (stage2_first_sector - src_part_start, 1, >- stage2_first_buffer)) >+ *stage2_first_buffer)) > goto fail; > > if (! devwrite (stage2_second_sector - src_part_start, 1, >diff -ru grub-0.97-orig/stage2/shared.h grub-0.97/stage2/shared.h >--- grub-0.97-orig/stage2/shared.h 2005-05-08 20:29:59.000000000 -0600 >+++ grub-0.97/stage2/shared.h 2005-05-08 21:24:10.000000000 -0600 >@@ -36,8 +36,8 @@ > > /* Maybe redirect memory requests through grub_scratch_mem. */ > #ifdef GRUB_UTIL >-extern char *grub_scratch_mem; >-# define RAW_ADDR(x) ((x) + (int) grub_scratch_mem) >+extern void *grub_scratch_mem; >+# define RAW_ADDR(x) ((x) + (unsigned long) grub_scratch_mem) > # define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4) > #else > # define RAW_ADDR(x) (x)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 91959
:
58419
| 58421 |
58422