Skip to content

Commit

Permalink
Merged PR 2710: BaseTools/Conf: Add OEM Data build rule
Browse files Browse the repository at this point in the history
BaseTools/Conf: Add OEM Data build rule

Adds a new build rule for OEM data files which are structured
compiled data. The rule provides support for MSFT, GCC, and
Clang toolchains.
  • Loading branch information
makubacki committed Sep 23, 2020
1 parent 284cd1d commit f416458
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 1 deletion.
14 changes: 14 additions & 0 deletions BaseTools/BinWrappers/PosixLike/OemDataFormatter
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
#python `dirname $0`/RunToolFromSource.py `basename $0` $*

# If a ${PYTHON_COMMAND} command is available, use it in preference to python
if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
python_exe=${PYTHON_COMMAND}
fi

full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
dir=$(dirname "$full_cmd")
exe=$(basename "$full_cmd")

export PYTHONPATH="$dir/../../Source/Python${PYTHONPATH:+:"$PYTHONPATH"}"
exec "${python_exe:-python}" "$dir/../../Source/Python/$exe/$exe.py" "$@"
3 changes: 3 additions & 0 deletions BaseTools/BinWrappers/WindowsLike/OemDataFormatter.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@setlocal
@set ToolName=%~n0%
@%PYTHON_COMMAND% %BASE_TOOLS_PATH%\Source\Python\%ToolName%\%ToolName%.py %*
32 changes: 31 additions & 1 deletion BaseTools/Conf/build_rule.template
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@
# 2.01 - Add support for DEPS_FLAGS as well as
# 2.21 - Add Rust Definitions
# 2.22 - Remove Rust Definitions. More formal support will be added soon.
# 2.23 - Add OemData Definitions

#!VERSION=2.22
#!VERSION=2.23

[C-Code-File]
<InputFile>
Expand Down Expand Up @@ -518,6 +519,35 @@
"$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff
"$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff $(GENFW_FLAGS)

# MU_CHANGE BEGIN
[C-Code-File-OemData]
<InputFile>
?.oemdatac

<OutputFile>
$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.oemdatabin

<ExtraDependency>
$(MAKE_FILE)

<Command.MSFT>
"$(CC)" /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(DEPS_FLAGS) /nologo /c /FIAutoGen.h /TC /Dmain=main $(INC) ${src}
"$(DLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll /NODEFAULTLIB /ENTRY:main /SUBSYSTEM:CONSOLE $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
"$(GENFW)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.oemdatabin.i -b $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
OemDataFormatter $(OUTPUT_DIR)(+)${s_dir}

<Command.GCC>
"$(CC)" $(DEPS_FLAGS) -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) -fno-toplevel-reorder -x c $(DEPS_FLAGS) $(INC) ${src}
"$(DLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(DLINK_COMMON) -u $(IMAGE_ENTRY_POINT) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS)
"$(GENFW)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.oemdatabin.i -b $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
OemDataFormatter $(OUTPUT_DIR)(+)${s_dir}

<Command.CLANGPDB>
"$(CC)" $(DEPS_FLAGS) -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj -O0 -fkeep-static-consts --language=c $(DEPS_FLAGS) $(INC) ${src}
"$(DLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll /NODEFAULTLIB /ENTRY:main /SUBSYSTEM:CONSOLE $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj
"$(GENFW)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.oemdatabin.i -b $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS)
OemDataFormatter $(OUTPUT_DIR)(+)${s_dir}
# MU_CHANGE END

[Masm16-Code-File]
<InputFile>
Expand Down
97 changes: 97 additions & 0 deletions BaseTools/Source/Python/OemDataFormatter/OemDataFormatter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# @file
#
# Formats a collection of intermediate OEM data binary files
# in a given directory into a single OEM binary file
#
# Copyright (C) Microsoft Corporation. All rights reserved.
#
##

import glob
import io
import os
import sys
import struct
from collections import namedtuple


class OemDataFormatter:
STRUCT_SIGNATURE = b"__SDSH__"
ITEM_SIGNATURE = b"_SDDATA_"
OEM_ID = b"__MSFT__"

def __init__(self, directory_path):
if not os.path.isdir(directory_path):
raise NotADirectoryError(
f"{directory_path} is an invalid directory!")

self._directory_path = directory_path

def _get_bins(self):
return glob.glob(os.path.join(self._directory_path, '*.oemdatabin.i'))

def _get_signed_item(self, file_path):
with open(file_path, 'rb') as bin_file:
bin_data = bytearray(bin_file.read())

signed_item_pos = 0
while True:
signed_item_pos = bin_data.find(
self.ITEM_SIGNATURE, signed_item_pos)

if signed_item_pos == -1:
return

ItemHeader = namedtuple('ItemHeader', 'sig header_len id len')

item_header = ItemHeader._make(struct.unpack_from(
'<QHHI', bin_data, signed_item_pos))

print(f"Signed data item found")
print(f" Item ID: {item_header.id}")
print(f" Item Length: {item_header.len} bytes")

signed_item = bin_data[signed_item_pos:signed_item_pos +
item_header.header_len + item_header.len]

yield signed_item
signed_item_pos += (item_header.header_len + item_header.len)

def _get_signed_structure(self):
signed_items = [i for b in self._get_bins() for i in
self._get_signed_item(b)]

StructureHeader = namedtuple('StructureHeader',
'sig rev header_len oem_id desc_count')

struct_header = StructureHeader(
self.STRUCT_SIGNATURE,
1,
26,
self.OEM_ID,
len(signed_items))

struct_header_data = struct.pack('<8sHI8sI', *struct_header)

with io.BytesIO() as out_buffer:
out_buffer.write(struct_header_data)
for item in signed_items:
# Note: Just keep things packed tight for now
# aligned_boundary = (((~out_buffer.tell()) + 1) &
# self.ITEM_ALIGNMENT - 1)
# out_buffer.seek(out_buffer.tell() + aligned_boundary)
out_buffer.write(item)
return out_buffer.getvalue()

def get_file_data(self):
return {f: list(self._get_signed_item(f)) for f in self._get_bins()}

def write_data(self, out_file_path):
with open(out_file_path, 'wb') as out_bin_file:
out_bin_file.write(self._get_signed_structure())


# Todo: Clean up arg parsing, documentation, logger, etc.
if __name__ == '__main__':
oem_data = OemDataFormatter(sys.argv[1])
oem_data.write_data(os.path.join(sys.argv[1], 'data.oemdatabin'))

0 comments on commit f416458

Please sign in to comment.