OSDev.org https://forum.osdev.org/ |
|
Can't get memory map with E820 (SOLVED) https://forum.osdev.org/viewtopic.php?f=1&t=47038 |
Page 1 of 1 |
Author: | geomal [ Sat Jul 24, 2021 1:01 am ] |
Post subject: | Can't get memory map with E820 (SOLVED) |
Hello everyone! I've been trying to fetch a memory map with E820, but I am doing something wrong I guess. I have a C structure based on how E820 entries are supposed to be, and E820 runs successfully, but I end up getting no entries for some reason. Here are the relevant codes: Code: global do_e820 do_e820: pushad xor ax,ax ;mov ax, 0x0000 mov es,ax xor ebp, ebp ;/* entry number */ xor ebx, ebx ; /* ebx must be 0 to start */ mov edi, 0xA000 ; /* The E820 entries are supposed to be saved in es:edi, in our case 0x0A000. I made several attempts with different addresses. */ .loopy_e820: mov edx, 0x0534D4150 ;/* magical number: "SMAP" */ mov eax, 0xe820 mov ecx, 24 int 0x15 jc short .end_e820 cmp eax, edx jne short .fail_e820 ;/* eax != SMAP for error */ jcxz .next_e820 ;/* ignore 0-length entry */ inc ebp ;/* increase entry number */ add edi, 24 ;/* edi points next entry space */ .next_e820: test ebx, ebx ;/* if ebx equals 0, list ends */ je short .end_e820 mov eax, ebp cmp eax, 128 je short .fail_e820 ;/* entry number >= E820_MAX for error */ jmp short .loopy_e820 .end_e820: cmp eax, 0x01 ;/* entry number <= 1 for error */ je short .fail_e820 xor eax, eax mov [ 0x00000dfd0], ebp ; /* The total number of entries. Always 6 */ xor ebp,ebp popad ret .fail_e820: stc jmp .fail_e820 and the relevant C part: Code: void boot_memory_init() { int address = 0x00000dfd0; int* a = (int*)address; int content = *a; printlnVGA(itoa(content, ' ', 10)); //Prints the content of 0x00000dfd0 as decimal. Always 6. struct boot_param *myboot_param = (struct boot_param *)(E820_ADDRESS); //The address of es:edi. I tried with edi too, just in case. struct e820_entry *entry = myboot_param->memMapp; unsigned long i, npage, num = myboot_param->e820_num; printlnVGA(itoa(num, ' d', 10)); //Number of entries. Always 0. unsigned long memory_end = 0; printlnVGA("Memory map: "); for (i = 0; i < num; i++) { if (entry[i].type != E820_TYPE_FREE) continue; if (entry[i].addr + entry[i].length > memory_end){ memory_end = entry[i].addr + entry[i].length;} } npage = memory_end / PGSIZE; /* memory pages */ printlnVGA(itoa(npage * (4 / 1024), ' ', 10)); /* A function turning converting numbers to chars, once one gives the base (decimal in our case). Supposed to show available memory in MBs. Always 0. */ return; } The structures look like this: typedef struct e820_entry { unsigned int addr; unsigned int addr_high; unsigned int length; unsigned int length_high; unsigned int type; unsigned int pad; }; struct boot_param { struct e820_entry memMapp[128]; unsigned long e820_num; }; I know I am doing something wrong, but after many hours of googling as well as retarded trial and error , I think I've hit a dead end. This may seem n00bish to most of you, but I am just a fullstack dev who tries to do some low-level programming at the weekends. Thank you in advance! PS: The only thing that was wrong was me going on to make this without much knowledge of C. It just needed a '&' in this line: ' unsigned long i, npage, num = myboot_param->e820_num; ------> unsigned long i, npage, num = &myboot_param->e820_num |
Author: | davmac314 [ Sat Jul 24, 2021 1:56 am ] |
Post subject: | Re: Can't get memory map with E820 |
What have you tried, debugging-wise? The first thing I would do is run it in a VM with a debugger and single-step through the code to see what happens. A few potential problems I can spot by eyeballing: the code assumes edx is unchanged after the call to int 0x15, here: Code: cmp eax, edx I'm not sure that's a safe assumption - it's probably better to compare with the immediate value, to be on the safe side. Is your DS set the same as ES? Otherwise: Code: mov [ 0x00000dfd0], ebp ; /* The total number of entries. Always 6 */ ... probably isn't storing to the right location. Finally, and sorry if this is being too simplistic, but you haven't shown any code that actually calls/runs the do_e820 routine - are you sure that it executes? |
Author: | geomal [ Sat Jul 24, 2021 3:03 am ] |
Post subject: | Re: Can't get memory map with E820 |
davmac314 wrote: What have you tried, debugging-wise? The first thing I would do is run it in a VM with a debugger and single-step through the code to see what happens. A few potential problems I can spot by eyeballing: the code assumes edx is unchanged after the call to int 0x15, here: Code: cmp eax, edx I'm not sure that's a safe assumption - it's probably better to compare with the immediate value, to be on the safe side. Is your DS set the same as ES? Otherwise: Code: mov [ 0x00000dfd0], ebp ; /* The total number of entries. Always 6 */ ... probably isn't storing to the right location. Finally, and sorry if this is being too simplistic, but you haven't shown any code that actually calls/runs the do_e820 routine - are you sure that it executes? Not that this is the best way to debug a program, but so far I've used the so-called printf debugging . The ds is the same as es, and the ebp is indeed stored to 0x00000dfd0. If I comment the line out it becomes zero, and if I double-increase ebp it becomes twelve. The code surrounding the call looks like this: Code: xor ax, ax mov ds, ax mov es, ax mov ss, ax mov sp, MEM_POS ;address to store the kernel -0x1000 in our case mov ax, ERROR_MSG2 mov [BOOT_DRIVE], dl; Boot drive passed to us by the BIOS mov dh, 12 ; Number of sectors (kernel.bin) to read from disk mov bx, MEM_POS ; Load Kernel to ES:BX call load_kernel call a20_gate_fast call do_e820; ;the call xor eax,eax lgdt [gdt_descriptor] mov eax, cr0 or eax, 1 mov cr0, eax jmp dword CODE_SEG:init_pm |
Author: | iansjack [ Sat Jul 24, 2021 3:29 am ] |
Post subject: | Re: Can't get memory map with E820 |
How are you assembling/compiling you code? 32-bit toolset throughout? |
Author: | davmac314 [ Sat Jul 24, 2021 3:31 am ] |
Post subject: | Re: Can't get memory map with E820 |
I may have misunderstood the problem. Are you saying these two lines *should* be printing the same number, but aren't?: Code: printlnVGA(itoa(content, ' ', 10)); //Prints the content of 0x00000dfd0 as decimal. Always 6. printlnVGA(itoa(num, ' d', 10)); //Number of entries. Always 0. In that case I would add print statements for: Code: E820_ADDRESS , Code: entry , and Code: &myboot_param->e820_num . The fact that you're reading a different number implies that the address is different, or that the value has been overwritten (which doesn't seem likely).I'd look at a mismatch between your C structure and assembly as a likely culprit. |
Author: | geomal [ Sat Jul 24, 2021 12:14 pm ] |
Post subject: | Re: Can't get memory map with E820 |
davmac314 wrote: I may have misunderstood the problem. Are you saying these two lines *should* be printing the same number, but aren't?: Code: printlnVGA(itoa(content, ' ', 10)); //Prints the content of 0x00000dfd0 as decimal. Always 6. printlnVGA(itoa(num, ' d', 10)); //Number of entries. Always 0. In that case I would add print statements for: Code: E820_ADDRESS , Code: entry , and Code: &myboot_param->e820_num . The fact that you're reading a different number implies that the address is different, or that the value has been overwritten (which doesn't seem likely).I'd look at a mismatch between your C structure and assembly as a likely culprit. What a total idiot I am. The problem was that the '&' was missing. I would expect some kind of warning by the compiler, but I didn't see a thing... That was several hours wasted for nothing. Thanks for your help -and of course I won't even attempt to go any further with this before I really get familiar with C. |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |