OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Mar 19, 2024 12:15 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Can't get memory map with E820 (SOLVED)
PostPosted: Sat Jul 24, 2021 1:01 am 
Offline

Joined: Fri May 14, 2021 9:24 am
Posts: 5
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


Last edited by geomal on Sat Jul 24, 2021 12:18 pm, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: Can't get memory map with E820
PostPosted: Sat Jul 24, 2021 1:56 am 
Offline
Member
Member

Joined: Mon Jul 05, 2021 6:57 pm
Posts: 118
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?


Top
 Profile  
 
 Post subject: Re: Can't get memory map with E820
PostPosted: Sat Jul 24, 2021 3:03 am 
Offline

Joined: Fri May 14, 2021 9:24 am
Posts: 5
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


Top
 Profile  
 
 Post subject: Re: Can't get memory map with E820
PostPosted: Sat Jul 24, 2021 3:29 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
How are you assembling/compiling you code? 32-bit toolset throughout?


Top
 Profile  
 
 Post subject: Re: Can't get memory map with E820
PostPosted: Sat Jul 24, 2021 3:31 am 
Offline
Member
Member

Joined: Mon Jul 05, 2021 6:57 pm
Posts: 118
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.


Top
 Profile  
 
 Post subject: Re: Can't get memory map with E820
PostPosted: Sat Jul 24, 2021 12:14 pm 
Offline

Joined: Fri May 14, 2021 9:24 am
Posts: 5
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Majestic-12 [Bot] and 18 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group