0
$uname -i
x86_64
$ uname -r
4.15.0-041500-generic

I am trying to compile that gets memory map of a system. The OSDev shows some code how that can be done.

The code is as follows:

// running in real mode may require:
__asm__(".code16gcc\n");

// SMAP entry structure
#include <stdint.h>
typedef struct SMAP_entry {

    uint32_t BaseL; // base address uint64_t
    uint32_t BaseH;
    uint32_t LengthL; // length uint64_t
    uint32_t LengthH;
    uint32_t Type; // entry Type
    uint32_t ACPI; // extended

}__attribute__((packed)) SMAP_entry_t;

// load memory map to buffer - note: regparm(3) avoids stack issues with gcc in real mode
int __attribute__((noinline)) __attribute__((regparm(3))) detectMemory(SMAP_entry_t* buffer, int maxentries)
{
    uint32_t contID = 0;
    int entries = 0, signature, bytes;
    do 
    {
        __asm__ __volatile__ ("int  $0x15" 
                : "=a"(signature), "=c"(bytes), "=b"(contID)
                : "a"(0xE820), "b"(contID), "c"(24), "d"(0x534D4150), "D"(buffer));
        if (signature != 0x534D4150) 
            return -1; // error
        if (bytes > 20 && (buffer->ACPI & 0x0001) == 0)
        {
            // ignore this entry
        }
        else {
            buffer++;
            entries++;
        }
    } 
    while (contID != 0 && entries < maxentries);
    return entries;
}

// in your main routine - memory map is stored in 0000:1000 - 0000:2FFF for example
[...] {
    [...]
    SMAP_entry_t* smap = (SMAP_entry_t*) 0x1000;
    const int smap_size = 0x2000;

    int entry_count = detectMemory(smap, smap_size / sizeof(SMAP_entry_t));

    if (entry_count == -1) {
        // error - halt system and/or show error message
        [...]
    } else {
        // process memory map
        [...]
    }
}

Obviously the code has to be compiled in 16 bit mode. So I used gcc -m16 smapentry.c -o smap This has resulted in a error which says.

usr/bin/x86_64-linux-gnu-ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/7/libgcc.a when searching for -lgcc
/usr/bin/x86_64-linux-gnu-ld: cannot find -lgcc

which means I have a 64 libgcc installed. For this reason, -m64 and -m32 works fine. only -m16 doesn't work. It looks like I need to install libgcc version to compile 16 bit code. Which library should I use?

  • I'm assuming you've read through all of [this page](https://wiki.osdev.org/Libgcc)? (I'm not really sure if it's relevant to your problem, just trying to figure out where you've been that got you here) Also, are you sure you need `-m16`? – Thomas Jager May 31 '18 at 12:58
  • I get an error `/tmp/cckEqVMD.s:19: Error: bad register name `%rdi'` – BODDU MANOHAR REDDY May 31 '18 at 14:56
  • 1
    You really need to know what you are doing with 16 bit code and GCC. You don't show all your code for the project but you are compiling with `gcc -m16 smapentry.c -o smap` to an executable. If that is what you are doing you are going to want to use `-ffreestanding` option. But you are going to have to have proper bootstrap code to set up real mode correctly etc. I think there is going to be more issues than you can realize here. – Michael Petch May 31 '18 at 15:32
  • The goal is to get E820 system memory map. https://wiki.osdev.org/Detecting_Memory_(x86)#Getting_an_E820_Memory_Map – BODDU MANOHAR REDDY May 31 '18 at 15:46
  • 1
    GCC itself doesn't have a 16-bit libgcc. 16-bit code is an after thought and a serious hack. If you really want to write a bootloader in C might I recommend the Smaller C compiler by Alex Frunze: https://github.com/alexfru – Michael Petch May 31 '18 at 15:46
  • 1
    I know what your goal is but what you provided here is incomplete and not an [mcve] , There is a lot that section of OSDev leaves out. Things like linker scripts.I also question in the code comments of that snippet about _avoids stack issues with gcc in real mode_ .That indicates to me the author has done something wrong himself or doesn't have complete understanding of the intricacies of 16-bit code. – Michael Petch May 31 '18 at 15:49

0 Answers0