U-Boot là gì trong embedded Linux? Đây là bootloader xuất hiện rất phổ biến trên các board Linux nhúng và thường là stage đứng ngay trước kernel. Sau bài tổng quan về boot chain trong embedded Linux, đây là thành phần cần nhìn kỹ vì nó quyết định hệ thống boot từ đâu, dùng kernel nào, lấy DTB nào, truyền bootargs gì và có rẽ sang recovery hay không.
Nếu làm embedded Linux, gần như sớm muộn gì cũng sẽ phải đọc log, sửa environment hoặc debug một vấn đề liên quan tới U-Boot. Đây là một trong những điểm chạm thường xuyên nhất khi phân tích lỗi boot.
Mục lục
Khái niệm U-Boot trong embedded Linux
U-Boot là một bootloader rất phổ biến trong embedded Linux. Nó đứng giữa các bước khởi động sớm của phần cứng và kernel Linux, rồi chuẩn bị các điều kiện cần thiết để kernel có thể bắt đầu boot.
Nói ngắn gọn, U-Boot thường là nơi thực thi hoặc điều phối việc thiết bị sẽ load kernel nào, load từ đâu, dùng DTB nào, truyền bootargs gì và đi theo nhánh boot nào.
Vị trí của U-Boot trong boot chain
U-Boot thường nằm ở gần cuối boot chain, sau Boot ROM và first-stage bootloader hoặc SPL, nhưng trước kernel Linux. Một flow quen thuộc có thể là:
- Boot ROM chạy trước.
- First-stage Bootloader hoặc SPL chạy tiếp theo.
- U-Boot chạy sau khi đã có đủ điều kiện cần thiết.
- U-Boot load kernel, DTB và các thông tin boot liên quan.
- Kernel Linux bắt đầu boot.
- Userspace lên sau khi kernel mount được root filesystem.
Cần nhớ rằng U-Boot chưa phải đích cuối của quá trình boot. Nó chỉ là một stage trong boot chain, nhưng là stage nắm nhiều quyết định quan trọng ngay trước khi kernel chạy.
Với MCU, bootloader thường kết thúc ở bước jump sang application image. Với embedded Linux, U-Boot mới chỉ là phần chuẩn bị rồi chuyển quyền điều khiển cho kernel bắt đầu boot.
Các nhiệm vụ chính của U-Boot
Các nhiệm vụ chính của U-Boot là chuẩn bị kernel và các thông tin cần thiết để hệ thống có thể boot đúng nhánh. Những việc thường gặp nhất là:
- Load kernel image.
- Load DTB, tức device tree blob.
- Chuẩn bị bootargs cho kernel.
- Chọn nơi boot, ví dụ eMMC, SD card, NAND, NOR hoặc network.
- Chọn partition hoặc root filesystem phù hợp.
- Đi vào recovery, rescue boot hoặc update mode nếu cần.
Thực tế, nhiều flow update và recovery trên embedded Linux cũng xoay quanh U-Boot, vì đây là nơi quyết định hệ thống sẽ boot theo nhánh nào.
Sự khác nhau giữa U-Boot và bootloader MCU
Khác biệt lớn nhất giữa U-Boot và bootloader MCU là phạm vi công việc. Bootloader MCU thường tập trung vào flash memory, state machine, image validation và jump sang application image. U-Boot thì rộng hơn nhiều.
Nó phải quan tâm tới storage, partition, kernel image, DTB, bootargs, root filesystem và nhiều biến cấu hình khác. Vì vậy cách làm việc với U-Boot cũng gần với một môi trường boot có thể cấu hình được, chứ không chỉ là một đoạn code nhảy app như trên MCU.
Environment, bootcmd và bootargs
Một điểm rất đặc trưng của U-Boot là cơ chế environment variables. Đây là tập biến dùng để điều khiển boot flow, nên trong nhiều trường hợp có thể đổi cách boot mà chưa cần sửa code C.
Trong số đó, hai cái hay gặp nhất là bootcmd và bootargs.
bootcmd là chuỗi lệnh U-Boot sẽ chạy để boot hệ thống.
bootargs là chuỗi tham số truyền xuống kernel Linux.
Vì vậy, chỉ cần environment thay đổi, boot flow thực tế cũng có thể đổi theo: boot từ storage khác, đổi rootfs, thêm tham số kernel hoặc bật tạm một mode rescue.
SPL và cấu trúc nhiều stage của U-Boot
SPL là stage U-Boot rút gọn chạy sớm để chuẩn bị tài nguyên tối thiểu trước khi bản U-Boot đầy đủ có thể hoạt động. Nhiều nền tảng embedded Linux không thể chạy bản U-Boot đầy đủ ngay từ đầu vì lúc đó DRAM có thể chưa được init, SRAM còn ít và phần cứng mới chỉ ở trạng thái tối thiểu.
Vì vậy người ta hay tách ra một stage nhỏ hơn, thường gọi là SPL. Stage này làm việc tối thiểu như init DRAM hoặc chuẩn bị điều kiện để stage U-Boot đầy đủ chạy tiếp.
U-Boot trong update và recovery
Trong nhiều hệ, U-Boot còn là thành phần trung tâm điều phối update và recovery, không chỉ đơn thuần dùng để boot kernel.
- Chọn partition active hoặc inactive.
- Boot vào root filesystem dự phòng.
- Boot vào rescue image hoặc update mode.
- Boot từ network để cứu hệ thống.
- Phối hợp với A/B partition hoặc verified boot.
Vì vậy, khi debug update hoặc recovery trên embedded Linux, rất nhiều khi vấn đề nằm ngay ở U-Boot chứ không phải ở kernel hay userspace.
Những lỗi hay gặp khi làm việc với U-Boot
Những lỗi dưới đây là các vấn đề rất hay gặp khi debug U-Boot:
- Load sai kernel image.
- Dùng sai DTB.
- Bootargs sai nên kernel không mount được root filesystem.
- Environment bị hỏng hoặc lưu sai giá trị.
- Offset, partition hoặc storage target bị trỏ nhầm.
- Boot flow thực tế khác với điều mình tưởng vì bootcmd đang chạy nhánh khác.
Đây là lý do lúc debug U-Boot, nhìn đúng environment và đúng bootcmd thường quan trọng không kém việc nhìn kernel log. Nếu muốn đối chiếu lại bức tranh tổng thể trước khi đi sâu vào log và biến môi trường, anh có thể xem lại bài boot chain trong embedded Linux.
Kết luận
U-Boot là một trong những thành phần trung tâm của boot flow embedded Linux. Nó không chỉ load kernel, mà còn quyết định nhiều thứ liên quan tới DTB, bootargs, storage, update và recovery. Nếu muốn hiểu vì sao một board Linux boot được hoặc không boot được, U-Boot gần như luôn là một điểm phải nhìn vào.
Bài tiếp theo, nếu đi tiếp theo đúng mạch series, nên đào sâu vào environment, bootcmd và bootargs vì đó là nơi rất nhiều lỗi boot thực tế bắt đầu lộ ra.








