diff --git a/Makefile b/Makefile index 88c1991..b335f20 100644 --- a/Makefile +++ b/Makefile @@ -426,7 +426,7 @@ $(Q)$(MAKE) $(build)=$(@) # Objects we will link into barebox / subdirs we need to visit -common-y := common/ drivers/ commands/ lib/ crypto/ net/ fs/ +common-y := common/ drivers/ commands/ lib/ crypto/ net/ fs/ firmware/ ifeq ($(dot-config),1) # Read in config diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 37cde0c..bd73628 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -414,3 +414,4 @@ source fs/Kconfig source lib/Kconfig source crypto/Kconfig +source firmware/Kconfig diff --git a/firmware/Kconfig b/firmware/Kconfig new file mode 100644 index 0000000..e0cc7ab --- /dev/null +++ b/firmware/Kconfig @@ -0,0 +1,7 @@ +menu "Firmware files" + +config EXTRA_FIRMWARE_DIR + string "Firmware blobs root directory" + default "firmware" + +endmenu diff --git a/firmware/Makefile b/firmware/Makefile new file mode 100644 index 0000000..52984fd --- /dev/null +++ b/firmware/Makefile @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# kbuild file for firmware/ +# + +# Create $(fwabs) from $(CONFIG_EXTRA_FIRMWARE_DIR) -- if it doesn't have a +# leading /, it's relative to $(srctree). +fwdir := $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE_DIR)) +fwabs := $(addprefix $(srctree)/,$(filter-out /%,$(fwdir)))$(filter /%,$(fwdir)) + +fw-external-y := $(firmware-y) + +quiet_cmd_fwbin = MK_FW $@ + cmd_fwbin = FWNAME="$(patsubst firmware/%.gen.S,%,$@)"; \ + FWSTR="$(subst /,_,$(subst .,_,$(subst -,_,$(patsubst \ + firmware/%.gen.S,%,$@))))"; \ + ASM_WORD=$(if $(CONFIG_64BIT),.quad,.long); \ + ASM_ALIGN=$(if $(CONFIG_64BIT),3,2); \ + PROGBITS=$(if $(CONFIG_ARM),%,@)progbits; \ + echo "/* Generated by firmware/Makefile */" > $@;\ + echo " .section .rodata.$${FWSTR}" >>$@;\ + echo " .p2align $${ASM_ALIGN}" >>$@;\ + echo ".global _fw_$${FWSTR}_start" >>$@;\ + echo "_fw_$${FWSTR}_start:" >>$@;\ + echo " .incbin \"$(2)\"" >>$@;\ + echo ".global _fw_$${FWSTR}_end" >>$@;\ + echo "_fw_$${FWSTR}_end:" >>$@; + +# One of these files will change, or come into existence, whenever +# the configuration changes between 32-bit and 64-bit. The .S files +# need to change when that happens. +wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h) + +$(patsubst %,$(obj)/%.gen.S, $(fw-external-y)): %: $(wordsize_deps) \ + include/config/extra/firmware/dir.h + $(call cmd,fwbin,$(fwabs)/$(patsubst $(obj)/%.gen.S,%,$@)) + +# The .o files depend on the binaries directly; the .S files don't. +$(patsubst %,$(obj)/%.gen.o, $(fw-external-y)): $(obj)/%.gen.o: $(fwdir)/% + +obj-pbl-y += $(patsubst %,%.gen.o, $(fw-external-y)) + +ifeq ($(KBUILD_SRC),) +# Makefile.build only creates subdirectories for O= builds, but external +# firmware might live outside the kernel source tree +_dummy := $(foreach d,$(addprefix $(obj)/,$(dir $(fw-external-y))), $(shell [ -d $(d) ] || mkdir -p $(d))) +endif + +targets := $(patsubst $(obj)/%,%, \ + $(shell find $(obj) -name \*.gen.S 2>/dev/null)) + +# just to build a built-in.o. Otherwise compilation fails when no devicetree is +# created. +obj- += dummy.o diff --git a/include/firmware.h b/include/firmware.h index f6f78c8..284e0f9 100644 --- a/include/firmware.h +++ b/include/firmware.h @@ -39,4 +39,12 @@ int firmwaremgr_load_file(struct firmware_mgr *, const char *path); +#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; \ + } + #endif /* FIRMWARE_H */