Allow rom to grow beyond 64K.
If rom is over 64K then use part of e-segment for 32bit code. Push 32bit code as high as it can go in the f-segment. Do version building before layoutrom.py - this way layoutrom knows full size of rom. Make layoutrom.py build the full ld script - remove now unused ld scripts that just imported the output of layoutrom.py. Also, use "objdump" instead of "nm" - reduce toolchain requirements. Enhance tools/checkrom.py so that it can pad bios.bin to size qemu is happy with. Also, add dependencies to build rules for local tools - if tool changes automatically rerun it. Make sure option roms don't overwrite the 32bit code (should the 32bit code be in the e-segment). Make sure shadow code works even if part of the code is in the e-segment.
This commit is contained in:
parent
31ae638cda
commit
5b8f809920
41
Makefile
41
Makefile
|
@ -51,7 +51,6 @@ endif
|
|||
|
||||
OBJCOPY=objcopy
|
||||
OBJDUMP=objdump
|
||||
NM=nm
|
||||
STRIP=strip
|
||||
|
||||
.PHONY : all FORCE
|
||||
|
@ -112,47 +111,43 @@ $(OUT)asm-offsets.h: $(OUT)asm-offsets.s
|
|||
|
||||
$(OUT)ccode.16.s: ; $(call whole-compile, $(CFLAGS16) -S, $(addprefix src/, $(SRC16)),$@)
|
||||
|
||||
$(OUT)ccode32.o: ; $(call whole-compile, $(CFLAGS), $(addprefix src/, $(SRC32)),$@)
|
||||
|
||||
$(OUT)code16.o: romlayout.S $(OUT)ccode.16.s $(OUT)asm-offsets.h
|
||||
@echo " Compiling (16bit) $@"
|
||||
$(Q)$(CC) $(CFLAGS16INC) -c -D__ASSEMBLY__ $< -o $@
|
||||
|
||||
$(OUT)code32.o: ; $(call whole-compile, $(CFLAGS), $(addprefix src/, $(SRC32)),$@)
|
||||
|
||||
$(OUT)romlayout16.lds $(OUT)romlayout32.lds: $(OUT)code32.o $(OUT)code16.o
|
||||
@echo " Building layout information $@"
|
||||
$(OUT)romlayout16.lds $(OUT)romlayout32.lds $(OUT)code32.o: $(OUT)ccode32.o $(OUT)code16.o tools/layoutrom.py
|
||||
@echo " Building ld scripts (version \"$(VERSION)\")"
|
||||
$(Q)echo 'const char VERSION[] = "$(VERSION)";' > $(OUT)version.c
|
||||
$(Q)$(CC) $(CFLAGS) -c $(OUT)version.c -o $(OUT)version.o
|
||||
$(Q)$(LD) -melf_i386 -r $(OUT)ccode32.o $(OUT)version.o -o $(OUT)code32.o
|
||||
$(Q)$(OBJDUMP) -thr $(OUT)code32.o > $(OUT)code32.o.objdump
|
||||
$(Q)$(OBJDUMP) -thr $(OUT)code16.o > $(OUT)code16.o.objdump
|
||||
$(Q)./tools/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32.lds
|
||||
|
||||
$(OUT)layout16.lds: $(OUT)romlayout16.lds
|
||||
$(OUT)rombios32.lds: $(OUT)romlayout32.lds
|
||||
|
||||
|
||||
$(OUT)rom16.o: $(OUT)code16.o $(OUT)rom32.o $(OUT)layout16.lds
|
||||
$(OUT)rom16.o: $(OUT)code16.o $(OUT)rom32.o $(OUT)romlayout16.lds
|
||||
@echo " Linking (no relocs) $@"
|
||||
$(Q)$(LD) -r -T $(OUT)layout16.lds $< -o $@
|
||||
$(Q)$(LD) -r -T $(OUT)romlayout16.lds $< -o $@
|
||||
|
||||
$(OUT)rom32.o: $(OUT)code32.o $(OUT)rombios32.lds
|
||||
$(OUT)rom32.o: $(OUT)code32.o $(OUT)romlayout32.lds
|
||||
@echo " Linking (no relocs) $@"
|
||||
$(Q)$(LD) -r -T $(OUT)rombios32.lds $< -o $@
|
||||
$(Q)$(LD) -r -T $(OUT)romlayout32.lds $< -o $@
|
||||
|
||||
$(OUT)rom.o: $(OUT)rom16.o $(OUT)rom32.o $(OUT)rombios16.lds $(OUT)rombios.lds
|
||||
@echo " Linking $@ (version \"$(VERSION)\")"
|
||||
$(Q)echo 'const char VERSION[] __attribute__((section(".data32.version"))) = "$(VERSION)";' > $(OUT)version.c
|
||||
$(Q)$(CC) $(CFLAGS) -c $(OUT)version.c -o $(OUT)version.o
|
||||
$(Q)$(LD) -T $(OUT)rombios16.lds $(OUT)rom16.o -R $(OUT)rom32.o -o $(OUT)rom16.reloc.o
|
||||
$(Q)$(STRIP) $(OUT)rom16.reloc.o -o $(OUT)rom16.final.o
|
||||
$(Q)$(OBJCOPY) --adjust-vma 0xf0000 $(OUT)rom16.o $(OUT)rom16.moved.o
|
||||
$(Q)$(LD) -T $(OUT)rombios.lds $(OUT)rom16.final.o $(OUT)rom32.o $(OUT)version.o -R $(OUT)rom16.moved.o -o $@
|
||||
$(Q)$(LD) -T $(OUT)rombios.lds $(OUT)rom16.final.o $(OUT)rom32.o -R $(OUT)rom16.moved.o -o $@
|
||||
|
||||
$(OUT)bios.bin.elf: $(OUT)rom.o
|
||||
$(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py
|
||||
@echo " Prepping $@"
|
||||
$(Q)$(NM) $< | ./tools/checkrom.py
|
||||
$(Q)$(STRIP) $< -o $@
|
||||
|
||||
$(OUT)bios.bin: $(OUT)bios.bin.elf
|
||||
@echo " Extracting binary $@"
|
||||
$(Q)$(OBJCOPY) -O binary $< $@
|
||||
$(Q)$(OBJDUMP) -thr $< > $<.objdump
|
||||
$(Q)$(OBJCOPY) -O binary $< $(OUT)bios.bin.raw
|
||||
$(Q)./tools/checkrom.py $<.objdump $(OUT)bios.bin.raw $(OUT)bios.bin
|
||||
$(Q)$(STRIP) $< -o $(OUT)bios.bin.elf
|
||||
|
||||
|
||||
################ VGA build rules
|
||||
|
@ -175,7 +170,7 @@ $(OUT)vgabios.bin.raw: $(OUT)vgarom.o
|
|||
@echo " Extracting binary $@"
|
||||
$(Q)$(OBJCOPY) -O binary $< $@
|
||||
|
||||
$(OUT)vgabios.bin: $(OUT)vgabios.bin.raw
|
||||
$(OUT)vgabios.bin: $(OUT)vgabios.bin.raw tools/buildrom.py
|
||||
@echo " Finalizing rom $@"
|
||||
$(Q)./tools/buildrom.py $< $@
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
// Placement of the 16bit code.
|
||||
//
|
||||
// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU LGPLv3 license.
|
||||
|
||||
#include "config.h" // BUILD_BIOS_ADDR
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH("i386")
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
// The actual placement of the 16bit sections is determined by the
|
||||
// script tools/layoutrom.py
|
||||
#include "../out/romlayout16.lds"
|
||||
|
||||
// Discard regular data sections to force a link error if
|
||||
// 16bit code attempts to access data not marked with VAR16.
|
||||
/DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
|
||||
}
|
|
@ -164,12 +164,22 @@ get_pci_rom(struct rom_header *rom)
|
|||
return pci;
|
||||
}
|
||||
|
||||
// Return the memory position up to which roms may be located.
|
||||
static inline u32
|
||||
max_rom()
|
||||
{
|
||||
extern u8 code32_start[];
|
||||
if ((u32)code32_start > BUILD_BIOS_ADDR)
|
||||
return BUILD_BIOS_ADDR;
|
||||
return (u32)code32_start;
|
||||
}
|
||||
|
||||
// Copy a rom to its permanent location below 1MiB
|
||||
static struct rom_header *
|
||||
copy_rom(struct rom_header *rom)
|
||||
{
|
||||
u32 romsize = rom->size * 512;
|
||||
if (RomEnd + romsize > BUILD_BIOS_ADDR) {
|
||||
if (RomEnd + romsize > max_rom()) {
|
||||
// Option rom doesn't fit.
|
||||
dprintf(1, "Option rom %p doesn't fit.\n", rom);
|
||||
return NULL;
|
||||
|
@ -213,8 +223,7 @@ lookup_hardcode(u32 vendev)
|
|||
&& ((OPTIONROM_VENDEV_2 >> 16)
|
||||
| ((OPTIONROM_VENDEV_2 & 0xffff)) << 16) == vendev)
|
||||
return copy_rom((void*)OPTIONROM_MEM_2);
|
||||
int ret = cbfs_copy_optionrom((void*)RomEnd, BUILD_BIOS_ADDR - RomEnd
|
||||
, vendev);
|
||||
int ret = cbfs_copy_optionrom((void*)RomEnd, max_rom() - RomEnd, vendev);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
return (void*)RomEnd;
|
||||
|
@ -229,7 +238,7 @@ run_cbfs_roms(const char *prefix, int isvga)
|
|||
file = cbfs_findprefix(prefix, file);
|
||||
if (!file)
|
||||
break;
|
||||
int ret = cbfs_copyfile(file, (void*)RomEnd, BUILD_BIOS_ADDR - RomEnd);
|
||||
int ret = cbfs_copyfile(file, (void*)RomEnd, max_rom() - RomEnd);
|
||||
if (ret > 0)
|
||||
init_optionrom((void*)RomEnd, 0, isvga);
|
||||
}
|
||||
|
@ -343,7 +352,7 @@ optionrom_setup()
|
|||
if (CONFIG_OPTIONROMS_DEPLOYED) {
|
||||
// Option roms are already deployed on the system.
|
||||
u32 pos = RomEnd;
|
||||
while (pos < BUILD_BIOS_ADDR) {
|
||||
while (pos < max_rom()) {
|
||||
int ret = init_optionrom((void*)pos, 0, 0);
|
||||
if (ret)
|
||||
pos += OPTION_ROM_ALIGN;
|
||||
|
|
|
@ -4,16 +4,17 @@
|
|||
//
|
||||
// This file may be distributed under the terms of the GNU LGPLv3 license.
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
#include "config.h" // BUILD_BIOS_ADDR
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386")
|
||||
OUTPUT_ARCH("i386")
|
||||
ENTRY(post32)
|
||||
SECTIONS
|
||||
{
|
||||
.text code32_start : {
|
||||
*(.text32)
|
||||
*(.data32.version)
|
||||
|
||||
. = code16_start ;
|
||||
. = code16_start + BUILD_BIOS_ADDR - code32_start ;
|
||||
*(.text16)
|
||||
final_code16_end = . ;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
//
|
||||
// This file may be distributed under the terms of the GNU LGPLv3 license.
|
||||
|
||||
#include "config.h" // BUILD_BIOS_ADDR
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH("i386")
|
||||
SECTIONS
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
// Linker definitions for 32 bit code
|
||||
//
|
||||
// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU LGPLv3 license.
|
||||
|
||||
#include "config.h" // BUILD_BIOS_ADDR
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH("i386")
|
||||
SECTIONS
|
||||
{
|
||||
.text32 BUILD_BIOS_ADDR : {
|
||||
code32_start = ABSOLUTE(.) ;
|
||||
|
||||
// The actual sections kept is determined by the script tools/layoutrom.py
|
||||
#include "../out/romlayout32.lds"
|
||||
|
||||
freespace_start = . ;
|
||||
code32_end = ABSOLUTE(.) ;
|
||||
}
|
||||
}
|
66
src/shadow.c
66
src/shadow.c
|
@ -23,28 +23,8 @@
|
|||
|
||||
// Enable shadowing and copy bios.
|
||||
static void
|
||||
copy_bios(u16 bdf)
|
||||
__make_bios_writable(u16 bdf)
|
||||
{
|
||||
pci_config_writeb(bdf, 0x59, 0x30);
|
||||
memcpy((void*)BUILD_BIOS_ADDR, (void*)BIOS_SRC_ADDR, BUILD_BIOS_SIZE);
|
||||
}
|
||||
|
||||
// Make the 0xc0000-0x100000 area read/writable.
|
||||
void
|
||||
make_bios_writable()
|
||||
{
|
||||
if (CONFIG_COREBOOT)
|
||||
return;
|
||||
|
||||
dprintf(3, "enabling shadow ram\n");
|
||||
|
||||
// Locate chip controlling ram shadowing.
|
||||
int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
|
||||
if (bdf < 0) {
|
||||
dprintf(1, "Unable to unlock ram - bridge not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make ram from 0xc0000-0xf0000 writable
|
||||
int clear = 0;
|
||||
int i;
|
||||
|
@ -68,24 +48,46 @@ make_bios_writable()
|
|||
if (clear)
|
||||
memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
|
||||
|
||||
// Make ram from 0xf0000-0x100000 writable
|
||||
int reg = pci_config_readb(bdf, 0x59);
|
||||
if (reg & 0x10) {
|
||||
// Ram already present - just enable writes
|
||||
pci_config_writeb(bdf, 0x59, 0x30);
|
||||
pci_config_writeb(bdf, 0x59, 0x30);
|
||||
if (reg & 0x10)
|
||||
// Ram already present.
|
||||
return;
|
||||
|
||||
// Copy bios.
|
||||
memcpy((void*)BUILD_BIOS_ADDR, (void*)BIOS_SRC_ADDR, BUILD_BIOS_SIZE);
|
||||
}
|
||||
|
||||
// Make the 0xc0000-0x100000 area read/writable.
|
||||
void
|
||||
make_bios_writable()
|
||||
{
|
||||
if (CONFIG_COREBOOT)
|
||||
return;
|
||||
|
||||
dprintf(3, "enabling shadow ram\n");
|
||||
|
||||
// Locate chip controlling ram shadowing.
|
||||
int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
|
||||
if (bdf < 0) {
|
||||
dprintf(1, "Unable to unlock ram - bridge not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable shadowing and copy bios.
|
||||
if (IN_RANGE((u32)copy_bios, BUILD_BIOS_ADDR, BUILD_BIOS_SIZE)) {
|
||||
// Jump to shadow enable function - use the copy in the
|
||||
// temporary storage area so that memory does not change under
|
||||
// the executing code.
|
||||
u32 pos = (u32)copy_bios - BUILD_BIOS_ADDR + BIOS_SRC_ADDR;
|
||||
int reg = pci_config_readb(bdf, 0x59);
|
||||
if (!(reg & 0x10)) {
|
||||
// QEMU doesn't fully implement the piix shadow capabilities -
|
||||
// if ram isn't backing the bios segment when shadowing is
|
||||
// disabled, the code itself wont be in memory. So, run the
|
||||
// code from the high-memory flash location.
|
||||
u32 pos = (u32)__make_bios_writable - BUILD_BIOS_ADDR + BIOS_SRC_ADDR;
|
||||
void (*func)(u16 bdf) = (void*)pos;
|
||||
func(bdf);
|
||||
} else {
|
||||
copy_bios(bdf);
|
||||
return;
|
||||
}
|
||||
// Ram already present - just enable writes
|
||||
__make_bios_writable(bdf);
|
||||
}
|
||||
|
||||
// Make the BIOS code segment area (0xf0000) read-only.
|
||||
|
|
|
@ -6,33 +6,56 @@
|
|||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
import sys
|
||||
import layoutrom
|
||||
|
||||
def main():
|
||||
# Read in symbols (that are valid)
|
||||
syms = {}
|
||||
for line in sys.stdin.readlines():
|
||||
try:
|
||||
addr, type, sym = line.split()
|
||||
syms[sym] = int(addr, 16)
|
||||
except:
|
||||
pass
|
||||
# Get args
|
||||
objinfo, rawfile, outfile = sys.argv[1:]
|
||||
|
||||
# Read in symbols
|
||||
objinfofile = open(objinfo, 'rb')
|
||||
symbols = layoutrom.parseObjDump(objinfofile)[1]
|
||||
syms = {}
|
||||
for name, (addr, section) in symbols.items():
|
||||
syms[name] = addr
|
||||
|
||||
# Read in raw file
|
||||
f = open(rawfile, 'rb')
|
||||
rawdata = f.read()
|
||||
f.close()
|
||||
datasize = len(rawdata)
|
||||
finalsize = 64*1024
|
||||
if datasize > 64*1024:
|
||||
finalsize = 128*1024
|
||||
|
||||
# Sanity checks
|
||||
c16e = syms['code16_end'] + 0xf0000
|
||||
f16e = syms['final_code16_end']
|
||||
if c16e != f16e:
|
||||
print "Error! 16bit code moved during linking (0x%x vs 0x%x)" % (
|
||||
c16e, f16e)
|
||||
sys.exit(1)
|
||||
if datasize > finalsize:
|
||||
print "Error! Code is too big (0x%x vs 0x%x)" % (
|
||||
datasize, finalsize)
|
||||
sys.exit(1)
|
||||
|
||||
# Print statistics
|
||||
sizefree = syms['freespace_end'] - syms['freespace_start']
|
||||
size16 = syms['code16_end'] - syms['code16_start']
|
||||
size32 = syms['code32_end'] - syms['code32_start']
|
||||
totalc = size16+size32
|
||||
print "16bit size: %d" % size16
|
||||
print "32bit size: %d" % size32
|
||||
print "Total size: %d Free space: %d Percent used: %.1f%%" % (
|
||||
totalc, sizefree
|
||||
, (totalc / float(size16+size32+sizefree)) * 100.0)
|
||||
print "Total size: %d Free space: %d Percent used: %.1f%% (%dKiB rom)" % (
|
||||
totalc, sizefree + finalsize - datasize
|
||||
, (totalc / float(finalsize)) * 100.0
|
||||
, finalsize / 1024)
|
||||
|
||||
# Write final file
|
||||
f = open(outfile, 'wb')
|
||||
f.write(("\0" * (finalsize - datasize)) + rawdata)
|
||||
f.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
# Script to arrange sections to ensure fixed offsets.
|
||||
# Script to analyze code and arrange ld sections.
|
||||
#
|
||||
# Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
|
||||
#
|
||||
|
@ -7,18 +7,49 @@
|
|||
|
||||
import sys
|
||||
|
||||
|
||||
# Align 'pos' to 'alignbytes' offset
|
||||
def alignpos(pos, alignbytes):
|
||||
mask = alignbytes - 1
|
||||
return (pos + mask) & ~mask
|
||||
|
||||
# LD script headers/trailers
|
||||
COMMONHEADER = """
|
||||
/* DO NOT EDIT! This is an autogenerated file. See tools/layoutrom.py. */
|
||||
OUTPUT_FORMAT("elf32-i386")
|
||||
OUTPUT_ARCH("i386")
|
||||
SECTIONS
|
||||
{
|
||||
"""
|
||||
COMMONTRAILER = """
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
######################################################################
|
||||
# 16bit fixed address section fitting
|
||||
######################################################################
|
||||
|
||||
MAXPOS = 0x10000
|
||||
# Get the maximum start position for a list of sections that end at an
|
||||
# address.
|
||||
def getSectionsStart(sections, endaddr, minalign=1):
|
||||
totspace = 0
|
||||
for size, align, name in sections:
|
||||
if align > minalign:
|
||||
minalign = align
|
||||
totspace = alignpos(totspace, align) + size
|
||||
return (endaddr - totspace) / minalign * minalign
|
||||
|
||||
# Write LD script includes for the given sections
|
||||
def outSections(file, sections):
|
||||
for size, align, name in sections:
|
||||
file.write("*(%s)\n" % (name,))
|
||||
|
||||
# The 16bit code can't exceed 64K of space.
|
||||
MAXPOS = 64*1024
|
||||
|
||||
# Layout the 16bit code. This ensures sections with fixed offset
|
||||
# requirements are placed in the correct location. It also places the
|
||||
# 16bit code as high as possible in the f-segment.
|
||||
def doLayout16(sections, outname):
|
||||
textsections = []
|
||||
rodatasections = []
|
||||
|
@ -103,18 +134,6 @@ def doLayout16(sections, outname):
|
|||
# , fitnextaddr, nextfixedaddr - fitnextaddr)
|
||||
firstfixed = fixedsections[0][0]
|
||||
|
||||
# Find overall start position
|
||||
restalign = 0
|
||||
restspace = 0
|
||||
restsections = []
|
||||
for section in textsections + rodatasections + datasections:
|
||||
size, align, name = section
|
||||
if align > restalign:
|
||||
restalign = align
|
||||
restspace = alignpos(restspace, align) + size
|
||||
restsections.append(section)
|
||||
startrest = (firstfixed - restspace) / restalign * restalign
|
||||
|
||||
# Report stats
|
||||
total = MAXPOS-firstfixed
|
||||
slack = total - totalused
|
||||
|
@ -123,20 +142,23 @@ def doLayout16(sections, outname):
|
|||
firstfixed, MAXPOS, total, slack,
|
||||
(float(slack) / total) * 100.0))
|
||||
|
||||
# Find overall start position
|
||||
start16 = getSectionsStart(
|
||||
textsections + rodatasections + datasections, firstfixed)
|
||||
|
||||
# Write header
|
||||
output = open(outname, 'wb')
|
||||
output.write("""
|
||||
output.write(COMMONHEADER + """
|
||||
.text16 0x%x : {
|
||||
code16_start = ABSOLUTE(.) ;
|
||||
freespace_end = . ;
|
||||
""" % startrest)
|
||||
""" % start16)
|
||||
|
||||
# Write regular sections
|
||||
for section in restsections:
|
||||
name = section[2]
|
||||
if rodatasections and name == rodatasections[0][2]:
|
||||
output.write("code16_rodata = . ;\n")
|
||||
output.write("*(%s)\n" % (name,))
|
||||
outSections(output, textsections)
|
||||
output.write("code16_rodata = . ;\n")
|
||||
outSections(output, rodatasections)
|
||||
outSections(output, datasections)
|
||||
|
||||
# Write fixed sections
|
||||
for addr, section, extrasections in fixedsections:
|
||||
|
@ -150,32 +172,66 @@ def doLayout16(sections, outname):
|
|||
output.write("""
|
||||
code16_end = ABSOLUTE(.) ;
|
||||
}
|
||||
""")
|
||||
|
||||
/* Discard regular data sections to force a link error if
|
||||
* 16bit code attempts to access data not marked with VAR16
|
||||
*/
|
||||
/DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
|
||||
""" + COMMONTRAILER)
|
||||
|
||||
return start16
|
||||
|
||||
|
||||
######################################################################
|
||||
# 32bit section outputting
|
||||
######################################################################
|
||||
|
||||
def outsections(file, sections, prefix):
|
||||
# Return the subset of sections with a given name prefix
|
||||
def getSectionsPrefix(sections, prefix):
|
||||
lp = len(prefix)
|
||||
out = []
|
||||
for size, align, name in sections:
|
||||
if name[:lp] == prefix:
|
||||
file.write("*(%s)\n" % (name,))
|
||||
out.append((size, align, name))
|
||||
return out
|
||||
|
||||
def doLayout32(sections, outname):
|
||||
# Layout the 32bit code. This places the code as high as possible.
|
||||
def doLayout32(sections, outname, start16):
|
||||
start16 += 0xf0000
|
||||
# Find sections to output
|
||||
textsections = getSectionsPrefix(sections, '.text.')
|
||||
rodatasections = getSectionsPrefix(sections, '.rodata')
|
||||
datasections = getSectionsPrefix(sections, '.data.')
|
||||
bsssections = getSectionsPrefix(sections, '.bss.')
|
||||
start32 = getSectionsStart(
|
||||
textsections + rodatasections + datasections + bsssections, start16, 512)
|
||||
|
||||
# Write sections
|
||||
output = open(outname, 'wb')
|
||||
outsections(output, sections, '.text.')
|
||||
output.write(COMMONHEADER + """
|
||||
.text32 0x%x : {
|
||||
code32_start = ABSOLUTE(.) ;
|
||||
""" % start32)
|
||||
|
||||
outSections(output, textsections)
|
||||
output.write("code32_rodata = . ;\n")
|
||||
outsections(output, sections, '.rodata')
|
||||
outsections(output, sections, '.data.')
|
||||
outsections(output, sections, '.bss.')
|
||||
outSections(output, rodatasections)
|
||||
outSections(output, datasections)
|
||||
outSections(output, bsssections)
|
||||
|
||||
output.write("""
|
||||
freespace_start = . ;
|
||||
code32_end = ABSOLUTE(.) ;
|
||||
}
|
||||
""" + COMMONTRAILER)
|
||||
|
||||
|
||||
######################################################################
|
||||
# Section garbage collection
|
||||
######################################################################
|
||||
|
||||
# Note required section, and recursively set all referenced sections
|
||||
# as required.
|
||||
def keepsection(name, pri, alt):
|
||||
if name in pri[3]:
|
||||
# Already kept - nothing to do.
|
||||
|
@ -186,15 +242,18 @@ def keepsection(name, pri, alt):
|
|||
return
|
||||
# Keep all sections that this section points to
|
||||
for symbol in relocs:
|
||||
section = pri[1].get(symbol)
|
||||
if section is not None and section[:9] != '.discard.':
|
||||
addr, section = pri[1].get(symbol, (None, None))
|
||||
if (section is not None and '*' not in section
|
||||
and section[:9] != '.discard.'):
|
||||
keepsection(section, pri, alt)
|
||||
continue
|
||||
# Not in primary sections - it may be a cross 16/32 reference
|
||||
section = alt[1].get(symbol)
|
||||
if section is not None:
|
||||
addr, section = alt[1].get(symbol, (None, None))
|
||||
if section is not None and '*' not in section:
|
||||
keepsection(section, alt, pri)
|
||||
|
||||
# Determine which sections are actually referenced and need to be
|
||||
# placed into the output file.
|
||||
def gc(info16, info32):
|
||||
# pri = (sections, symbols, relocs, keep sections)
|
||||
pri = (info16[0], info16[1], info16[2], [])
|
||||
|
@ -261,8 +320,8 @@ def parseObjDump(file):
|
|||
try:
|
||||
section, off, symbol = line[17:].split()
|
||||
off = int(off, 16)
|
||||
if '*' not in section:
|
||||
symbols[symbol] = section
|
||||
addr = int(line[:8], 16)
|
||||
symbols[symbol] = addr, section
|
||||
except:
|
||||
pass
|
||||
continue
|
||||
|
@ -287,8 +346,8 @@ def main():
|
|||
|
||||
sections16, sections32 = gc(info16, info32)
|
||||
|
||||
doLayout16(sections16, out16)
|
||||
doLayout32(sections32, out32)
|
||||
start16 = doLayout16(sections16, out16)
|
||||
doLayout32(sections32, out32, start16)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
Loading…
Reference in New Issue