gpt4 book ai didi

assembly - Grub 错误 28 : selected item cannot fit into memory when writing higher half kernel

转载 作者:行者123 更新时间:2023-12-03 06:24:25 30 4
gpt4 key购买 nike

我正在尝试为 i386 32 位编写一个非常基本的内核。我一直在关注 JamesM 的内核教程。我的内核代码本身目前几乎没有做任何事情 - 我正在努力让 grub 正确加载我选择使用的高半格式。

这样做的建议是 described in this answer我正在大致使用 higher half bare bones 。我的测试环境是 bochs,带有 grub 软盘(0.97/legacy)。

为了让您了解我在做什么,我有一个非常简单的几乎什么都不做的“主要”例程:

[section .text]
align 4

; setting up entry point for linker
start equ (start_vma - 0xBFF00000)

; entry point
start_vma:
push ebx
mov eax, 0xCCCCCCCC
hlt

这种技术给了我:

bjdump -x kernel | grep "start"
start address 0x00100000
c0000000 g .text 00000000 start_vma
00100000 g .text 00000000 start

然后我所做的是使用链接器脚本将 LMA(物理地址加载点)设置为 1MB,但将 VMA 设置为 3GB,如下所示:

OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
KERNEL_MBOOT = 0x400;
KERNEL_VMA = 0xC0000000;
KERNEL_LMA_OFFSET = 0xBFF00000;

PHDRS
{
headers PT_PHDR PHDRS ;
mboot PT_LOAD FILEHDR ;
text PT_LOAD FILEHDR ;
data PT_LOAD ;
}

SECTIONS
{
. = KERNEL_MBOOT;

.mboot : AT(KERNEL_VMA - KERNEL_LMA_OFFSET)
{
*(.mboot)
} : mboot

. = KERNEL_VMA;

.text : AT(ADDR(.text)+ADDR(.mboot) - KERNEL_LMA_OFFSET)
{
code = .; _code = .; __code = .;*/
*(.text)
*(.rodata*)
} : text

.data ALIGN (0x1000) : AT(ADDR(.data) - KERNEL_LMA_OFFSET)
{
data = .; _data = .; __data = .;
*(.data)
*(.rodata)
} : data

.bss : AT(ADDR(.bss) - KERNEL_LMA_OFFSET)
{
bss = .; _bss = .; __bss = .;
*(.bss)
*(COMMON)
ebss = .;
} : data

end = .; _end = .; __end = .;
}

或者至少我是这么认为的。 Explanation 。当然,这就是我的对象中的内容:

$ objdump -h kernel.bin
file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .mboot 0000000c 00000400 00100000 00000400 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 0000002e c0000000 00100400 00001000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .data 00000001 c0001000 00101000 00002000 2**12
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00004000 c0001020 00101020 00002001 2**5
ALLOC

.mboot 部分仅包含多重引导 header 。事实上,运行 mbchk 会给出:

kernel: The Multiboot header is found at the offset 1024.
kernel: Page alignment is turned on.
kernel: Memory information is turned on.
kernel: Address fields is turned off.
kernel: All checks passed.

总而言之,这看起来是一个有效的,应该启动完全不执行任何操作的 elf 内核。

但是,它实际上没有启动。相反,grub 会这样提示:

error 28: selected item cannot fit into memory

我正在 x64 fedora 上使用 gcc 4.7.2 进行构建,其中:

CFLAGS=-nostdlib -fno-builtin -fno-stack-protector -ffreestanding -m32 
LDFLAGS=-melf_i386 -Tlink.ld

其中 link.ld 是我上面包含的脚本。

我的问题是,我在上面做错了什么,让 grub 相信内核可以装入内存?我尝试过:

  • 更改 VMA_OFFSET 字段以使 VMA 与 LMA 匹配,即以 1MB 物理和虚拟大小加载所有内容,这没有什么区别,即我遇到了相同的错误。
  • 将 LMA 降至 1MB 以下。导致 grub 错误 7:无法按预期加载低于 1MB。
  • Guzzle 茶和咖啡。

这些都不起作用。我感觉我错过了一些非常明显的东西,但无法弄清楚它是什么。

<小时/>

更新:查看 grub multiboot elf 行,这是我所看到的:

 [Multiboot-elf, <0xffc00:0x40c:0x0>

至关重要的是,我相信我应该看到类似于 this question 中的线条。 ,即它应该有一个 entry= 部分!

无论如何,我考虑提供一个初始化区域:

[section .init]
; setting up entry point for linker

; entry point
start:
push ebx
mov eax, 0xCCCCCCCC
; jmp later
hlt

我像这样链接:

.init : AT(ADDR(.mboot) + (KERNEL_VMA - KERNEL_LMA_OFFSET))
{
*(.init)
} : init

给予:

 Idx Name          Size      VMA       LMA       File off  Algn
1 .init 0000000c 00100000 00100400 00001000 2**0

其 VMA/LMA 约为 1M,因此应该加载...但我仍然收到有关所选项目不适合内存的投诉。

最佳答案

在 grub 中 0.97 source code ,此错误消息来自 stage2/common.c:89

[ERR_WONT_FIT] = "Selected item cannot fit into memory",

这段代码被使用了十几次:

stage2/char_io.c:1215:    errnum = ERR_WONT_FIT;
stage2/boot.c:276: errnum = ERR_WONT_FIT;
stage2/boot.c:280: errnum = ERR_WONT_FIT;
stage2/shared.h:540: ERR_WONT_FIT,
stage2/builtins.c:1822: errnum = ERR_WONT_FIT;
stage2/builtins.c:2386: errnum = ERR_WONT_FIT;
stage2/builtins.c:2498: errnum = ERR_WONT_FIT;
stage2/builtins.c:2594: errnum = ERR_WONT_FIT;
stage2/builtins.c:2932: errnum = ERR_WONT_FIT;
stage2/builtins.c:3711: errnum = ERR_WONT_FIT;
stage2/builtins.c:3744: errnum = ERR_WONT_FIT;

既然您在启动过程中收到此消息,让我们深入了解一下 boot.c

 if (! big_linux
&& text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
{
grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
errnum = ERR_WONT_FIT;
}
else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
> RAW_ADDR ((char *) (mbi.mem_lower << 10)))
errnum = ERR_WONT_FIT;

由于您没有 grub_printf 消息,也许您处于以下情况:

linux_data_real_addr + LINUX_SETUP_MOVE_SIZE > RAW_ADDR ((char *) (mbi.mem_lower << 10))

=> 也许您的问题与您的 3 GB 目标有关。您可以尝试让它与 1GB 内存一起工作。计算机科学已经发现了 32 位 CPU 的文件或内存 > 2GB 的许多问题。

找到它的另一个机会在于 stage2/char_io.c:1215

  if ((addr < RAW_ADDR (0x1000))
|| (addr < RAW_ADDR (0x100000)
&& RAW_ADDR (mbi.mem_lower * 1024) < (addr + len))
|| (addr >= RAW_ADDR (0x100000)
&& RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
errnum = ERR_WONT_FIT;

您从 0x00100000 开始的地址可能会触发此条件。

关于assembly - Grub 错误 28 : selected item cannot fit into memory when writing higher half kernel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17223834/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com