diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 933aefe77..86ec85bfc 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -67,7 +67,7 @@ datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) # For relocator.mod. pkglib_MODULES += relocator.mod -relocator_mod_SOURCES = lib/$(target_cpu)/relocator.c lib/relocator.c lib/$(target_cpu)/relocator_asm.S +relocator_mod_SOURCES = lib/$(target_cpu)/relocator.c lib/relocator.c lib/$(target_cpu)/relocator_asm.S lib/ieee1275/relocator.c relocator_mod_CFLAGS = $(COMMON_CFLAGS) relocator_mod_ASFLAGS = $(COMMON_ASFLAGS) relocator_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/tests.rmk b/conf/tests.rmk index d48bc3dd9..e86c315d3 100644 --- a/conf/tests.rmk +++ b/conf/tests.rmk @@ -2,7 +2,7 @@ # For grub-shell grub-shell: tests/util/grub-shell.in config.status - ./config.status --file=$@:$< + ./config.status --file=-:$< | sed -e 's,@pkglib_DATA@,$(pkglib_DATA),g' > $@ chmod +x $@ check_SCRIPTS += grub-shell CLEANFILES += grub-shell diff --git a/include/grub/powerpc/memory.h b/include/grub/powerpc/memory.h new file mode 100644 index 000000000..b748f33c5 --- /dev/null +++ b/include/grub/powerpc/memory.h @@ -0,0 +1,47 @@ +/* memory.h - describe the memory map */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_MEMORY_CPU_HEADER +#define GRUB_MEMORY_CPU_HEADER 1 + +#ifndef ASM_FILE + +typedef grub_addr_t grub_phys_addr_t; + +static inline grub_phys_addr_t +grub_vtop (void *a) +{ + return (grub_phys_addr_t) a; +} + +static inline void * +grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused))) +{ + return (void *) a; +} + +static inline void +grub_unmap_memory (void *a __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused))) +{ +} + +#endif + +#endif /* ! GRUB_MEMORY_CPU_HEADER */ diff --git a/include/grub/relocator_private.h b/include/grub/relocator_private.h index 10e445bfe..1c563cb64 100644 --- a/include/grub/relocator_private.h +++ b/include/grub/relocator_private.h @@ -40,6 +40,8 @@ void grub_cpu_relocator_backward (void *rels, void *src, void *tgt, grub_size_t size); void grub_cpu_relocator_jumper (void *rels, grub_addr_t addr); +/* Remark: GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG = 1 or 2 + aren't supported. */ #ifdef GRUB_MACHINE_IEEE1275 #define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 1 #define GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG 0 @@ -50,6 +52,12 @@ void grub_cpu_relocator_jumper (void *rels, grub_addr_t addr); #define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 0 #endif +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS && GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG != 0 +#define GRUB_RELOCATOR_HAVE_LEFTOVERS 1 +#else +#define GRUB_RELOCATOR_HAVE_LEFTOVERS 0 +#endif + #if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS #define GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT (1 << GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG) #endif @@ -67,6 +75,8 @@ struct grub_relocator_mmap_event /* To track the regions already in heap. */ FIRMWARE_BLOCK_START = 6, FIRMWARE_BLOCK_END = FIRMWARE_BLOCK_START | 1, +#endif +#if GRUB_RELOCATOR_HAVE_LEFTOVERS REG_LEFTOVER_START = 8, REG_LEFTOVER_END = REG_LEFTOVER_START | 1, #endif diff --git a/lib/powerpc/relocator.c b/lib/powerpc/relocator.c index 9f5fc1c7f..85dfbeaf3 100644 --- a/lib/powerpc/relocator.c +++ b/lib/powerpc/relocator.c @@ -107,15 +107,15 @@ grub_err_t grub_relocator32_boot (struct grub_relocator *rel, struct grub_relocator32_state state) { - grub_addr_t target; - void *src, *ptr; + void *ptr; grub_err_t err; - grub_addr_t relst; + void *relst; grub_size_t relsize; grub_size_t stateset_size = 32 * REGW_SIZEOF + JUMP_SIZEOF; unsigned i; + grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_align (rel, &src, &target, 0, + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, (0xffffffff - stateset_size) + 1, stateset_size, sizeof (grub_uint32_t), @@ -123,12 +123,13 @@ grub_relocator32_boot (struct grub_relocator *rel, if (err) return err; - ptr = src; + ptr = get_virtual_current_address (ch); for (i = 0; i < 32; i++) write_reg (i, state.gpr[i], &ptr); write_jump (&ptr); - err = grub_relocator_prepare_relocs (rel, target, &relst, &relsize); + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, &relsize); if (err) return err; diff --git a/lib/relocator.c b/lib/relocator.c index 4c180e72a..6fbdb71d7 100644 --- a/lib/relocator.c +++ b/lib/relocator.c @@ -45,7 +45,9 @@ struct grub_relocator_subchunk grub_size_t size; grub_size_t pre_size; struct grub_relocator_extra_block *extra; +#if GRUB_RELOCATOR_HAVE_LEFTOVERS struct grub_relocator_fw_leftover *pre, *post; +#endif }; struct grub_relocator_chunk @@ -67,7 +69,7 @@ struct grub_relocator_extra_block grub_phys_addr_t end; }; -#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS +#if GRUB_RELOCATOR_HAVE_LEFTOVERS struct grub_relocator_fw_leftover { struct grub_relocator_fw_leftover *next; @@ -241,7 +243,7 @@ allocate_inreg (grub_phys_addr_t paddr, grub_size_t size, } } -#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS +#if GRUB_RELOCATOR_HAVE_LEFTOVERS static void check_leftover (struct grub_relocator_fw_leftover *lo) { @@ -367,6 +369,7 @@ free_subchunk (const struct grub_relocator_subchunk *subchu) GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); if (fstart < fend) grub_relocator_firmware_free_region (fstart, fend - fstart); +#if GRUB_RELOCATOR_HAVE_LEFTOVERS if (subchu->pre) { int off = subchu->start - fstart @@ -384,6 +387,7 @@ free_subchunk (const struct grub_relocator_subchunk *subchu) subchu->pre->freebytes[off / 8] |= ((1 << (8 - (off % 8))) - 1); check_leftover (subchu->post); } +#endif *subchu->extra->prev = subchu->extra->next; grub_free (subchu->extra); } @@ -450,7 +454,9 @@ malloc_in_range (struct grub_relocator *rel, maxevents += 2; maxevents += grub_relocator_firmware_get_max_events (); +#endif +#if GRUB_RELOCATOR_HAVE_LEFTOVERS { struct grub_relocator_fw_leftover *cur; for (cur = leftovers; cur; cur = cur->next) @@ -500,8 +506,8 @@ malloc_in_range (struct grub_relocator *rel, for (r = grub_mm_base; r; r = r->next) { grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n", - (grub_addr_t) r - r->pre_size, - (grub_addr_t) (r + 1) + r->size); + (unsigned long) r - r->pre_size, + (unsigned long) (r + 1) + r->size); events[N].type = FIRMWARE_BLOCK_START; events[N].pos = (grub_addr_t) r - r->pre_size; N++; @@ -514,7 +520,7 @@ malloc_in_range (struct grub_relocator *rel, for (cur = extra_blocks; cur; cur = cur->next) { grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n", - cur->start, cur->end); + (unsigned long) cur->start, (unsigned long) cur->end); events[N].type = FIRMWARE_BLOCK_START; events[N].pos = cur->start; N++; @@ -526,6 +532,7 @@ malloc_in_range (struct grub_relocator *rel, N += grub_relocator_firmware_fill_events (events + N); +#if GRUB_RELOCATOR_HAVE_LEFTOVERS { struct grub_relocator_fw_leftover *cur; for (cur = leftovers; cur; cur = cur->next) @@ -552,6 +559,7 @@ malloc_in_range (struct grub_relocator *rel, } } } +#endif #endif /* No malloc from this point. */ @@ -636,7 +644,11 @@ malloc_in_range (struct grub_relocator *rel, /* Now events are nicely sorted. */ { int nstarted = 0, ncollisions = 0, nstartedfw = 0, nblockfw = 0; +#if GRUB_RELOCATOR_HAVE_LEFTOVERS int nlefto = 0; +#else + const int nlefto = 0; +#endif grub_addr_t starta = 0; int numstarted; for (j = from_low_priv ? 0 : N - 1; from_low_priv ? j < N : (j + 1); @@ -663,6 +675,9 @@ malloc_in_range (struct grub_relocator *rel, case FIRMWARE_BLOCK_END: nblockfw--; break; +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS case REG_LEFTOVER_START: nlefto++; break; @@ -794,7 +809,8 @@ malloc_in_range (struct grub_relocator *rel, = ALIGN_UP (alloc_end, GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); grub_dprintf ("relocator", "requesting %lx-%lx\n", - fstart, fend); + (unsigned long) fstart, + (unsigned long) fend); /* The failure here can be very expensive. */ if (!grub_relocator_firmware_alloc_region (fstart, fend - fstart)) @@ -807,6 +823,9 @@ malloc_in_range (struct grub_relocator *rel, } break; } +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS case CHUNK_TYPE_LEFTOVER: { unsigned offstart = alloc_start @@ -857,14 +876,6 @@ malloc_in_range (struct grub_relocator *rel, fwin--; break; - case REG_LEFTOVER_START: - fwlefto++; - break; - - case REG_LEFTOVER_END: - fwlefto--; - break; - case FIRMWARE_BLOCK_START: fwb++; break; @@ -873,6 +884,16 @@ malloc_in_range (struct grub_relocator *rel, fwb--; break; #endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case REG_LEFTOVER_START: + fwlefto++; + break; + + case REG_LEFTOVER_END: + fwlefto--; + break; +#endif case COLLISION_START: ncol++; break; @@ -971,8 +992,6 @@ malloc_in_range (struct grub_relocator *rel, if (!oom && typepre == CHUNK_TYPE_FIRMWARE) { grub_addr_t fstart, fend; - struct grub_relocator_fw_leftover *lo1 = NULL; - struct grub_relocator_fw_leftover *lo2 = NULL; fstart = ALIGN_DOWN (alloc_start, @@ -981,68 +1000,77 @@ malloc_in_range (struct grub_relocator *rel, = ALIGN_UP (alloc_end, GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); - if (fstart != alloc_start) - lo1 = grub_malloc (sizeof (*lo1)); - if (fend != alloc_end) - lo2 = grub_malloc (sizeof (*lo2)); - if ((!lo1 && fstart != alloc_start) - || (!lo2 && fend != alloc_end)) - { - struct grub_relocator_extra_block *ne; - grub_free (lo1); - grub_free (lo2); - lo1 = NULL; - lo2 = NULL; - oom = 1; - grub_memcpy (&tofree, curschu, sizeof (tofree)); - ne = extra_blocks; - extra_blocks = extra_blocks->next; - grub_free (ne); - } - if (lo1) - { - lo1->quantstart = fstart; - grub_memset (lo1->freebytes, 0xff, - (alloc_start - fstart) / 8); - lo1->freebytes[(alloc_start - fstart) / 8] - = (1 << ((alloc_start - fstart) % 8)) - 1; - grub_memset (lo1->freebytes - + ((alloc_start - fstart) / 8) + 1, 0, - sizeof (lo1->freebytes) - - (alloc_start - fstart) / 8 - 1); - lo1->next = leftovers; - lo1->prev = &leftovers; - if (leftovers) - leftovers->prev = &lo1->next; - leftovers = lo1; - } - if (lo2) - { - lo2->quantstart - = fend - GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; - grub_memset (lo2->freebytes, 0, - (alloc_end - lo2->quantstart) / 8); - lo2->freebytes[(alloc_end - lo2->quantstart) / 8] - = ~((1 << ((alloc_end - lo2->quantstart) % 8)) - 1); - grub_memset (lo2->freebytes - + ((alloc_end - lo2->quantstart) / 8) - + 1, 0, sizeof (lo2->freebytes) - - (alloc_end - lo2->quantstart) / 8 - 1); - lo2->prev = &leftovers; - if (leftovers) - leftovers->prev = &lo2->next; - lo2->next = leftovers; - leftovers = lo2; - } - curschu->pre = lo1; - curschu->post = lo2; +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + { + struct grub_relocator_fw_leftover *lo1 = NULL; + struct grub_relocator_fw_leftover *lo2 = NULL; + if (fstart != alloc_start) + lo1 = grub_malloc (sizeof (*lo1)); + if (fend != alloc_end) + lo2 = grub_malloc (sizeof (*lo2)); + if ((!lo1 && fstart != alloc_start) + || (!lo2 && fend != alloc_end)) + { + struct grub_relocator_extra_block *ne; + grub_free (lo1); + grub_free (lo2); + lo1 = NULL; + lo2 = NULL; + oom = 1; + grub_memcpy (&tofree, curschu, sizeof (tofree)); + ne = extra_blocks; + extra_blocks = extra_blocks->next; + grub_free (ne); + } + if (lo1) + { + lo1->quantstart = fstart; + grub_memset (lo1->freebytes, 0xff, + (alloc_start - fstart) / 8); + lo1->freebytes[(alloc_start - fstart) / 8] + = (1 << ((alloc_start - fstart) % 8)) - 1; + grub_memset (lo1->freebytes + + ((alloc_start - fstart) / 8) + 1, 0, + sizeof (lo1->freebytes) + - (alloc_start - fstart) / 8 - 1); + lo1->next = leftovers; + lo1->prev = &leftovers; + if (leftovers) + leftovers->prev = &lo1->next; + leftovers = lo1; + } + if (lo2) + { + lo2->quantstart + = fend - GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + grub_memset (lo2->freebytes, 0, + (alloc_end - lo2->quantstart) / 8); + lo2->freebytes[(alloc_end - lo2->quantstart) / 8] + = ~((1 << ((alloc_end - lo2->quantstart) % 8)) - 1); + grub_memset (lo2->freebytes + + ((alloc_end - lo2->quantstart) / 8) + + 1, 0, sizeof (lo2->freebytes) + - (alloc_end - lo2->quantstart) / 8 - 1); + lo2->prev = &leftovers; + if (leftovers) + leftovers->prev = &lo2->next; + lo2->next = leftovers; + leftovers = lo2; + } + curschu->pre = lo1; + curschu->post = lo2; + } +#endif } +#if GRUB_RELOCATOR_HAVE_LEFTOVERS if (typepre == CHUNK_TYPE_LEFTOVER) { curschu->pre = events[last_start].leftover; curschu->post = events[last_start].leftover; } +#endif + #endif if (!oom) cural++; @@ -1077,14 +1105,6 @@ malloc_in_range (struct grub_relocator *rel, fwin--; break; - case REG_LEFTOVER_START: - fwlefto++; - break; - - case REG_LEFTOVER_END: - fwlefto--; - break; - case FIRMWARE_BLOCK_START: fwb++; break; @@ -1093,6 +1113,16 @@ malloc_in_range (struct grub_relocator *rel, fwb--; break; #endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case REG_LEFTOVER_START: + fwlefto++; + break; + + case REG_LEFTOVER_END: + fwlefto--; + break; +#endif case COLLISION_START: ncol++; break; diff --git a/loader/powerpc/ieee1275/linux.c b/loader/powerpc/ieee1275/linux.c index 930c0cb41..c9feec975 100644 --- a/loader/powerpc/ieee1275/linux.c +++ b/loader/powerpc/ieee1275/linux.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include