부트로더 CI 구축 — build matrix와 자동 부팅 테스트
#한 줄 요약
“부트로더 CI는 빌드가 끝이 아니라 boot가 끝입니다.” — 컴파일이 성공해도 board에서
=>프롬프트가 안 뜨면 의미가 없습니다. PR마다 QEMU 또는 실 보드에서 부팅 로그까지 검증하는 pipeline이 부트로더 CI의 본체입니다.
#부트로더 CI의 어려움
application CI는 unit test로 끝납니다. 부트로더 CI는 그렇게 끝낼 수 없습니다. 컴파일러가 통과시킨 코드가 실 보드에서 DDR training에 실패해 hang하는 일이 자주 일어나고, 어셈블리 한 줄·linker script 한 항목·DTB 한 노드의 변경이 boot 자체를 막을 수 있습니다. 그 사실은 실행해 봐야 알 수 있습니다. 어려움을 만드는 요소가 네 가지입니다.
| 요소 | 내용 | 영향 |
|---|---|---|
| 보드 실기 필요 | DDR·clock·PMIC는 simulator로 못 재현 | 실 보드 farm 운영 비용 |
| 빌드 다양성 | defconfig가 보드마다 다름. SoC 변형 × revision × 옵션 | matrix 차원이 빠르게 폭증 |
| artifact 크기 | debug ELF가 50 ~ 100 MB. multi-target이면 GB 단위 | CI artifact limit 압박 |
| 부팅 자체가 1단계 검증 | 빌드 성공 ≠ boot 성공 | QEMU/real board 자동 boot test 필수 |
Ch 21: 새 보드 포팅에서 본 것처럼 한 보드의 U-Boot defconfig가 정상화되는 데 수십 commit이 들어갑니다. 그 사이 과거 정상 보드가 회귀하지 않게 하려면 CI matrix가 모든 보드를 매 PR마다 검증해야 합니다. 이 장은 pipeline을 build matrix → QEMU boot test → 실 보드 farm → regression 검출 → secure boot 키 관리의 다섯 단으로 쌓아 갑니다.
#build matrix — defconfig·TF-A·OP-TEE 동시
U-Boot은 단독 빌드가 아닙니다. ARMv8-A에서는 TF-A의 BL31과 옵션 OP-TEE가 함께 묶여야 부팅 가능한 image가 됩니다. CI matrix는 세 trees가 동시 build에 들어가는 것을 전제로 합니다.
# .gitlab-ci.yml — U-Boot · TF-A · OP-TEE를 DAG로 묶음stages: [build, boot-test, archive]
.uboot_build: &uboot_build stage: build image: registry.example.com/bootloader-builder:2026.02 cache: { key: "uboot-${BOARD}", paths: [u-boot/.ccache/] } script: - cd u-boot && make ${BOARD}_defconfig - make -j$(nproc) 2>&1 | tee build.log - size u-boot u-boot-spl 2>/dev/null | tee size.txt artifacts: name: "uboot-${BOARD}-${CI_COMMIT_SHORT_SHA}" paths: [u-boot/u-boot.bin, u-boot/u-boot.dtb, u-boot/u-boot.map, u-boot/spl/u-boot-spl.bin, u-boot/size.txt] expire_in: 1 year
build:qemu_arm64: <<: *uboot_build variables: { BOARD: qemu_arm64 }
build:imx8mp: <<: *uboot_build variables: { BOARD: imx8mp_evk } needs: [build:tfa_imx8mp, build:optee_imx8mp]
build:tfa_imx8mp: stage: build script: [cd trusted-firmware-a, make PLAT=imx8mp bl31 -j$(nproc)] artifacts: { paths: [trusted-firmware-a/build/imx8mp/release/bl31.bin] }
build:optee_imx8mp: stage: build script: [cd optee_os, make PLATFORM=imx-mx8mpevk CFG_ARM64_core=y -j$(nproc)] artifacts: { paths: [optee_os/out/arm-plat-imx/core/tee.bin] }핵심은 needs: directive입니다. build:imx8mp는 TF-A와 OP-TEE 결과물에 의존하므로 두 job이 끝나야 시작합니다. GitLab은 이 의존을 DAG로 해석해 불필요한 직렬화 없이 병렬화합니다.
matrix 차원은 세 가지가 표준입니다.
| 차원 | 예 | 용도 |
|---|---|---|
| 보드 | qemu_arm64 / imx8mp / rk3399 | hardware 변형마다 검증 |
| variant | mainline / vendor-fork | 둘 다 유지하는 팀에 필요 |
| secure | non-secure / secure (TF-A + signed) | secure boot regression |
세 차원을 다 켜면 3 × 2 × 2 = 12 job. 작아 보이지만 각 job이 TF-A + OP-TEE + U-Boot을 묶으면 실제 빌드 단위는 36개입니다. self-hosted runner pool 없이는 queue가 깁니다.
#QEMU boot test 자동화
ARMv8-A U-Boot은 QEMU virt에서 -bios u-boot.bin 한 줄로 뜹니다. CI에서 expect script로 부팅 로그의 anchor를 잡아 검증합니다.
#!/usr/bin/env bashset -euo pipefailUBOOT_BIN="${1:-u-boot/u-boot.bin}"LOG="qemu-boot.log"
timeout 30s qemu-system-aarch64 \ -machine virt -cpu cortex-a53 -m 1G \ -nographic -no-reboot -bios "$UBOOT_BIN" > "$LOG" 2>&1 &QEMU_PID=$!
# anchor — U-Boot prompt가 떴는지for i in $(seq 1 30); do if grep -q '^=> ' "$LOG"; then echo "[PASS] U-Boot prompt reached in ${i}s" kill $QEMU_PID 2>/dev/null || true; exit 0 fi sleep 1done
echo "[FAIL] U-Boot prompt not reached"; tail -30 "$LOG"kill $QEMU_PID 2>/dev/null || true; exit 1이 script가 검증하는 것은 DRAM training + driver probe + console init 통과입니다. => 한 줄이 뜨려면 U-Boot이 명령 인터프리터에 진입해야 하므로 부트 체인의 절반 이상이 살아 있다는 신호입니다. 더 깊은 검증은 expect로 version·bdinfo 같은 읽기 전용 명령의 응답까지 확인합니다. write 명령(mw, setenv saveenv)은 flash backing store가 더러워져 다음 run이 영향을 받으므로 피합니다.
Ch 22: 디버깅 워크플로에서 본 로그 anchor 기반 검증이 CI 자동 boot test의 본체입니다.
#LAVA — 실 보드 farm
QEMU로는 잡히지 않는 회귀가 있습니다. 실제 DDR controller, PMIC 시퀀스, eMMC bus, ethernet PHY는 real silicon에서만 드러납니다. Linaro의 LAVA(Linaro Automated Validation Architecture)는 이 문제를 위한 오픈소스 board farm 관리자입니다. 세 가지 개념이 본체입니다. device는 등록된 실 보드, job은 한 device의 flash→boot→test 시퀀스, dispatcher는 device 옆에서 USB·UART·PDU를 잡는 worker입니다.
# imx8mp-boot.yaml — deploy → boot → test의 3단device_type: imx8mp-evkjob_name: u-boot-boot-testtimeouts: { job: { minutes: 15 }, action: { minutes: 5 } }
actions: - deploy: to: usb images: { boot: { url: "https://artifacts.example.com/imx8mp/${SHA}/flash.bin" } } os: u-boot - boot: method: u-boot prompts: ["=> "] timeout: { minutes: 3 } - test: name: uboot-smoke definitions: - { repository: "https://git.example.com/qa/uboot-tests", from: git, path: smoke.yaml, name: smoke }dispatcher는 USB-to-UART로 콘솔을 잡고 *PDU(Power Distribution Unit)*로 전원을 껐다 켭니다. flash는 보드별 SDP/uuu/J-Link를 통합한 deploy method가 처리합니다. LAVA의 실 가치는 trace 보관입니다. 모든 job의 boot log·command output·timing이 영구 저장되어 6개월 뒤 어느 commit에서 어떤 boot 메시지가 바뀌었는지를 git bisect와 함께 추적할 수 있습니다.
#Buildbot·self-hosted runner
LAVA가 부담스러우면 self-hosted runner + USB flash로 더 가볍게 갈 수 있습니다. GitHub Actions self-hosted runner를 보드 옆 PC에 설치하고, runner가 USB 케이블로 flash·reset·console 캡처를 직접 수행합니다.
# .github/workflows/board-test.yml — self-hosted runner가 USB flash → bootjobs: flash-and-boot: runs-on: [self-hosted, board-imx8mp] steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: { name: uboot-imx8mp } - name: Flash via uuu (SDP mode) run: | ./scripts/pdu.sh on port=2 && sleep 1 uuu -b emmc flash.bin - name: Capture console boot log run: | ./scripts/pdu.sh cycle port=2 timeout 30s tio /dev/ttyUSB0 > console.log & sleep 30 && grep -q '^=> ' console.log - uses: actions/upload-artifact@v4 with: { name: console-imx8mp, path: console.log }[self-hosted, board-imx8mp] label로 해당 보드가 연결된 runner에만 job을 라우팅합니다. PDU script가 USB controllable power strip을 제어합니다. 보드 단일 dependency는 단점이지만 학습 곡선이 낮고 초기 비용이 작아 1~2 보드 단계에서 충분합니다. 옵션을 비교하면 다음과 같습니다.
| 옵션 | 보드 수 | 학습 비용 | 적합 |
|---|---|---|---|
| LAVA | 수십 ~ 수백 | 높음 | 양산 라인, 검증 팀 |
| self-hosted runner | 1 ~ 10 | 낮음 | 소규모 팀, 초기 |
| Buildbot worker | 5 ~ 50 | 중간 | 자유도 높은 lab |
| 수동 boot test | 1 ~ 3 | 0 | prototyping 단계 |
#regression 검출
빌드가 통과하고 boot가 떠도 조용한 회귀가 있습니다. image size가 서서히 자라 SPL SRAM 한계에 가까워지거나, boot time이 50 ms씩 누적되는 일입니다. CI에 수치 metric을 박아두고 PR마다 baseline과 비교합니다.
$ size u-boot u-boot-spl/u-boot-spl text data bss dec hex filename 712384 24832 91240 828456 ca4e8 u-boot 78912 1024 12288 92224 168c0 u-boot-spl/u-boot-spl이 값을 JSON으로 떨궈 commit별 추세를 추적하고, CI 마지막 단계에서 baseline과 비교해 임계 초과면 PR을 fail시킵니다.
PR_SIZE=$(jq .text metric-pr.json)BASE_SIZE=$(jq .text metric-base.json)GROWTH=$(( PR_SIZE - BASE_SIZE ))PCT=$(( GROWTH * 100 / BASE_SIZE ))
if [ "$PCT" -gt 2 ]; then echo "REGRESSION: u-boot.bin text grew ${PCT}% (${GROWTH} bytes)" exit 1fi추적할 metric의 예입니다.
| metric | 측정 방식 | 임계 |
|---|---|---|
| u-boot.bin text size | size u-boot | +2% / PR |
| u-boot-spl size | size u-boot-spl | SRAM 한도 - 5% |
| boot time | 첫 printk timestamp 대비 => 시각 | +100 ms / PR |
| DDR training time | SPL 시작 ~ DDR pass anchor | +50 ms / PR |
| secure verify time | BL2가 BL31 검증한 시간 | +20 ms / PR |
| memory test pass rate | mtest 명령 결과 | 100% 미만 즉시 fail |
Ch 25: 부트 시간 측정에서 본 timestamp 기반 측정을 CI metric pipeline에 통합하면 회귀 추세가 자동으로 잡힙니다.
#bisect 자동화
회귀가 잡히면 언제 들어왔는지가 다음 질문입니다. git bisect는 binary search로 첫 failing commit을 찾는 표준 도구입니다. CI artifact가 commit별로 보관되어 있으면 bisect를 자동화할 수 있습니다.
#!/usr/bin/env bash# test.sh — bisect가 호출할 stubset -euo pipefail
cd u-bootmake qemu_arm64_defconfig >/dev/nullmake -j$(nproc) >/dev/null 2>&1 || exit 125 # build fail = skip
../scripts/qemu-boot-test.sh u-boot.bin || exit 1 # boot fail = badexit 0 # boot ok = goodexit 125는 bisect skip 신호입니다. 빌드 자체가 깨진 commit은 good/bad 판정 불가로 처리해 건너뜁니다.
$ git bisect start && git bisect bad HEAD && git bisect good v2024.04$ git bisect run ./test.shBisecting: 187 revisions left to test after this (roughly 8 steps)... (8회 빌드·boot test 자동 반복)e7a9c1f0d is the first bad commit arm: Refactor MMU table generation8 단계면 256 commit 범위를 한 시간 안에 좁힙니다. self-hosted runner pool이 충분하면 밤사이 자동 bisect가 흔한 운영 패턴입니다. CI artifact를 보관할 때 모든 commit의 ELF를 두면 bisect를 재빌드 없이 돌릴 수도 있지만 retention 정책과 짝지어야 합니다.
#artifact 아카이브
부트로더 artifact는 6개월 ~ 1년 보관이 표준입니다. 양산 image가 필드에 깔린 뒤 그 commit의 ELF·map·DTB가 있어야 core dump 해석과 crash address 역추적이 가능합니다.
| 산출물 | 크기 (typical) | 용도 |
|---|---|---|
u-boot.bin | 700 KB | flash 가능한 image |
u-boot (ELF, with debug) | 30 ~ 80 MB | gdb·addr2line |
u-boot.map / System.map | 1 MB / 500 KB | symbol 위치 / kallsyms 매칭 |
u-boot.dtb | 30 KB | runtime device tree |
flash.bin (TF-A + U-Boot) | 1.2 MB | 양산용 flash image |
| boot log | 50 KB | 회귀 비교 (6개월 보관) |
# scripts/archive.sh — image + 메타데이터를 함께 보관TAG=$(git describe --always --tags)DEST="s3://artifacts.example.com/bootloader/${BOARD}/${TAG}"
aws s3 cp u-boot/u-boot.bin "${DEST}/u-boot.bin"aws s3 cp u-boot/u-boot "${DEST}/u-boot.elf"aws s3 cp u-boot/u-boot.map "${DEST}/u-boot.map"aws s3 cp flash.bin "${DEST}/flash.bin"
cat > meta.json <<EOF{ "sha": "$(git rev-parse HEAD)", "tag": "${TAG}", "board": "${BOARD}", "built_at": "$(date -u +%FT%TZ)" }EOFaws s3 cp meta.json "${DEST}/meta.json"meta.json이 함께 가는 것이 핵심입니다. 6개월 뒤 어느 image인지 식별하려면 SHA·tag·board·시각이 묶여 있어야 합니다.
#secure boot CI
서명된 image pipeline은 키 관리가 본체입니다. Ch 27: 신뢰 체인에서 본 production key를 CI runner에 그대로 둘 수는 없습니다. 키 정책은 두 단계로 분리합니다.
| 키 종류 | 용도 | 저장소 | 접근 |
|---|---|---|---|
| ephemeral CI key | PR 검증·dev image | CI secret store (Vault·OIDC) | 모든 CI job |
| production key | release image | HSM (YubiHSM·Cloud KMS) | release pipeline 한정 |
CI는 ephemeral key로 signing flow가 동작하는지만 검증합니다. 양산 image는 별도 release pipeline이 HSM 안에서 서명합니다. private key가 CI runner를 지나가지 않는 것이 필수입니다.
# 서명·hash 검증 — ephemeral key 사용KEY_ID="ephemeral-ci-${CI_COMMIT_SHORT_SHA}"sha256sum u-boot/u-boot.bin > u-boot.bin.sha256
# Vault에서 ephemeral key로 서명 → 검증vault write -field=signature transit/sign/${KEY_ID}/sha2-256 \ input=$(base64 -w0 u-boot.bin.sha256) > u-boot.bin.sig
vault write -field=valid transit/verify/${KEY_ID}/sha2-256 \ input=$(base64 -w0 u-boot.bin.sha256) \ signature=$(cat u-boot.bin.sig)# 출력: true 가 나와야 함production pipeline은 별도 branch protection과 별도 runner pool을 둡니다. release tag(v*)에만 trigger되고 그 runner는 HSM이 연결된 단일 호스트입니다. CI 일반 runner는 production key를 볼 수 없도록 network·secret level 양쪽에서 차단합니다.
#흔한 함정
- flash farm 단일 보드 dependency — 보드가 죽으면 main 머지가 막힙니다. 같은 board_type을 최소 2대 이상 두어 fail-over가 되게 합니다.
- expect script timing fragile —
sleep 5; expect "=> "처럼 sleep을 박으면 느린 boot 한 번에 false fail. 항상 anchor 기반 대기로 작성합니다. - secure boot key leak — CI variable에 base64로 박아두면 job log에 print되는 사고가 종종 납니다. Vault·OIDC short-lived token이 표준입니다.
- artifact 크기가 RUN을 죽임 — ELF + DTB + map을 매 PR마다 보관하면 수 GB / day. 보관은 main 머지 + release tag에만 두고, PR artifact는 14일 retention으로 줄입니다.
- regression 임계가 너무 빡빡 —
+0.1%로 잡으면 vendor patch 한 번에 fail. 보통 +2% 또는 절대값 + 10 KB가 운영 가능한 임계입니다. - boot test가 production rootfs까지 — CI에서 user space까지 부팅하려 들면 시간이 10분을 넘습니다. U-Boot prompt +
bootm시작 anchor까지가 부트로더 CI의 책임 범위입니다. - bisect script가
exit 125를 안 다룸 — 빌드 fail commit을 bad로 판정하면 wrong commit을 지목합니다. 빌드 실패는 반드시 skip(125).
| CI 플랫폼 | matrix | self-hosted | secret store | 보드 farm 통합 |
|---|---|---|---|---|
| GitLab CI | parallel: matrix | docker/shell runner | Vault·File | LAVA에 webhook |
| GitHub Actions | strategy.matrix | label로 routing | OIDC + Vault | LAVA에 webhook |
| Jenkins | declarative pipeline | agent label | Credentials Plugin | LAVA plugin 존재 |
| Buildbot | builders × steps | worker per board | secret module | 내장 |
| Drone | matrix | docker runner | secret refs | webhook |
LAVA를 직접 통합하려면 빌드 → S3 업로드 → LAVA submit-job → polling → 결과 회수의 5단을 묶어야 합니다. Buildbot은 LAVA worker가 builder로 직접 노출되어 통합이 가장 짧습니다.
#시리즈 마무리
30장을 통해 부트로더가 POR 직후의 죽은 CPU에서 Linux user space까지 다리를 놓는 전 과정을 따라왔습니다. BootROM의 결정, SPL의 SRAM 안 좁은 공간, DDR training의 까다로움, U-Boot Proper의 driver model, ARMv8-A의 BL31·BL33 분업, secure boot의 chain of trust, A/B fallback의 부팅을 끊어내지 않는 설계, 그리고 마지막으로 그 모든 코드가 PR마다 검증되는 CI까지.
부트로더는 눈에 띄지 않는 시스템입니다. 잘 만들어진 부트로더는 0.5초 만에 사라지고 사용자가 의식하지 않습니다. 잘못 만들어진 부트로더는 제품을 brick으로 바꾸어 라인 전체를 멈춥니다. 그 무게의 비대칭이 이 시리즈를 쓴 이유였습니다.
다음 시리즈로 이어가고 싶은 방향이 셋 있습니다. 부트로더 다음에 Linux kernel이 어떻게 시작하는지를 따라가는 Linux Kernel Internals, 부트로더와 커널과 rootfs를 한 product로 묶어내는 BSP Engineering, 그리고 대량 양산용 image 빌드 파이프라인인 Buildroot Practical입니다.
| 추천 시리즈 | 다루는 범위 | 부트로더와의 연결 |
|---|---|---|
| Linux Kernel Internals | head.S → start_kernel → init | 커널 진입 ABI 이후의 흐름 |
| BSP Engineering | U-Boot 포팅·driver·DTS·image | 새 보드 전체 stack 통합 |
| Buildroot Practical | rootfs 빌드·OTA·SDK | image pipeline 자동화 |
각 시리즈가 부트로더와 한 면씩 맞붙어 있어 자연스러운 확장이 됩니다.
#정리
- 부트로더 CI는 컴파일 성공이 아니라 boot 성공이 종료 조건입니다. PR마다 QEMU 또는 실 보드에서 부팅 로그까지 검증합니다.
- build matrix는 U-Boot·TF-A·OP-TEE를 DAG로 묶어 병렬화합니다. 차원은 보드 × variant × secure가 표준입니다.
- QEMU boot test는
=>prompt anchor를 잡는 expect script로 가볍게 시작합니다.version·bdinfo같은 읽기 전용 명령만 검증에 씁니다. - 실 보드 farm은 LAVA(대규모)와 self-hosted runner(소규모) 두 갈래입니다. PDU로 전원 cycle, USB-to-UART로 콘솔 캡처가 공통 패턴입니다.
- regression metric은 image size·boot time·DDR training time이 표준이고 임계는 +2% 또는 +10 KB 정도가 운영 가능합니다.
git bisect run에서 빌드 실패는 반드시 exit 125로 skip 처리합니다. - artifact는
u-boot.bin·ELF·map·DTB·flash.bin +meta.json을 1년 보관. SHA·tag·board가 묶여 있어야 6개월 뒤 추적이 됩니다. - secure boot 키는 ephemeral CI key와 production HSM key를 분리합니다. CI runner는 production key를 볼 수 없어야 합니다.
- 흔한 함정은 flash farm 단일 보드, expect timing fragile, 키 leak, artifact 폭증, bisect skip 누락 다섯입니다.
- 부트로더 CI의 본체는 cache 공유보다 boot 검증과 키 정책입니다. application CI와 가장 크게 다른 지점입니다.
#관련 항목
- Ch 21: 새 보드 포팅 — defconfig부터 첫 부팅까지 — matrix에 새 보드를 추가하는 출발점
- Ch 22: 디버깅 워크플로 — JTAG·printk·boot log — boot test에서 로그 anchor를 잡는 근거
- Ch 25: 부트 시간 측정 — regression metric의 timestamp source
- Ch 27: 신뢰 체인 — secure boot key 관리 — secure boot CI의 key 정책 전제
- Buildroot Ch 19: CI/CD — container build와 cache 공유 — rootfs CI와의 비교
- 원문 — LAVA 공식 문서 — board farm 자동화
- 원문 — U-Boot test/py 프레임워크 — U-Boot 공식 boot test 인프라
Bootloader Internals · 30 of 37
- 1ROM부터 init까지 — 임베디드 부팅 단계의 빈자리 분석
- 2Das U-Boot vs TF-A vs EDK II — 임베디드 부트로더 생태계 비교
- 3U-Boot 빌드 시스템 분석 — Kconfig·Makefile·defconfig 동작 추적
- 4ARM 임베디드 부트 4단계 분해 — BL1·SPL·TPL·U-Boot Proper의 역할
- 5U-Boot Falcon Mode — SPL이 U-Boot Proper 없이 커널 직접 부팅
- 6Device Tree DTB 부트로더 처리 — 로딩 시점과 fixup 메커니즘 추적
- 7U-Boot Driver Model 내부 — uclass·driver·device 추상화 구조
- 8U-Boot 보드 초기화 시퀀스 — board_init_f와 board_init_r 분리 이유
- 9DDR Controller 프로그래밍과 PHY Training — SPL의 가장 어려운 작업
- 10임베디드 스토리지 부팅 분석 — MMC·SCSI·NAND·SPI Flash 비교
- 11임베디드 네트워크 부팅 — TFTP·PXE·BOOTP 시퀀스 분석
- 12U-Boot USB 부팅 — fastboot·UMS·USB host 메커니즘
- 13U-Boot 환경 변수와 bootcmd — 부팅 시나리오 정의하기
- 14Modern U-Boot bootflow / bootmeth — 새 추상화 레이어 분석
- 15FIT image 구조 분석 — multi-image·hash·configuration 추적
- 16U-Boot Verified Boot — RSA 서명과 public key 임베딩 흐름
- 17임베디드 A/B 부팅 이중화 — OTA 안전성을 위한 부트 슬롯 설계
- 18U-Boot의 EFI 호환 분석 — bootefi 명령과 EFI loader 동작 원리
- 19Linux Boot ABI — ARM/ARM64 커널 진입 규약 추적
- 20임베디드 펌웨어 업데이트 — RAUC vs SWUpdate 비교
- 21새 보드 U-Boot 포팅 실전 — defconfig 작성부터 첫 부팅까지
- 22부트로더 디버깅 기법 — DEBUG·JTAG·serial·post-mortem 분석
- 23SoC BootROM·eFuse·OTP — 부팅의 0단계 분석
- 24SPL·TPL 내부 해부 — 가장 작은 부트 단계의 동작 추적
- 25ARM Trusted Firmware-A 통합 — BL1·BL2·BL31·BL32·BL33 흐름
- 26DDR Training과 PHY Calibration — 보드별 파라미터 튜닝
- 27임베디드 Chain of Trust — 다단계 서명 검증의 전체 흐름
- 28임베디드 Flash Layout 설계 — partition·NAND·eMMC·UBI 비교
- 29U-Boot Distro Boot — extlinux·boot.scr 표준화 분석
- 30부트로더 CI 구축 — build matrix와 자동 부팅 테스트
- 31TF-A BL31 EL3 Runtime 분석 — PSCI·SDEI·RAS dispatcher 추적
- 32PSCI와 SMCCC ABI — ARM 표준 SMC 호출 규약 분석
- 33ARM64 Secondary Core Bring-up — PSCI CPU_ON 호출부터 EL1 진입까지
- 34U-Boot PCIe Enumeration — 부트로더가 디바이스를 찾는 흐름 분석
- 35EFI·UEFI에서 CXL 초기화 — CEDT 생성과 HDM Decoder 사전 설정
- 36부트 시 메모리 토폴로지 결정 — DDR + CXL.mem 통합 인식
- 37UEFI Secure Boot 인증서 만료 — 2011→2023 CA 롤오버와 PQC 대비
관련 글
UEFI Secure Boot 인증서 만료 — 2011→2023 CA 롤오버와 PQC 대비
2026년 6월부터 시작되는 Microsoft Secure Boot 2011 인증서 만료 — PK·KEK·db·dbx 계층, 2023 CA 체인과 Option ROM CA 분리, 임베디드 기기 영향, 그리고 post-quantum 서명으로의 길.
부트 시 메모리 토폴로지 결정 — DDR + CXL.mem 통합 인식
부트로더가 DDR DIMM·CXL.mem·HBM을 하나의 메모리 토폴로지로 통합하는 흐름 — SRAT·HMAT·SLIT 생성과 NUMA 노드 매핑.
EFI·UEFI에서 CXL 초기화 — CEDT 생성과 HDM Decoder 사전 설정
EDK II 기반 UEFI에서 CXL 디바이스 초기화 — CEDT(CXL Early Discovery Table) 생성, HDM Decoder 사전 설정, ACPI handoff.