# Day2 Boot image header in RISC-V Linux

${linux}/Documentation/arch 里面有 5 篇文件,前面这几天,大概都会是从这几篇文件着墨;昨天的第 1 篇是描述 riscv-linux 的维护守则,今天来看的是,Boot image header in RISC-V Linux!描述的是一个 RISC-V 启动影像档,该要包含什麽样的标头,才可以被辨识为正确的启动影像档。

文件

============================
RISC-V Linux 的启动影像档标头
============================

:Author: Atish Patra <[email protected]>
:Date:   20 May 2019

这份文件仅描述 RISC-V Linux 启动影像档标头的详细讯息。

待完成:
  写一份完整的启动流程指南。
  
解压缩後的 Linux 核心影像档中会含有以下 64 位元组的标头::

    u32 code0;                /* 可执行程序码 */
    u32 code1;                /* 可执行程序码 */
    u64 text_offset;          /* 载入影像的偏移量  */
    u64 image_size;           /* 有效影像大小,小端序 */
    u64 flags;                /* 核心旗标,小端序 */
    u32 version;              /* 标头版本 */
    u32 res1 = 0;             /* 保留 */
    u64 res2 = 0;             /* 保留 */
    u64 magic = 0x5643534952; /* 魔术数字,小端序,"RISCV" */
    u32 magic2 = 0x05435352;  /* 魔术数字 2,小端序,"RSC\x05" */
    u32 res3;                 /* 保留 PE COFF 的偏移量 */

这种标头格式是深受 ARM64 标头的影响并且相容於 PE/COFF 标头。
因此,将来可以将 ARM64 和 RISC-V 标头合并为一个通用标头。

注
==
- 将来,这个标头还可用来支援 RISC-V 的 EFI 模拟实作。 EFI 规范需要核心影像开头的 PE/COFF 影像标头,以便将其视作 EFI 应用程序来运行。为了支援 EFI 模拟,code0 应替换为 "MZ" 魔术字串,res3(偏移量 0x3c)应指向 PE/COFF 标头的其余部分。

- 版本栏位标示的是版本号

    ==========  =====
    位元 0:15   小版号
    位元 16:31  大版号
    ==========  =====

  这样可以保证新、旧版本间的相容性。
  目前的版本被定义为 0.2。

- 自 0.2 版後,"magic" 栏位已不适用。在未来的版本中,它可能会被删除。这本来应该和 ARM64 标头 "magic" 栏位相符,但不幸的是没有。 "magic 2" 栏位是用来替换 "magic" 的,并且与 ARM64 标头相符。

- 在目前的标头中,旗标栏位仅只有一个栏位。

    ======  ===============================================
    位元 0   核心的位元组顺序。 小端序,则为 1;大端序,则为 0。
    ======  ===============================================

- 启动载入程序会需要核心影像档案的大小资讯,否则启动程序将会失败。

我的理解

  • 一般来说,开机流程都会由一个 Boot Loader 来把 Kernel 安置在一个理想的位置,再把控制权转交过去;而 header 的用处,就是让 Boot Loader 确认这个他看到的档案,是一个正确的影像档,举例来说,RISC-V 的 Kernel 影像档。
  • 以 u-boot 来说,在 booti 指令实作中,就有针对 header 的检查:
booti 的使用方式: $ booti <kernel image addr> - <fdt addr>

/* ${uboot}/arch/riscv/lib/image.c */
int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
        bool force_reloc)
{
    struct linux_image_h *lhdr;

    lhdr = (struct linux_image_h *)map_sysmem(image, 0);  // booti 指令中 kernel image 的 addr

    if (lhdr->magic != LINUX_RISCV_IMAGE_MAGIC) {         // 比对 magic 2 的栏位
        puts("Bad Linux RISCV Image magic!\n");
        return -EINVAL;
    }

    if (lhdr->image_size == 0) {                          // 确认 image_size 不为零
        puts("Image lacks image_size field, error!\n");
        return -EINVAL;
    }
    *size = lhdr->image_size;
    ...
}
  • 在 Kernel 中,则是在 ${linux}/arch/riscv/kernel/head.S 中,把 Kernel Image 的 header 加上去的
__HEAD                                                 /* MACRO --> .head.text */
ENTRY(_start)
    /*
     * Image header expected by Linux boot-loaders. The image header data
     * structure is described in asm/image.h.
     * Do not modify it without modifying the structure and all bootloaders
     * that expects this header format!!
     */
    /* jump to start kernel */
    j _start_kernel                                    /* 可执行程序码 */
    /* reserved */
    .word 0                                            /* 可执行程序码 */
    .balign 8
#if __riscv_xlen == 64
    /* Image load offset(2MB) from start of RAM */
    .dword 0x200000                                    /* 载入影像的偏移量 */
#else
    /* Image load offset(4MB) from start of RAM */
    .dword 0x400000                                    /* 载入影像的偏移量 */
#endif
    /* Effective size of kernel image */
    .dword _end - _start                               /* 有效影像大小,小端序 */
    .dword __HEAD_FLAGS                                /* 核心旗标,小端序 */
    .word RISCV_HEADER_VERSION                         /* 标头版本 */
    .word 0                                            /* 保留 */
    .dword 0                                           /* 保留 */
    .ascii RISCV_IMAGE_MAGIC                           /* 魔术数字,小端序,"RISCV" */
    .balign 4
    .ascii RISCV_IMAGE_MAGIC2                          /* 魔术数字 2,小端序,"RSC\x05" */
    .word 0                                            /* 保留 PE COFF 的偏移量 */
  • 可以透过 xxdhexdump 等工具来检视
$ xxd ${linux}/arch/riscv/boot/Image |less
0000000: 6f10 0000 0000 0000 0000 2000 0000 0000  o......... .....
0000010: 3c30 7701 0000 0000 0000 0000 0000 0000  <0w.............
0000020: 0200 0000 0000 0000 0000 0000 0000 0000  ................
0000030: 5249 5343 5600 0000 5253 4305 0000 0000  RISCV...RSC.....
...

Patch Time

不免俗地来送个 patch 吧!

$ git send-email --to [email protected] \
                 --to [email protected] \
                 --to [email protected] \
                 --to [email protected] \
                 --to [email protected] \
                 --cc [email protected] \
                 --cc [email protected] \
                 0001-docs-zh_TW-Add-translation-for-riscv-boot-image-head.patch

後记

原来持续的 output 会这麽累啊,才写 2 篇文章,就筋疲力尽的感觉~XDD
感谢各位收看,让我重整旗鼓,我们明日再战!


<<:  【LeetCode】Binary Search Tree

>>:  CSS-Model 盒模型

Day 17 - canvas 文字换行

程序码 今天来学习文字换行 export default function App() { cons...

第 12 天 范本变数加范本输入变数|template variables、template input variables

前情提要 简单地聊聊范本驱动表单(Template Driven Fomrs)後,应该会觉得范本变数...

鬼故事 - 总有刁民想害朕

鬼故事 - 总有刁民想害朕 Credit: 海绵宝宝 灵感来源:UCCU Hacker 故事开始 故...

RestTemplate介绍(Day10)

熟悉JWT的我敲开了大门的门锁,走进了房间 同学:来,你过来~~ 我:干嘛啦 (被推着坐下),哇,同...

【在厨房想30天的演算法】Day 24 资讯安全与演算法 : 共用金钥密码系统

Aloha!又是我少女人妻 Uerica !最近 KTV 终於解封了,只是戴口罩又只能喝水要怎麽唱,...