mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 07:31:15 +00:00
convert rockchip to use binman
patman fix for checkpatch binman optional entries, improved support for ELF symbols trace improvements minor fdt refactoring -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAmPIpV4RHHNqZ0BjaHJv bWl1bS5vcmcACgkQfxc6PpAIreZuqwgA0UpYQEX6/MegzHSCIx3AMT4rCF1Ytitr LS4Cbvj1Q09Rt9jriW7wAV5AobVPwGf2L5SVcnWv2I9+MmypDIXEe8HIrt2fRFu9 bzn/2GOzXczuXqPFa/CWOUwjvCzTb8Sl9NtRszrP5NvOzuN15x00ZUYaXFO7fgsB zZMzOKxemwjdtLaox+x+VIJ95HMDEkYrWTAqTPg74CNVSjRbbLNqNq0zqkHB8SnH ubgphtIKYItTeIXcfIa9V4LeQp0ZitkzSfAibX+nIPCMPg9jbG9MrQQ+VvSZDjnM y8wa8gFj47Ek+gGNFXMHIpO6tBd83uHRgtf2x+zhcovLELYnZ6fDGw== =1K6m -----END PGP SIGNATURE----- Merge tag 'dm-pull-18jan23' of https://source.denx.de/u-boot/custodians/u-boot-dm convert rockchip to use binman patman fix for checkpatch binman optional entries, improved support for ELF symbols trace improvements minor fdt refactoring
This commit is contained in:
commit
53c47c59e6
78 changed files with 1617 additions and 537 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,6 +6,7 @@
|
|||
# Normal rules (sorted alphabetically)
|
||||
#
|
||||
.*
|
||||
!.checkpatch.conf
|
||||
*.a
|
||||
*.asn1.[ch]
|
||||
*.bin
|
||||
|
|
11
Makefile
11
Makefile
|
@ -1006,14 +1006,9 @@ ifeq ($(CONFIG_INIT_SP_RELATIVE)$(CONFIG_OF_SEPARATE),yy)
|
|||
INPUTS-y += init_sp_bss_offset_check
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_ROCKCHIP)$(CONFIG_SPL),yy)
|
||||
# Binman image dependencies
|
||||
ifeq ($(CONFIG_ARM64),y)
|
||||
INPUTS-y += u-boot.itb
|
||||
else
|
||||
ifeq ($(CONFIG_ARCH_ROCKCHIP)_$(CONFIG_SPL_FRAMEWORK),y_)
|
||||
INPUTS-y += u-boot.img
|
||||
endif
|
||||
endif
|
||||
|
||||
INPUTS-$(CONFIG_X86) += u-boot-x86-start16.bin u-boot-x86-reset16.bin \
|
||||
$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
|
||||
|
@ -1370,9 +1365,6 @@ $(U_BOOT_ITS): $(subst ",,$(CONFIG_SPL_FIT_SOURCE))
|
|||
else
|
||||
ifneq ($(CONFIG_USE_SPL_FIT_GENERATOR),)
|
||||
U_BOOT_ITS := u-boot.its
|
||||
ifeq ($(CONFIG_SPL_FIT_GENERATOR),"arch/arm/mach-rockchip/make_fit_atf.py")
|
||||
U_BOOT_ITS_DEPS += u-boot
|
||||
endif
|
||||
$(U_BOOT_ITS): $(U_BOOT_ITS_DEPS) FORCE
|
||||
$(srctree)/$(CONFIG_SPL_FIT_GENERATOR) \
|
||||
$(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) > $@
|
||||
|
@ -1477,7 +1469,6 @@ OBJCOPYFLAGS_u-boot-with-spl.bin = -I binary -O binary \
|
|||
u-boot-with-spl.bin: $(SPL_IMAGE) $(SPL_PAYLOAD) FORCE
|
||||
$(call if_changed,pad_cat)
|
||||
|
||||
|
||||
ifeq ($(CONFIG_ARCH_LPC32XX)$(CONFIG_SPL),yy)
|
||||
MKIMAGEFLAGS_lpc32xx-spl.img = -T lpc32xximage -a $(CONFIG_SPL_TEXT_BASE)
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ unsigned long get_timer(unsigned long base)
|
|||
return time_ms - base;
|
||||
}
|
||||
|
||||
unsigned long __attribute__((no_instrument_function)) timer_get_us(void)
|
||||
unsigned long notrace timer_get_us(void)
|
||||
{
|
||||
static unsigned long base_time_us;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
/*
|
||||
* Generic timer implementation of get_tbclk()
|
||||
*/
|
||||
unsigned long get_tbclk(void)
|
||||
unsigned long notrace get_tbclk(void)
|
||||
{
|
||||
unsigned long cntfrq;
|
||||
asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq));
|
||||
|
@ -78,7 +78,7 @@ unsigned long timer_read_counter(void)
|
|||
/*
|
||||
* timer_read_counter() using the Arm Generic Timer (aka arch timer).
|
||||
*/
|
||||
unsigned long timer_read_counter(void)
|
||||
unsigned long notrace timer_read_counter(void)
|
||||
{
|
||||
unsigned long cntpct;
|
||||
|
||||
|
@ -89,7 +89,7 @@ unsigned long timer_read_counter(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
uint64_t get_ticks(void)
|
||||
uint64_t notrace get_ticks(void)
|
||||
{
|
||||
unsigned long ticks = timer_read_counter();
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
&binman {
|
||||
simple-bin {
|
||||
blob {
|
||||
fit {
|
||||
offset = <((CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR - 64) * 512)>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -46,14 +46,14 @@
|
|||
|
||||
&binman {
|
||||
simple-bin {
|
||||
blob {
|
||||
fit {
|
||||
offset = <((CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR - 64) * 512)>;
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_SPI_IMAGE
|
||||
simple-bin-spi {
|
||||
blob {
|
||||
fit {
|
||||
/* same as u-boot,spl-payload-offset */
|
||||
offset = <0x80000>;
|
||||
};
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
|
||||
#if defined(CONFIG_ROCKCHIP_SPI_IMAGE) && defined(CONFIG_HAS_ROM)
|
||||
&binman {
|
||||
multiple-images;
|
||||
rom {
|
||||
filename = "u-boot.rom";
|
||||
size = <0x400000>;
|
||||
|
@ -82,7 +83,7 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
#endif
|
||||
#endif /* CONFIG_ROCKCHIP_SPI_IMAGE && CONFIG_HAS_ROM */
|
||||
|
||||
&cru {
|
||||
u-boot,dm-pre-reloc;
|
||||
|
|
|
@ -30,14 +30,79 @@
|
|||
};
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
blob {
|
||||
#if defined(CONFIG_SPL_FIT) && defined(CONFIG_ARM64)
|
||||
fit: fit {
|
||||
description = "FIT image for U-Boot with bl31 (TF-A)";
|
||||
#address-cells = <1>;
|
||||
fit,fdt-list = "of-list";
|
||||
filename = "u-boot.itb";
|
||||
fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
|
||||
offset = <CONFIG_SPL_PAD_TO>;
|
||||
images {
|
||||
u-boot {
|
||||
description = "U-Boot (64-bit)";
|
||||
type = "standalone";
|
||||
os = "U-Boot";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
load = <CONFIG_TEXT_BASE>;
|
||||
entry = <CONFIG_TEXT_BASE>;
|
||||
u-boot-nodtb {
|
||||
};
|
||||
};
|
||||
|
||||
@atf-SEQ {
|
||||
fit,operation = "split-elf";
|
||||
description = "ARM Trusted Firmware";
|
||||
type = "firmware";
|
||||
arch = "arm64";
|
||||
os = "arm-trusted-firmware";
|
||||
compression = "none";
|
||||
fit,load;
|
||||
fit,entry;
|
||||
fit,data;
|
||||
|
||||
atf-bl31 {
|
||||
};
|
||||
};
|
||||
@tee-SEQ {
|
||||
fit,operation = "split-elf";
|
||||
description = "TEE";
|
||||
type = "tee";
|
||||
arch = "arm64";
|
||||
os = "tee";
|
||||
compression = "none";
|
||||
fit,load;
|
||||
fit,entry;
|
||||
fit,data;
|
||||
|
||||
tee-os {
|
||||
optional;
|
||||
};
|
||||
};
|
||||
|
||||
@fdt-SEQ {
|
||||
description = "fdt-NAME";
|
||||
compression = "none";
|
||||
type = "flat_dt";
|
||||
};
|
||||
};
|
||||
|
||||
configurations {
|
||||
default = "@config-DEFAULT-SEQ";
|
||||
@config-SEQ {
|
||||
description = "NAME.dtb";
|
||||
fdt = "fdt-SEQ";
|
||||
firmware = "u-boot";
|
||||
fit,loadables;
|
||||
};
|
||||
};
|
||||
};
|
||||
#else
|
||||
u-boot-img {
|
||||
#endif
|
||||
offset = <CONFIG_SPL_PAD_TO>;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_SPI_IMAGE
|
||||
|
@ -59,7 +124,8 @@
|
|||
};
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
blob {
|
||||
fit {
|
||||
type = "blob";
|
||||
filename = "u-boot.itb";
|
||||
#else
|
||||
u-boot-img {
|
||||
|
@ -68,6 +134,6 @@
|
|||
offset = <CONFIG_SYS_SPI_U_BOOT_OFFS>;
|
||||
};
|
||||
};
|
||||
#endif
|
||||
#endif /* CONFIG_ROCKCHIP_SPI_IMAGE */
|
||||
};
|
||||
#endif
|
||||
#endif /* CONFIG_SPL */
|
||||
|
|
|
@ -248,7 +248,7 @@ static inline char *s5p_get_cpu_name(void)
|
|||
}
|
||||
|
||||
#define IS_SAMSUNG_TYPE(type, id) \
|
||||
static inline int __attribute__((no_instrument_function)) cpu_is_##type(void) \
|
||||
static inline int notrace cpu_is_##type(void) \
|
||||
{ \
|
||||
return (s5p_cpu_id >> 12) == id; \
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ IS_SAMSUNG_TYPE(exynos4, 0x4)
|
|||
IS_SAMSUNG_TYPE(exynos5, 0x5)
|
||||
|
||||
#define IS_EXYNOS_TYPE(type, id) \
|
||||
static inline int __attribute__((no_instrument_function)) \
|
||||
static inline int notrace \
|
||||
proid_is_##type(void) \
|
||||
{ \
|
||||
return s5p_cpu_id == id; \
|
||||
|
@ -272,7 +272,7 @@ IS_EXYNOS_TYPE(exynos5422, 0x5422)
|
|||
#define proid_is_exynos542x() (proid_is_exynos5420() || proid_is_exynos5422())
|
||||
|
||||
#define SAMSUNG_BASE(device, base) \
|
||||
static inline unsigned long __attribute__((no_instrument_function)) \
|
||||
static inline unsigned long notrace \
|
||||
samsung_get_base_##device(void) \
|
||||
{ \
|
||||
if (cpu_is_exynos4()) { \
|
||||
|
|
|
@ -1,267 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# A script to generate FIT image source for rockchip boards
|
||||
# with ARM Trusted Firmware
|
||||
# and multiple device trees (given on the command line)
|
||||
#
|
||||
# usage: $0 <dt_name> [<dt_name> [<dt_name] ...]
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import getopt
|
||||
import logging
|
||||
import struct
|
||||
|
||||
DT_HEADER = """
|
||||
/*
|
||||
* This is a generated file.
|
||||
*/
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "FIT image for U-Boot with bl31 (TF-A)";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
"""
|
||||
|
||||
DT_UBOOT = """
|
||||
uboot {
|
||||
description = "U-Boot (64-bit)";
|
||||
data = /incbin/("u-boot-nodtb.bin");
|
||||
type = "standalone";
|
||||
os = "U-Boot";
|
||||
arch = "arm64";
|
||||
compression = "none";
|
||||
load = <0x%08x>;
|
||||
};
|
||||
|
||||
"""
|
||||
|
||||
DT_IMAGES_NODE_END = """ };
|
||||
|
||||
"""
|
||||
|
||||
DT_END = "};"
|
||||
|
||||
def append_bl31_node(file, atf_index, phy_addr, elf_entry):
|
||||
# Append BL31 DT node to input FIT dts file.
|
||||
data = 'bl31_0x%08x.bin' % phy_addr
|
||||
file.write('\t\tatf_%d {\n' % atf_index)
|
||||
file.write('\t\t\tdescription = \"ARM Trusted Firmware\";\n')
|
||||
file.write('\t\t\tdata = /incbin/("%s");\n' % data)
|
||||
file.write('\t\t\ttype = "firmware";\n')
|
||||
file.write('\t\t\tarch = "arm64";\n')
|
||||
file.write('\t\t\tos = "arm-trusted-firmware";\n')
|
||||
file.write('\t\t\tcompression = "none";\n')
|
||||
file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
|
||||
if atf_index == 1:
|
||||
file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
|
||||
file.write('\t\t};\n')
|
||||
file.write('\n')
|
||||
|
||||
def append_tee_node(file, atf_index, phy_addr, elf_entry):
|
||||
# Append TEE DT node to input FIT dts file.
|
||||
data = 'tee_0x%08x.bin' % phy_addr
|
||||
file.write('\t\tatf_%d {\n' % atf_index)
|
||||
file.write('\t\t\tdescription = \"TEE\";\n')
|
||||
file.write('\t\t\tdata = /incbin/("%s");\n' % data)
|
||||
file.write('\t\t\ttype = "tee";\n')
|
||||
file.write('\t\t\tarch = "arm64";\n')
|
||||
file.write('\t\t\tos = "tee";\n')
|
||||
file.write('\t\t\tcompression = "none";\n')
|
||||
file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
|
||||
file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
|
||||
file.write('\t\t};\n')
|
||||
file.write('\n')
|
||||
|
||||
def append_fdt_node(file, dtbs):
|
||||
# Append FDT nodes.
|
||||
cnt = 1
|
||||
for dtb in dtbs:
|
||||
dtname = os.path.basename(dtb)
|
||||
file.write('\t\tfdt_%d {\n' % cnt)
|
||||
file.write('\t\t\tdescription = "%s";\n' % dtname)
|
||||
file.write('\t\t\tdata = /incbin/("%s");\n' % dtb)
|
||||
file.write('\t\t\ttype = "flat_dt";\n')
|
||||
file.write('\t\t\tcompression = "none";\n')
|
||||
file.write('\t\t};\n')
|
||||
file.write('\n')
|
||||
cnt = cnt + 1
|
||||
|
||||
def append_conf_section(file, cnt, dtname, segments):
|
||||
file.write('\t\tconfig_%d {\n' % cnt)
|
||||
file.write('\t\t\tdescription = "%s";\n' % dtname)
|
||||
file.write('\t\t\tfirmware = "atf_1";\n')
|
||||
file.write('\t\t\tloadables = "uboot"')
|
||||
if segments > 1:
|
||||
file.write(',')
|
||||
for i in range(1, segments):
|
||||
file.write('"atf_%d"' % (i + 1))
|
||||
if i != (segments - 1):
|
||||
file.write(',')
|
||||
else:
|
||||
file.write(';\n')
|
||||
if segments <= 1:
|
||||
file.write(';\n')
|
||||
file.write('\t\t\tfdt = "fdt_%d";\n' % cnt)
|
||||
file.write('\t\t};\n')
|
||||
file.write('\n')
|
||||
|
||||
def append_conf_node(file, dtbs, segments):
|
||||
# Append configeration nodes.
|
||||
cnt = 1
|
||||
file.write('\tconfigurations {\n')
|
||||
file.write('\t\tdefault = "config_1";\n')
|
||||
for dtb in dtbs:
|
||||
dtname = os.path.basename(dtb)
|
||||
append_conf_section(file, cnt, dtname, segments)
|
||||
cnt = cnt + 1
|
||||
file.write('\t};\n')
|
||||
file.write('\n')
|
||||
|
||||
def generate_atf_fit_dts_uboot(fit_file, uboot_file_name):
|
||||
segments = unpack_elf(uboot_file_name)
|
||||
if len(segments) != 1:
|
||||
raise ValueError("Invalid u-boot ELF image '%s'" % uboot_file_name)
|
||||
index, entry, p_paddr, data = segments[0]
|
||||
fit_file.write(DT_UBOOT % p_paddr)
|
||||
|
||||
def generate_atf_fit_dts_bl31(fit_file, bl31_file_name, tee_file_name, dtbs_file_name):
|
||||
segments = unpack_elf(bl31_file_name)
|
||||
for index, entry, paddr, data in segments:
|
||||
append_bl31_node(fit_file, index + 1, paddr, entry)
|
||||
num_segments = len(segments)
|
||||
|
||||
if tee_file_name:
|
||||
tee_segments = unpack_tee_file(tee_file_name)
|
||||
for index, entry, paddr, data in tee_segments:
|
||||
append_tee_node(fit_file, num_segments + index + 1, paddr, entry)
|
||||
num_segments = num_segments + len(tee_segments)
|
||||
|
||||
append_fdt_node(fit_file, dtbs_file_name)
|
||||
fit_file.write(DT_IMAGES_NODE_END)
|
||||
append_conf_node(fit_file, dtbs_file_name, num_segments)
|
||||
|
||||
def generate_atf_fit_dts(fit_file_name, bl31_file_name, tee_file_name, uboot_file_name, dtbs_file_name):
|
||||
# Generate FIT script for ATF image.
|
||||
if fit_file_name != sys.stdout:
|
||||
fit_file = open(fit_file_name, "wb")
|
||||
else:
|
||||
fit_file = sys.stdout
|
||||
|
||||
fit_file.write(DT_HEADER)
|
||||
generate_atf_fit_dts_uboot(fit_file, uboot_file_name)
|
||||
generate_atf_fit_dts_bl31(fit_file, bl31_file_name, tee_file_name, dtbs_file_name)
|
||||
fit_file.write(DT_END)
|
||||
|
||||
if fit_file_name != sys.stdout:
|
||||
fit_file.close()
|
||||
|
||||
def generate_atf_binary(bl31_file_name):
|
||||
for index, entry, paddr, data in unpack_elf(bl31_file_name):
|
||||
file_name = 'bl31_0x%08x.bin' % paddr
|
||||
with open(file_name, "wb") as atf:
|
||||
atf.write(data)
|
||||
|
||||
def generate_tee_binary(tee_file_name):
|
||||
if tee_file_name:
|
||||
for index, entry, paddr, data in unpack_tee_file(tee_file_name):
|
||||
file_name = 'tee_0x%08x.bin' % paddr
|
||||
with open(file_name, "wb") as atf:
|
||||
atf.write(data)
|
||||
|
||||
def unpack_elf(filename):
|
||||
with open(filename, 'rb') as file:
|
||||
elf = file.read()
|
||||
if elf[0:7] != b'\x7fELF\x02\x01\x01' or elf[18:20] != b'\xb7\x00':
|
||||
raise ValueError("Invalid arm64 ELF file '%s'" % filename)
|
||||
|
||||
e_entry, e_phoff = struct.unpack_from('<2Q', elf, 0x18)
|
||||
e_phentsize, e_phnum = struct.unpack_from('<2H', elf, 0x36)
|
||||
segments = []
|
||||
|
||||
for index in range(e_phnum):
|
||||
offset = e_phoff + e_phentsize * index
|
||||
p_type, p_flags, p_offset = struct.unpack_from('<LLQ', elf, offset)
|
||||
if p_type == 1: # PT_LOAD
|
||||
p_paddr, p_filesz = struct.unpack_from('<2Q', elf, offset + 0x18)
|
||||
if p_filesz > 0:
|
||||
p_data = elf[p_offset:p_offset + p_filesz]
|
||||
segments.append((index, e_entry, p_paddr, p_data))
|
||||
return segments
|
||||
|
||||
def unpack_tee_file(filename):
|
||||
if filename.endswith('.elf'):
|
||||
return unpack_elf(filename)
|
||||
with open(filename, 'rb') as file:
|
||||
bin = file.read()
|
||||
segments = []
|
||||
if bin[0:5] == b'OPTE\x01':
|
||||
# OP-TEE v1 format (tee.bin)
|
||||
init_sz, start_hi, start_lo, _, paged_sz = struct.unpack_from('<5I',
|
||||
bin,
|
||||
0x8)
|
||||
if paged_sz != 0:
|
||||
raise ValueError("OP-TEE paged mode not supported")
|
||||
e_entry = (start_hi << 32) + start_lo
|
||||
p_addr = e_entry
|
||||
p_data = bin[0x1c:]
|
||||
if len(p_data) != init_sz:
|
||||
raise ValueError("Invalid file '%s': size mismatch "
|
||||
"(expected %d, have %d)" % (filename, init_sz,
|
||||
len(p_data)))
|
||||
segments.append((0, e_entry, p_addr, p_data))
|
||||
else:
|
||||
raise ValueError("Unknown format for TEE file '%s'" % filename)
|
||||
return segments
|
||||
|
||||
def main():
|
||||
uboot_elf = "./u-boot"
|
||||
fit_its = sys.stdout
|
||||
if "BL31" in os.environ:
|
||||
bl31_elf=os.getenv("BL31");
|
||||
elif os.path.isfile("./bl31.elf"):
|
||||
bl31_elf = "./bl31.elf"
|
||||
else:
|
||||
os.system("echo 'int main(){}' > bl31.c")
|
||||
os.system("${CROSS_COMPILE}gcc -c bl31.c -o bl31.elf")
|
||||
bl31_elf = "./bl31.elf"
|
||||
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
|
||||
logging.warning(' BL31 file bl31.elf NOT found, resulting binary is non-functional')
|
||||
logging.warning(' Please read Building section in doc/README.rockchip')
|
||||
|
||||
if "TEE" in os.environ:
|
||||
tee_file = os.getenv("TEE")
|
||||
elif os.path.isfile("./tee.bin"):
|
||||
tee_file = "./tee.bin"
|
||||
elif os.path.isfile("./tee.elf"):
|
||||
tee_file = "./tee.elf"
|
||||
else:
|
||||
tee_file = ""
|
||||
|
||||
opts, args = getopt.getopt(sys.argv[1:], "o:u:b:t:h")
|
||||
for opt, val in opts:
|
||||
if opt == "-o":
|
||||
fit_its = val
|
||||
elif opt == "-u":
|
||||
uboot_elf = val
|
||||
elif opt == "-b":
|
||||
bl31_elf = val
|
||||
elif opt == "-t":
|
||||
tee_file = val
|
||||
elif opt == "-h":
|
||||
print(__doc__)
|
||||
sys.exit(2)
|
||||
|
||||
dtbs = args
|
||||
|
||||
generate_atf_fit_dts(fit_its, bl31_elf, tee_file, uboot_elf, dtbs)
|
||||
generate_atf_binary(bl31_elf)
|
||||
generate_tee_binary(tee_file)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <bootstage.h>
|
||||
#include <debug_uart.h>
|
||||
#include <dm.h>
|
||||
#include <hang.h>
|
||||
|
@ -70,15 +71,15 @@ void board_init_f(ulong dummy)
|
|||
U_BOOT_TIME ")\n");
|
||||
#endif
|
||||
#endif
|
||||
/* Init secure timer */
|
||||
rockchip_stimer_init();
|
||||
|
||||
ret = spl_early_init();
|
||||
if (ret) {
|
||||
debug("spl_early_init() failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
/* Init secure timer */
|
||||
rockchip_stimer_init();
|
||||
|
||||
/* Init ARM arch timer */
|
||||
if (IS_ENABLED(CONFIG_SYS_ARCH_TIMER))
|
||||
timer_init();
|
||||
|
@ -93,6 +94,15 @@ void board_init_f(ulong dummy)
|
|||
int board_return_to_bootrom(struct spl_image_info *spl_image,
|
||||
struct spl_boot_device *bootdev)
|
||||
{
|
||||
#ifdef CONFIG_BOOTSTAGE_STASH
|
||||
int ret;
|
||||
|
||||
bootstage_mark_name(BOOTSTAGE_ID_END_TPL, "end tpl");
|
||||
ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
|
||||
CONFIG_BOOTSTAGE_STASH_SIZE);
|
||||
if (ret)
|
||||
debug("Failed to stash bootstage: err=%d\n", ret);
|
||||
#endif
|
||||
back_to_bootrom(BROM_BOOT_NEXTSTAGE);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -137,7 +137,7 @@ struct arch_global_data {
|
|||
|
||||
#define DECLARE_GLOBAL_DATA_PTR extern struct global_data *global_data_ptr
|
||||
# else
|
||||
static inline __attribute__((no_instrument_function)) gd_t *get_fs_gd_ptr(void)
|
||||
static inline notrace gd_t *get_fs_gd_ptr(void)
|
||||
{
|
||||
gd_t *gd_ptr;
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ static inline unsigned long long native_read_tscp(unsigned int *aux)
|
|||
#define EAX_EDX_RET(val, low, high) "=A" (val)
|
||||
#endif
|
||||
|
||||
static inline __attribute__((no_instrument_function))
|
||||
static inline notrace
|
||||
unsigned long long native_read_msr(unsigned int msr)
|
||||
{
|
||||
DECLARE_ARGS(val, low, high);
|
||||
|
|
|
@ -108,7 +108,7 @@ void board_init_f_r(void) __attribute__ ((noreturn));
|
|||
int arch_misc_init(void);
|
||||
|
||||
/* Read the time stamp counter */
|
||||
static inline __attribute__((no_instrument_function)) uint64_t rdtsc(void)
|
||||
static inline notrace uint64_t rdtsc(void)
|
||||
{
|
||||
uint32_t high, low;
|
||||
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
|
||||
|
|
|
@ -282,12 +282,11 @@ config SPL_FIT_SOURCE
|
|||
config USE_SPL_FIT_GENERATOR
|
||||
bool "Use a script to generate the .its script"
|
||||
depends on SPL_FIT
|
||||
default y if !ARCH_SUNXI && !RISCV
|
||||
default y if SPL_FIT && ARCH_ZYNQMP
|
||||
|
||||
config SPL_FIT_GENERATOR
|
||||
string ".its file generator script for U-Boot FIT image"
|
||||
depends on USE_SPL_FIT_GENERATOR
|
||||
default "arch/arm/mach-rockchip/make_fit_atf.py" if SPL_LOAD_FIT && ARCH_ROCKCHIP
|
||||
default "arch/arm/mach-zynqmp/mkimage_fit_atf.sh" if SPL_LOAD_FIT && ARCH_ZYNQMP
|
||||
help
|
||||
Specifies a (platform specific) script file to generate the FIT
|
||||
|
|
|
@ -599,6 +599,7 @@ static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node,
|
|||
debug("Ignoring compatible = %s property\n",
|
||||
compatible);
|
||||
}
|
||||
return 0;
|
||||
|
||||
ret = fpga_load(devnum, (void *)fpga_image->load_addr,
|
||||
fpga_image->size, BIT_FULL, flags);
|
||||
|
|
|
@ -179,3 +179,4 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0451
|
|||
CONFIG_USB_GADGET_PRODUCT_NUM=0x6162
|
||||
CONFIG_USB_GADGET_DOWNLOAD=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_PHANDLE_CHECK_SEQ=y
|
||||
|
|
|
@ -120,3 +120,4 @@ CONFIG_WDT=y
|
|||
CONFIG_SHA384=y
|
||||
CONFIG_HEXDUMP=y
|
||||
# CONFIG_EFI_LOADER is not set
|
||||
CONFIG_PHANDLE_CHECK_SEQ=y
|
||||
|
|
|
@ -29,6 +29,7 @@ CONFIG_SILENT_CONSOLE=y
|
|||
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
||||
CONFIG_SPL_PAD_TO=0x7f8000
|
||||
CONFIG_SPL_NO_BSS_LIMIT=y
|
||||
# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
|
||||
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||
CONFIG_SPL_STACK=0xff718000
|
||||
CONFIG_SPL_STACK_R=y
|
||||
|
|
|
@ -9,6 +9,7 @@ CONFIG_ENV_OFFSET=0x3F8000
|
|||
CONFIG_DEFAULT_DEVICE_TREE="rk3399-rockpro64"
|
||||
CONFIG_ROCKCHIP_RK3399=y
|
||||
CONFIG_TARGET_ROCKPRO64_RK3399=y
|
||||
CONFIG_BOOTSTAGE_STASH_ADDR=0xff8e0000
|
||||
CONFIG_DEBUG_UART_BASE=0xFF1A0000
|
||||
CONFIG_DEBUG_UART_CLOCK=24000000
|
||||
CONFIG_SPL_SPI_FLASH_SUPPORT=y
|
||||
|
@ -17,6 +18,12 @@ CONFIG_SYS_LOAD_ADDR=0x800800
|
|||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
|
||||
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000
|
||||
CONFIG_BOOTSTAGE=y
|
||||
CONFIG_SPL_BOOTSTAGE=y
|
||||
CONFIG_TPL_BOOTSTAGE=y
|
||||
CONFIG_BOOTSTAGE_REPORT=y
|
||||
CONFIG_SPL_BOOTSTAGE_RECORD_COUNT=10
|
||||
CONFIG_BOOTSTAGE_STASH=y
|
||||
CONFIG_USE_PREBOOT=y
|
||||
CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-rockpro64.dtb"
|
||||
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
||||
|
@ -40,6 +47,7 @@ CONFIG_CMD_PCI=y
|
|||
CONFIG_CMD_USB=y
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_CMD_BOOTSTAGE=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
|
||||
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
||||
|
|
|
@ -79,3 +79,4 @@ CONFIG_TIMER=y
|
|||
CONFIG_MCHP_PIT64B_TIMER=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
# CONFIG_EFI_LOADER_HII is not set
|
||||
CONFIG_PHANDLE_CHECK_SEQ=y
|
||||
|
|
|
@ -79,3 +79,4 @@ CONFIG_TIMER=y
|
|||
CONFIG_MCHP_PIT64B_TIMER=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
# CONFIG_EFI_LOADER_HII is not set
|
||||
CONFIG_PHANDLE_CHECK_SEQ=y
|
||||
|
|
|
@ -185,7 +185,7 @@ this produces sensible results for your board. Suitable sources for
|
|||
this timer include high resolution timers, PWMs or profile timers if
|
||||
available. Most modern SOCs have a suitable timer for this. Make sure
|
||||
that you mark this timer (and anything it calls) with
|
||||
__attribute__((no_instrument_function)) so that the trace library can
|
||||
notrace so that the trace library can
|
||||
use it without causing an infinite loop.
|
||||
|
||||
|
||||
|
|
|
@ -403,13 +403,6 @@ static int __maybe_unused pinctrl_post_bind(struct udevice *dev)
|
|||
{
|
||||
const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
|
||||
|
||||
/*
|
||||
* Make sure that the pinctrl driver gets probed after binding
|
||||
* as some pinctrl drivers also register the GPIO driver during
|
||||
* probe, and if they are not probed GPIO-s are not registered.
|
||||
*/
|
||||
dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
|
||||
|
||||
if (!ops) {
|
||||
dev_dbg(dev, "ops is not set. Do not bind.\n");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -554,15 +554,6 @@ uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
|
|||
*/
|
||||
int fdtdec_get_is_enabled(const void *blob, int node);
|
||||
|
||||
/**
|
||||
* Make sure we have a valid fdt available to control U-Boot.
|
||||
*
|
||||
* If not, a message is printed to the console if the console is ready.
|
||||
*
|
||||
* Return: 0 if all ok, -1 if not
|
||||
*/
|
||||
int fdtdec_prepare_fdt(void);
|
||||
|
||||
/**
|
||||
* Checks that we have a valid fdt available to control U-Boot.
|
||||
|
||||
|
|
27
lib/Kconfig
27
lib/Kconfig
|
@ -316,7 +316,7 @@ config BITREVERSE
|
|||
config TRACE
|
||||
bool "Support for tracing of function calls and timing"
|
||||
imply CMD_TRACE
|
||||
select TIMER_EARLY
|
||||
imply TIMER_EARLY
|
||||
help
|
||||
Enables function tracing within U-Boot. This allows recording of call
|
||||
traces including timing information. The command can write data to
|
||||
|
@ -422,6 +422,7 @@ config TPM
|
|||
config SPL_TPM
|
||||
bool "Trusted Platform Module (TPM) Support in SPL"
|
||||
depends on SPL_DM
|
||||
imply SPL_CRC8
|
||||
help
|
||||
This enables support for TPMs which can be used to provide security
|
||||
features for your board. The TPM can be connected via LPC or I2C
|
||||
|
@ -617,6 +618,23 @@ config SPL_MD5
|
|||
security applications, but it can be useful for providing a quick
|
||||
checksum of a block of data.
|
||||
|
||||
config CRC8
|
||||
def_bool y
|
||||
help
|
||||
Enables CRC8 support in U-Boot. This is normally required. CRC8 is
|
||||
a simple and fast checksumming algorithm which does a bytewise
|
||||
checksum with feedback to produce an 8-bit result. The code is small
|
||||
and it does not require a lookup table (unlike CRC32).
|
||||
|
||||
config SPL_CRC8
|
||||
bool "Support CRC8 in SPL"
|
||||
depends on SPL
|
||||
help
|
||||
Enables CRC8 support in SPL. This is not normally required. CRC8 is
|
||||
a simple and fast checksumming algorithm which does a bytewise
|
||||
checksum with feedback to produce an 8-bit result. The code is small
|
||||
and it does not require a lookup table (unlike CRC32).
|
||||
|
||||
config CRC32
|
||||
def_bool y
|
||||
help
|
||||
|
@ -1042,6 +1060,13 @@ config LMB_RESERVED_REGIONS
|
|||
Define the number of supported reserved regions in the library logical
|
||||
memory blocks.
|
||||
|
||||
config PHANDLE_CHECK_SEQ
|
||||
bool "Enable phandle check while getting sequence number"
|
||||
help
|
||||
When there are multiple device tree nodes with same name,
|
||||
enable this config option to distinguish them using
|
||||
phandles in fdtdec_get_alias_seq() function.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "FWU Multi Bank Updates"
|
||||
|
|
|
@ -57,12 +57,13 @@ endif
|
|||
|
||||
obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-common.o
|
||||
ifeq ($(CONFIG_$(SPL_TPL_)TPM),y)
|
||||
obj-y += crc8.o
|
||||
obj-$(CONFIG_TPM) += tpm_api.o
|
||||
obj-$(CONFIG_TPM_V1) += tpm-v1.o
|
||||
obj-$(CONFIG_TPM_V2) += tpm-v2.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_$(SPL_TPL_)CRC8) += crc8.o
|
||||
|
||||
obj-y += crypto/
|
||||
|
||||
obj-$(CONFIG_$(SPL_TPL_)GENERATE_ACPI_TABLE) += acpi/
|
||||
|
|
|
@ -100,7 +100,7 @@ void *memset(void *s, int c, size_t n)
|
|||
* func_ptr: Pointer to function being entered
|
||||
* caller: Pointer to function which called this function
|
||||
*/
|
||||
void __attribute__((no_instrument_function))
|
||||
void notrace
|
||||
__cyg_profile_func_enter(void *func_ptr, void *caller)
|
||||
{
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ __cyg_profile_func_enter(void *func_ptr, void *caller)
|
|||
* func_ptr: Pointer to function being entered
|
||||
* caller: Pointer to function which called this function
|
||||
*/
|
||||
void __attribute__((no_instrument_function))
|
||||
void notrace
|
||||
__cyg_profile_func_exit(void *func_ptr, void *caller)
|
||||
{
|
||||
}
|
||||
|
|
92
lib/fdtdec.c
92
lib/fdtdec.c
|
@ -13,6 +13,7 @@
|
|||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <net.h>
|
||||
#include <spl.h>
|
||||
#include <env.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
|
@ -518,8 +519,11 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
|
|||
* Adding an extra check to distinguish DT nodes with
|
||||
* same name
|
||||
*/
|
||||
if (offset != fdt_path_offset(blob, prop))
|
||||
continue;
|
||||
if (IS_ENABLED(CONFIG_PHANDLE_CHECK_SEQ)) {
|
||||
if (fdt_get_phandle(blob, offset) !=
|
||||
fdt_get_phandle(blob, fdt_path_offset(blob, prop)))
|
||||
continue;
|
||||
}
|
||||
|
||||
val = trailing_strtol(name);
|
||||
if (val != -1) {
|
||||
|
@ -586,6 +590,34 @@ int fdtdec_get_chosen_node(const void *blob, const char *name)
|
|||
return fdt_path_offset(blob, prop);
|
||||
}
|
||||
|
||||
/**
|
||||
* fdtdec_prepare_fdt() - Check we have a valid fdt available to control U-Boot
|
||||
*
|
||||
* @blob: Blob to check
|
||||
*
|
||||
* If not, a message is printed to the console if the console is ready.
|
||||
*
|
||||
* Return: 0 if all ok, -ENOENT if not
|
||||
*/
|
||||
static int fdtdec_prepare_fdt(const void *blob)
|
||||
{
|
||||
if (!blob || ((uintptr_t)blob & 3) || fdt_check_header(blob)) {
|
||||
if (spl_phase() <= PHASE_SPL) {
|
||||
puts("Missing DTB\n");
|
||||
} else {
|
||||
printf("No valid device tree binary found at %p\n",
|
||||
blob);
|
||||
if (_DEBUG && blob) {
|
||||
printf("fdt_blob=%p\n", blob);
|
||||
print_buffer((ulong)blob, blob, 4, 32, 0);
|
||||
}
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdtdec_check_fdt(void)
|
||||
{
|
||||
/*
|
||||
|
@ -594,34 +626,7 @@ int fdtdec_check_fdt(void)
|
|||
* FDT (prior to console ready) will need to make their own
|
||||
* arrangements and do their own checks.
|
||||
*/
|
||||
assert(!fdtdec_prepare_fdt());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is a little odd in that it accesses global data. At some
|
||||
* point if the architecture board.c files merge this will make more sense.
|
||||
* Even now, it is common code.
|
||||
*/
|
||||
int fdtdec_prepare_fdt(void)
|
||||
{
|
||||
if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
|
||||
fdt_check_header(gd->fdt_blob)) {
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
puts("Missing DTB\n");
|
||||
#else
|
||||
printf("No valid device tree binary found at %p\n",
|
||||
gd->fdt_blob);
|
||||
# ifdef DEBUG
|
||||
if (gd->fdt_blob) {
|
||||
printf("fdt_blob=%p\n", gd->fdt_blob);
|
||||
print_buffer((ulong)gd->fdt_blob, gd->fdt_blob, 4,
|
||||
32, 0);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
assert(!fdtdec_prepare_fdt(gd->fdt_blob));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1229,6 +1234,29 @@ static void *fdt_find_separate(void)
|
|||
#else
|
||||
/* FDT is at end of image */
|
||||
fdt_blob = (ulong *)&_end;
|
||||
|
||||
if (_DEBUG && !fdtdec_prepare_fdt(fdt_blob)) {
|
||||
int stack_ptr;
|
||||
const void *top = fdt_blob + fdt_totalsize(fdt_blob);
|
||||
|
||||
/*
|
||||
* Perform a sanity check on the memory layout. If this fails,
|
||||
* it indicates that the device tree is positioned above the
|
||||
* global data pointer or the stack pointer. This should not
|
||||
* happen.
|
||||
*
|
||||
* If this fails, check that SYS_INIT_SP_ADDR has enough space
|
||||
* below it for SYS_MALLOC_F_LEN and global_data, as well as the
|
||||
* stack, without overwriting the device tree or U-Boot itself.
|
||||
* Since the device tree is sitting at _end (the start of the
|
||||
* BSS region), we need the top of the device tree to be below
|
||||
* any memory allocated by board_init_f_alloc_reserve().
|
||||
*/
|
||||
if (top > (void *)gd || top > (void *)&stack_ptr) {
|
||||
printf("FDT %p gd %p\n", fdt_blob, gd);
|
||||
panic("FDT overlap");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return fdt_blob;
|
||||
|
@ -1666,7 +1694,7 @@ int fdtdec_setup(void)
|
|||
if (CONFIG_IS_ENABLED(MULTI_DTB_FIT))
|
||||
setup_multi_dtb_fit();
|
||||
|
||||
ret = fdtdec_prepare_fdt();
|
||||
ret = fdtdec_prepare_fdt(gd->fdt_blob);
|
||||
if (!ret)
|
||||
ret = fdtdec_board_setup(gd->fdt_blob);
|
||||
oftree_reset();
|
||||
|
@ -1698,7 +1726,7 @@ int fdtdec_resetup(int *rescan)
|
|||
|
||||
*rescan = 1;
|
||||
gd->fdt_blob = fdt_blob;
|
||||
return fdtdec_prepare_fdt();
|
||||
return fdtdec_prepare_fdt(fdt_blob);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
29
lib/trace.c
29
lib/trace.c
|
@ -40,7 +40,8 @@ struct trace_hdr {
|
|||
int max_depth;
|
||||
};
|
||||
|
||||
static struct trace_hdr *hdr; /* Pointer to start of trace buffer */
|
||||
/* Pointer to start of trace buffer */
|
||||
static struct trace_hdr *hdr __section(".data");
|
||||
|
||||
static inline uintptr_t __attribute__((no_instrument_function))
|
||||
func_ptr_to_num(void *func_ptr)
|
||||
|
@ -68,7 +69,7 @@ static volatile gd_t *trace_gd;
|
|||
/**
|
||||
* trace_save_gd() - save the value of the gd register
|
||||
*/
|
||||
static void __attribute__((no_instrument_function)) trace_save_gd(void)
|
||||
static void notrace trace_save_gd(void)
|
||||
{
|
||||
trace_gd = gd;
|
||||
}
|
||||
|
@ -81,7 +82,7 @@ static void __attribute__((no_instrument_function)) trace_save_gd(void)
|
|||
* have to set the gd register to the U-Boot value when entering a trace
|
||||
* point and set it back to the application value when exiting the trace point.
|
||||
*/
|
||||
static void __attribute__((no_instrument_function)) trace_swap_gd(void)
|
||||
static void notrace trace_swap_gd(void)
|
||||
{
|
||||
volatile gd_t *temp_gd = trace_gd;
|
||||
|
||||
|
@ -91,18 +92,17 @@ static void __attribute__((no_instrument_function)) trace_swap_gd(void)
|
|||
|
||||
#else
|
||||
|
||||
static void __attribute__((no_instrument_function)) trace_save_gd(void)
|
||||
static void notrace trace_save_gd(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void __attribute__((no_instrument_function)) trace_swap_gd(void)
|
||||
static void notrace trace_swap_gd(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void __attribute__((no_instrument_function)) add_ftrace(void *func_ptr,
|
||||
void *caller, ulong flags)
|
||||
static void notrace add_ftrace(void *func_ptr, void *caller, ulong flags)
|
||||
{
|
||||
if (hdr->depth > hdr->depth_limit) {
|
||||
hdr->ftrace_too_deep_count++;
|
||||
|
@ -118,7 +118,7 @@ static void __attribute__((no_instrument_function)) add_ftrace(void *func_ptr,
|
|||
hdr->ftrace_count++;
|
||||
}
|
||||
|
||||
static void __attribute__((no_instrument_function)) add_textbase(void)
|
||||
static void notrace add_textbase(void)
|
||||
{
|
||||
if (hdr->ftrace_count < hdr->ftrace_size) {
|
||||
struct trace_call *rec = &hdr->ftrace[hdr->ftrace_count];
|
||||
|
@ -139,8 +139,7 @@ static void __attribute__((no_instrument_function)) add_textbase(void)
|
|||
* @func_ptr: pointer to function being entered
|
||||
* @caller: pointer to function which called this function
|
||||
*/
|
||||
void __attribute__((no_instrument_function)) __cyg_profile_func_enter(
|
||||
void *func_ptr, void *caller)
|
||||
void notrace __cyg_profile_func_enter(void *func_ptr, void *caller)
|
||||
{
|
||||
if (trace_enabled) {
|
||||
int func;
|
||||
|
@ -167,8 +166,7 @@ void __attribute__((no_instrument_function)) __cyg_profile_func_enter(
|
|||
* @func_ptr: pointer to function being entered
|
||||
* @caller: pointer to function which called this function
|
||||
*/
|
||||
void __attribute__((no_instrument_function)) __cyg_profile_func_exit(
|
||||
void *func_ptr, void *caller)
|
||||
void notrace __cyg_profile_func_exit(void *func_ptr, void *caller)
|
||||
{
|
||||
if (trace_enabled) {
|
||||
trace_swap_gd();
|
||||
|
@ -327,7 +325,7 @@ void trace_print_stats(void)
|
|||
puts(" calls not traced due to depth\n");
|
||||
}
|
||||
|
||||
void __attribute__((no_instrument_function)) trace_set_enabled(int enabled)
|
||||
void notrace trace_set_enabled(int enabled)
|
||||
{
|
||||
trace_enabled = enabled != 0;
|
||||
}
|
||||
|
@ -339,8 +337,7 @@ void __attribute__((no_instrument_function)) trace_set_enabled(int enabled)
|
|||
* @buff_size: Size of trace buffer
|
||||
* Return: 0 if ok
|
||||
*/
|
||||
int __attribute__((no_instrument_function)) trace_init(void *buff,
|
||||
size_t buff_size)
|
||||
int notrace trace_init(void *buff, size_t buff_size)
|
||||
{
|
||||
ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
|
||||
size_t needed;
|
||||
|
@ -404,7 +401,7 @@ int __attribute__((no_instrument_function)) trace_init(void *buff,
|
|||
*
|
||||
* Return: 0 if ok, -ENOSPC if not enough memory is available
|
||||
*/
|
||||
int __attribute__((no_instrument_function)) trace_early_init(void)
|
||||
int notrace trace_early_init(void)
|
||||
{
|
||||
ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
|
||||
size_t buff_size = CONFIG_TRACE_EARLY_SIZE;
|
||||
|
|
|
@ -487,6 +487,14 @@ For x86 devices (with the end-at-4gb property) this base address is not added
|
|||
since it is assumed that images are XIP and the offsets already include the
|
||||
address.
|
||||
|
||||
While U-Boot's symbol updating is handled automatically by the u-boot-spl
|
||||
entry type (and others), it is possible to use this feature with any blob. To
|
||||
do this, add a `write-symbols` (boolean) property to the node, set the ELF
|
||||
filename using `elf-filename` and set 'elf-base-sym' to the base symbol for the
|
||||
start of the binary image (this defaults to `__image_copy_start` which is what
|
||||
U-Boot uses). See `testBlobSymbol()` for an example.
|
||||
|
||||
.. _binman_fdt:
|
||||
|
||||
Access to binman entry offsets at run time (fdt)
|
||||
------------------------------------------------
|
||||
|
@ -689,6 +697,15 @@ no-expanded:
|
|||
`no-expanded` property disables this just for a single entry. Put the
|
||||
`no-expanded` boolean property in the node to select this behaviour.
|
||||
|
||||
optional:
|
||||
External blobs are normally required to be present for the image to be
|
||||
built (but see `External blobs`_). This properly allows an entry to be
|
||||
optional, so that when it is cannot be found, this problem is ignored and
|
||||
an empty file is used for this blob. This should be used only when the blob
|
||||
is entirely optional and is not needed for correct operation of the image.
|
||||
Note that missing, optional blobs do not produce a non-zero exit code from
|
||||
binman, although it does show a warning about the missing external blob.
|
||||
|
||||
The attributes supported for images and sections are described below. Several
|
||||
are similar to those for entries.
|
||||
|
||||
|
@ -782,6 +799,37 @@ align-default:
|
|||
symlink:
|
||||
Adds a symlink to the image with string given in the symlink property.
|
||||
|
||||
overlap:
|
||||
Indicates that this entry overlaps with others in the same section. These
|
||||
entries should appear at the end of the section. Overlapping entries are not
|
||||
packed with other entries, but their contents are written over other entries
|
||||
in the section. Overlapping entries must have an explicit offset and size.
|
||||
|
||||
write-symbols:
|
||||
Indicates that the blob should be updated with symbol values calculated by
|
||||
binman. This is automatic for certain entry types, e.g. `u-boot-spl`. See
|
||||
binman_syms_ for more information.
|
||||
|
||||
elf-filename:
|
||||
Sets the file name of a blob's associated ELF file. For example, if the
|
||||
blob is `zephyr.bin` then the ELF file may be `zephyr.elf`. This allows
|
||||
binman to locate symbols and understand the structure of the blob. See
|
||||
binman_syms_ for more information.
|
||||
|
||||
elf-base-sym:
|
||||
Sets the name of the ELF symbol that points to the start of a blob. For
|
||||
U-Boot this is `__image_copy_start` and that is the default used by binman
|
||||
if this property is missing. For other projects, a difference symbol may be
|
||||
needed. Add this symbol to the properties for the blob so that symbols can
|
||||
be read correctly. See binman_syms_ for more information.
|
||||
|
||||
offset-from-elf:
|
||||
Sets the offset of an entry based on a symbol value in an another entry.
|
||||
The format is <&phandle>, "sym_name", <offset> where phandle is the entry
|
||||
containing the blob (with associated ELF file providing symbols), <sym_name>
|
||||
is the symbol to lookup (relative to elf-base-sym) and <offset> is an offset
|
||||
to add to that value.
|
||||
|
||||
Examples of the above options can be found in the tests. See the
|
||||
tools/binman/test directory.
|
||||
|
||||
|
@ -836,6 +884,11 @@ name-prefix:
|
|||
renamed to 'ro-u-boot' and 'rw-u-boot'. This can be useful to
|
||||
distinguish binaries with otherwise identical names.
|
||||
|
||||
filename:
|
||||
This allows the contents of the section to be written to a file in the
|
||||
output directory. This can sometimes be useful to use the data in one
|
||||
section in different image, since there is currently no way to share data
|
||||
beteen images other than through files.
|
||||
|
||||
Image Properties
|
||||
----------------
|
||||
|
@ -1007,6 +1060,28 @@ For the BSS case, a 'spl-bss-pad' entry arg controls whether it is present. All
|
|||
entry args are provided by the U-Boot Makefile.
|
||||
|
||||
|
||||
Optional entries
|
||||
----------------
|
||||
|
||||
Some entries need to exist only if certain conditions are met. For example, an
|
||||
entry may want to appear in the image only if a file has a particular format.
|
||||
Obviously the entry must exist in the image description for it to be processed
|
||||
at all, so a way needs to be found to have the entry remove itself.
|
||||
|
||||
To handle this, when entry.ObtainContents() is called, the entry can call
|
||||
entry.mark_absent() to mark itself as absent, passing a suitable message as the
|
||||
reason.
|
||||
|
||||
Any absent entries are dropped immediately after ObtainContents() has been
|
||||
called on all entries.
|
||||
|
||||
It is not possible for an entry to mark itself absent at any other point in the
|
||||
processing. It must happen in the ObtainContents() method.
|
||||
|
||||
The effect is as if the entry had never been present at all, since the image
|
||||
is packed without it and it disappears from the list of entries.
|
||||
|
||||
|
||||
Compression
|
||||
-----------
|
||||
|
||||
|
@ -1683,7 +1758,8 @@ implementation of Pack() is usually sufficient.
|
|||
|
||||
Note: for sections, this also checks that the entries do not overlap, nor extend
|
||||
outside the section. If the section does not have a defined size, the size is
|
||||
set large enough to hold all the entries.
|
||||
set large enough to hold all the entries. For entries that are explicitly marked
|
||||
as overlapping, this check is skipped.
|
||||
|
||||
6. SetImagePos() - sets the image position of every entry. This is the absolute
|
||||
position 'image-pos', as opposed to 'offset' which is relative to the containing
|
||||
|
|
|
@ -552,6 +552,7 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
|
|||
image.SetAllowMissing(allow_missing)
|
||||
image.SetAllowFakeBlob(allow_fake_blobs)
|
||||
image.GetEntryContents()
|
||||
image.drop_absent()
|
||||
image.GetEntryOffsets()
|
||||
|
||||
# We need to pack the entries to figure out where everything
|
||||
|
@ -593,12 +594,14 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
|
|||
image.BuildImage()
|
||||
if write_map:
|
||||
image.WriteMap()
|
||||
|
||||
missing_list = []
|
||||
image.CheckMissing(missing_list)
|
||||
if missing_list:
|
||||
tout.warning("Image '%s' is missing external blobs and is non-functional: %s" %
|
||||
(image.name, ' '.join([e.name for e in missing_list])))
|
||||
_ShowHelpForMissingBlobs(missing_list)
|
||||
|
||||
faked_list = []
|
||||
image.CheckFakedBlobs(faked_list)
|
||||
if faked_list:
|
||||
|
@ -606,6 +609,15 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
|
|||
"Image '%s' has faked external blobs and is non-functional: %s" %
|
||||
(image.name, ' '.join([os.path.basename(e.GetDefaultFilename())
|
||||
for e in faked_list])))
|
||||
|
||||
optional_list = []
|
||||
image.CheckOptional(optional_list)
|
||||
if optional_list:
|
||||
tout.warning(
|
||||
"Image '%s' is missing external blobs but is still functional: %s" %
|
||||
(image.name, ' '.join([e.name for e in optional_list])))
|
||||
_ShowHelpForMissingBlobs(optional_list)
|
||||
|
||||
missing_bintool_list = []
|
||||
image.check_missing_bintools(missing_bintool_list)
|
||||
if missing_bintool_list:
|
||||
|
|
|
@ -210,7 +210,31 @@ def GetPackString(sym, msg):
|
|||
raise ValueError('%s has size %d: only 4 and 8 are supported' %
|
||||
(msg, sym.size))
|
||||
|
||||
def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False):
|
||||
def GetSymbolOffset(elf_fname, sym_name, base_sym=None):
|
||||
"""Read the offset of a symbol compared to base symbol
|
||||
|
||||
This is useful for obtaining the value of a single symbol relative to the
|
||||
base of a binary blob.
|
||||
|
||||
Args:
|
||||
elf_fname: Filename of the ELF file to read
|
||||
sym_name (str): Name of symbol to read
|
||||
base_sym (str): Base symbol to sue to calculate the offset (or None to
|
||||
use '__image_copy_start'
|
||||
|
||||
Returns:
|
||||
int: Offset of the symbol relative to the base symbol
|
||||
"""
|
||||
if not base_sym:
|
||||
base_sym = '__image_copy_start'
|
||||
fname = tools.get_input_filename(elf_fname)
|
||||
syms = GetSymbols(fname, [base_sym, sym_name])
|
||||
base = syms[base_sym].address
|
||||
val = syms[sym_name].address
|
||||
return val - base
|
||||
|
||||
def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False,
|
||||
base_sym=None):
|
||||
"""Replace all symbols in an entry with their correct values
|
||||
|
||||
The entry contents is updated so that values for referenced symbols will be
|
||||
|
@ -223,7 +247,10 @@ def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False):
|
|||
entry
|
||||
entry: Entry to process
|
||||
section: Section which can be used to lookup symbol values
|
||||
base_sym: Base symbol marking the start of the image
|
||||
"""
|
||||
if not base_sym:
|
||||
base_sym = '__image_copy_start'
|
||||
fname = tools.get_input_filename(elf_fname)
|
||||
syms = GetSymbols(fname, ['image', 'binman'])
|
||||
if is_elf:
|
||||
|
@ -243,7 +270,7 @@ def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False):
|
|||
if not syms:
|
||||
tout.debug('LookupAndWriteSymbols: no syms')
|
||||
return
|
||||
base = syms.get('__image_copy_start')
|
||||
base = syms.get(base_sym)
|
||||
if not base and not is_elf:
|
||||
tout.debug('LookupAndWriteSymbols: no base')
|
||||
return
|
||||
|
@ -518,3 +545,18 @@ def read_loadable_segments(data):
|
|||
rend = start + segment['p_filesz']
|
||||
segments.append((i, segment['p_paddr'], data[start:rend]))
|
||||
return segments, entry
|
||||
|
||||
def is_valid(data):
|
||||
"""Check if some binary data is a valid ELF file
|
||||
|
||||
Args:
|
||||
data (bytes): Bytes to check
|
||||
|
||||
Returns:
|
||||
bool: True if a valid Elf file, False if not
|
||||
"""
|
||||
try:
|
||||
DecodeElf(data, 0)
|
||||
return True
|
||||
except ELFError:
|
||||
return False
|
||||
|
|
|
@ -348,6 +348,16 @@ class TestElf(unittest.TestCase):
|
|||
finally:
|
||||
elf.ELF_TOOLS = old_val
|
||||
|
||||
def test_is_valid(self):
|
||||
"""Test is_valid()"""
|
||||
self.assertEqual(False, elf.is_valid(b''))
|
||||
self.assertEqual(False, elf.is_valid(b'1234'))
|
||||
|
||||
fname = self.ElfTestFile('elf_sections')
|
||||
data = tools.read_file(fname)
|
||||
self.assertEqual(True, elf.is_valid(data))
|
||||
self.assertEqual(False, elf.is_valid(data[4:]))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -216,9 +216,9 @@ This is a blob containing a device tree. The contents of the blob are
|
|||
obtained from the list of available device-tree files, managed by the
|
||||
'state' module.
|
||||
|
||||
Additional Properties / Entry arguments:
|
||||
- prepend: Header type to use:
|
||||
length: 32-bit length header
|
||||
Additional attributes:
|
||||
prepend: Header used (e.g. 'length')
|
||||
|
||||
|
||||
|
||||
.. _etype_blob_ext:
|
||||
|
@ -1178,11 +1178,13 @@ Properties / Entry arguments:
|
|||
- multiple-data-files: boolean to tell binman to pass all files as
|
||||
datafiles to mkimage instead of creating a temporary file the result
|
||||
of datafiles concatenation
|
||||
- filename: filename of output binary generated by mkimage
|
||||
|
||||
The data passed to mkimage via the -d flag is collected from subnodes of the
|
||||
mkimage node, e.g.::
|
||||
|
||||
mkimage {
|
||||
filename = "imximage.bin";
|
||||
args = "-n test -T imximage";
|
||||
|
||||
u-boot-spl {
|
||||
|
@ -1190,13 +1192,14 @@ mkimage node, e.g.::
|
|||
};
|
||||
|
||||
This calls mkimage to create an imximage with `u-boot-spl.bin` as the data
|
||||
file, which mkimage being called like this::
|
||||
file, with mkimage being called like this::
|
||||
|
||||
mkimage -d <data_file> -n test -T imximage <output_file>
|
||||
|
||||
The output from mkimage then becomes part of the image produced by
|
||||
binman. If you need to put mulitple things in the data file, you can use
|
||||
a section, or just multiple subnodes like this::
|
||||
binman but also is written into `imximage.bin` file. If you need to put
|
||||
multiple things in the data file, you can use a section, or just multiple
|
||||
subnodes like this::
|
||||
|
||||
mkimage {
|
||||
args = "-n test -T imximage";
|
||||
|
@ -1208,17 +1211,20 @@ a section, or just multiple subnodes like this::
|
|||
};
|
||||
};
|
||||
|
||||
Note that binman places the contents (here SPL and TPL) into a single file
|
||||
and passes that to mkimage using the -d option.
|
||||
|
||||
To pass all datafiles untouched to mkimage::
|
||||
|
||||
mkimage {
|
||||
args = "-n rk3399 -T rkspi";
|
||||
multiple-data-files;
|
||||
args = "-n rk3399 -T rkspi";
|
||||
multiple-data-files;
|
||||
|
||||
u-boot-tpl {
|
||||
};
|
||||
u-boot-tpl {
|
||||
};
|
||||
|
||||
u-boot-spl {
|
||||
};
|
||||
u-boot-spl {
|
||||
};
|
||||
};
|
||||
|
||||
This calls mkimage to create a Rockchip RK3399-specific first stage
|
||||
|
@ -1242,17 +1248,17 @@ the 'data-to-imagename' property::
|
|||
|
||||
mkimage {
|
||||
args = "-T imximage";
|
||||
data-to-imagename';
|
||||
data-to-imagename;
|
||||
|
||||
u-boot-spl {
|
||||
};
|
||||
};
|
||||
|
||||
That will pass the data to mkimage both as the data file (with -d) and as
|
||||
the image name (with -n).
|
||||
the image name (with -n). In both cases, a filename is passed as the
|
||||
argument, with the actual data being in that file.
|
||||
|
||||
|
||||
If need to pass different data in with -n, then use an imagename subnode::
|
||||
If need to pass different data in with -n, then use an `imagename` subnode::
|
||||
|
||||
mkimage {
|
||||
args = "-T imximage";
|
||||
|
@ -1271,6 +1277,20 @@ This will pass in u-boot-spl as the input data and the .cfgout file as the
|
|||
-n data.
|
||||
|
||||
|
||||
|
||||
.. _etype_null:
|
||||
|
||||
Entry: null: An entry which has no contents of its own
|
||||
------------------------------------------------------
|
||||
|
||||
Note that the size property must be set since otherwise this entry does not
|
||||
know how large it should be.
|
||||
|
||||
The contents are set by the containing section, e.g. the section's pad
|
||||
byte.
|
||||
|
||||
|
||||
|
||||
.. _etype_opensbi:
|
||||
|
||||
Entry: opensbi: RISC-V OpenSBI fw_dynamic blob
|
||||
|
@ -1478,6 +1498,10 @@ skip-at-start
|
|||
be written at offset 4 in the image file, since the first 16 bytes are
|
||||
skipped when writing.
|
||||
|
||||
filename
|
||||
filename to write the unpadded section contents to within the output
|
||||
directory (None to skip this).
|
||||
|
||||
Since a section is also an entry, it inherits all the properies of entries
|
||||
too.
|
||||
|
||||
|
@ -1497,12 +1521,47 @@ Entry: tee-os: Entry containing an OP-TEE Trusted OS (TEE) blob
|
|||
|
||||
Properties / Entry arguments:
|
||||
- tee-os-path: Filename of file to read into entry. This is typically
|
||||
called tee-pager.bin
|
||||
called tee.bin or tee.elf
|
||||
|
||||
This entry holds the run-time firmware, typically started by U-Boot SPL.
|
||||
See the U-Boot README for your architecture or board for how to use it. See
|
||||
https://github.com/OP-TEE/optee_os for more information about OP-TEE.
|
||||
|
||||
Note that if the file is in ELF format, it must go in a FIT. In that case,
|
||||
this entry will mark itself as absent, providing the data only through the
|
||||
read_elf_segments() method.
|
||||
|
||||
Marking this entry as absent means that it if is used in the wrong context
|
||||
it can be automatically dropped. Thus it is possible to add an OP-TEE entry
|
||||
like this::
|
||||
|
||||
binman {
|
||||
tee-os {
|
||||
};
|
||||
};
|
||||
|
||||
and pass either an ELF or plain binary in with -a tee-os-path <filename>
|
||||
and have binman do the right thing:
|
||||
|
||||
- include the entry if tee.bin is provided and it does NOT have the v1
|
||||
header
|
||||
- drop it otherwise
|
||||
|
||||
When used within a FIT, we can do::
|
||||
|
||||
binman {
|
||||
fit {
|
||||
tee-os {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
which will split the ELF into separate nodes for each segment, if an ELF
|
||||
file is provided (see :ref:`etype_fit`), or produce a single node if the
|
||||
OP-TEE binary v1 format is provided (see optee_doc_) .
|
||||
|
||||
.. _optee_doc: https://optee.readthedocs.io/en/latest/architecture/core.html#partitioning-of-the-binary
|
||||
|
||||
|
||||
|
||||
.. _etype_text:
|
||||
|
@ -1567,11 +1626,7 @@ This is the U-Boot binary, containing relocation information to allow it
|
|||
to relocate itself at runtime. The binary typically includes a device tree
|
||||
blob at the end of it.
|
||||
|
||||
U-Boot can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (fdt)'
|
||||
|
||||
in the binman README for more information.
|
||||
U-Boot can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
Note that this entry is automatically replaced with u-boot-expanded unless
|
||||
--no-expanded is used or the node has a 'no-expanded' property.
|
||||
|
@ -1701,9 +1756,7 @@ not relocatable so must be loaded to the correct address in SRAM, or written
|
|||
to run from the correct address if direct flash execution is possible (e.g.
|
||||
on x86 devices).
|
||||
|
||||
SPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
@ -1806,9 +1859,7 @@ entry after this one, or use a u-boot-spl entry instead' which normally
|
|||
expands to a section containing u-boot-spl-dtb, u-boot-spl-bss-pad and
|
||||
u-boot-spl-dtb
|
||||
|
||||
SPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
@ -1844,9 +1895,7 @@ loader. Note that SPL is not relocatable so must be loaded to the correct
|
|||
address in SRAM, or written to run from the correct address if direct
|
||||
flash execution is possible (e.g. on x86 devices).
|
||||
|
||||
SPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
@ -1961,9 +2010,7 @@ entry after this one, or use a u-boot-tpl entry instead, which normally
|
|||
expands to a section containing u-boot-tpl-dtb, u-boot-tpl-bss-pad and
|
||||
u-boot-tpl-dtb
|
||||
|
||||
TPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
TPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
@ -2034,6 +2081,128 @@ Entry types that have a part to play in handling microcode:
|
|||
|
||||
|
||||
|
||||
.. _etype_u_boot_vpl:
|
||||
|
||||
Entry: u-boot-vpl: U-Boot VPL binary
|
||||
------------------------------------
|
||||
|
||||
Properties / Entry arguments:
|
||||
- filename: Filename of u-boot-vpl.bin (default 'vpl/u-boot-vpl.bin')
|
||||
|
||||
This is the U-Boot VPL (Verifying Program Loader) binary. This is a small
|
||||
binary which loads before SPL, typically into on-chip SRAM. It is
|
||||
responsible for locating, loading and jumping to SPL, the next-stage
|
||||
loader. Note that VPL is not relocatable so must be loaded to the correct
|
||||
address in SRAM, or written to run from the correct address if direct
|
||||
flash execution is possible (e.g. on x86 devices).
|
||||
|
||||
SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
The ELF file 'vpl/u-boot-vpl' must also be available for this to work, since
|
||||
binman uses that to look up symbols to write into the VPL binary.
|
||||
|
||||
|
||||
|
||||
.. _etype_u_boot_vpl_bss_pad:
|
||||
|
||||
Entry: u-boot-vpl-bss-pad: U-Boot VPL binary padded with a BSS region
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Properties / Entry arguments:
|
||||
None
|
||||
|
||||
This holds the padding added after the VPL binary to cover the BSS (Block
|
||||
Started by Symbol) region. This region holds the various variables used by
|
||||
VPL. It is set to 0 by VPL when it starts up. If you want to append data to
|
||||
the VPL image (such as a device tree file), you must pad out the BSS region
|
||||
to avoid the data overlapping with U-Boot variables. This entry is useful in
|
||||
that case. It automatically pads out the entry size to cover both the code,
|
||||
data and BSS.
|
||||
|
||||
The contents of this entry will a certain number of zero bytes, determined
|
||||
by __bss_size
|
||||
|
||||
The ELF file 'vpl/u-boot-vpl' must also be available for this to work, since
|
||||
binman uses that to look up the BSS address.
|
||||
|
||||
|
||||
|
||||
.. _etype_u_boot_vpl_dtb:
|
||||
|
||||
Entry: u-boot-vpl-dtb: U-Boot VPL device tree
|
||||
---------------------------------------------
|
||||
|
||||
Properties / Entry arguments:
|
||||
- filename: Filename of u-boot.dtb (default 'vpl/u-boot-vpl.dtb')
|
||||
|
||||
This is the VPL device tree, containing configuration information for
|
||||
VPL. VPL needs this to know what devices are present and which drivers
|
||||
to activate.
|
||||
|
||||
|
||||
|
||||
.. _etype_u_boot_vpl_elf:
|
||||
|
||||
Entry: u-boot-vpl-elf: U-Boot VPL ELF image
|
||||
-------------------------------------------
|
||||
|
||||
Properties / Entry arguments:
|
||||
- filename: Filename of VPL u-boot (default 'vpl/u-boot-vpl')
|
||||
|
||||
This is the U-Boot VPL ELF image. It does not include a device tree but can
|
||||
be relocated to any address for execution.
|
||||
|
||||
|
||||
|
||||
.. _etype_u_boot_vpl_expanded:
|
||||
|
||||
Entry: u-boot-vpl-expanded: U-Boot VPL flat binary broken out into its component parts
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
Properties / Entry arguments:
|
||||
- vpl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
|
||||
select)
|
||||
|
||||
This is a section containing the U-Boot binary, BSS padding if needed and a
|
||||
devicetree. Using this entry type automatically creates this section, with
|
||||
the following entries in it:
|
||||
|
||||
u-boot-vpl-nodtb
|
||||
u-boot-vpl-bss-pad
|
||||
u-boot-dtb
|
||||
|
||||
Having the devicetree separate allows binman to update it in the final
|
||||
image, so that the entries positions are provided to the running U-Boot.
|
||||
|
||||
This entry is selected based on the value of the 'vpl-dtb' entryarg. If
|
||||
this is non-empty (and not 'n' or '0') then this expanded entry is selected.
|
||||
|
||||
|
||||
|
||||
.. _etype_u_boot_vpl_nodtb:
|
||||
|
||||
Entry: u-boot-vpl-nodtb: VPL binary without device tree appended
|
||||
----------------------------------------------------------------
|
||||
|
||||
Properties / Entry arguments:
|
||||
- filename: Filename to include (default 'vpl/u-boot-vpl-nodtb.bin')
|
||||
|
||||
This is the U-Boot VPL binary, It does not include a device tree blob at
|
||||
the end of it so may not be able to work without it, assuming VPL needs
|
||||
a device tree to operate on your platform. You can add a u_boot_vpl_dtb
|
||||
entry after this one, or use a u_boot_vpl entry instead, which normally
|
||||
expands to a section containing u-boot-vpl-dtb, u-boot-vpl-bss-pad and
|
||||
u-boot-vpl-dtb
|
||||
|
||||
VPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
The ELF file 'vpl/u-boot-vpl' must also be available for this to work, since
|
||||
binman uses that to look up symbols to write into the VPL binary.
|
||||
|
||||
|
||||
|
||||
.. _etype_u_boot_with_ucode_ptr:
|
||||
|
||||
Entry: u-boot-with-ucode-ptr: U-Boot with embedded microcode pointer
|
||||
|
|
|
@ -73,7 +73,9 @@ class Entry(object):
|
|||
compress: Compression algoithm used (e.g. 'lz4'), 'none' if none
|
||||
orig_offset: Original offset value read from node
|
||||
orig_size: Original size value read from node
|
||||
missing: True if this entry is missing its contents
|
||||
missing: True if this entry is missing its contents. Note that if it is
|
||||
optional, this entry will not appear in the list generated by
|
||||
entry.CheckMissing() since it is considered OK for it to be missing.
|
||||
allow_missing: Allow children of this entry to be missing (used by
|
||||
subclasses such as Entry_section)
|
||||
allow_fake: Allow creating a dummy fake file if the blob file is not
|
||||
|
@ -91,6 +93,12 @@ class Entry(object):
|
|||
file, or is a binary file produced from an ELF file
|
||||
auto_write_symbols (bool): True to write ELF symbols into this entry's
|
||||
contents
|
||||
absent (bool): True if this entry is absent. This can be controlled by
|
||||
the entry itself, allowing it to vanish in certain circumstances.
|
||||
An absent entry is removed during processing so that it does not
|
||||
appear in the map
|
||||
optional (bool): True if this entry contains an optional external blob
|
||||
overlap (bool): True if this entry overlaps with others
|
||||
"""
|
||||
fake_dir = None
|
||||
|
||||
|
@ -133,6 +141,11 @@ class Entry(object):
|
|||
self.comp_bintool = None
|
||||
self.elf_fname = None
|
||||
self.auto_write_symbols = auto_write_symbols
|
||||
self.absent = False
|
||||
self.optional = False
|
||||
self.overlap = False
|
||||
self.elf_base_sym = None
|
||||
self.offset_from_elf = None
|
||||
|
||||
@staticmethod
|
||||
def FindEntryClass(etype, expanded):
|
||||
|
@ -284,9 +297,15 @@ class Entry(object):
|
|||
self.offset_unset = fdt_util.GetBool(self._node, 'offset-unset')
|
||||
self.extend_size = fdt_util.GetBool(self._node, 'extend-size')
|
||||
self.missing_msg = fdt_util.GetString(self._node, 'missing-msg')
|
||||
self.optional = fdt_util.GetBool(self._node, 'optional')
|
||||
self.overlap = fdt_util.GetBool(self._node, 'overlap')
|
||||
if self.overlap:
|
||||
self.required_props += ['offset', 'size']
|
||||
|
||||
# This is only supported by blobs and sections at present
|
||||
self.compress = fdt_util.GetString(self._node, 'compress', 'none')
|
||||
self.offset_from_elf = fdt_util.GetPhandleNameOffset(self._node,
|
||||
'offset-from-elf')
|
||||
|
||||
def GetDefaultFilename(self):
|
||||
return None
|
||||
|
@ -444,7 +463,7 @@ class Entry(object):
|
|||
|
||||
Returns:
|
||||
True if the contents were found, False if another call is needed
|
||||
after the other entries are processed.
|
||||
after the other entries are processed, None if there is no contents
|
||||
"""
|
||||
# No contents by default: subclasses can implement this
|
||||
return True
|
||||
|
@ -483,7 +502,10 @@ class Entry(object):
|
|||
if self.offset_unset:
|
||||
self.Raise('No offset set with offset-unset: should another '
|
||||
'entry provide this correct offset?')
|
||||
self.offset = tools.align(offset, self.align)
|
||||
elif self.offset_from_elf:
|
||||
self.offset = self.lookup_offset()
|
||||
else:
|
||||
self.offset = tools.align(offset, self.align)
|
||||
needed = self.pad_before + self.contents_size + self.pad_after
|
||||
needed = tools.align(needed, self.align_size)
|
||||
size = self.size
|
||||
|
@ -572,7 +594,9 @@ class Entry(object):
|
|||
|
||||
Returns:
|
||||
bytes content of the entry, excluding any padding. If the entry is
|
||||
compressed, the compressed data is returned
|
||||
compressed, the compressed data is returned. If the entry data
|
||||
is not yet available, False can be returned. If the entry data
|
||||
is null, then None is returned.
|
||||
"""
|
||||
self.Detail('GetData: size %s' % to_hex_size(self.data))
|
||||
return self.data
|
||||
|
@ -659,7 +683,7 @@ class Entry(object):
|
|||
# Check if we are writing symbols into an ELF file
|
||||
is_elf = self.GetDefaultFilename() == self.elf_fname
|
||||
elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage(),
|
||||
is_elf)
|
||||
is_elf, self.elf_base_sym)
|
||||
|
||||
def CheckEntries(self):
|
||||
"""Check that the entry offsets are correct
|
||||
|
@ -1034,14 +1058,15 @@ features to produce new behaviours.
|
|||
self.allow_fake = allow_fake
|
||||
|
||||
def CheckMissing(self, missing_list):
|
||||
"""Check if any entries in this section have missing external blobs
|
||||
"""Check if the entry has missing external blobs
|
||||
|
||||
If there are missing blobs, the entries are added to the list
|
||||
If there are missing (non-optional) blobs, the entries are added to the
|
||||
list
|
||||
|
||||
Args:
|
||||
missing_list: List of Entry objects to be added to
|
||||
"""
|
||||
if self.missing:
|
||||
if self.missing and not self.optional:
|
||||
missing_list.append(self)
|
||||
|
||||
def check_fake_fname(self, fname, size=0):
|
||||
|
@ -1080,6 +1105,17 @@ features to produce new behaviours.
|
|||
# This is meaningless for anything other than blobs
|
||||
pass
|
||||
|
||||
def CheckOptional(self, optional_list):
|
||||
"""Check if the entry has missing but optional external blobs
|
||||
|
||||
If there are missing (optional) blobs, the entries are added to the list
|
||||
|
||||
Args:
|
||||
optional_list (list): List of Entry objects to be added to
|
||||
"""
|
||||
if self.missing and self.optional:
|
||||
optional_list.append(self)
|
||||
|
||||
def GetAllowMissing(self):
|
||||
"""Get whether a section allows missing external blobs
|
||||
|
||||
|
@ -1281,3 +1317,31 @@ features to produce new behaviours.
|
|||
not_present.append(prop)
|
||||
if not_present:
|
||||
self.Raise(f"'{self.etype}' entry is missing properties: {' '.join(not_present)}")
|
||||
|
||||
def mark_absent(self, msg):
|
||||
tout.info("Entry '%s' marked absent: %s" % (self._node.path, msg))
|
||||
self.absent = True
|
||||
|
||||
def read_elf_segments(self):
|
||||
"""Read segments from an entry that can generate an ELF file
|
||||
|
||||
Returns:
|
||||
tuple:
|
||||
list of segments, each:
|
||||
int: Segment number (0 = first)
|
||||
int: Start address of segment in memory
|
||||
bytes: Contents of segment
|
||||
int: entry address of ELF file
|
||||
"""
|
||||
return None
|
||||
|
||||
def lookup_offset(self):
|
||||
node, sym_name, offset = self.offset_from_elf
|
||||
entry = self.section.FindEntryByNode(node)
|
||||
if not entry:
|
||||
self.Raise("Cannot find entry for node '%s'" % node.name)
|
||||
if not entry.elf_fname:
|
||||
entry.Raise("Need elf-fname property '%s'" % node.name)
|
||||
val = elf.GetSymbolOffset(entry.elf_fname, sym_name,
|
||||
entry.elf_base_sym)
|
||||
return val + offset
|
||||
|
|
|
@ -63,6 +63,7 @@ class Entry__testing(Entry):
|
|||
'bad-update-contents-twice')
|
||||
self.return_contents_later = fdt_util.GetBool(self._node,
|
||||
'return-contents-later')
|
||||
self.set_to_absent = fdt_util.GetBool(self._node, 'set-to-absent')
|
||||
|
||||
# Set to True when the entry is ready to process the FDT.
|
||||
self.process_fdt_ready = False
|
||||
|
@ -119,6 +120,8 @@ class Entry__testing(Entry):
|
|||
if self.require_bintool_for_contents:
|
||||
if self.bintool_for_contents is None:
|
||||
self.Raise("Required bintool unusable in ObtainContents()")
|
||||
if self.set_to_absent:
|
||||
self.mark_absent('for testing purposes')
|
||||
return True
|
||||
|
||||
def GetOffsets(self):
|
||||
|
|
|
@ -35,11 +35,17 @@ class Entry_blob(Entry):
|
|||
super().__init__(section, etype, node,
|
||||
auto_write_symbols=auto_write_symbols)
|
||||
self._filename = fdt_util.GetString(self._node, 'filename', self.etype)
|
||||
self.elf_fname = fdt_util.GetString(self._node, 'elf-filename',
|
||||
self.elf_fname)
|
||||
self.elf_base_sym = fdt_util.GetString(self._node, 'elf-base-sym')
|
||||
if not self.auto_write_symbols:
|
||||
if fdt_util.GetBool(self._node, 'write-symbols'):
|
||||
self.auto_write_symbols = True
|
||||
|
||||
def ObtainContents(self, fake_size=0):
|
||||
self._filename = self.GetDefaultFilename()
|
||||
self._pathname = tools.get_input_filename(self._filename,
|
||||
self.external and self.section.GetAllowMissing())
|
||||
self.external and (self.optional or self.section.GetAllowMissing()))
|
||||
# Allow the file to be missing
|
||||
if not self._pathname:
|
||||
self._pathname, faked = self.check_fake_fname(self._filename,
|
||||
|
|
|
@ -392,8 +392,8 @@ class Entry_fit(Entry_section):
|
|||
|
||||
_add_entries(self._node, 0, self._node)
|
||||
|
||||
# Keep a copy of all entries, including generator entries, since these
|
||||
# removed from self._entries later.
|
||||
# Keep a copy of all entries, including generator entries, since those
|
||||
# are removed from self._entries later.
|
||||
self._priv_entries = dict(self._entries)
|
||||
|
||||
def BuildSectionData(self, required):
|
||||
|
@ -540,50 +540,50 @@ class Entry_fit(Entry_section):
|
|||
else:
|
||||
self.Raise("Generator node requires 'fit,fdt-list' property")
|
||||
|
||||
def _gen_split_elf(base_node, node, elf_data, missing):
|
||||
def _gen_split_elf(base_node, node, segments, entry_addr):
|
||||
"""Add nodes for the ELF file, one per group of contiguous segments
|
||||
|
||||
Args:
|
||||
base_node (Node): Template node from the binman definition
|
||||
node (Node): Node to replace (in the FIT being built)
|
||||
data (bytes): ELF-format data to process (may be empty)
|
||||
missing (bool): True if any of the data is missing
|
||||
|
||||
segments (list): list of segments, each:
|
||||
int: Segment number (0 = first)
|
||||
int: Start address of segment in memory
|
||||
bytes: Contents of segment
|
||||
entry_addr (int): entry address of ELF file
|
||||
"""
|
||||
# If any pieces are missing, skip this. The missing entries will
|
||||
# show an error
|
||||
if not missing:
|
||||
try:
|
||||
segments, entry = elf.read_loadable_segments(elf_data)
|
||||
except ValueError as exc:
|
||||
self._raise_subnode(node,
|
||||
f'Failed to read ELF file: {str(exc)}')
|
||||
for (seq, start, data) in segments:
|
||||
node_name = node.name[1:].replace('SEQ', str(seq + 1))
|
||||
with fsw.add_node(node_name):
|
||||
loadables.append(node_name)
|
||||
for pname, prop in node.props.items():
|
||||
if not pname.startswith('fit,'):
|
||||
fsw.property(pname, prop.bytes)
|
||||
elif pname == 'fit,load':
|
||||
fsw.property_u32('load', start)
|
||||
elif pname == 'fit,entry':
|
||||
if seq == 0:
|
||||
fsw.property_u32('entry', entry)
|
||||
elif pname == 'fit,data':
|
||||
fsw.property('data', bytes(data))
|
||||
elif pname != 'fit,operation':
|
||||
self._raise_subnode(
|
||||
node, f"Unknown directive '{pname}'")
|
||||
for (seq, start, data) in segments:
|
||||
node_name = node.name[1:].replace('SEQ', str(seq + 1))
|
||||
with fsw.add_node(node_name):
|
||||
loadables.append(node_name)
|
||||
for pname, prop in node.props.items():
|
||||
if not pname.startswith('fit,'):
|
||||
fsw.property(pname, prop.bytes)
|
||||
elif pname == 'fit,load':
|
||||
fsw.property_u32('load', start)
|
||||
elif pname == 'fit,entry':
|
||||
if seq == 0:
|
||||
fsw.property_u32('entry', entry_addr)
|
||||
elif pname == 'fit,data':
|
||||
fsw.property('data', bytes(data))
|
||||
elif pname != 'fit,operation':
|
||||
self._raise_subnode(
|
||||
node, f"Unknown directive '{pname}'")
|
||||
|
||||
def _gen_node(base_node, node, depth, in_images, entry):
|
||||
"""Generate nodes from a template
|
||||
|
||||
This creates one node for each member of self._fdts using the
|
||||
provided template. If a property value contains 'NAME' it is
|
||||
replaced with the filename of the FDT. If a property value contains
|
||||
SEQ it is replaced with the node sequence number, where 1 is the
|
||||
first.
|
||||
This creates one or more nodes depending on the fit,operation being
|
||||
used.
|
||||
|
||||
For OP_GEN_FDT_NODES it creates one node for each member of
|
||||
self._fdts using the provided template. If a property value contains
|
||||
'NAME' it is replaced with the filename of the FDT. If a property
|
||||
value contains SEQ it is replaced with the node sequence number,
|
||||
where 1 is the first.
|
||||
|
||||
For OP_SPLIT_ELF it emits one node for each section in the ELF file.
|
||||
If the file is missing, nothing is generated.
|
||||
|
||||
Args:
|
||||
base_node (Node): Base Node of the FIT (with 'description'
|
||||
|
@ -592,6 +592,8 @@ class Entry_fit(Entry_section):
|
|||
depth (int): Current node depth (0 is the base 'fit' node)
|
||||
in_images (bool): True if this is inside the 'images' node, so
|
||||
that 'data' properties should be generated
|
||||
entry (entry_Section): Entry for the section containing the
|
||||
contents of this node
|
||||
"""
|
||||
oper = self._get_operation(base_node, node)
|
||||
if oper == OP_GEN_FDT_NODES:
|
||||
|
@ -600,13 +602,28 @@ class Entry_fit(Entry_section):
|
|||
# Entry_section.ObtainContents() either returns True or
|
||||
# raises an exception.
|
||||
data = None
|
||||
missing_list = []
|
||||
missing_opt_list = []
|
||||
entry.ObtainContents()
|
||||
entry.Pack(0)
|
||||
data = entry.GetData()
|
||||
entry.CheckMissing(missing_list)
|
||||
entry.CheckMissing(missing_opt_list)
|
||||
entry.CheckOptional(missing_opt_list)
|
||||
|
||||
_gen_split_elf(base_node, node, data, bool(missing_list))
|
||||
# If any pieces are missing, skip this. The missing entries will
|
||||
# show an error
|
||||
if not missing_opt_list:
|
||||
segs = entry.read_elf_segments()
|
||||
if segs:
|
||||
segments, entry_addr = segs
|
||||
else:
|
||||
elf_data = entry.GetData()
|
||||
try:
|
||||
segments, entry_addr = (
|
||||
elf.read_loadable_segments(elf_data))
|
||||
except ValueError as exc:
|
||||
self._raise_subnode(
|
||||
node, f'Failed to read ELF file: {str(exc)}')
|
||||
|
||||
_gen_split_elf(base_node, node, segments, entry_addr)
|
||||
|
||||
def _add_node(base_node, depth, node):
|
||||
"""Add nodes to the output FIT
|
||||
|
@ -638,8 +655,7 @@ class Entry_fit(Entry_section):
|
|||
|
||||
for subnode in node.subnodes:
|
||||
subnode_path = f'{rel_path}/{subnode.name}'
|
||||
if has_images and not (subnode.name.startswith('hash') or
|
||||
subnode.name.startswith('signature')):
|
||||
if has_images and not self.IsSpecialSubnode(subnode):
|
||||
# This subnode is a content node not meant to appear in
|
||||
# the FIT (e.g. "/images/kernel/u-boot"), so don't call
|
||||
# fsw.add_node() or _add_node() for it.
|
||||
|
|
|
@ -57,24 +57,24 @@ class Entry_mkimage(Entry):
|
|||
Note that binman places the contents (here SPL and TPL) into a single file
|
||||
and passes that to mkimage using the -d option.
|
||||
|
||||
To pass all datafiles untouched to mkimage::
|
||||
To pass all datafiles untouched to mkimage::
|
||||
|
||||
mkimage {
|
||||
args = "-n rk3399 -T rkspi";
|
||||
multiple-data-files;
|
||||
mkimage {
|
||||
args = "-n rk3399 -T rkspi";
|
||||
multiple-data-files;
|
||||
|
||||
u-boot-tpl {
|
||||
};
|
||||
u-boot-tpl {
|
||||
};
|
||||
|
||||
u-boot-spl {
|
||||
};
|
||||
};
|
||||
u-boot-spl {
|
||||
};
|
||||
};
|
||||
|
||||
This calls mkimage to create a Rockchip RK3399-specific first stage
|
||||
bootloader, made of TPL+SPL. Since this first stage bootloader requires to
|
||||
align the TPL and SPL but also some weird hacks that is handled by mkimage
|
||||
directly, binman is told to not perform the concatenation of datafiles prior
|
||||
to passing the data to mkimage.
|
||||
This calls mkimage to create a Rockchip RK3399-specific first stage
|
||||
bootloader, made of TPL+SPL. Since this first stage bootloader requires to
|
||||
align the TPL and SPL but also some weird hacks that is handled by mkimage
|
||||
directly, binman is told to not perform the concatenation of datafiles prior
|
||||
to passing the data to mkimage.
|
||||
|
||||
To use CONFIG options in the arguments, use a string list instead, as in
|
||||
this example which also produces four arguments::
|
||||
|
|
25
tools/binman/etype/null.py
Normal file
25
tools/binman/etype/null.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright 2023 Google LLC
|
||||
# Written by Simon Glass <sjg@chromium.org>
|
||||
#
|
||||
|
||||
from binman.entry import Entry
|
||||
from dtoc import fdt_util
|
||||
from patman import tools
|
||||
|
||||
class Entry_null(Entry):
|
||||
"""An entry which has no contents of its own
|
||||
|
||||
Note that the size property must be set since otherwise this entry does not
|
||||
know how large it should be.
|
||||
|
||||
The contents are set by the containing section, e.g. the section's pad
|
||||
byte.
|
||||
"""
|
||||
def __init__(self, section, etype, node):
|
||||
super().__init__(section, etype, node)
|
||||
self.required_props = ['size']
|
||||
|
||||
def ObtainContents(self):
|
||||
# null contents
|
||||
return None
|
|
@ -144,6 +144,10 @@ class Entry_section(Entry):
|
|||
be written at offset 4 in the image file, since the first 16 bytes are
|
||||
skipped when writing.
|
||||
|
||||
filename
|
||||
filename to write the unpadded section contents to within the output
|
||||
directory (None to skip this).
|
||||
|
||||
Since a section is also an entry, it inherits all the properies of entries
|
||||
too.
|
||||
|
||||
|
@ -163,6 +167,18 @@ class Entry_section(Entry):
|
|||
self._skip_at_start = None
|
||||
self._end_4gb = False
|
||||
self._ignore_missing = False
|
||||
self._filename = None
|
||||
|
||||
def IsSpecialSubnode(self, node):
|
||||
"""Check if a node is a special one used by the section itself
|
||||
|
||||
Some notes are used for hashing / signatures and do not add entries to
|
||||
the actual section.
|
||||
|
||||
Returns:
|
||||
bool: True if the node is a special one, else False
|
||||
"""
|
||||
return node.name.startswith('hash') or node.name.startswith('signature')
|
||||
|
||||
def ReadNode(self):
|
||||
"""Read properties from the section node"""
|
||||
|
@ -183,12 +199,14 @@ class Entry_section(Entry):
|
|||
self._skip_at_start = 0
|
||||
self._name_prefix = fdt_util.GetString(self._node, 'name-prefix')
|
||||
self.align_default = fdt_util.GetInt(self._node, 'align-default', 0)
|
||||
self._filename = fdt_util.GetString(self._node, 'filename',
|
||||
self._filename)
|
||||
|
||||
self.ReadEntries()
|
||||
|
||||
def ReadEntries(self):
|
||||
for node in self._node.subnodes:
|
||||
if node.name.startswith('hash') or node.name.startswith('signature'):
|
||||
if self.IsSpecialSubnode(node):
|
||||
continue
|
||||
entry = Entry.Create(self, node,
|
||||
expanded=self.GetImage().use_expanded,
|
||||
|
@ -258,6 +276,7 @@ class Entry_section(Entry):
|
|||
|
||||
Args:
|
||||
entry: Entry to check
|
||||
entry_data: Data for the entry, False if is null
|
||||
|
||||
Returns:
|
||||
Contents of the entry along with any pad bytes before and
|
||||
|
@ -312,14 +331,32 @@ class Entry_section(Entry):
|
|||
# earlier in the image description. See testCollectionSection().
|
||||
if not required and entry_data is None:
|
||||
return None
|
||||
data = self.GetPaddedDataForEntry(entry, entry_data)
|
||||
|
||||
entry_data_final = entry_data
|
||||
if entry_data is None:
|
||||
pad_byte = (entry._pad_byte if isinstance(entry, Entry_section)
|
||||
else self._pad_byte)
|
||||
entry_data_final = tools.get_bytes(self._pad_byte, entry.size)
|
||||
|
||||
data = self.GetPaddedDataForEntry(entry, entry_data_final)
|
||||
# Handle empty space before the entry
|
||||
pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
|
||||
if pad > 0:
|
||||
section_data += tools.get_bytes(self._pad_byte, pad)
|
||||
|
||||
# Add in the actual entry data
|
||||
section_data += data
|
||||
if entry.overlap:
|
||||
end_offset = entry.offset + entry.size
|
||||
if end_offset > len(section_data):
|
||||
entry.Raise("Offset %#x (%d) ending at %#x (%d) must overlap with existing entries" %
|
||||
(entry.offset, entry.offset, end_offset,
|
||||
end_offset))
|
||||
# Don't write anything for null entries'
|
||||
if entry_data is not None:
|
||||
section_data = (section_data[:entry.offset] + data +
|
||||
section_data[entry.offset + entry.size:])
|
||||
else:
|
||||
section_data += data
|
||||
|
||||
self.Detail('GetData: %d entries, total size %#x' %
|
||||
(len(self._entries), len(section_data)))
|
||||
|
@ -348,7 +385,8 @@ class Entry_section(Entry):
|
|||
"""Get the contents of an entry
|
||||
|
||||
This builds the contents of the section, stores this as the contents of
|
||||
the section and returns it
|
||||
the section and returns it. If the section has a filename, the data is
|
||||
written there also.
|
||||
|
||||
Args:
|
||||
required: True if the data must be present, False if it is OK to
|
||||
|
@ -363,6 +401,8 @@ class Entry_section(Entry):
|
|||
if data is None:
|
||||
return None
|
||||
self.SetContents(data)
|
||||
if self._filename:
|
||||
tools.write_file(tools.get_output_filename(self._filename), data)
|
||||
return data
|
||||
|
||||
def GetOffsets(self):
|
||||
|
@ -439,12 +479,13 @@ class Entry_section(Entry):
|
|||
(entry.offset, entry.offset, entry.size, entry.size,
|
||||
self._node.path, self._skip_at_start,
|
||||
self._skip_at_start, max_size, max_size))
|
||||
if entry.offset < offset and entry.size:
|
||||
entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
|
||||
"ending at %#x (%d)" %
|
||||
(entry.offset, entry.offset, prev_name, offset, offset))
|
||||
offset = entry.offset + entry.size
|
||||
prev_name = entry.GetPath()
|
||||
if not entry.overlap:
|
||||
if entry.offset < offset and entry.size:
|
||||
entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' ending at %#x (%d)" %
|
||||
(entry.offset, entry.offset, prev_name, offset,
|
||||
offset))
|
||||
offset = entry.offset + entry.size
|
||||
prev_name = entry.GetPath()
|
||||
|
||||
def WriteSymbols(self, section):
|
||||
"""Write symbol values into binary files for access at run time"""
|
||||
|
@ -662,10 +703,13 @@ class Entry_section(Entry):
|
|||
|
||||
def GetEntryContents(self, skip_entry=None):
|
||||
"""Call ObtainContents() for each entry in the section
|
||||
|
||||
Note that this may set entry.absent to True if the entry is not
|
||||
actually needed
|
||||
"""
|
||||
def _CheckDone(entry):
|
||||
if entry != skip_entry:
|
||||
if not entry.ObtainContents():
|
||||
if entry.ObtainContents() is False:
|
||||
next_todo.append(entry)
|
||||
return entry
|
||||
|
||||
|
@ -706,6 +750,10 @@ class Entry_section(Entry):
|
|||
todo)
|
||||
return True
|
||||
|
||||
def drop_absent(self):
|
||||
"""Drop entries which are absent"""
|
||||
self._entries = {n: e for n, e in self._entries.items() if not e.absent}
|
||||
|
||||
def _SetEntryOffsetSize(self, name, offset, size):
|
||||
"""Set the offset and size of an entry
|
||||
|
||||
|
@ -846,7 +894,8 @@ class Entry_section(Entry):
|
|||
def CheckMissing(self, missing_list):
|
||||
"""Check if any entries in this section have missing external blobs
|
||||
|
||||
If there are missing blobs, the entries are added to the list
|
||||
If there are missing (non-optional) blobs, the entries are added to the
|
||||
list
|
||||
|
||||
Args:
|
||||
missing_list: List of Entry objects to be added to
|
||||
|
@ -865,6 +914,17 @@ class Entry_section(Entry):
|
|||
for entry in self._entries.values():
|
||||
entry.CheckFakedBlobs(faked_blobs_list)
|
||||
|
||||
def CheckOptional(self, optional_list):
|
||||
"""Check the section for missing but optional external blobs
|
||||
|
||||
If there are missing (optional) blobs, the entries are added to the list
|
||||
|
||||
Args:
|
||||
optional_list (list): List of Entry objects to be added to
|
||||
"""
|
||||
for entry in self._entries.values():
|
||||
entry.CheckOptional(optional_list)
|
||||
|
||||
def check_missing_bintools(self, missing_list):
|
||||
"""Check if any entries in this section have missing bintools
|
||||
|
||||
|
@ -931,3 +991,12 @@ class Entry_section(Entry):
|
|||
super().AddBintools(btools)
|
||||
for entry in self._entries.values():
|
||||
entry.AddBintools(btools)
|
||||
|
||||
def read_elf_segments(self):
|
||||
entries = self.GetEntries()
|
||||
|
||||
# If the section only has one entry, see if it can provide ELF segments
|
||||
if len(entries) == 1:
|
||||
for entry in entries.values():
|
||||
return entry.read_elf_segments()
|
||||
return None
|
||||
|
|
|
@ -4,19 +4,93 @@
|
|||
# Entry-type module for OP-TEE Trusted OS firmware blob
|
||||
#
|
||||
|
||||
import struct
|
||||
|
||||
from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
|
||||
from binman import elf
|
||||
|
||||
class Entry_tee_os(Entry_blob_named_by_arg):
|
||||
"""Entry containing an OP-TEE Trusted OS (TEE) blob
|
||||
|
||||
Properties / Entry arguments:
|
||||
- tee-os-path: Filename of file to read into entry. This is typically
|
||||
called tee-pager.bin
|
||||
called tee.bin or tee.elf
|
||||
|
||||
This entry holds the run-time firmware, typically started by U-Boot SPL.
|
||||
See the U-Boot README for your architecture or board for how to use it. See
|
||||
https://github.com/OP-TEE/optee_os for more information about OP-TEE.
|
||||
|
||||
Note that if the file is in ELF format, it must go in a FIT. In that case,
|
||||
this entry will mark itself as absent, providing the data only through the
|
||||
read_elf_segments() method.
|
||||
|
||||
Marking this entry as absent means that it if is used in the wrong context
|
||||
it can be automatically dropped. Thus it is possible to add an OP-TEE entry
|
||||
like this::
|
||||
|
||||
binman {
|
||||
tee-os {
|
||||
};
|
||||
};
|
||||
|
||||
and pass either an ELF or plain binary in with -a tee-os-path <filename>
|
||||
and have binman do the right thing:
|
||||
|
||||
- include the entry if tee.bin is provided and it does NOT have the v1
|
||||
header
|
||||
- drop it otherwise
|
||||
|
||||
When used within a FIT, we can do::
|
||||
|
||||
binman {
|
||||
fit {
|
||||
tee-os {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
which will split the ELF into separate nodes for each segment, if an ELF
|
||||
file is provided (see :ref:`etype_fit`), or produce a single node if the
|
||||
OP-TEE binary v1 format is provided (see optee_doc_) .
|
||||
|
||||
.. _optee_doc: https://optee.readthedocs.io/en/latest/architecture/core.html#partitioning-of-the-binary
|
||||
"""
|
||||
def __init__(self, section, etype, node):
|
||||
super().__init__(section, etype, node, 'tee-os')
|
||||
self.external = True
|
||||
|
||||
@staticmethod
|
||||
def is_optee_bin_v1(data):
|
||||
return len(data) >= 8 and data[0:5] == b'OPTE\x01'
|
||||
|
||||
def ObtainContents(self, fake_size=0):
|
||||
result = super().ObtainContents(fake_size)
|
||||
if not self.missing:
|
||||
# If using the flat binary (without the OP-TEE header), then it is
|
||||
# just included as a blob. But if it is an ELF or usees the v1
|
||||
# binary header, then the FIT implementation will call
|
||||
# read_elf_segments() to get the segment information
|
||||
if elf.is_valid(self.data):
|
||||
self.mark_absent('uses Elf format which must be in a FIT')
|
||||
elif self.is_optee_bin_v1(self.data):
|
||||
# The FIT implementation will call read_elf_segments() to get
|
||||
# the segment information
|
||||
self.mark_absent('uses v1 format which must be in a FIT')
|
||||
return result
|
||||
|
||||
def read_elf_segments(self):
|
||||
data = self.GetData()
|
||||
if self.is_optee_bin_v1(data):
|
||||
# OP-TEE v1 format (tee.bin)
|
||||
init_sz, start_hi, start_lo, _, paged_sz = (
|
||||
struct.unpack_from('<5I', data, 0x8))
|
||||
if paged_sz != 0:
|
||||
self.Raise("OP-TEE paged mode not supported")
|
||||
e_entry = (start_hi << 32) + start_lo
|
||||
p_addr = e_entry
|
||||
p_data = data[0x1c:]
|
||||
if len(p_data) != init_sz:
|
||||
self.Raise("Invalid OP-TEE file: size mismatch (expected %#x, have %#x)" %
|
||||
(init_sz, len(p_data)))
|
||||
return [[0, p_addr, p_data]], e_entry
|
||||
return None
|
||||
|
|
|
@ -18,11 +18,7 @@ class Entry_u_boot(Entry_blob):
|
|||
to relocate itself at runtime. The binary typically includes a device tree
|
||||
blob at the end of it.
|
||||
|
||||
U-Boot can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (fdt)'
|
||||
|
||||
in the binman README for more information.
|
||||
U-Boot can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
Note that this entry is automatically replaced with u-boot-expanded unless
|
||||
--no-expanded is used or the node has a 'no-expanded' property.
|
||||
|
|
|
@ -21,9 +21,7 @@ class Entry_u_boot_spl(Entry_blob):
|
|||
to run from the correct address if direct flash execution is possible (e.g.
|
||||
on x86 devices).
|
||||
|
||||
SPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
@ -36,7 +34,6 @@ class Entry_u_boot_spl(Entry_blob):
|
|||
def __init__(self, section, etype, node):
|
||||
super().__init__(section, etype, node, auto_write_symbols=True)
|
||||
self.elf_fname = 'spl/u-boot-spl'
|
||||
self.auto_write_symbols = True
|
||||
|
||||
def GetDefaultFilename(self):
|
||||
return 'spl/u-boot-spl.bin'
|
||||
|
|
|
@ -21,9 +21,7 @@ class Entry_u_boot_spl_nodtb(Entry_blob):
|
|||
expands to a section containing u-boot-spl-dtb, u-boot-spl-bss-pad and
|
||||
u-boot-spl-dtb
|
||||
|
||||
SPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@ class Entry_u_boot_tpl(Entry_blob):
|
|||
address in SRAM, or written to run from the correct address if direct
|
||||
flash execution is possible (e.g. on x86 devices).
|
||||
|
||||
SPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@ class Entry_u_boot_tpl_nodtb(Entry_blob):
|
|||
expands to a section containing u-boot-tpl-dtb, u-boot-tpl-bss-pad and
|
||||
u-boot-tpl-dtb
|
||||
|
||||
TPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
TPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@ class Entry_u_boot_vpl(Entry_blob):
|
|||
address in SRAM, or written to run from the correct address if direct
|
||||
flash execution is possible (e.g. on x86 devices).
|
||||
|
||||
SPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
in the binman README for more information.
|
||||
|
||||
|
|
|
@ -21,11 +21,7 @@ class Entry_u_boot_vpl_nodtb(Entry_blob):
|
|||
expands to a section containing u-boot-vpl-dtb, u-boot-vpl-bss-pad and
|
||||
u-boot-vpl-dtb
|
||||
|
||||
VPL can access binman symbols at runtime. See:
|
||||
|
||||
'Access to binman entry offsets at run time (symbols)'
|
||||
|
||||
in the binman README for more information.
|
||||
VPL can access binman symbols at runtime. See :ref:`binman_fdt`.
|
||||
|
||||
The ELF file 'vpl/u-boot-vpl' must also be available for this to work, since
|
||||
binman uses that to look up symbols to write into the VPL binary.
|
||||
|
|
|
@ -112,6 +112,8 @@ REPACK_DTB_PROPS = ['orig-offset', 'orig-size']
|
|||
# Supported compression bintools
|
||||
COMP_BINTOOLS = ['bzip2', 'gzip', 'lz4', 'lzma_alone', 'lzop', 'xz', 'zstd']
|
||||
|
||||
TEE_ADDR = 0x5678
|
||||
|
||||
class TestFunctional(unittest.TestCase):
|
||||
"""Functional tests for binman
|
||||
|
||||
|
@ -219,6 +221,9 @@ class TestFunctional(unittest.TestCase):
|
|||
TestFunctional._MakeInputFile('tee.elf',
|
||||
tools.read_file(cls.ElfTestFile('elf_sections')))
|
||||
|
||||
# Newer OP_TEE file in v1 binary format
|
||||
cls.make_tee_bin('tee.bin')
|
||||
|
||||
cls.comp_bintools = {}
|
||||
for name in COMP_BINTOOLS:
|
||||
cls.comp_bintools[name] = bintool.Bintool.create(name)
|
||||
|
@ -644,6 +649,14 @@ class TestFunctional(unittest.TestCase):
|
|||
def ElfTestFile(cls, fname):
|
||||
return os.path.join(cls._elf_testdir, fname)
|
||||
|
||||
@classmethod
|
||||
def make_tee_bin(cls, fname, paged_sz=0, extra_data=b''):
|
||||
init_sz, start_hi, start_lo, dummy = (len(U_BOOT_DATA), 0, TEE_ADDR, 0)
|
||||
data = b'OPTE\x01xxx' + struct.pack('<5I', init_sz, start_hi, start_lo,
|
||||
dummy, paged_sz) + U_BOOT_DATA
|
||||
data += extra_data
|
||||
TestFunctional._MakeInputFile(fname, data)
|
||||
|
||||
def AssertInList(self, grep_list, target):
|
||||
"""Assert that at least one of a list of things is in a target
|
||||
|
||||
|
@ -6077,5 +6090,225 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
|
|||
'Cannot write symbols to an ELF file without Python elftools',
|
||||
str(exc.exception))
|
||||
|
||||
def testSectionFilename(self):
|
||||
"""Check writing of section contents to a file"""
|
||||
data = self._DoReadFile('261_section_fname.dts')
|
||||
expected = (b'&&' + U_BOOT_DATA + b'&&&' +
|
||||
tools.get_bytes(ord('!'), 7) +
|
||||
U_BOOT_DATA + tools.get_bytes(ord('&'), 12))
|
||||
self.assertEqual(expected, data)
|
||||
|
||||
sect_fname = tools.get_output_filename('outfile.bin')
|
||||
self.assertTrue(os.path.exists(sect_fname))
|
||||
sect_data = tools.read_file(sect_fname)
|
||||
self.assertEqual(U_BOOT_DATA, sect_data)
|
||||
|
||||
def testAbsent(self):
|
||||
"""Check handling of absent entries"""
|
||||
data = self._DoReadFile('262_absent.dts')
|
||||
self.assertEqual(U_BOOT_DATA + U_BOOT_IMG_DATA, data)
|
||||
|
||||
def testPackTeeOsOptional(self):
|
||||
"""Test that an image with an optional TEE binary can be created"""
|
||||
entry_args = {
|
||||
'tee-os-path': 'tee.elf',
|
||||
}
|
||||
data = self._DoReadFileDtb('263_tee_os_opt.dts',
|
||||
entry_args=entry_args)[0]
|
||||
self.assertEqual(U_BOOT_DATA + U_BOOT_IMG_DATA, data)
|
||||
|
||||
def checkFitTee(self, dts, tee_fname):
|
||||
"""Check that a tee-os entry works and returns data
|
||||
|
||||
Args:
|
||||
dts (str): Device tree filename to use
|
||||
tee_fname (str): filename containing tee-os
|
||||
|
||||
Returns:
|
||||
bytes: Image contents
|
||||
"""
|
||||
if not elf.ELF_TOOLS:
|
||||
self.skipTest('Python elftools not available')
|
||||
entry_args = {
|
||||
'of-list': 'test-fdt1 test-fdt2',
|
||||
'default-dt': 'test-fdt2',
|
||||
'tee-os-path': tee_fname,
|
||||
}
|
||||
test_subdir = os.path.join(self._indir, TEST_FDT_SUBDIR)
|
||||
data = self._DoReadFileDtb(dts, entry_args=entry_args,
|
||||
extra_indirs=[test_subdir])[0]
|
||||
return data
|
||||
|
||||
def testFitTeeOsOptionalFit(self):
|
||||
"""Test an image with a FIT with an optional OP-TEE binary"""
|
||||
data = self.checkFitTee('264_tee_os_opt_fit.dts', 'tee.bin')
|
||||
|
||||
# There should be only one node, holding the data set up in SetUpClass()
|
||||
# for tee.bin
|
||||
dtb = fdt.Fdt.FromData(data)
|
||||
dtb.Scan()
|
||||
node = dtb.GetNode('/images/tee-1')
|
||||
self.assertEqual(TEE_ADDR,
|
||||
fdt_util.fdt32_to_cpu(node.props['load'].value))
|
||||
self.assertEqual(TEE_ADDR,
|
||||
fdt_util.fdt32_to_cpu(node.props['entry'].value))
|
||||
self.assertEqual(U_BOOT_DATA, node.props['data'].bytes)
|
||||
|
||||
def testFitTeeOsOptionalFitBad(self):
|
||||
"""Test an image with a FIT with an optional OP-TEE binary"""
|
||||
with self.assertRaises(ValueError) as exc:
|
||||
self.checkFitTee('265_tee_os_opt_fit_bad.dts', 'tee.bin')
|
||||
self.assertIn(
|
||||
"Node '/binman/fit': subnode 'images/@tee-SEQ': Failed to read ELF file: Magic number does not match",
|
||||
str(exc.exception))
|
||||
|
||||
def testFitTeeOsBad(self):
|
||||
"""Test an OP-TEE binary with wrong formats"""
|
||||
self.make_tee_bin('tee.bad1', 123)
|
||||
with self.assertRaises(ValueError) as exc:
|
||||
self.checkFitTee('264_tee_os_opt_fit.dts', 'tee.bad1')
|
||||
self.assertIn(
|
||||
"Node '/binman/fit/images/@tee-SEQ/tee-os': OP-TEE paged mode not supported",
|
||||
str(exc.exception))
|
||||
|
||||
self.make_tee_bin('tee.bad2', 0, b'extra data')
|
||||
with self.assertRaises(ValueError) as exc:
|
||||
self.checkFitTee('264_tee_os_opt_fit.dts', 'tee.bad2')
|
||||
self.assertIn(
|
||||
"Node '/binman/fit/images/@tee-SEQ/tee-os': Invalid OP-TEE file: size mismatch (expected 0x4, have 0xe)",
|
||||
str(exc.exception))
|
||||
|
||||
def testExtblobOptional(self):
|
||||
"""Test an image with an external blob that is optional"""
|
||||
with test_util.capture_sys_output() as (stdout, stderr):
|
||||
data = self._DoReadFile('266_blob_ext_opt.dts')
|
||||
self.assertEqual(REFCODE_DATA, data)
|
||||
err = stderr.getvalue()
|
||||
self.assertRegex(
|
||||
err,
|
||||
"Image '.*' is missing external blobs but is still functional: missing")
|
||||
|
||||
def testSectionInner(self):
|
||||
"""Test an inner section with a size"""
|
||||
data = self._DoReadFile('267_section_inner.dts')
|
||||
expected = U_BOOT_DATA + tools.get_bytes(0, 12)
|
||||
self.assertEqual(expected, data)
|
||||
|
||||
def testNull(self):
|
||||
"""Test an image with a null entry"""
|
||||
data = self._DoReadFile('268_null.dts')
|
||||
self.assertEqual(U_BOOT_DATA + b'\xff\xff\xff\xff' + U_BOOT_IMG_DATA, data)
|
||||
|
||||
def testOverlap(self):
|
||||
"""Test an image with a overlapping entry"""
|
||||
data = self._DoReadFile('269_overlap.dts')
|
||||
self.assertEqual(U_BOOT_DATA[:1] + b'aa' + U_BOOT_DATA[3:], data)
|
||||
|
||||
image = control.images['image']
|
||||
entries = image.GetEntries()
|
||||
|
||||
self.assertIn('inset', entries)
|
||||
inset = entries['inset']
|
||||
self.assertEqual(1, inset.offset);
|
||||
self.assertEqual(1, inset.image_pos);
|
||||
self.assertEqual(2, inset.size);
|
||||
|
||||
def testOverlapNull(self):
|
||||
"""Test an image with a null overlap"""
|
||||
data = self._DoReadFile('270_overlap_null.dts')
|
||||
self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
|
||||
|
||||
# Check the FMAP
|
||||
fhdr, fentries = fmap_util.DecodeFmap(data[len(U_BOOT_DATA):])
|
||||
self.assertEqual(4, fhdr.nareas)
|
||||
fiter = iter(fentries)
|
||||
|
||||
fentry = next(fiter)
|
||||
self.assertEqual(b'SECTION', fentry.name)
|
||||
self.assertEqual(0, fentry.offset)
|
||||
self.assertEqual(len(U_BOOT_DATA), fentry.size)
|
||||
self.assertEqual(0, fentry.flags)
|
||||
|
||||
fentry = next(fiter)
|
||||
self.assertEqual(b'U_BOOT', fentry.name)
|
||||
self.assertEqual(0, fentry.offset)
|
||||
self.assertEqual(len(U_BOOT_DATA), fentry.size)
|
||||
self.assertEqual(0, fentry.flags)
|
||||
|
||||
# Make sure that the NULL entry appears in the FMAP
|
||||
fentry = next(fiter)
|
||||
self.assertEqual(b'NULL', fentry.name)
|
||||
self.assertEqual(1, fentry.offset)
|
||||
self.assertEqual(2, fentry.size)
|
||||
self.assertEqual(0, fentry.flags)
|
||||
|
||||
fentry = next(fiter)
|
||||
self.assertEqual(b'FMAP', fentry.name)
|
||||
self.assertEqual(len(U_BOOT_DATA), fentry.offset)
|
||||
|
||||
def testOverlapBad(self):
|
||||
"""Test an image with a bad overlapping entry"""
|
||||
with self.assertRaises(ValueError) as exc:
|
||||
self._DoReadFile('271_overlap_bad.dts')
|
||||
self.assertIn(
|
||||
"Node '/binman/inset': Offset 0x10 (16) ending at 0x12 (18) must overlap with existing entries",
|
||||
str(exc.exception))
|
||||
|
||||
def testOverlapNoOffset(self):
|
||||
"""Test an image with a bad overlapping entry"""
|
||||
with self.assertRaises(ValueError) as exc:
|
||||
self._DoReadFile('272_overlap_no_size.dts')
|
||||
self.assertIn(
|
||||
"Node '/binman/inset': 'fill' entry is missing properties: size",
|
||||
str(exc.exception))
|
||||
|
||||
def testBlobSymbol(self):
|
||||
"""Test a blob with symbols read from an ELF file"""
|
||||
elf_fname = self.ElfTestFile('blob_syms')
|
||||
TestFunctional._MakeInputFile('blob_syms', tools.read_file(elf_fname))
|
||||
TestFunctional._MakeInputFile('blob_syms.bin',
|
||||
tools.read_file(self.ElfTestFile('blob_syms.bin')))
|
||||
|
||||
data = self._DoReadFile('273_blob_symbol.dts')
|
||||
|
||||
syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
|
||||
addr = elf.GetSymbolAddress(elf_fname, '__my_start_sym')
|
||||
self.assertEqual(syms['_binman_sym_magic'].address, addr)
|
||||
self.assertEqual(syms['_binman_inset_prop_offset'].address, addr + 4)
|
||||
self.assertEqual(syms['_binman_inset_prop_size'].address, addr + 8)
|
||||
|
||||
sym_values = struct.pack('<LLL', elf.BINMAN_SYM_MAGIC_VALUE, 4, 8)
|
||||
expected = sym_values
|
||||
self.assertEqual(expected, data[:len(expected)])
|
||||
|
||||
def testOffsetFromElf(self):
|
||||
"""Test a blob with symbols read from an ELF file"""
|
||||
elf_fname = self.ElfTestFile('blob_syms')
|
||||
TestFunctional._MakeInputFile('blob_syms', tools.read_file(elf_fname))
|
||||
TestFunctional._MakeInputFile('blob_syms.bin',
|
||||
tools.read_file(self.ElfTestFile('blob_syms.bin')))
|
||||
|
||||
data = self._DoReadFile('274_offset_from_elf.dts')
|
||||
|
||||
syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
|
||||
base = elf.GetSymbolAddress(elf_fname, '__my_start_sym')
|
||||
|
||||
image = control.images['image']
|
||||
entries = image.GetEntries()
|
||||
|
||||
self.assertIn('inset', entries)
|
||||
inset = entries['inset']
|
||||
|
||||
self.assertEqual(base + 4, inset.offset);
|
||||
self.assertEqual(base + 4, inset.image_pos);
|
||||
self.assertEqual(4, inset.size);
|
||||
|
||||
self.assertIn('inset2', entries)
|
||||
inset = entries['inset2']
|
||||
self.assertEqual(base + 8, inset.offset);
|
||||
self.assertEqual(base + 8, inset.image_pos);
|
||||
self.assertEqual(4, inset.size);
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -94,9 +94,6 @@ class Image(section.Entry_section):
|
|||
|
||||
def ReadNode(self):
|
||||
super().ReadNode()
|
||||
filename = fdt_util.GetString(self._node, 'filename')
|
||||
if filename:
|
||||
self._filename = filename
|
||||
self.allow_repack = fdt_util.GetBool(self._node, 'allow-repack')
|
||||
self._symlink = fdt_util.GetString(self._node, 'symlink')
|
||||
|
||||
|
|
29
tools/binman/test/261_section_fname.dts
Normal file
29
tools/binman/test/261_section_fname.dts
Normal file
|
@ -0,0 +1,29 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
pad-byte = <0x26>;
|
||||
size = <0x20>;
|
||||
section@0 {
|
||||
size = <0x10>;
|
||||
pad-byte = <0x21>;
|
||||
pad-before = <2>;
|
||||
pad-after = <3>;
|
||||
|
||||
section {
|
||||
filename = "outfile.bin";
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
};
|
||||
section@1 {
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
20
tools/binman/test/262_absent.dts
Normal file
20
tools/binman/test/262_absent.dts
Normal file
|
@ -0,0 +1,20 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
u-boot {
|
||||
};
|
||||
|
||||
_testing {
|
||||
set-to-absent;
|
||||
};
|
||||
|
||||
u-boot-img {
|
||||
};
|
||||
};
|
||||
};
|
22
tools/binman/test/263_tee_os_opt.dts
Normal file
22
tools/binman/test/263_tee_os_opt.dts
Normal file
|
@ -0,0 +1,22 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
u-boot {
|
||||
};
|
||||
tee-os {
|
||||
/*
|
||||
* this results in nothing being added since only the
|
||||
* .bin format is supported by this etype, unless it is
|
||||
* part of a FIT
|
||||
*/
|
||||
};
|
||||
u-boot-img {
|
||||
};
|
||||
};
|
||||
};
|
33
tools/binman/test/264_tee_os_opt_fit.dts
Normal file
33
tools/binman/test/264_tee_os_opt_fit.dts
Normal file
|
@ -0,0 +1,33 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
fit {
|
||||
description = "test-desc";
|
||||
#address-cells = <1>;
|
||||
fit,fdt-list = "of-list";
|
||||
|
||||
images {
|
||||
@tee-SEQ {
|
||||
fit,operation = "split-elf";
|
||||
description = "TEE";
|
||||
type = "tee";
|
||||
arch = "arm64";
|
||||
os = "tee";
|
||||
compression = "none";
|
||||
fit,load;
|
||||
fit,entry;
|
||||
fit,data;
|
||||
|
||||
tee-os {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
40
tools/binman/test/265_tee_os_opt_fit_bad.dts
Normal file
40
tools/binman/test/265_tee_os_opt_fit_bad.dts
Normal file
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
fit {
|
||||
description = "test-desc";
|
||||
#address-cells = <1>;
|
||||
fit,fdt-list = "of-list";
|
||||
|
||||
images {
|
||||
@tee-SEQ {
|
||||
fit,operation = "split-elf";
|
||||
description = "TEE";
|
||||
type = "tee";
|
||||
arch = "arm64";
|
||||
os = "tee";
|
||||
compression = "none";
|
||||
fit,load;
|
||||
fit,entry;
|
||||
fit,data;
|
||||
|
||||
tee-os {
|
||||
};
|
||||
|
||||
/*
|
||||
* mess up the ELF data by adding
|
||||
* another bit of data at the end
|
||||
*/
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
21
tools/binman/test/266_blob_ext_opt.dts
Normal file
21
tools/binman/test/266_blob_ext_opt.dts
Normal file
|
@ -0,0 +1,21 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
ok {
|
||||
type = "blob-ext";
|
||||
filename = "refcode.bin";
|
||||
};
|
||||
|
||||
missing {
|
||||
type = "blob-ext";
|
||||
filename = "missing.bin";
|
||||
optional;
|
||||
};
|
||||
};
|
||||
};
|
16
tools/binman/test/267_section_inner.dts
Normal file
16
tools/binman/test/267_section_inner.dts
Normal file
|
@ -0,0 +1,16 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
section {
|
||||
size = <0x10>;
|
||||
u-boot {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
19
tools/binman/test/268_null.dts
Normal file
19
tools/binman/test/268_null.dts
Normal file
|
@ -0,0 +1,19 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
pad-byte = <0xff>;
|
||||
u-boot {
|
||||
};
|
||||
null {
|
||||
size = <4>;
|
||||
};
|
||||
u-boot-img {
|
||||
};
|
||||
};
|
||||
};
|
21
tools/binman/test/269_overlap.dts
Normal file
21
tools/binman/test/269_overlap.dts
Normal file
|
@ -0,0 +1,21 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
u-boot {
|
||||
};
|
||||
|
||||
inset {
|
||||
type = "fill";
|
||||
fill-byte = [61];
|
||||
offset = <1>;
|
||||
size = <2>;
|
||||
overlap;
|
||||
};
|
||||
};
|
||||
};
|
24
tools/binman/test/270_overlap_null.dts
Normal file
24
tools/binman/test/270_overlap_null.dts
Normal file
|
@ -0,0 +1,24 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
section {
|
||||
u-boot {
|
||||
};
|
||||
|
||||
null {
|
||||
offset = <1>;
|
||||
size = <2>;
|
||||
overlap;
|
||||
};
|
||||
};
|
||||
|
||||
fmap {
|
||||
};
|
||||
};
|
||||
};
|
21
tools/binman/test/271_overlap_bad.dts
Normal file
21
tools/binman/test/271_overlap_bad.dts
Normal file
|
@ -0,0 +1,21 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
u-boot {
|
||||
};
|
||||
|
||||
inset {
|
||||
type = "fill";
|
||||
fill-byte = [61];
|
||||
offset = <0x10>;
|
||||
size = <2>;
|
||||
overlap;
|
||||
};
|
||||
};
|
||||
};
|
19
tools/binman/test/272_overlap_no_size.dts
Normal file
19
tools/binman/test/272_overlap_no_size.dts
Normal file
|
@ -0,0 +1,19 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
u-boot {
|
||||
};
|
||||
|
||||
inset {
|
||||
type = "fill";
|
||||
fill-byte = [61];
|
||||
overlap;
|
||||
};
|
||||
};
|
||||
};
|
24
tools/binman/test/273_blob_symbol.dts
Normal file
24
tools/binman/test/273_blob_symbol.dts
Normal file
|
@ -0,0 +1,24 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
blob {
|
||||
filename = "blob_syms.bin";
|
||||
write-symbols;
|
||||
elf-filename = "blob_syms";
|
||||
elf-base-sym = "__my_start_sym";
|
||||
};
|
||||
|
||||
inset {
|
||||
type = "null";
|
||||
offset = <4>;
|
||||
size = <8>;
|
||||
overlap;
|
||||
};
|
||||
};
|
||||
};
|
30
tools/binman/test/274_offset_from_elf.dts
Normal file
30
tools/binman/test/274_offset_from_elf.dts
Normal file
|
@ -0,0 +1,30 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
blob: blob {
|
||||
filename = "blob_syms.bin";
|
||||
elf-filename = "blob_syms";
|
||||
elf-base-sym = "__my_start_sym";
|
||||
};
|
||||
|
||||
inset {
|
||||
type = "null";
|
||||
offset-from-elf = <&blob>, "val3", <0>;
|
||||
size = <4>;
|
||||
overlap;
|
||||
};
|
||||
|
||||
inset2 {
|
||||
type = "null";
|
||||
offset-from-elf = <&blob>, "val3", <4>;
|
||||
size = <4>;
|
||||
overlap;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -30,11 +30,12 @@ LDS_BINMAN_BAD := -T $(SRC)u_boot_binman_syms_bad.lds
|
|||
LDS_BINMAN_X86 := -T $(SRC)u_boot_binman_syms_x86.lds
|
||||
LDS_BINMAN_EMBED := -T $(SRC)u_boot_binman_embed.lds
|
||||
LDS_EFL_SECTIONS := -T $(SRC)elf_sections.lds
|
||||
LDS_BLOB := -T $(SRC)blob_syms.lds
|
||||
|
||||
TARGETS = u_boot_ucode_ptr u_boot_no_ucode_ptr bss_data \
|
||||
u_boot_binman_syms u_boot_binman_syms.bin u_boot_binman_syms_bad \
|
||||
u_boot_binman_syms_size u_boot_binman_syms_x86 embed_data \
|
||||
u_boot_binman_embed u_boot_binman_embed_sm elf_sections
|
||||
u_boot_binman_embed u_boot_binman_embed_sm elf_sections blob_syms.bin
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
|
@ -71,6 +72,12 @@ u_boot_binman_embed: u_boot_binman_embed.c
|
|||
u_boot_binman_embed_sm: CFLAGS += $(LDS_BINMAN_EMBED)
|
||||
u_boot_binman_embed_sm: u_boot_binman_embed_sm.c
|
||||
|
||||
blob_syms.bin: blob_syms
|
||||
$(OBJCOPY) -O binary $< -R .note.gnu.build-id $@
|
||||
|
||||
blob_syms: CFLAGS += $(LDS_BLOB)
|
||||
blob_syms: blob_syms.c
|
||||
|
||||
elf_sections: CFLAGS += $(LDS_EFL_SECTIONS)
|
||||
elf_sections: elf_sections.c
|
||||
|
||||
|
|
20
tools/binman/test/blob_syms.c
Normal file
20
tools/binman/test/blob_syms.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2017 Google, Inc
|
||||
*
|
||||
* Simple program to create some binman symbols. This is used by binman tests.
|
||||
*/
|
||||
|
||||
typedef unsigned long ulong;
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <binman_sym.h>
|
||||
|
||||
DECLARE_BINMAN_MAGIC_SYM;
|
||||
|
||||
unsigned long val1 = 123;
|
||||
unsigned long val2 = 456;
|
||||
binman_sym_declare(unsigned long, inset, offset);
|
||||
unsigned long val3 = 789;
|
||||
unsigned long val4 = 999;
|
||||
binman_sym_declare(unsigned long, inset, size);
|
30
tools/binman/test/blob_syms.lds
Normal file
30
tools/binman/test/blob_syms.lds
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (c) 2016 Google, Inc
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000010;
|
||||
_start = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
__my_start_sym = .;
|
||||
*(.text*)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.binman_sym_table : {
|
||||
__binman_sym_start = .;
|
||||
KEEP(*(SORT(.binman_sym*)));
|
||||
__binman_sym_end = .;
|
||||
}
|
||||
.interp : { *(.interp*) }
|
||||
|
||||
}
|
|
@ -281,6 +281,34 @@ def GetPhandleList(node, propname):
|
|||
value = [value]
|
||||
return [fdt32_to_cpu(v) for v in value]
|
||||
|
||||
def GetPhandleNameOffset(node, propname):
|
||||
"""Get a <&phandle>, "string", <offset> value from a property
|
||||
|
||||
Args:
|
||||
node: Node object to read from
|
||||
propname: property name to read
|
||||
|
||||
Returns:
|
||||
tuple:
|
||||
Node object
|
||||
str
|
||||
int
|
||||
or None if the property does not exist
|
||||
"""
|
||||
prop = node.props.get(propname)
|
||||
if not prop:
|
||||
return None
|
||||
value = prop.bytes
|
||||
phandle = fdt32_to_cpu(value[:4])
|
||||
node = node.GetFdt().LookupPhandle(phandle)
|
||||
name = ''
|
||||
for byte in value[4:]:
|
||||
if not byte:
|
||||
break
|
||||
name += chr(byte)
|
||||
val = fdt32_to_cpu(value[4 + len(name) + 1:])
|
||||
return node, name, val
|
||||
|
||||
def GetDatatype(node, propname, datatype):
|
||||
"""Get a value of a given type from a property
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
u-boot,dm-pre-reloc;
|
||||
compatible = "source";
|
||||
clocks = <&phandle &phandle_1 11 &phandle_2 12 13 &phandle>;
|
||||
phandle-name-offset = <&phandle_2>, "fred", <123>;
|
||||
};
|
||||
|
||||
phandle-source2 {
|
||||
|
|
|
@ -929,6 +929,7 @@ U_BOOT_DRVINFO(spl_test) = {
|
|||
self._check_strings(HEADER + '''
|
||||
struct dtd_source {
|
||||
\tstruct phandle_2_arg clocks[4];
|
||||
\tunsigned char phandle_name_offset[13];
|
||||
};
|
||||
struct dtd_target {
|
||||
\tfdt32_t\t\tintval;
|
||||
|
@ -981,6 +982,8 @@ static struct dtd_source dtv_phandle_source = {
|
|||
\t\t\t{0, {11}},
|
||||
\t\t\t{1, {12, 13}},
|
||||
\t\t\t{4, {}},},
|
||||
\t.phandle_name_offset = {0x0, 0x0, 0x0, 0x3, 0x66, 0x72, 0x65, 0x64,
|
||||
\t\t0x0, 0x0, 0x0, 0x0, 0x7b},
|
||||
};
|
||||
U_BOOT_DRVINFO(phandle_source) = {
|
||||
\t.name\t\t= "source",
|
||||
|
|
|
@ -795,6 +795,17 @@ class TestFdtUtil(unittest.TestCase):
|
|||
finally:
|
||||
tools.outdir= old_outdir
|
||||
|
||||
def test_get_phandle_name_offset(self):
|
||||
val = fdt_util.GetPhandleNameOffset(self.node, 'missing')
|
||||
self.assertIsNone(val)
|
||||
|
||||
dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
|
||||
node = dtb.GetNode('/phandle-source')
|
||||
node, name, offset = fdt_util.GetPhandleNameOffset(node,
|
||||
'phandle-name-offset')
|
||||
self.assertEqual('phandle3-target', node.name)
|
||||
self.assertEqual('fred', name)
|
||||
self.assertEqual(123, offset)
|
||||
|
||||
def run_test_coverage(build_dir):
|
||||
"""Run the tests and check that we get 100% coverage
|
||||
|
|
|
@ -36,8 +36,10 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
|
|||
|
||||
tfd = mmap_fdt(params->cmdname, tmpfile, size_inc, &ptr, &sbuf, true,
|
||||
false);
|
||||
if (tfd < 0)
|
||||
if (tfd < 0) {
|
||||
fprintf(stderr, "Cannot map FDT file '%s'\n", tmpfile);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (params->keydest) {
|
||||
struct stat dest_sbuf;
|
||||
|
|
|
@ -1292,8 +1292,12 @@ int fit_add_verification_data(const char *keydir, const char *keyfile,
|
|||
ret = fit_image_add_verification_data(keydir, keyfile, keydest,
|
||||
fit, noffset, comment, require_keys, engine_id,
|
||||
cmdname, algo_name);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
printf("Can't add verification data for node '%s' (%s)\n",
|
||||
fdt_get_name(fit, noffset, NULL),
|
||||
fdt_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there are no keys, we can't sign configurations */
|
||||
|
|
1
tools/patman/.checkpatch.conf
Symbolic link
1
tools/patman/.checkpatch.conf
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../.checkpatch.conf
|
|
@ -211,7 +211,7 @@ def check_patch(fname, verbose=False, show_types=False, use_tree=False):
|
|||
stdout: Full output of checkpatch
|
||||
"""
|
||||
chk = find_check_patch()
|
||||
args = [chk, '--u-boot', '--strict']
|
||||
args = [chk]
|
||||
if not use_tree:
|
||||
args.append('--no-tree')
|
||||
if show_types:
|
||||
|
|
|
@ -81,14 +81,15 @@ static void outf(int level, const char *fmt, ...)
|
|||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: proftool -cds -v3 <cmd> <profdata>\n"
|
||||
"Usage: proftool [-cmtv] <cmd> <profdata>\n"
|
||||
"\n"
|
||||
"Commands\n"
|
||||
" dump-ftrace\t\tDump out textual data in ftrace format\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -c <cfg>\tSpecific config file\n"
|
||||
" -m <map>\tSpecify Systen.map file\n"
|
||||
" -t <trace>\tSpecific trace data file (from U-Boot)\n"
|
||||
" -t <fname>\tSpecify trace data file (from U-Boot 'trace calls')\n"
|
||||
" -v <0-4>\tSpecify verbosity\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -162,7 +163,7 @@ static int read_data(FILE *fin, void *buff, int size)
|
|||
if (!err)
|
||||
return 1;
|
||||
if (err != size) {
|
||||
error("Cannot read profile file at pos %ld\n", ftell(fin));
|
||||
error("Cannot read profile file at pos %lx\n", ftell(fin));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -495,10 +496,17 @@ static int make_ftrace(void)
|
|||
int missing_count = 0, skip_count = 0;
|
||||
int i;
|
||||
|
||||
printf("# tracer: ftrace\n"
|
||||
"#\n"
|
||||
"# TASK-PID CPU# TIMESTAMP FUNCTION\n"
|
||||
"# | | | | |\n");
|
||||
printf("# tracer: function\n"
|
||||
"#\n"
|
||||
"# entries-in-buffer/entries-written: 140080/250280 #P:4\n"
|
||||
"#\n"
|
||||
"# _-----=> irqs-off\n"
|
||||
"# / _----=> need-resched\n"
|
||||
"# | / _---=> hardirq/softirq\n"
|
||||
"# || / _--=> preempt-depth\n"
|
||||
"# ||| / delay\n"
|
||||
"# TASK-PID CPU# |||| TIMESTAMP FUNCTION\n"
|
||||
"# | | | |||| | |\n");
|
||||
for (i = 0, call = call_list; i < call_count; i++, call++) {
|
||||
struct func_info *func = find_func_by_offset(call->func);
|
||||
ulong time = call->flags & FUNCF_TIMESTAMP_MASK;
|
||||
|
@ -520,7 +528,7 @@ static int make_ftrace(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
printf("%16s-%-5d [01] %lu.%06lu: ", "uboot", 1,
|
||||
printf("%16s-%-5d [000] .... %lu.%06lu: ", "uboot", 1,
|
||||
time / 1000000, time % 1000000);
|
||||
|
||||
out_func(call->func, 0, " <- ");
|
||||
|
@ -562,23 +570,23 @@ static int prof_tool(int argc, char *const argv[],
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *map_fname = "System.map";
|
||||
const char *prof_fname = NULL;
|
||||
const char *trace_config_fname = NULL;
|
||||
const char *trace_fname = NULL;
|
||||
const char *config_fname = NULL;
|
||||
int opt;
|
||||
|
||||
verbose = 2;
|
||||
while ((opt = getopt(argc, argv, "m:p:t:v:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "c:m:t:v:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
config_fname = optarg;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
map_fname = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
prof_fname = optarg;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
trace_config_fname = optarg;
|
||||
trace_fname = optarg;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
|
@ -594,6 +602,5 @@ int main(int argc, char *argv[])
|
|||
usage();
|
||||
|
||||
debug("Debug enabled\n");
|
||||
return prof_tool(argc, argv, prof_fname, map_fname,
|
||||
trace_config_fname);
|
||||
return prof_tool(argc, argv, trace_fname, map_fname, config_fname);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue