← Bootloader DUJINLABS.COM

Barebox · source analysis

Barebox 빌드 산출물과 PBL image

Kconfig와 linker 단계가 barebox ELF, PBL, DTB와 보드별 images를 만드는 구조를 정리합니다.

Series
01 / 19
Baseline
v2026.06.1
Commit
314c679eea2d
Source
Makefile:1074

Barebox 빌드 산출물과 PBL image 단계에서 실제로 바뀌는 상태는 무엇인가?

barebox 실행 파일과 images/ 아래 ROM 투입 파일을 구분한다. PBL 압축, 헤더, load address가 최종 파일에서 어디에 놓이는지 본다.

ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다. 이 문장을 기준으로 코드를 위에서 아래로 읽으면, 함수 이름을 외우는 대신 어느 시점에 어떤 상태를 신뢰할 수 있는지 판단할 수 있다.

객체와 주소가 놓이는 구조

그림 1. Barebox 빌드 산출물과 PBL image에서 입력, 내부 상태, 출력의 경계
입력과 전제내부 상태외부로 공개되는 결과
01main image
02PBL objects
03embedded DTB
04SoC boot image
INVARIANT

ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다.

barebox: $를 중심에 놓고 왼쪽의 입력이 어떤 검사를 거쳐 오른쪽 결과로 공개되는지 표시했다. 실제 디버깅에서는 각 블록의 주소와 크기를 로그에 대입한다.

실행 흐름

그림 2. 정상 경로의 주요 호출과 상태 전달
Kconfig
built-in objects
barebox ELF
PBL and DTB
images/

화살표는 단순 호출 순서만 뜻하지 않는다. 각 단계가 성공을 반환할 때 다음 단계가 읽을 수 있는 상태가 무엇인지 함께 확인한다. 오류 반환이 발생하면 바로 다음 화살표로 진행하지 않고 해당 단계의 정리 경로를 따라간다.

단계별 입력과 출력

호출 순서를 함수 이름으로만 외우지 않고, 각 단계가 무엇을 받아 무엇을 공개하는지 적은 표다. 실제 소스에서 생산 필드가 다르면 표를 고치는 방식으로 사용한다.

#단계진입 시 신뢰할 상태성공 뒤 남아야 할 상태다음 소비자
01Kconfig빌드 시점main imagebuilt-in objects
02built-in objectsKconfig 완료 상태PBL objectsbarebox ELF
03barebox ELFbuilt-in objects 완료 상태embedded DTBPBL and DTB
04PBL and DTBbarebox ELF 완료 상태SoC boot imageimages/
05images/PBL and DTB 완료 상태SoC boot image최종 barebox, barebox.bin, PBL, images/* 또는 다음 stage

공통 불변 조건: ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다. 한 단계의 출력이 다음 단계의 입력 조건을 만족하지 않으면 오류가 실제로 드러난 위치보다 앞의 생산 단계부터 조사한다.

주소와 객체의 이동을 그림으로 읽기

아래 그림은 호출 이름보다 주소, 객체 수명과 handoff 경계를 먼저 볼 수 있도록 구성했다. 실제 주소와 크기는 사용 중인 보드의 bdinfo, map과 linker symbol을 대입한다.

그림 3. Kconfig에서 ROM용 images 산출물까지

호출 이름만 나열하지 않고, 각 단계가 다음 단계에 넘기는 상태를 기준으로 실행 순서를 표시한다.

01defconfig·Kconfig
02built-in object
03barebox ELF
04PBL object subset
05compression·embedded DTB
06SoC image header
07images/*
그림 4. 빌드 산출물의 입력과 소비자

왼쪽 생산자가 가운데 상태를 완성하고, 오른쪽 소비자가 그 상태를 처음 사용하는 관계다.

01KconfigCONFIG_PBL_IMAGEPBL objects
02linker scriptbarebox symbolsbarebox ELF
03DTBboard identificationPBL image
04compressionpacked main payloadPBL decompressor
05imagetoolROM headerBoot ROM

원본 코드

아래 코드는 Barebox v2026.06.1의 Makefile에서 1074-1162줄을 그대로 가져온 것이다. 설명을 위해 실제 코드를 가짜 의사 코드로 바꾸지 않았다.

commit314c679eea2d0ca847c64d1b646a1cf91225c0ecsymbolbarebox: $(BAREBOX_LDS)
1074# This target has pytest select the YAML env matching CONFIG_NAME if available.
1075# Use pytest --lg-env $labgrid_env_yaml directly if you need more than that.
1076
1077labgrid-env := $(srctree)/test/$(SRCARCH)/$(CONFIG_NAME).yaml
1078
1079check:
1080ifeq ($(CONFIG_NAME),"")
1081	@echo "error: can't autoload labgrid env with CONFIG_NAME unset!" >&2
1082	@exit 1
1083endif
1084	@if [ ! -r "$(labgrid-env)" ]; then \
1085		echo "error: No Labgrid environment at $(labgrid-env)!" >&2; \
1086		echo "Choose a different config (or change CONFIG_NAME)" >&2; \
1087		echo "that can be automatically tested" >&2; \
1088		exit 1; \
1089	fi
1090	@echo
1091	@# This is intentionally not @suppressed, to make it easier to reproduce
1092	(cd $(srctree); KBUILD_OUTPUT=$(abs_objtree) $(PYTEST))
1093
1094PHONY += check
1095
1096# barebox image
1097# ---------------------------------------------------------------------------
1098barebox: $(BAREBOX_LDS) $(BAREBOX_OBJS) $(kallsyms.o) FORCE
1099	$(call if_changed_rule,barebox__)
1100ifeq ($(BAREBOX_PROPER),barebox)
1101	$(Q)rm -f .old_version
1102endif
1103
1104barebox.fit: images/barebox-$(CONFIG_ARCH_LINUX_NAME).fit
1105	$(Q)ln -fsn $< $@
1106
1107barebox.srec: barebox
1108	$(OBJCOPY) -O srec $< $@
1109
1110OBJCOPYFLAGS_vmbarebox = $(call objcopy-option,--strip-section-headers,--strip-all)  \
1111			 --remove-section=.comment \
1112			 --remove-section=.note* \
1113			 --remove-section=.gnu.hash
1114
1115vmbarebox: barebox FORCE
1116	$(call if_changed,objcopy)
1117
1118quiet_cmd_barebox_proper__ = CC      $@
1119      cmd_barebox_proper__ = $(CC) -r -o $@ -Wl,--whole-archive $(BAREBOX_OBJS)
1120
1121.tmp_barebox.o: $(BAREBOX_OBJS) $(kallsyms.o) FORCE
1122	$(if $(CONFIG_KALLSYMS),,+$(call cmd,barebox_version))
1123	$(call cmd,barebox_proper__)
1124	$(Q)echo 'savedcmd_$@ := $(cmd_barebox_proper__)' > $(@D)/.$(@F).cmd
1125	$(Q)rm -f .old_version
1126
1127barebox.o: .tmp_barebox.o FORCE
1128	$(call if_changed,objcopy)
1129
1130# The actual objects are generated when descending,
1131# make sure no implicit rule kicks in
1132$(sort $(BAREBOX_OBJS)) $(BAREBOX_LDS) $(BAREBOX_PBL_OBJS): $(barebox-dirs) ;
1133
1134# Handle descending into subdirectories listed in $(barebox-dirs)
1135# Preset locale variables to speed up the build process. Limit locale
1136# tweaks to this spot to avoid wrong language settings when running
1137# make menuconfig etc.
1138# Error messages still appears in the original language
1139
1140PHONY += $(barebox-dirs)
1141$(barebox-dirs): prepare scripts
1142	$(Q)$(MAKE) $(build)=$@
1143
1144# Store (new) KERNELRELASE string in include/config/kernel.release
1145localversion = $(shell $(srctree)/scripts/setlocalversion $(srctree))
1146include/config/kernel.release: FORCE
1147	$(Q)rm -f $@
1148	$(Q)echo $(KERNELVERSION)$(localversion) > $@
1149
1150# Additional helpers built in scripts/
1151# Carefully list dependencies so we do not try to build scripts twice
1152# in parallel
1153PHONY += scripts
1154scripts: scripts_basic scripts_dtc include/generated/utsrelease.h
1155	$(Q)$(MAKE) $(build)=$(@)
1156
1157# Things we need to do before we recursively start building the kernel
1158# or the modules are listed in "prepare".
1159# A multi level approach is used. prepareN is processed before prepareN-1.
1160# archprepare is used in arch Makefiles and when processed asm symlink,
1161# version.h and scripts_basic is processed / created.
1162

1074-1162줄 해설

원본에 보이는 모든 줄을 순서대로 설명한다. 빈 줄도 block 경계로 남겨, 코드와 설명의 위치가 어긋나지 않게 했다.

1074# This target has pytest select the YAML env matching CONFIG_NAME if available.

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. 관련 설정은 CONFIG_NAME이다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1075# Use pytest --lg-env $labgrid_env_yaml directly if you need more than that.

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1076(빈 줄)

# Use pytest --lg-env $labgrid_env_yaml directly if you need more than that.까지의 동작과 labgrid-env := $(srctree)/test/$(SRCARCH)/$(CONFIG_NAME).yaml에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 embedded DTB 상태가 아래 블록의 입력으로 사용되는 경계다.

1077labgrid-env := $(srctree)/test/$(SRCARCH)/$(CONFIG_NAME).yaml

원본 1077번 줄의 labgrid-env := $(srctree)/test/$(SRCARCH)/$(CONFIG_NAME).yaml는 앞의 이전 block 경계 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1078(빈 줄)

labgrid-env := $(srctree)/test/$(SRCARCH)/$(CONFIG_NAME).yaml까지의 동작과 check:에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1079check:

'check' label이다. 이곳을 참조하는 branch를 역검색하고 각 진입 경로의 register, stack, lock 조건이 같은지 확인한다.

1080ifeq ($(CONFIG_NAME),"")

ifeq($(CONFIG_NAME),"")를 호출한다. 반환값을 직접 사용하지 않으므로 이 함수가 실패를 내부 처리하는지 확인해야 한다. pointer 인자는 barebox: $의 소유권을 넘기는지 호출 동안만 빌리는지 구분하고, 호출 뒤 공개되는 상태를 SoC boot image 항목과 대조한다.

1081@echo "error: can't autoload labgrid env with CONFIG_NAME unset!" >&2

원본 1081번 줄의 @echo "error: can't autoload labgrid env with CONFIG_NAME unset!" >&2는 앞의 ifeq ($(CONFIG_NAME),"") 결과를 받아 다음 @exit 1로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1082@exit 1

원본 1082번 줄의 @exit 1는 앞의 @echo "error: can't autoload labgrid env with CONFIG_NAME unset!" >&2 결과를 받아 다음 endif로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1083endif

원본 1083번 줄의 endif는 앞의 @exit 1 결과를 받아 다음 @if [ ! -r "$(labgrid-env)" ]; then \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1084@if [ ! -r "$(labgrid-env)" ]; then \

원본 1084번 줄의 @if [ ! -r "$(labgrid-env)" ]; then \는 앞의 endif 결과를 받아 다음 echo "error: No Labgrid environment at $(labgrid-env)!" >&2; \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1085echo "error: No Labgrid environment at $(labgrid-env)!" >&2; \

원본 1085번 줄의 echo "error: No Labgrid environment at $(labgrid-env)!" >&2; \는 앞의 @if [ ! -r "$(labgrid-env)" ]; then \ 결과를 받아 다음 echo "Choose a different config (or change CONFIG_NAME)" >&2; \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1086echo "Choose a different config (or change CONFIG_NAME)" >&2; \

config(or change CONFIG_NAME)를 호출한다. 반환값을 직접 사용하지 않으므로 이 함수가 실패를 내부 처리하는지 확인해야 한다. pointer 인자는 barebox: $의 소유권을 넘기는지 호출 동안만 빌리는지 구분하고, 호출 뒤 공개되는 상태를 SoC boot image 항목과 대조한다.

1087echo "that can be automatically tested" >&2; \

원본 1087번 줄의 echo "that can be automatically tested" >&2; \는 앞의 echo "Choose a different config (or change CONFIG_NAME)" >&2; \ 결과를 받아 다음 exit 1; \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1088exit 1; \

원본 1088번 줄의 exit 1; \는 앞의 echo "that can be automatically tested" >&2; \ 결과를 받아 다음 fi로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1089fi

원본 1089번 줄의 fi는 앞의 exit 1; \ 결과를 받아 다음 @echo로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1090@echo

원본 1090번 줄의 @echo는 앞의 fi 결과를 받아 다음 @# This is intentionally not @suppressed, to make it easier to reproduce로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1091@# This is intentionally not @suppressed, to make it easier to reproduce

원본 1091번 줄의 @# This is intentionally not @suppressed, to make it easier to reproduce는 앞의 @echo 결과를 받아 다음 (cd $(srctree); KBUILD_OUTPUT=$(abs_objtree) $(PYTEST))로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1092(cd $(srctree); KBUILD_OUTPUT=$(abs_objtree) $(PYTEST))

원본 1092번 줄의 (cd $(srctree); KBUILD_OUTPUT=$(abs_objtree) $(PYTEST))는 앞의 @# This is intentionally not @suppressed, to make it easier to reproduce 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1093(빈 줄)

(cd $(srctree); KBUILD_OUTPUT=$(abs_objtree) $(PYTEST))까지의 동작과 PHONY += check에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1094PHONY += check

원본 1094번 줄의 PHONY += check는 앞의 이전 block 경계 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1095(빈 줄)

PHONY += check까지의 동작과 # barebox image에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1096# barebox image

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1097# ---------------------------------------------------------------------------

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1098barebox: $(BAREBOX_LDS) $(BAREBOX_OBJS) $(kallsyms.o) FORCE

원본 1098번 줄의 barebox: $(BAREBOX_LDS) $(BAREBOX_OBJS) $(kallsyms.o) FORCE는 앞의 # --------------------------------------------------------------------------- 결과를 받아 다음 $(call if_changed_rule,barebox__)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1099$(call if_changed_rule,barebox__)

원본 1099번 줄의 $(call if_changed_rule,barebox__)는 앞의 barebox: $(BAREBOX_LDS) $(BAREBOX_OBJS) $(kallsyms.o) FORCE 결과를 받아 다음 ifeq ($(BAREBOX_PROPER),barebox)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1100ifeq ($(BAREBOX_PROPER),barebox)

ifeq($(BAREBOX_PROPER),barebox)를 호출한다. 반환값을 직접 사용하지 않으므로 이 함수가 실패를 내부 처리하는지 확인해야 한다. pointer 인자는 barebox: $의 소유권을 넘기는지 호출 동안만 빌리는지 구분하고, 호출 뒤 공개되는 상태를 SoC boot image 항목과 대조한다.

1101$(Q)rm -f .old_version

원본 1101번 줄의 $(Q)rm -f .old_version는 앞의 ifeq ($(BAREBOX_PROPER),barebox) 결과를 받아 다음 endif로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1102endif

원본 1102번 줄의 endif는 앞의 $(Q)rm -f .old_version 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1103(빈 줄)

endif까지의 동작과 barebox.fit: images/barebox-$(CONFIG_ARCH_LINUX_NAME).fit에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1104barebox.fit: images/barebox-$(CONFIG_ARCH_LINUX_NAME).fit

원본 1104번 줄의 barebox.fit: images/barebox-$(CONFIG_ARCH_LINUX_NAME).fit는 앞의 이전 block 경계 결과를 받아 다음 $(Q)ln -fsn $< $@로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1105$(Q)ln -fsn $< $@

원본 1105번 줄의 $(Q)ln -fsn $< $@는 앞의 barebox.fit: images/barebox-$(CONFIG_ARCH_LINUX_NAME).fit 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1106(빈 줄)

$(Q)ln -fsn $< $@까지의 동작과 barebox.srec: barebox에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1107barebox.srec: barebox

원본 1107번 줄의 barebox.srec: barebox는 앞의 이전 block 경계 결과를 받아 다음 $(OBJCOPY) -O srec $< $@로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1108$(OBJCOPY) -O srec $< $@

원본 1108번 줄의 $(OBJCOPY) -O srec $< $@는 앞의 barebox.srec: barebox 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1109(빈 줄)

$(OBJCOPY) -O srec $< $@까지의 동작과 OBJCOPYFLAGS_vmbarebox = $(call objcopy-option,--strip-section-headers,--strip-all) \에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1110OBJCOPYFLAGS_vmbarebox = $(call objcopy-option,--strip-section-headers,--strip-all) \

원본 1110번 줄의 OBJCOPYFLAGS_vmbarebox = $(call objcopy-option,--strip-section-headers,--strip-all) \는 앞의 이전 block 경계 결과를 받아 다음 --remove-section=.comment \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1111--remove-section=.comment \

원본 1111번 줄의 --remove-section=.comment \는 앞의 OBJCOPYFLAGS_vmbarebox = $(call objcopy-option,--strip-section-headers,--strip-all) \ 결과를 받아 다음 --remove-section=.note* \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1112--remove-section=.note* \

원본 1112번 줄의 --remove-section=.note* \는 앞의 --remove-section=.comment \ 결과를 받아 다음 --remove-section=.gnu.hash로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1113--remove-section=.gnu.hash

원본 1113번 줄의 --remove-section=.gnu.hash는 앞의 --remove-section=.note* \ 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1114(빈 줄)

--remove-section=.gnu.hash까지의 동작과 vmbarebox: barebox FORCE에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1115vmbarebox: barebox FORCE

원본 1115번 줄의 vmbarebox: barebox FORCE는 앞의 이전 block 경계 결과를 받아 다음 $(call if_changed,objcopy)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1116$(call if_changed,objcopy)

원본 1116번 줄의 $(call if_changed,objcopy)는 앞의 vmbarebox: barebox FORCE 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1117(빈 줄)

$(call if_changed,objcopy)까지의 동작과 quiet_cmd_barebox_proper__ = CC $@에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1118quiet_cmd_barebox_proper__ = CC $@

원본 1118번 줄의 quiet_cmd_barebox_proper__ = CC $@는 앞의 이전 block 경계 결과를 받아 다음 cmd_barebox_proper__ = $(CC) -r -o $@ -Wl,--whole-archive $(BAREBOX_OBJS)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1119cmd_barebox_proper__ = $(CC) -r -o $@ -Wl,--whole-archive $(BAREBOX_OBJS)

원본 1119번 줄의 cmd_barebox_proper__ = $(CC) -r -o $@ -Wl,--whole-archive $(BAREBOX_OBJS)는 앞의 quiet_cmd_barebox_proper__ = CC $@ 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1120(빈 줄)

cmd_barebox_proper__ = $(CC) -r -o $@ -Wl,--whole-archive $(BAREBOX_OBJS)까지의 동작과 .tmp_barebox.o: $(BAREBOX_OBJS) $(kallsyms.o) FORCE에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1121.tmp_barebox.o: $(BAREBOX_OBJS) $(kallsyms.o) FORCE

원본 1121번 줄의 .tmp_barebox.o: $(BAREBOX_OBJS) $(kallsyms.o) FORCE는 앞의 이전 block 경계 결과를 받아 다음 $(if $(CONFIG_KALLSYMS),,+$(call cmd,barebox_version))로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1122$(if $(CONFIG_KALLSYMS),,+$(call cmd,barebox_version))

원본 1122번 줄의 $(if $(CONFIG_KALLSYMS),,+$(call cmd,barebox_version))는 앞의 .tmp_barebox.o: $(BAREBOX_OBJS) $(kallsyms.o) FORCE 결과를 받아 다음 $(call cmd,barebox_proper__)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1123$(call cmd,barebox_proper__)

원본 1123번 줄의 $(call cmd,barebox_proper__)는 앞의 $(if $(CONFIG_KALLSYMS),,+$(call cmd,barebox_version)) 결과를 받아 다음 $(Q)echo 'savedcmd_$@ := $(cmd_barebox_proper__)' > $(@D)/.$(@F).cmd로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1124$(Q)echo 'savedcmd_$@ := $(cmd_barebox_proper__)' > $(@D)/.$(@F).cmd

원본 1124번 줄의 $(Q)echo 'savedcmd_$@ := $(cmd_barebox_proper__)' > $(@D)/.$(@F).cmd는 앞의 $(call cmd,barebox_proper__) 결과를 받아 다음 $(Q)rm -f .old_version로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1125$(Q)rm -f .old_version

원본 1125번 줄의 $(Q)rm -f .old_version는 앞의 $(Q)echo 'savedcmd_$@ := $(cmd_barebox_proper__)' > $(@D)/.$(@F).cmd 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1126(빈 줄)

$(Q)rm -f .old_version까지의 동작과 barebox.o: .tmp_barebox.o FORCE에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1127barebox.o: .tmp_barebox.o FORCE

원본 1127번 줄의 barebox.o: .tmp_barebox.o FORCE는 앞의 이전 block 경계 결과를 받아 다음 $(call if_changed,objcopy)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1128$(call if_changed,objcopy)

원본 1128번 줄의 $(call if_changed,objcopy)는 앞의 barebox.o: .tmp_barebox.o FORCE 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1129(빈 줄)

$(call if_changed,objcopy)까지의 동작과 # The actual objects are generated when descending,에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1130# The actual objects are generated when descending,

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1131# make sure no implicit rule kicks in

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1132$(sort $(BAREBOX_OBJS)) $(BAREBOX_LDS) $(BAREBOX_PBL_OBJS): $(barebox-dirs) ;

원본 1132번 줄의 $(sort $(BAREBOX_OBJS)) $(BAREBOX_LDS) $(BAREBOX_PBL_OBJS): $(barebox-dirs) ;는 앞의 # make sure no implicit rule kicks in 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1133(빈 줄)

$(sort $(BAREBOX_OBJS)) $(BAREBOX_LDS) $(BAREBOX_PBL_OBJS): $(barebox-dirs) ;까지의 동작과 # Handle descending into subdirectories listed in $(barebox-dirs)에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1134# Handle descending into subdirectories listed in $(barebox-dirs)

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1135# Preset locale variables to speed up the build process. Limit locale

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1136# tweaks to this spot to avoid wrong language settings when running

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1137# make menuconfig etc.

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1138# Error messages still appears in the original language

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1139(빈 줄)

# Error messages still appears in the original language까지의 동작과 PHONY += $(barebox-dirs)에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1140PHONY += $(barebox-dirs)

원본 1140번 줄의 PHONY += $(barebox-dirs)는 앞의 이전 block 경계 결과를 받아 다음 $(barebox-dirs): prepare scripts로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1141$(barebox-dirs): prepare scripts

원본 1141번 줄의 $(barebox-dirs): prepare scripts는 앞의 PHONY += $(barebox-dirs) 결과를 받아 다음 $(Q)$(MAKE) $(build)=$@로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1142$(Q)$(MAKE) $(build)=$@

원본 1142번 줄의 $(Q)$(MAKE) $(build)=$@는 앞의 $(barebox-dirs): prepare scripts 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1143(빈 줄)

$(Q)$(MAKE) $(build)=$@까지의 동작과 # Store (new) KERNELRELASE string in include/config/kernel.release에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1144# Store (new) KERNELRELASE string in include/config/kernel.release

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1145localversion = $(shell $(srctree)/scripts/setlocalversion $(srctree))

원본 1145번 줄의 localversion = $(shell $(srctree)/scripts/setlocalversion $(srctree))는 앞의 # Store (new) KERNELRELASE string in include/config/kernel.release 결과를 받아 다음 include/config/kernel.release: FORCE로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1146include/config/kernel.release: FORCE

원본 1146번 줄의 include/config/kernel.release: FORCE는 앞의 localversion = $(shell $(srctree)/scripts/setlocalversion $(srctree)) 결과를 받아 다음 $(Q)rm -f $@로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1147$(Q)rm -f $@

원본 1147번 줄의 $(Q)rm -f $@는 앞의 include/config/kernel.release: FORCE 결과를 받아 다음 $(Q)echo $(KERNELVERSION)$(localversion) > $@로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1148$(Q)echo $(KERNELVERSION)$(localversion) > $@

원본 1148번 줄의 $(Q)echo $(KERNELVERSION)$(localversion) > $@는 앞의 $(Q)rm -f $@ 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1149(빈 줄)

$(Q)echo $(KERNELVERSION)$(localversion) > $@까지의 동작과 # Additional helpers built in scripts/에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1150# Additional helpers built in scripts/

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1151# Carefully list dependencies so we do not try to build scripts twice

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1152# in parallel

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1153PHONY += scripts

원본 1153번 줄의 PHONY += scripts는 앞의 # in parallel 결과를 받아 다음 scripts: scripts_basic scripts_dtc include/generated/utsrelease.h로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1154scripts: scripts_basic scripts_dtc include/generated/utsrelease.h

원본 1154번 줄의 scripts: scripts_basic scripts_dtc include/generated/utsrelease.h는 앞의 PHONY += scripts 결과를 받아 다음 $(Q)$(MAKE) $(build)=$(@)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1155$(Q)$(MAKE) $(build)=$(@)

원본 1155번 줄의 $(Q)$(MAKE) $(build)=$(@)는 앞의 scripts: scripts_basic scripts_dtc include/generated/utsrelease.h 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

1156(빈 줄)

$(Q)$(MAKE) $(build)=$(@)까지의 동작과 # Things we need to do before we recursively start building the kernel에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

1157# Things we need to do before we recursively start building the kernel

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1158# or the modules are listed in "prepare".

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1159# A multi level approach is used. prepareN is processed before prepareN-1.

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1160# archprepare is used in arch Makefiles and when processed asm symlink,

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1161# version.h and scripts_basic is processed / created.

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

1162(빈 줄)

# version.h and scripts_basic is processed / created.까지의 동작과 다음 block 경계에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

함께 읽어야 하는 원본 코드

첫 코드 조각만으로 동작이 완성되지 않는 경우 호출 매크로, 객체 정의와 실제 실행 목록을 같은 페이지에 묶었다. 각 조각은 같은 기준 commit에서 가져왔다.

01. PBL ELF와 binary image를 링크하는 규칙

images/Makefile 61-137줄이다.

fileimages/Makefileanchor$(obj)/%.pbl:
61else
62BAREBOX_PIGGY_OBJS = $(obj)/../$(BAREBOX_PROPER)
63endif
64
65quiet_cmd_elf__ ?= LD      $@
66      cmd_elf__ ?= $(LD) $(LDFLAGS_$(patsubst .%,%,$(suffix $(@F)))) 	\
67		-e $(2) -Map [email protected] $(LDFLAGS_$(@F)) -o $@		\
68		--gc-sections --defsym=__pbl_board_entry=$(2)  		\
69		-T $(pbl-lds)						\
70		--whole-archive $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) \
71
72PBL_CPPFLAGS	+= -fdata-sections -ffunction-sections
73
74define rule_elf
75	$(call cmd,elf__,$(*F))
76	$(call cmd,prelink__)
77endef
78
79$(obj)/%.pbl: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE
80	$(call if_changed_rule,elf)
81
82$(obj)/%.elf: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE
83	$(call if_changed_rule,elf)
84
85
86# Convert the ELF into a linear binary, check for missing firmware
87# and verify file sizes:
88#
89# For each start symbol create three variables containing the
90# relevant sizes in the image:
91# PBL_CODE_SIZE_$(symbol)   - contains the pure code size of the image
92# PBL_MEMORY_SIZE_$(symbol) - contains the code size + bss size of the
93#                             image
94# PBL_IMAGE_SIZE_$(symbol)  - contains the full image size including the
95#                             compressed payload
96#
97# if MAX_PBL_xxx_SIZE_$(symbol) is defined it contains the maximum size the
98# code/memory/image for this PBL may get. Check these values.
99define rule_pblb
100	$(call cmd,objcopy_bin,$(*F))
101	$(call cmd,check_missing_fw,$@,$<)
102	$(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))
103
104	$(if $(MAX_PBL_CODE_SIZE_$*), \
105		$(call cmd,check_size,$(PBL_CODE_SIZE_$*),$(MAX_PBL_CODE_SIZE_$*)) \
106	)
107
108	$(if $(MAX_PBL_MEMORY_SIZE_$*), \
109		$(call cmd,check_size,$(PBL_MEMORY_SIZE_$*),$(MAX_PBL_MEMORY_SIZE_$*)) \
110	)
111
112	$(if $(MAX_PBL_IMAGE_SIZE_$*), \
113		$(call cmd,check_size,$(PBL_IMAGE_SIZE_$*),$(MAX_PBL_IMAGE_SIZE_$*)) \
114	)
115endef
116
117$(obj)/%.pblb: $(obj)/%.pbl FORCE
118	$(eval PBL_CODE_SIZE_$* = \
119		$(shell $(srctree)/scripts/extract_symbol_offset pbl_code_size $^))
120	$(eval PBL_MEMORY_SIZE_$*= \
121		$(shell $(srctree)/scripts/extract_symbol_offset pbl_memory_size $^))
122	$(eval PBL_IMAGE_SIZE_$*= \
123		$(shell $(srctree)/scripts/extract_symbol_offset pbl_image_size $^))
124
125	$(call if_changed_rule,pblb)
126
127$(obj)/%.s: $(obj)/% FORCE
128	$(call if_changed,disasm)
129
130quiet_cmd_itb = FIT.ITS $@
131cmd_itb = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) \
132	-D'$(subst -,_,$(*F))_dts=1' $(foreach f,$< $(2),-include '$(f)') /dev/null ; \
133	$(MKIMAGE) -f $(dtc-tmp) $@ -E \
134	cat $(depfile).pre $(depfile).dtc > $(depfile)
135
136$(obj)/%.itb: $(obj)/%.its FORCE
137	$(call if_changed,itb)

61-137줄 해설

61else

원본 61번 줄의 else는 앞의 이전 block 경계 결과를 받아 다음 BAREBOX_PIGGY_OBJS = $(obj)/../$(BAREBOX_PROPER)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

62BAREBOX_PIGGY_OBJS = $(obj)/../$(BAREBOX_PROPER)

원본 62번 줄의 BAREBOX_PIGGY_OBJS = $(obj)/../$(BAREBOX_PROPER)는 앞의 else 결과를 받아 다음 endif로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

63endif

원본 63번 줄의 endif는 앞의 BAREBOX_PIGGY_OBJS = $(obj)/../$(BAREBOX_PROPER) 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

64(빈 줄)

endif까지의 동작과 quiet_cmd_elf__ ?= LD $@에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

65quiet_cmd_elf__ ?= LD $@

원본 65번 줄의 quiet_cmd_elf__ ?= LD $@는 앞의 이전 block 경계 결과를 받아 다음 cmd_elf__ ?= $(LD) $(LDFLAGS_$(patsubst .%,%,$(suffix $(@F)))) \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

66cmd_elf__ ?= $(LD) $(LDFLAGS_$(patsubst .%,%,$(suffix $(@F)))) \

원본 66번 줄의 cmd_elf__ ?= $(LD) $(LDFLAGS_$(patsubst .%,%,$(suffix $(@F)))) \는 앞의 quiet_cmd_elf__ ?= LD $@ 결과를 받아 다음 -e $(2) -Map [email protected] $(LDFLAGS_$(@F)) -o $@ \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

67-e $(2) -Map [email protected] $(LDFLAGS_$(@F)) -o $@ \

원본 67번 줄의 -e $(2) -Map [email protected] $(LDFLAGS_$(@F)) -o $@ \는 앞의 cmd_elf__ ?= $(LD) $(LDFLAGS_$(patsubst .%,%,$(suffix $(@F)))) \ 결과를 받아 다음 --gc-sections --defsym=__pbl_board_entry=$(2) \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

68--gc-sections --defsym=__pbl_board_entry=$(2) \

원본 68번 줄의 --gc-sections --defsym=__pbl_board_entry=$(2) \는 앞의 -e $(2) -Map [email protected] $(LDFLAGS_$(@F)) -o $@ \ 결과를 받아 다음 -T $(pbl-lds) \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

69-T $(pbl-lds) \

원본 69번 줄의 -T $(pbl-lds) \는 앞의 --gc-sections --defsym=__pbl_board_entry=$(2) \ 결과를 받아 다음 --whole-archive $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

70--whole-archive $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) \

원본 70번 줄의 --whole-archive $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) \는 앞의 -T $(pbl-lds) \ 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

71(빈 줄)

--whole-archive $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) \까지의 동작과 PBL_CPPFLAGS += -fdata-sections -ffunction-sections에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

72PBL_CPPFLAGS += -fdata-sections -ffunction-sections

원본 72번 줄의 PBL_CPPFLAGS += -fdata-sections -ffunction-sections는 앞의 이전 block 경계 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

73(빈 줄)

PBL_CPPFLAGS += -fdata-sections -ffunction-sections까지의 동작과 define rule_elf에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

74define rule_elf

원본 74번 줄의 define rule_elf는 앞의 이전 block 경계 결과를 받아 다음 $(call cmd,elf__,$(*F))로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

75$(call cmd,elf__,$(*F))

원본 75번 줄의 $(call cmd,elf__,$(*F))는 앞의 define rule_elf 결과를 받아 다음 $(call cmd,prelink__)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

76$(call cmd,prelink__)

원본 76번 줄의 $(call cmd,prelink__)는 앞의 $(call cmd,elf__,$(*F)) 결과를 받아 다음 endef로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

77endef

원본 77번 줄의 endef는 앞의 $(call cmd,prelink__) 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

78(빈 줄)

endef까지의 동작과 $(obj)/%.pbl: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

79$(obj)/%.pbl: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE

원본 79번 줄의 $(obj)/%.pbl: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE는 앞의 이전 block 경계 결과를 받아 다음 $(call if_changed_rule,elf)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

80$(call if_changed_rule,elf)

원본 80번 줄의 $(call if_changed_rule,elf)는 앞의 $(obj)/%.pbl: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

81(빈 줄)

$(call if_changed_rule,elf)까지의 동작과 $(obj)/%.elf: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

82$(obj)/%.elf: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE

원본 82번 줄의 $(obj)/%.elf: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE는 앞의 이전 block 경계 결과를 받아 다음 $(call if_changed_rule,elf)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

83$(call if_changed_rule,elf)

원본 83번 줄의 $(call if_changed_rule,elf)는 앞의 $(obj)/%.elf: $(pbl-lds) $(BAREBOX_PBL_OBJS) $(BAREBOX_PIGGY_OBJS) FORCE 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

84(빈 줄)

$(call if_changed_rule,elf)까지의 동작과 다음 block 경계에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

85(빈 줄)

이전 block 경계까지의 동작과 # Convert the ELF into a linear binary, check for missing firmware에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

86# Convert the ELF into a linear binary, check for missing firmware

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

87# and verify file sizes:

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

88#

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

89# For each start symbol create three variables containing the

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

90# relevant sizes in the image:

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

91# PBL_CODE_SIZE_$(symbol) - contains the pure code size of the image

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

92# PBL_MEMORY_SIZE_$(symbol) - contains the code size + bss size of the

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

93# image

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

94# PBL_IMAGE_SIZE_$(symbol) - contains the full image size including the

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

95# compressed payload

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

96#

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

97# if MAX_PBL_xxx_SIZE_$(symbol) is defined it contains the maximum size the

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

98# code/memory/image for this PBL may get. Check these values.

# 전처리 지시문으로 이 줄 아래의 code가 binary에 존재할지를 결정한다. architecture 또는 build stage 조건을 여닫는다. 현재 .config와 compiler의 -dD -E 출력에서 실제로 남은 branch를 확인한 뒤 line-by-line 흐름에 포함한다.

99define rule_pblb

원본 99번 줄의 define rule_pblb는 앞의 # code/memory/image for this PBL may get. Check these values. 결과를 받아 다음 $(call cmd,objcopy_bin,$(*F))로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

100$(call cmd,objcopy_bin,$(*F))

원본 100번 줄의 $(call cmd,objcopy_bin,$(*F))는 앞의 define rule_pblb 결과를 받아 다음 $(call cmd,check_missing_fw,$@,$<)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

101$(call cmd,check_missing_fw,$@,$<)

원본 101번 줄의 $(call cmd,check_missing_fw,$@,$<)는 앞의 $(call cmd,objcopy_bin,$(*F)) 결과를 받아 다음 $(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

102$(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))

원본 102번 줄의 $(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))는 앞의 $(call cmd,check_missing_fw,$@,$<) 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

103(빈 줄)

$(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))까지의 동작과 $(if $(MAX_PBL_CODE_SIZE_$*), \에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

104$(if $(MAX_PBL_CODE_SIZE_$*), \

원본 104번 줄의 $(if $(MAX_PBL_CODE_SIZE_$*), \는 앞의 이전 block 경계 결과를 받아 다음 $(call cmd,check_size,$(PBL_CODE_SIZE_$*),$(MAX_PBL_CODE_SIZE_$*)) \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

105$(call cmd,check_size,$(PBL_CODE_SIZE_$*),$(MAX_PBL_CODE_SIZE_$*)) \

원본 105번 줄의 $(call cmd,check_size,$(PBL_CODE_SIZE_$*),$(MAX_PBL_CODE_SIZE_$*)) \는 앞의 $(if $(MAX_PBL_CODE_SIZE_$*), \ 결과를 받아 다음 )로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

106)

현재 block, initializer 또는 호출의 경계를 닫는다. 이 지점까지 획득한 resource가 성공 경로와 실패 경로에서 대칭인지 점검한다.

107(빈 줄)

)까지의 동작과 $(if $(MAX_PBL_MEMORY_SIZE_$*), \에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

108$(if $(MAX_PBL_MEMORY_SIZE_$*), \

원본 108번 줄의 $(if $(MAX_PBL_MEMORY_SIZE_$*), \는 앞의 이전 block 경계 결과를 받아 다음 $(call cmd,check_size,$(PBL_MEMORY_SIZE_$*),$(MAX_PBL_MEMORY_SIZE_$*)) \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

109$(call cmd,check_size,$(PBL_MEMORY_SIZE_$*),$(MAX_PBL_MEMORY_SIZE_$*)) \

원본 109번 줄의 $(call cmd,check_size,$(PBL_MEMORY_SIZE_$*),$(MAX_PBL_MEMORY_SIZE_$*)) \는 앞의 $(if $(MAX_PBL_MEMORY_SIZE_$*), \ 결과를 받아 다음 )로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

110)

현재 block, initializer 또는 호출의 경계를 닫는다. 이 지점까지 획득한 resource가 성공 경로와 실패 경로에서 대칭인지 점검한다.

111(빈 줄)

)까지의 동작과 $(if $(MAX_PBL_IMAGE_SIZE_$*), \에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

112$(if $(MAX_PBL_IMAGE_SIZE_$*), \

원본 112번 줄의 $(if $(MAX_PBL_IMAGE_SIZE_$*), \는 앞의 이전 block 경계 결과를 받아 다음 $(call cmd,check_size,$(PBL_IMAGE_SIZE_$*),$(MAX_PBL_IMAGE_SIZE_$*)) \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

113$(call cmd,check_size,$(PBL_IMAGE_SIZE_$*),$(MAX_PBL_IMAGE_SIZE_$*)) \

원본 113번 줄의 $(call cmd,check_size,$(PBL_IMAGE_SIZE_$*),$(MAX_PBL_IMAGE_SIZE_$*)) \는 앞의 $(if $(MAX_PBL_IMAGE_SIZE_$*), \ 결과를 받아 다음 )로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

114)

현재 block, initializer 또는 호출의 경계를 닫는다. 이 지점까지 획득한 resource가 성공 경로와 실패 경로에서 대칭인지 점검한다.

115endef

원본 115번 줄의 endef는 앞의 ) 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

116(빈 줄)

endef까지의 동작과 $(obj)/%.pblb: $(obj)/%.pbl FORCE에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

117$(obj)/%.pblb: $(obj)/%.pbl FORCE

원본 117번 줄의 $(obj)/%.pblb: $(obj)/%.pbl FORCE는 앞의 이전 block 경계 결과를 받아 다음 $(eval PBL_CODE_SIZE_$* = \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

118$(eval PBL_CODE_SIZE_$* = \

원본 118번 줄의 $(eval PBL_CODE_SIZE_$* = \는 앞의 $(obj)/%.pblb: $(obj)/%.pbl FORCE 결과를 받아 다음 $(shell $(srctree)/scripts/extract_symbol_offset pbl_code_size $^))로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

119$(shell $(srctree)/scripts/extract_symbol_offset pbl_code_size $^))

원본 119번 줄의 $(shell $(srctree)/scripts/extract_symbol_offset pbl_code_size $^))는 앞의 $(eval PBL_CODE_SIZE_$* = \ 결과를 받아 다음 $(eval PBL_MEMORY_SIZE_$*= \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

120$(eval PBL_MEMORY_SIZE_$*= \

원본 120번 줄의 $(eval PBL_MEMORY_SIZE_$*= \는 앞의 $(shell $(srctree)/scripts/extract_symbol_offset pbl_code_size $^)) 결과를 받아 다음 $(shell $(srctree)/scripts/extract_symbol_offset pbl_memory_size $^))로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

121$(shell $(srctree)/scripts/extract_symbol_offset pbl_memory_size $^))

원본 121번 줄의 $(shell $(srctree)/scripts/extract_symbol_offset pbl_memory_size $^))는 앞의 $(eval PBL_MEMORY_SIZE_$*= \ 결과를 받아 다음 $(eval PBL_IMAGE_SIZE_$*= \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

122$(eval PBL_IMAGE_SIZE_$*= \

원본 122번 줄의 $(eval PBL_IMAGE_SIZE_$*= \는 앞의 $(shell $(srctree)/scripts/extract_symbol_offset pbl_memory_size $^)) 결과를 받아 다음 $(shell $(srctree)/scripts/extract_symbol_offset pbl_image_size $^))로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

123$(shell $(srctree)/scripts/extract_symbol_offset pbl_image_size $^))

원본 123번 줄의 $(shell $(srctree)/scripts/extract_symbol_offset pbl_image_size $^))는 앞의 $(eval PBL_IMAGE_SIZE_$*= \ 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

124(빈 줄)

$(shell $(srctree)/scripts/extract_symbol_offset pbl_image_size $^))까지의 동작과 $(call if_changed_rule,pblb)에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

125$(call if_changed_rule,pblb)

원본 125번 줄의 $(call if_changed_rule,pblb)는 앞의 이전 block 경계 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

126(빈 줄)

$(call if_changed_rule,pblb)까지의 동작과 $(obj)/%.s: $(obj)/% FORCE에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

127$(obj)/%.s: $(obj)/% FORCE

원본 127번 줄의 $(obj)/%.s: $(obj)/% FORCE는 앞의 이전 block 경계 결과를 받아 다음 $(call if_changed,disasm)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

128$(call if_changed,disasm)

원본 128번 줄의 $(call if_changed,disasm)는 앞의 $(obj)/%.s: $(obj)/% FORCE 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

129(빈 줄)

$(call if_changed,disasm)까지의 동작과 quiet_cmd_itb = FIT.ITS $@에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

130quiet_cmd_itb = FIT.ITS $@

원본 130번 줄의 quiet_cmd_itb = FIT.ITS $@는 앞의 이전 block 경계 결과를 받아 다음 cmd_itb = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

131cmd_itb = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) \

원본 131번 줄의 cmd_itb = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) \는 앞의 quiet_cmd_itb = FIT.ITS $@ 결과를 받아 다음 -D'$(subst -,_,$(*F))_dts=1' $(foreach f,$< $(2),-include '$(f)') /dev/null ; \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

132-D'$(subst -,_,$(*F))_dts=1' $(foreach f,$< $(2),-include '$(f)') /dev/null ; \

원본 132번 줄의 -D'$(subst -,_,$(*F))_dts=1' $(foreach f,$< $(2),-include '$(f)') /dev/null ; \는 앞의 cmd_itb = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) \ 결과를 받아 다음 $(MKIMAGE) -f $(dtc-tmp) $@ -E \로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

133$(MKIMAGE) -f $(dtc-tmp) $@ -E \

원본 133번 줄의 $(MKIMAGE) -f $(dtc-tmp) $@ -E \는 앞의 -D'$(subst -,_,$(*F))_dts=1' $(foreach f,$< $(2),-include '$(f)') /dev/null ; \ 결과를 받아 다음 cat $(depfile).pre $(depfile).dtc > $(depfile)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

134cat $(depfile).pre $(depfile).dtc > $(depfile)

원본 134번 줄의 cat $(depfile).pre $(depfile).dtc > $(depfile)는 앞의 $(MKIMAGE) -f $(dtc-tmp) $@ -E \ 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

135(빈 줄)

cat $(depfile).pre $(depfile).dtc > $(depfile)까지의 동작과 $(obj)/%.itb: $(obj)/%.its FORCE에서 시작하는 동작을 나누는 빈 줄이다. 앞 블록이 만든 SoC boot image 상태가 아래 블록의 입력으로 사용되는 경계다.

136$(obj)/%.itb: $(obj)/%.its FORCE

원본 136번 줄의 $(obj)/%.itb: $(obj)/%.its FORCE는 앞의 이전 block 경계 결과를 받아 다음 $(call if_changed,itb)로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

137$(call if_changed,itb)

원본 137번 줄의 $(call if_changed,itb)는 앞의 $(obj)/%.itb: $(obj)/%.its FORCE 결과를 받아 다음 다음 block 경계로 넘기는 중간 연산이다. 이 줄이 바꾸는 register·field·list link를 찾고, 변경 뒤에도 'ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다' 조건이 유지되는지 확인한다.

내부 동작을 더 깊게 읽기

01

진입 조건을 먼저 고정한다

Kconfig에서 들어온 실행은 빌드 시점에 놓여 있다. 이때 interrupt, MMU/cache, stack, heap 중 무엇이 이미 준비되었는지 소스의 호출자까지 올라가 확인한다. 같은 함수라도 SPL, relocation 전후, app thread처럼 호출 문맥이 달라지면 허용되는 API와 지연 시간이 달라진다.

barebox 실행 파일과 images/ 아래 ROM 투입 파일을 구분한다. PBL 압축, 헤더, load address가 최종 파일에서 어디에 놓이는지 본다.

02

중심 객체의 생성과 공개를 나눈다

이 글의 중심 객체는 barebox: $다. 메모리를 확보한 시점, 필드를 채운 시점, 전역 list나 다른 subsystem에 공개한 시점을 구분한다. 공개 뒤 오류가 발생한다면 목록에서 제거하고 child, buffer, reference를 역순으로 정리하는지 확인한다.

빌드 산출물 관점에서는 barebox, barebox.bin, PBL, images/* 안에 해당 symbol과 section이 실제로 포함되었는지도 map과 objdump로 검증한다.

03

주소, 크기와 정렬을 계산한다

부트 코드의 오류는 논리보다 주소 계산에서 먼저 드러나는 경우가 많다. source range, destination range, header가 말하는 payload size, block 또는 page 단위를 표로 적고 각 구간의 끝 주소를 직접 계산한다. 끝 주소는 start + size - 1인지 exclusive end인지 API 계약을 확인한다.

ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다.

04

성공 flag와 실제 완료 시점을 맞춘다

built-in objects → barebox ELF → PBL and DTB 구간에서는 부분 초기화 상태가 생길 수 있다. flag, list insertion, callback 등록, storage write 완료 중 무엇이 성공의 기준인지 찾는다. hardware write나 DMA가 포함되면 함수 반환과 장치 완료가 같은 시점인지도 확인한다.

다른 CPU, interrupt handler, USB completion 또는 shell command가 상태를 관찰할 수 있다면 memory ordering과 lock 범위도 함께 읽는다.

05

마지막 handoff의 계약을 적는다

정상 경로는 images/에서 끝난다. 이 단계가 함수 반환인지, scheduler 전환인지, 다른 image로의 비복귀 분기인지 구분한다. 비복귀 handoff라면 cache clean/invalidate, interrupt disable, 장치 quiesce, argument register와 FDT 또는 image address가 최종 점검 항목이다.

반환하는 경로라면 caller가 오류와 부분 성공을 구분하고 다음 후보 또는 복구 경로를 선택하는지 확인한다.

구현을 읽을 때 놓치기 쉬운 부분

01

PBL과 full barebox는 서로 다른 실행 환경을 가진다

PBL은 Boot ROM이 제공한 SRAM과 제한된 stack에서 DDR 또는 다음 image를 준비한다. full barebox의 driver, malloc, shell API가 source tree에 있다고 PBL에서 호출할 수 있는 것은 아니며 __PBL__ 조건과 PBL object 목록을 확인해야 한다.

같은 함수 이름도 PBL용 구현과 runtime 구현이 따로 선택될 수 있다.

02

링크 주소와 image packing 단계를 분리한다

PBL ELF의 text 주소, raw payload offset, SoC header가 선언한 load/entry 주소가 모두 맞아야 ROM에서 첫 instruction에 도달한다. piggydata로 full image를 포함하면 압축 data의 source와 decompression destination도 memory map에 추가한다.

map, objdump, final image hexdump에서 각 boundary를 같은 표로 대조한다.

03

크기 제한은 section과 기능 단위로 관리한다

SRAM 제한을 넘으면 header 생성은 성공해도 runtime stack이나 decompressor 영역이 겹칠 수 있다. text/data/BSS, embedded DT와 stack의 최대치를 따로 계산한다.

feature toggle 전후 section delta와 PBL call graph를 기록해 full-only code가 끌려 들어온 원인을 찾는다.

객체와 수명

대상만들어지는 시점유효 범위확인할 조건
barebox: $built-in objectsimages/ 또는 오류 정리 완료까지ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다.
입력 buffer / metadataKconfigparse와 검증이 끝날 때까지길이, 정렬, 소유권, 변조 가능성
등록된 list / descriptorbarebox ELFsubsystem 종료 또는 image handoff까지이중 등록, dangling pointer, 오류 unwind
hardware 또는 persistent state실제 write/probe가 완료된 뒤reset 또는 명시적 해제·갱신까지flush, timeout, 전원 차단, rollback
barebox, barebox.bin, PBL, images/*link/image 생성 시점다음 stage가 새 image로 교체할 때까지load address, entry, section과 header 일치

실패 지점과 증상

#조건관찰되는 증상먼저 볼 단계
01잘못된 image targetROM header 없음built-in objects
02PBL/main address overlap압축 해제 손상barebox ELF
03DTB 미포함보드 식별 실패PBL and DTB

로그가 끊긴 마지막 함수만 고치지 않는다. 그 함수가 받은 주소, size, flag가 만들어진 앞 단계까지 올라가고, 오류 뒤 등록 객체와 hardware 상태가 남았는지도 확인한다.

소스 밖에서 확인할 증거

소스 해석은 실제 빌드 산출물과 target 로그로 닫아야 한다. 아래 명령의 보드 이름과 toolchain prefix는 사용 중인 빌드 환경에 맞게 바꾼다.

#목적명령 또는 계측판정 기준
01빌드 구성make <board>_defconfig && make V=1Kconfig, linker section과 최종 barebox image 생성 명령을 보관한다.
02symbol과 section${CROSS_COMPILE}nm -n barebox | grep 'barebox'initcall, command, driver descriptor가 image에 남았는지 확인한다.
03주소와 resourceiomemimage, malloc, stack, device resource와 reserved 영역의 겹침을 확인한다.
04device 상태devinfo; drvinfo; of_dumpDT node 생성, device 등록, driver probe를 서로 구분한다.
05boot 정책boot -d -v; state -dentry 탐색 결과와 persistent state가 실제 선택에 미친 영향을 확인한다.

직접 확인할 실험

  1. 01
    make V=1로 PBL과 main 링크 명령 분리

    built-in objects 진입 전후에 main image의 주소·크기·반환값과 timestamp를 함께 남긴다. 결과는 정상 부팅 여부로 끝내지 말고 ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다. 조건이 처음 깨지는 줄을 기록한다.

  2. 02
    readelf와 barebox.map 주소 대조

    barebox ELF 진입 전후에 PBL objects의 주소·크기·반환값과 timestamp를 함께 남긴다. 결과는 정상 부팅 여부로 끝내지 말고 ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다. 조건이 처음 깨지는 줄을 기록한다.

  3. 03
    images/*.imx 또는 *.img 헤더 도구로 검사

    PBL and DTB 진입 전후에 embedded DTB의 주소·크기·반환값과 timestamp를 함께 남긴다. 결과는 정상 부팅 여부로 끝내지 말고 ROM용 image의 header, load address, entry와 포함된 PBL/main payload의 위치가 보드 부트 규약과 일치해야 한다. 조건이 처음 깨지는 줄을 기록한다.

원문과 다음 글