Multiboot2标签遍历遇无效标签及请求被忽略问题咨询
关于Multiboot2标签遍历与type=25标签的问题
我在基于GRUB2实现Multiboot2兼容的操作系统启动时,遍历GRUB2提供的标签时遇到两个问题:
- 收到了type=25的标签
- 请求的type=6(内存映射标签)被忽略
不确定当前的标签遍历方法是否正确,也想了解type=25标签的相关信息。
相关代码
multiboot2.asm
;; multiboot2.asm %define mb2_magic 0xE85250D6 %define mb2_arch 0 section .boot _mb2: dd mb2_magic dd mb2_arch dd _emb2 - _mb2 dd 0x100000000 - (mb2_magic + mb2_arch + (_emb2 - _mb2)) align 8 .mb2_ir: dw 1 ; information request dw 0 dd .emb2_ir - .mb2_ir dd 6 ; memory map tag .emb2_ir: align 8 .end_tag: dd 0 dd 8 _emb2:
entry.asm
;entry.asm [BITS32] __start: mov [.mb2_magic], eax mov [.mb2_info], ebx ;; ... call check_multiboot ;; ... lgdt [gdt64.ptr] jmp gdt64.code:realm64 .mb2_magic: dd 0 .mb2_info: dq 0 check_multiboot: mov eax, [__start.mb2_magic] cmp eax, 0x36D76289 ; multiboot2 magic number jne .fail ret .fail: mov ebx, .message call quick_print ; defined in file hlt .message: db "Boot Check Failed:", 0x0A, 0x0A, "Was not booted from MultiBoot2", 0x0A, "MBR (Master Boot Record) is incompatible", 0x00 ;; ... [BITS 64] realm64: ;; ... [extern main] mov rsi, [__start.mb2_magic] mov rdi, [__start.mb2_info] call main
kernel.c
// kernel.c int main(mb2_info_header* mbd, uint32_t magic) // magic checked in entry.asm { tty_init(); mb2_traverse(mbd); // ... }
multiboot2.c
// multiboot2.c typedef struct s_MB2_tag { uint32_t type; uint32_t size; } mb2_tag; typedef struct s_MB2_info_header { uint32_t total_size; uint32_t __RSV1; } mb2_info_header; void mb2_traverse(mb2_info_header *mbd) { uint64_t mb2_end = mbd->total_size + (uint64_t)mbd; mb2_tag *tag = (mb2_tag*)(mbd + sizeof(mb2_info_header)); while ((uint64_t)tag < mb2_end) { tty_printf("TAG %d\t[%d] @\t%x\n", tag->type, tag->size, tag); if (tag->type == 0) break; tag += tag->size; if ((uint64_t)tag & 0x7) tag += 8 - ((uint64_t)tag & 0x7); } }
运行输出:
TAG N [size] @ ptr
问题分析与解决
1. 标签遍历方法的错误
你的mb2_traverse函数中,tag += tag->size这一步存在致命错误:tag是指针类型,直接做加法会让指针偏移tag->size * sizeof(mb2_tag)字节,而不是tag->size字节(标签的size字段单位是字节)。这会导致遍历逻辑完全混乱,跳过正确标签甚至越界读取到错误的type值(比如type=25)。
正确的偏移方式是将指针转换为整数类型后再计算:
tag = (mb2_tag*)((uintptr_t)tag + tag->size);
2. type=25标签的说明
type=25是GRUB2自定义的EFI系统表标签,属于Multiboot2规范中"实现定义"的标签(规范规定type 10及以上为私有扩展)。仅当GRUB2在EFI模式下启动时才会生成该标签,用于传递EFI系统表的指针。如果你的操作系统不需要EFI相关功能,可以直接忽略这个标签。
3. 内存映射标签被忽略的原因
修复遍历逻辑后,应该能正常读取到type=6的内存映射标签。另外确认你的Multiboot2信息请求格式正确——你代码中mb2_ir部分的请求是合法的,指定了需要内存映射标签。
修复后的遍历函数
void mb2_traverse(mb2_info_header *mbd) { uintptr_t mb2_end = (uintptr_t)mbd + mbd->total_size; mb2_tag *tag = (mb2_tag*)((uintptr_t)mbd + sizeof(mb2_info_header)); while ((uintptr_t)tag < mb2_end) { tty_printf("TAG %d\t[%d] @\t%x\n", tag->type, tag->size, (uintptr_t)tag); if (tag->type == 0) // 终止标签,退出遍历 break; // 正确偏移到下一个标签的起始位置 tag = (mb2_tag*)((uintptr_t)tag + tag->size); // 确保标签地址8字节对齐 if ((uintptr_t)tag & 0x7) tag = (mb2_tag*)((uintptr_t)tag + (8 - ((uintptr_t)tag & 0x7))); } }
内容的提问来源于stack exchange,提问作者IsCoffeeTho
相关产品推荐
相关产品推荐

