Some 16bit accesses to "low" mem variables use 16bit relocations instead of the normal 32bit relocations. This causes build problems if the "low" mem sections move more than 64K during relocation.
The final location of the "low" memory can be determined during the build, so link the 16bit code with the final post-reloc location of the "low" mem variables instead. This eliminates the need to do these runtime relocations on the 16bit code.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/biosvar.h | 4 ++-- src/pmm.c | 14 ++++---------- src/post.c | 24 ++++++++++-------------- tools/layoutrom.py | 25 +++++++++++++------------ 4 files changed, 29 insertions(+), 38 deletions(-)
diff --git a/src/biosvar.h b/src/biosvar.h index fd2f1bf..eceee54 100644 --- a/src/biosvar.h +++ b/src/biosvar.h @@ -250,13 +250,13 @@ static inline u16 get_global_seg(void) { * "Low" memory variables ****************************************************************/
-extern u8 _datalow_seg, _datalow_base[]; +extern u8 _datalow_seg, datalow_base[]; #define SEG_LOW ((u32)&_datalow_seg)
#if MODESEGMENT #define GET_LOW(var) GET_FARVAR(SEG_LOW, (var)) #define SET_LOW(var, val) SET_FARVAR(SEG_LOW, (var), (val)) -#define LOWFLAT2LOW(var) ((typeof(var))((void*)(var) - (u32)_datalow_base)) +#define LOWFLAT2LOW(var) ((typeof(var))((void*)(var) - (u32)datalow_base)) #else #define GET_LOW(var) (var) #define SET_LOW(var, val) do { (var) = (val); } while (0) diff --git a/src/pmm.c b/src/pmm.c index 5d43645..1addb41 100644 --- a/src/pmm.c +++ b/src/pmm.c @@ -170,13 +170,6 @@ static struct allocinfo_s *RomBase;
#define OPROM_HEADER_RESERVE 16
-// Return maximum address of read/writable "low mem" space. -static inline u32 lowmemend(void) { - extern u8 code32flat_start[], code32init_end[]; - u32 end = CONFIG_RELOCATE_INIT ? (u32)code32init_end : (u32)code32flat_start; - return end > BUILD_BIOS_ADDR ? BUILD_BIOS_ADDR : end; -} - // Return the memory position up to which roms may be located. u32 rom_get_top(void) @@ -199,8 +192,8 @@ rom_reserve(u32 size) u32 newend = ALIGN(RomEnd + size, OPTION_ROM_ALIGN) + OPROM_HEADER_RESERVE; if (newend > (u32)RomBase->allocend) return NULL; - if (newend < (u32)_datalow_base + OPROM_HEADER_RESERVE) - newend = (u32)_datalow_base + OPROM_HEADER_RESERVE; + if (newend < (u32)datalow_base + OPROM_HEADER_RESERVE) + newend = (u32)datalow_base + OPROM_HEADER_RESERVE; RomBase->data = RomBase->dataend = (void*)newend; return (void*)RomEnd; } @@ -253,7 +246,8 @@ malloc_setup(void) // Populate other regions addSpace(&ZoneTmpLow, (void*)BUILD_STACK_ADDR, (void*)BUILD_EBDA_MINIMUM); addSpace(&ZoneFSeg, BiosTableSpace, &BiosTableSpace[CONFIG_MAX_BIOSTABLE]); - addSpace(&ZoneLow, _datalow_base + OPROM_HEADER_RESERVE, (void*)lowmemend()); + extern u8 final_datalow_start[]; + addSpace(&ZoneLow, datalow_base + OPROM_HEADER_RESERVE, final_datalow_start); RomBase = findLast(&ZoneLow); if (highram) { addSpace(&ZoneHigh, (void*)highram diff --git a/src/post.c b/src/post.c index 1d0d35a..3101505 100644 --- a/src/post.c +++ b/src/post.c @@ -97,7 +97,7 @@ init_bda(void) , E820_RESERVED);
// Init extra stack - StackPos = (void*)(&ExtraStack[BUILD_EXTRA_STACK_SIZE] - _datalow_base); + StackPos = (void*)(&ExtraStack[BUILD_EXTRA_STACK_SIZE] - datalow_base); }
static void @@ -293,14 +293,14 @@ maininit(void)
// Relocation fixup code that runs at new address after relocation complete. static void -afterReloc(void *datalow) +afterReloc(void) { // Running at new code address - do code relocation fixups malloc_fixupreloc();
// Move low-memory initial variable content to new location. - extern u8 datalow_start[], datalow_end[]; - memmove(datalow, datalow_start, datalow_end - datalow_start); + extern u8 datalow_start[], datalow_end[], final_datalow_start[]; + memmove(final_datalow_start, datalow_start, datalow_end - datalow_start);
// Run main code maininit(); @@ -331,24 +331,20 @@ reloc_init(void) extern u32 _reloc_init_start[], _reloc_init_end[]; extern u8 code32init_start[], code32init_end[]; extern u32 _reloc_datalow_start[], _reloc_datalow_end[]; - extern u8 _datalow_min_align; - extern u8 datalow_start[], datalow_end[]; + extern u8 datalow_start[], datalow_end[], final_datalow_start[];
// Allocate space for init code. u32 initsize = code32init_end - code32init_start; u32 codealign = (u32)&_reloc_min_align; void *codedest = memalign_tmp(codealign, initsize); - u32 datalowsize = datalow_end - datalow_start; - u32 datalowalign = (u32)&_datalow_min_align; - void *datalow = memalign_low(datalowalign, datalowsize); - if (!codedest || !datalow) + if (!codedest) panic("No space for init relocation.\n");
// Copy code and update relocs (init absolute, init relative, and runtime) dprintf(1, "Relocating low data from %p to %p (size %d)\n" - , datalow_start, datalow, datalowsize); + , datalow_start, final_datalow_start, datalow_end - datalow_start); updateRelocs(code32flat_start, _reloc_datalow_start, _reloc_datalow_end - , datalow - (void*)datalow_start); + , final_datalow_start - datalow_start); dprintf(1, "Relocating init from %p to %p (size %d)\n" , code32init_start, codedest, initsize); s32 delta = codedest - (void*)code32init_start; @@ -358,9 +354,9 @@ reloc_init(void) updateRelocs(code32flat_start, _reloc_init_start, _reloc_init_end, delta);
// Call maininit() in relocated code. - void (*func)(void*) = (void*)afterReloc + delta; + void (*func)(void) = (void*)afterReloc + delta; barrier(); - func(datalow); + func(); }
// Setup for code relocation and then call reloc_init diff --git a/tools/layoutrom.py b/tools/layoutrom.py index 74b410f..7a7d08c 100755 --- a/tools/layoutrom.py +++ b/tools/layoutrom.py @@ -48,8 +48,6 @@ def setSectionsStart(sections, endaddr, minalign=1, segoffset=0): totspace = alignpos(totspace, section.align) + section.size startaddr = (endaddr - totspace) / minalign * minalign curaddr = startaddr - # out = [(addr, sectioninfo), ...] - out = [] for section in sections: curaddr = alignpos(curaddr, section.align) section.finalloc = curaddr @@ -159,7 +157,7 @@ class LayoutInfo: sections32flat = sec32flat_start = sec32flat_align = None sections32init = sec32init_start = sec32init_align = None sections32low = sec32low_start = sec32low_align = None - datalow_base = None + datalow_base = final_sec32low_start = None
# Determine final memory addresses for sections def doLayout(sections, genreloc): @@ -219,13 +217,17 @@ def doLayout(sections, genreloc): li.sections32low = getSectionsCategory(sections, '32low') if genreloc: sec32low_top = li.sec32init_start - datalow_base = min(BUILD_BIOS_ADDR, li.sec32flat_start) - 64*1024 + final_sec32low_top = min(BUILD_BIOS_ADDR, li.sec32flat_start) else: sec32low_top = min(BUILD_BIOS_ADDR, li.sec32init_start) - datalow_base = sec32low_top - 64*1024 + final_sec32low_top = sec32low_top + relocdelta = final_sec32low_top - sec32low_top + datalow_base = final_sec32low_top - 64*1024 li.datalow_base = max(BUILD_ROM_START, alignpos(datalow_base, 2*1024)) li.sec32low_start, li.sec32low_align = setSectionsStart( - li.sections32low, sec32low_top, 16, segoffset=li.datalow_base) + li.sections32low, sec32low_top, 16 + , segoffset=li.datalow_base - relocdelta) + li.final_sec32low_start = li.sec32low_start + relocdelta
# Print statistics size16 = BUILD_BIOS_ADDR + BUILD_BIOS_SIZE - li.sec16_start @@ -311,7 +313,7 @@ def getSectionsStart(sections, defaddr=0): def writeLinkerScripts(li, entrysym, genreloc, out16, out32seg, out32flat): # Write 16bit linker script out = outXRefs(li.sections16, useseg=1) + """ - _datalow_base = 0x%x ; + datalow_base = 0x%x ; _datalow_seg = 0x%x ;
code16_start = 0x%x ; @@ -352,8 +354,7 @@ def writeLinkerScripts(li, entrysym, genreloc, out16, out32seg, out32flat): initrelocs = getRelocs( li.sections32flat + li.sections32low + li.sections16 + li.sections32seg, category='32init') - lowrelocs = getRelocs( - li.sections16 + li.sections32seg + sections32all, category='32low') + lowrelocs = getRelocs(sections32all, category='32low') relocstr = (strRelocs("_reloc_abs", "code32init_start", absrelocs) + strRelocs("_reloc_rel", "code32init_start", relrelocs) + strRelocs("_reloc_init", "code32flat_start", initrelocs) @@ -363,8 +364,8 @@ def writeLinkerScripts(li, entrysym, genreloc, out16, out32seg, out32flat): out = outXRefs(sections32all) + """ %s = 0x%x ; _reloc_min_align = 0x%x ; - _datalow_base = 0x%x ; - _datalow_min_align = 0x%x ; + datalow_base = 0x%x ; + final_datalow_start = 0x%x ;
code32flat_start = 0x%x ; .text code32flat_start : { @@ -385,7 +386,7 @@ def writeLinkerScripts(li, entrysym, genreloc, out16, out32seg, out32flat): """ % (entrysym.name, entrysympos, li.sec32init_align, li.datalow_base, - li.sec32low_align, + li.final_sec32low_start, sec32all_start, relocstr, outRelSections(li.sections32low, 'code32flat_start'),