diff options
-rw-r--r-- | arch/arm/lib/pbl.lds.S | 7 | ||||
-rw-r--r-- | firmware/Makefile | 38 | ||||
-rw-r--r-- | include/firmware.h | 42 |
3 files changed, 77 insertions, 10 deletions
diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S index e77b3220fc..44ad5b3353 100644 --- a/arch/arm/lib/pbl.lds.S +++ b/arch/arm/lib/pbl.lds.S @@ -101,6 +101,13 @@ SECTIONS } __piggydata_end = .; + . = ALIGN(4); + __pblext_start = .; + .pblext : { + *(.pblext.*) + } + __pblext_end = .; + .image_end : { KEEP(*(.__image_end)) } pbl_image_size = . - BASE; diff --git a/firmware/Makefile b/firmware/Makefile index 87bd033f6e..f6ff5b831b 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -30,16 +30,17 @@ firmware-$(CONFIG_FIRMWARE_CCBV2_OPTEE) += ccbv2_optee.bin # leading /, it's relative to $(srctree). fwdir := $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE_DIR)) fwdir := $(addprefix $(srctree)/,$(filter-out /%,$(fwdir)))$(filter /%,$(fwdir)) +fwobjdir := $(objtree)/firmware obj-pbl-y := $(addsuffix .gen.o, $(firmware-y)) -FWNAME = $(patsubst $(obj)/%.gen.S,%,$@) +FWNAME = $(patsubst $(obj)/%.extgen.S,%,$(patsubst $(obj)/%.gen.S,%,$@)) FWSTR = $(subst /,_,$(subst .,_,$(subst -,_,$(FWNAME)))) ASM_ALIGN = $(if $(CONFIG_64BIT),3,2) filechk_fwbin = { \ echo "/* Generated by $(src)/Makefile */" ;\ - echo " .section .rodata.$(FWSTR)" ;\ + echo " .section $2,\"$3\"" ;\ echo " .p2align $(ASM_ALIGN)" ;\ echo ".global _fw_$(FWSTR)_start" ;\ echo "_fw_$(FWSTR)_start:" ;\ @@ -48,19 +49,48 @@ filechk_fwbin = { \ echo "_fw_$(FWSTR)_end:" ;\ } +__fwbin_sha = { \ + echo " .section .rodata.$(FWSTR).sha" ;\ + echo " .p2align $(ASM_ALIGN)" ;\ + echo ".global _fw_$(FWSTR)_sha_start" ;\ + echo "_fw_$(FWSTR)_sha_start:" ;\ + echo " .incbin \"$(fwobjdir)/$(FWNAME).sha.bin\"" ;\ + echo ".global _fw_$(FWSTR)_sha_end" ;\ + echo "_fw_$(FWSTR)_sha_end:" ;\ +} + +filechk_fwbin_ext = { \ + $(filechk_fwbin) ;\ + $(__fwbin_sha) ;\ +} + $(obj)/%.gen.S: FORCE - $(call filechk,fwbin) + $(call filechk,fwbin,.rodata.$(FWSTR),) + +$(obj)/%.extgen.S: $(obj)/%.sha.bin FORCE + $(call filechk,fwbin_ext,.pblext.$(FWSTR),a) + +$(obj)/%.sha.bin: $(obj)/%.sum FORCE + $(call if_changed,sha256bin) + +$(obj)/%.sum: $(obj)/% FORCE + $(call if_changed,sha256sum) + +clean-files += *.sha.bin *.sum # The .o files depend on the binaries directly; the .S files don't. $(patsubst %,$(obj)/%.gen.o, $(obj-pbl-y)): $(obj)/%.gen.o: $(fwdir)/% # The same for pbl: $(patsubst %,$(obj)/%.gen.pbl.o, $(obj-pbl-y)): $(obj)/%.gen.pbl.o: $(fwdir)/% +$(patsubst %,$(obj)/%.extgen.pbl.o, $(pbl-y)): $(obj)/%.extgen.pbl.o: $(fwdir)/% -obj-pbl-y += $(patsubst %,%.gen.o, $(fw-external-y)) +pbl-y := $(addsuffix .extgen.o, $(fw-external-y)) targets := $(patsubst $(obj)/%,%, \ $(shell find $(obj) -name \*.gen.S 2>/dev/null)) +targets += $(patsubst $(obj)/%,%, \ + $(shell find $(obj) -name \*.extgen.S 2>/dev/null)) # just to build a built-in.o. Otherwise compilation fails when no # firmware is built. diff --git a/include/firmware.h b/include/firmware.h index 2583342230..2cfaeb1e6a 100644 --- a/include/firmware.h +++ b/include/firmware.h @@ -6,8 +6,11 @@ #ifndef FIRMWARE_H #define FIRMWARE_H +#include <pbl.h> #include <types.h> #include <driver.h> +#include <debug_ll.h> +#include <linux/kernel.h> struct firmware_handler { char *id; /* unique identifier for this firmware device */ @@ -57,12 +60,39 @@ static inline void firmware_set_searchpath(const char *path) void firmwaremgr_list_handlers(void); -#define get_builtin_firmware(name, start, size) \ - { \ - extern char _fw_##name##_start[]; \ - extern char _fw_##name##_end[]; \ - *start = (typeof(*start)) _fw_##name##_start; \ - *size = _fw_##name##_end - _fw_##name##_start; \ +static inline void firmware_ext_verify(const void *data_start, size_t data_size, + const void *hash_start, size_t hash_size) +{ + if (pbl_barebox_verify(data_start, data_size, + hash_start, hash_size) != 0) { + putc_ll('!'); + panic("hash mismatch, refusing to decompress"); } +} + +#define __get_builtin_firmware(name, offset, start, size) \ + do { \ + extern char _fw_##name##_start[]; \ + extern char _fw_##name##_end[]; \ + extern char _fw_##name##_sha_start[]; \ + extern char _fw_##name##_sha_end[]; \ + *start = (typeof(*start)) _fw_##name##_start; \ + *size = _fw_##name##_end - _fw_##name##_start; \ + if (!(offset)) \ + break; \ + *start += (offset); \ + firmware_ext_verify( \ + *start, *size, \ + _fw_##name##_sha_start, \ + _fw_##name##_sha_end - _fw_##name##_sha_start \ + ); \ + } while (0) + + +#define get_builtin_firmware(name, start, size) \ + __get_builtin_firmware(name, 0, start, size) + +#define get_builtin_firmware_ext(name, base, start, size) \ + __get_builtin_firmware(name, (long)base - (long)_text, start, size) #endif /* FIRMWARE_H */ |