forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
x86: generate RAM-based GDT dynamically
We will need this for stack memory protection scenarios where a writable GDT with Task State Segment descriptors will be used. The addresses of the TSS segments cannot be put in the GDT via preprocessor magic due to architecture requirments that the address be split up into different fields in the segment descriptor. Signed-off-by: Andrew Boie <[email protected]>
- Loading branch information
Andrew Boie
authored and
Anas Nashif
committed
Jul 25, 2017
1 parent
8a102e4
commit 08c2913
Showing
7 changed files
with
160 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
ifeq ($(KBUILD_VERBOSE),1) | ||
GENGDT_EXTRA_ARGS := --verbose | ||
else | ||
GENGDT_EXTRA_ARGS := | ||
endif | ||
|
||
GENGDT := $(srctree)/scripts/gen_gdt.py | ||
|
||
OUTPUT_FORMAT ?= elf32-i386 | ||
OUTPUT_ARCH ?= i386 | ||
|
||
quiet_cmd_gen_gdt = GDT $@ | ||
cmd_gen_gdt = \ | ||
( \ | ||
$(GENGDT) --kernel $(PREBUILT_KERNEL) \ | ||
--output-gdt gdt.bin \ | ||
$(GENGDT_EXTRA_ARGS) && \ | ||
$(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \ | ||
--rename-section .data=gdt_ram_data gdt.bin $@ \ | ||
) | ||
|
||
gdt.o: $(PREBUILT_KERNEL) $(GENGDT) | ||
$(call cmd,gen_gdt) | ||
|
||
GENERATED_KERNEL_OBJECT_FILES += gdt.o | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#!/usr/bin/env python3 | ||
# | ||
# Copyright (c) 2017 Intel Corporation | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import argparse | ||
import sys | ||
import struct | ||
import os | ||
from elftools.elf.elffile import ELFFile | ||
from elftools.elf.sections import SymbolTableSection | ||
|
||
gdt_pd_fmt = "<HIH" | ||
|
||
FLAGS_GRAN = 1 << 7 # page granularity | ||
ACCESS_EX = 1 << 3 # executable | ||
ACCESS_DC = 1 << 2 # direction/conforming | ||
ACCESS_RW = 1 << 1 # read or write permission | ||
|
||
# 6 byte pseudo descriptor, but we're going to actually use this as the | ||
# zero descriptor and return 8 bytes | ||
def create_gdt_pseudo_desc(addr, size): | ||
# ...and take back one byte for the Intel god whose Ark this is... | ||
size = size - 1 | ||
return struct.pack(gdt_pd_fmt, size, addr, 0) | ||
|
||
|
||
# Limit argument always in bytes | ||
def chop_base_limit(base, limit): | ||
base_lo = base & 0xFFFF | ||
base_mid = (base >> 16) & 0xFF | ||
base_hi = (base >> 24) & 0xFF | ||
|
||
limit_lo = limit & 0xFFFF | ||
limit_hi = (limit >> 16) & 0xF | ||
|
||
return (base_lo, base_mid, base_hi, limit_lo, limit_hi) | ||
|
||
|
||
gdt_ent_fmt = "<HHBBBB" | ||
|
||
def create_code_data_entry(base, limit, dpl, flags, access): | ||
base_lo, base_mid, base_hi, limit_lo, limit_hi = chop_base_limit(base, | ||
limit) | ||
|
||
# This is a valid descriptor | ||
present = 1 | ||
|
||
# 32-bit protected mode | ||
size = 1 | ||
|
||
# 1 = code or data, 0 = system type | ||
desc_type = 1 | ||
|
||
# Just set accessed to 1 already so the CPU doesn't need it update it, | ||
# prevents freakouts if the GDT is in ROM, we don't care about this | ||
# bit in the OS | ||
accessed = 1 | ||
|
||
access = access | (present << 7) | (desc_type << 4) | accessed | ||
flags = flags | (size << 6) | limit_hi | ||
|
||
return struct.pack(gdt_ent_fmt, limit_lo, base_lo, base_mid, | ||
access, flags, base_hi) | ||
|
||
|
||
def get_symbols(obj): | ||
for section in obj.iter_sections(): | ||
if isinstance(section, SymbolTableSection): | ||
return {sym.name: sym.entry.st_value | ||
for sym in section.iter_symbols()} | ||
|
||
raise LookupError("Could not find symbol table") | ||
|
||
|
||
def parse_args(): | ||
global args | ||
parser = argparse.ArgumentParser(description = __doc__, | ||
formatter_class = argparse.RawDescriptionHelpFormatter) | ||
|
||
parser.add_argument("-k", "--kernel", required=True, | ||
help="Zephyr kernel image") | ||
parser.add_argument("-v", "--verbose", action="store_true", | ||
help="Print extra debugging information") | ||
parser.add_argument("-o", "--output-gdt", required=True, | ||
help="output GDT binary") | ||
args = parser.parse_args() | ||
|
||
|
||
def main(): | ||
parse_args() | ||
|
||
with open(args.kernel, "rb") as fp: | ||
kernel = ELFFile(fp) | ||
syms = get_symbols(kernel) | ||
|
||
num_entries = 3 | ||
|
||
gdt_base = syms["_gdt"] | ||
|
||
with open(args.output_gdt, "wb") as fp: | ||
# The pseudo descriptor is stuffed into the NULL descriptor | ||
# since the CPU never looks at it | ||
fp.write(create_gdt_pseudo_desc(gdt_base, num_entries * 8)) | ||
|
||
# Selector 0x08: code descriptor | ||
fp.write(create_code_data_entry(0, 0xFFFFF, 0, | ||
FLAGS_GRAN, ACCESS_EX | ACCESS_RW)) | ||
|
||
# Selector 0x10: data descriptor | ||
fp.write(create_code_data_entry(0, 0xFFFFF, 0, | ||
FLAGS_GRAN, ACCESS_RW)) | ||
|
||
if __name__ == "__main__": | ||
main() | ||
|