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/