如何控制grub从磁盘加载到内存的内容量?

How to control the amount of contents loaded into memory from disk by grub?

我正在开发一个由 grub 启动的玩具 OS。

但是,内核映像中的某些部分(尤其是 objcopy-ed 到原始内核映像的部分)在启动时不会加载到物理内存中。 (即跳转到内核精灵定义的 ENTRY 后)

这里有一些问题。

是什么决定了grub从磁盘加载到内存的内容的大小?我可以配置它吗?

或者大小是固定的,我是否应该从磁盘中手动读取其余部分?

################更新################

There are 21 section headers, starting at offset 0x279bfc:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        01000000 001000 009a79 00  AX  0   0 16
  [ 2] .rodata           PROGBITS        0100a000 00b000 0012b0 00   A  0   0 4096
  [ 3] .eh_frame         PROGBITS        0100b2b0 00c2b0 0041b0 00   A  0   0  4
  [ 4] .data             PROGBITS        02000000 011000 002400 00  WA  0   0 4096
  [ 5] .bss              NOBITS          02002400 013400 108430 00  WA  0   0 1024
  [ 6] .percpu_data      PROGBITS        0210a880 11b880 002880 00  WA  0   0 4096
  [ 7] .comment          PROGBITS        00000000 11e100 000011 01  MS  0   0  1
  [ 8] .debug_aranges    PROGBITS        00000000 11e118 000620 00      0   0  8
  [ 9] .debug_info       PROGBITS        00000000 11e738 011352 00      0   0  1
  [10] .debug_abbrev     PROGBITS        00000000 12fa8a 004750 00      0   0  1
  [11] .debug_line       PROGBITS        00000000 1341da 00577b 00      0   0  1
  [12] .debug_str        PROGBITS        00000000 139955 00403c 01  MS  0   0  1
  [13] .debug_loc        PROGBITS        00000000 13d991 008966 00      0   0  1
  [14] .debug_ranges     PROGBITS        00000000 1462f7 000840 00      0   0  1
  [15] .part1            PROGBITS        0c000000 147000 096ba8 00   A  0   0  1
  [16] .part2            PROGBITS        0c100000 1de000 096b58 00   A  0   0  1
  [17] .srtos_conf       PROGBITS        0c1a0000 275000 00064f 00   A  0   0  1
  [18] .symtab           SYMTAB          00000000 275650 002780 10     19 157  4
  [19] .strtab           STRTAB          00000000 277dd0 001d64 00      0   0  1
  [20] .shstrtab         STRTAB          00000000 279b34 0000c7 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0x1000038
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0x01000000 0x01000000 0x0f460 0x0f460 R E 0x1000
  LOAD           0x011000 0x02000000 0x02000000 0x10d100 0x10d100 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata .eh_frame 
   01     .data .bss .percpu_data 

特别是,我想让 GRUB 加载 .part1.part2.srtos_conf 部分。

我猜它们没有加载,因为它们不是程序的一部分 headers。

如何将这些部分添加为程序 headers?

目前,这些使用 objcopy --add-section XXX 合并到内核中,节标志为 alloc,readonly,load,contents

我必须使用哪个选项才能将这些部分添加到程序中 headers?

向 ELF 添加新部分的 objcopy 方法似乎过于有限。 https://reverseengineering.stackexchange.com/a/14780 表示不可能 以这种方式添加程序头条目。

我建议使用 objcopy 为 .part1 等创建目标文件, 然后在构建 kernel.elf 时将这些指定为链接器的附加输入。 Objcopy 将放置文件 .data 部分中的内容,并将创建符号 _binary_x_start /_binary_x_end / _binary_x_size 为了方便。

举个例子:

从任何类型的文件创建目标文件(替换您的目标三元组):

i686-elf-objcopy --input binary -B i386 -O elf32-i386 x x.o

将 x.o 添加到链接器输入可扩展 .data 输出部分以包含 文件内容,自然会导致它被加载程序加载。

如果需要,您可以使用链接描述文件控制文件的加载位置。 (具有正确参数的 objcopy 也可以为您执行此操作,但是链接描述文件 通常是一种更清洁的方法。

例如,要将文件专门放置在 0x200000,您可以这样做:

/* ... */

.data : {
    *(EXCLUDE_FILE(x.o) .data)
}

. = 0x0200000;
.foo : {
    x.o (.data)
}

/* ... */

当然你也可以重命名目标文件中的部分以避免 EXCLUDE_FILE 这里。


您可能想要查看的另一个选项是使用多重引导模块。将文件作为模块可能是一种更简单的方法,但让您无法控制 where/how 它们的加载。
它还将您与多重启动联系在一起,超出您的想象(我喜欢我的引导加载程序简单且可更换 ;-)。