GCC, for reasons unknown, will refuse to compile code such as extern int bar; uint16_t foo = &bar;
The assembler would happily emit a R_386_16 relocation for this if asked nicely, and all would be well. But instead, GCC complains about the initialiser not being constant.
So we tend to fill in 16-bit offsets at run-time, which is only moderately inefficient. But for the CSM table used by EFI, it doesn't work. We need the offset to be present in the *image*, before a line of our own code has been run. Likewise the checksum.
This special-cases the table and entry point in checkrom.py rather than attempting to do something generic. I did have a functional generic implementation which could be invoked from csm.c along the lines of CHECKSUM(csm_compat_table, TableChecksum) ... and which would emit the required offsetof(typeof(\1), \2) into a special data section which was elided from the final build but parsed by 'objdump -s' and the location of the table to be checksummed was inferred from the name of the *variable* that got put into that special section... seriously, it's better just to special-case it.
It was baroque enough just for the checksums, and filling in the entry point which required access to *two* symbols was probably going to involve emitting a *string* into that special build-data section. It had to die.
So yes, we have hard-coded symbol names, and even magic numbers in the python script for table offsets etc., but that's because this is an ABI. It doesn't change, and neither do any of the other tables that we might now consider filling at build time just to avoid having to spend time on doing so at runtime.
Signed-off-by: David Woodhouse David.Woodhouse@intel.com --- tools/checkrom.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/tools/checkrom.py b/tools/checkrom.py index 69d65e8..00a652a 100755 --- a/tools/checkrom.py +++ b/tools/checkrom.py @@ -8,6 +8,17 @@ import sys import layoutrom
+def subst(data, offset, new): + return data[:offset] + new + data[offset + len(new):] + +def checksum(data, start, size, csum): + sumbyte = 0 + while size: + sumbyte = sumbyte + ord(data[start + size - 1]) + size = size - 1 + sumbyte = (0x100 - sumbyte) & 0xff + return subst(data, start+csum, chr(sumbyte)) + def main(): # Get args objinfo, rawfile, outfile = sys.argv[1:] @@ -45,6 +56,22 @@ def main(): datasize, expdatasize) sys.exit(1)
+ # Fix up CSM Compatibility16 table + if 'csm_compat_table' in symbols and 'entry_csm16' in symbols: + # Field offsets within EFI_COMPATIBILITY16_TABLE + ENTRY_FIELD_OFS = 14 # Compatibility16CallOffset (UINT16) + SIZE_FIELD_OFS = 5 # TableLength (UINT8) + CSUM_FIELD_OFS = 4 # TableChecksum (UINT8) + + tableofs = symbols['csm_compat_table'].offset - symbols['code32flat_start'].offset + entry_addr = symbols['entry_csm16'].offset - layoutrom.BUILD_BIOS_ADDR + byte1 = chr(entry_addr & 0xff) + byte2 = chr(entry_addr >> 8) + rawdata = subst(rawdata, tableofs+ENTRY_FIELD_OFS, byte1+byte2) + + tablesize = ord(rawdata[tableofs+SIZE_FIELD_OFS]) + rawdata = checksum(rawdata, tableofs, tablesize, CSUM_FIELD_OFS) + # Print statistics runtimesize = datasize if '_reloc_abs_start' in symbols: