#!/usr/bin/env python3
#
# Copyright (c) 2017 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0

"""Generate a Global Descriptor Table (GDT) for x86 CPUs.

For additional detail on GDT and x86 memory management, please
consult the IA Architecture SW Developer Manual, vol. 3.

This script accepts as input the zephyr_prebuilt.elf binary,
which is a link of the Zephyr kernel without various build-time
generated data structures (such as the GDT) inserted into it.
This kernel image has been properly padded such that inserting
these data structures will not disturb the memory addresses of
other symbols.

The input kernel ELF binary is used to obtain the following
information:

- Memory addresses of the Main and Double Fault TSS structures
  so GDT descriptors can be created for them
- Memory addresses of where the GDT lives in memory, so that this
  address can be populated in the GDT pseudo descriptor
- whether userspace or HW stack protection are enabled in Kconfig

The output is a GDT whose contents depend on the kernel
configuration. With no memory protection features enabled,
we generate flat 32-bit code and data segments. If hardware-
based stack overflow protection or userspace is enabled,
we additionally create descriptors for the main and double-
fault IA tasks, needed for userspace privilege elevation and
double-fault handling. If userspace is enabled, we also create
flat code/data segments for ring 3 execution.
"""

import argparse
import sys
import struct
import os
import elftools
from distutils.version import LooseVersion
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection

if LooseVersion(elftools.__version__) < LooseVersion('0.24'):
    sys.exit("pyelftools is out of date, need version 0.24 or later")


def debug(text):
    if not args.verbose:
        return
    sys.stdout.write(os.path.basename(sys.argv[0]) + ": " + text + "\n")


def error(text):
    sys.exit(os.path.basename(sys.argv[0]) + ": " + text)


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):
    debug("create pseudo decriptor: %x %x" % (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):
    debug("create code or data entry: %x %x %x %x %x" %
          (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) | (dpl << 5) | (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 create_tss_entry(base, limit, dpl):
    debug("create TSS entry: %x %x %x" % (base, limit, dpl))
    present = 1

    base_lo, base_mid, base_hi, limit_lo, limit_hi, = chop_base_limit(base,
                                                                      limit)

    type_code = 0x9  # non-busy 32-bit TSS descriptor
    gran = 0

    flags = (gran << 7) | limit_hi
    type_byte = ((present << 7) | (dpl << 5) | type_code)

    return struct.pack(gdt_ent_fmt, limit_lo, base_lo, base_mid,
                       type_byte, 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()
    if "VERBOSE" in os.environ:
        args.verbose = 1


def main():
    parse_args()

    with open(args.kernel, "rb") as fp:
        kernel = ELFFile(fp)
        syms = get_symbols(kernel)

    # NOTE: use-cases are extremely limited; we always have a basic flat
    # code/data segments. If we are doing stack protection, we are going to
    # have two TSS to manage the main task and the special task for double
    # fault exception handling
    if "CONFIG_USERSPACE" in syms:
        num_entries = 7
    elif "CONFIG_HW_STACK_PROTECTION" in syms:
        num_entries = 5
    else:
        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 num_entries >= 5:
            main_tss = syms["_main_tss"]
            df_tss = syms["_df_tss"]

            # Selector 0x18: main TSS
            fp.write(create_tss_entry(main_tss, 0x67, 0))

            # Selector 0x20: double-fault TSS
            fp.write(create_tss_entry(df_tss, 0x67, 0))

        if num_entries == 7:
            # Selector 0x28: code descriptor, dpl = 3
            fp.write(create_code_data_entry(0, 0xFFFFF, 3,
                                            FLAGS_GRAN, ACCESS_EX | ACCESS_RW))

            # Selector 0x30: data descriptor, dpl = 3
            fp.write(create_code_data_entry(0, 0xFFFFF, 3,
                                            FLAGS_GRAN, ACCESS_RW))


if __name__ == "__main__":
    main()
