While implementing a multiboot2 complaint OS booting with GRUB2, reading through the tags provided i have recieved type = 25
as well as my information request for type = 6
was ignored.
Not entirely sure if my method of traversing is valid.
No idea if this is a problem with GRUB2.
if it is correct, where is any information on type = 25
.
;; 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
[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
int main(mb2_info_header* mbd, uint32_t magic) // magic checked in entry.asm
{
tty_init();
mb2_traverse(mbd);
// ...
}
// 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);
}
}
Yeilding:
TAG N [size] @ ptr
TTY screenshot
@MichaelPetch provided these comments (Huge Appreciation):
Upon further inspection there is a similar casting issue (refering to previous comment) here as well:
tag += tag->size;
You could do something liketag = (mb2_tag *) ((uint8_t *) tag + ((tag->size + 7) & ~7)))
When you add
sizeof(mb2_info_header)
(which is 8) to mbd you aren't adding 8 bytes tombd
, you are adding 8 * 8 since each element ofmbd
is 8 bytes already. If you add 1 tombd
you are actually adding 1 * 8.
Realising that pointer arithmetic was the problem.
After adjusting the code to this new traversal in multiboot2.c
// multiboot2.c
void mb2_traverse(mb2_info_header *mbd, uint32_t magic)
{
if (magic != 0x36D76289)
{
tty_printf("Multiboot2 Magic Number is invalid");
asm volatile ("hlt");
}
tty_printf("MB2 [%d]\n", mbd->total_size);
uint64_t mb2_end = mbd->total_size + (uint64_t)mbd;
mb2_tag *tag = (mb2_tag*)((uint8_t *)mbd + sizeof(mb2_info_header)); // Adjusted to have (uint8_t *)
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;
switch (tag->type) {
// ...
default: break;
}
tag = (mb2_tag *) ((uint8_t *) tag + ((tag->size + 7) & ~7)); // Adjusted to have (uint8_t *) and altered byte aligment
}
}