2017-11-04 07:07:04 -04:00
|
|
|
#include "multiboot.h"
|
2017-11-01 08:57:56 -04:00
|
|
|
|
2017-11-04 07:43:55 -04:00
|
|
|
#include <kernelmq/stdlib.h>
|
|
|
|
|
2017-11-05 01:47:51 -04:00
|
|
|
#define MULTIBOOT_TAG_TYPE_END 0
|
|
|
|
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
|
|
|
#define MULTIBOOT_TAG_TYPE_MODULE 3
|
|
|
|
#define MULTIBOOT_TAG_TYPE_MMAP 6
|
2017-11-02 00:21:25 -04:00
|
|
|
|
|
|
|
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
|
|
|
#define MULTIBOOT_MEMORY_RESERVED 2
|
|
|
|
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
|
|
|
#define MULTIBOOT_MEMORY_NVS 4
|
|
|
|
|
|
|
|
struct multiboot_mmap_entry
|
|
|
|
{
|
|
|
|
unsigned long long addr;
|
|
|
|
unsigned long long len;
|
|
|
|
unsigned int type;
|
|
|
|
unsigned int zero;
|
|
|
|
}
|
|
|
|
__attribute__((packed));
|
|
|
|
|
|
|
|
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
2017-11-01 11:54:52 -04:00
|
|
|
|
|
|
|
struct multiboot_tag
|
|
|
|
{
|
|
|
|
unsigned int type;
|
|
|
|
unsigned int size;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct multiboot_tag_string
|
|
|
|
{
|
|
|
|
unsigned int type;
|
|
|
|
unsigned int size;
|
|
|
|
char string[0];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct multiboot_tag_module
|
|
|
|
{
|
|
|
|
unsigned int type;
|
|
|
|
unsigned int size;
|
|
|
|
unsigned int mod_start;
|
|
|
|
unsigned int mod_end;
|
|
|
|
char cmdline[0];
|
|
|
|
};
|
|
|
|
|
2017-11-02 00:21:25 -04:00
|
|
|
struct multiboot_tag_mmap
|
|
|
|
{
|
|
|
|
unsigned int type;
|
|
|
|
unsigned int size;
|
|
|
|
unsigned int entry_size;
|
|
|
|
unsigned int entry_version;
|
|
|
|
struct multiboot_mmap_entry entries[0];
|
|
|
|
};
|
|
|
|
|
2017-11-04 07:43:55 -04:00
|
|
|
static unsigned char print_multiboot_tag(struct KernelMQ_Info *kinfo, const struct multiboot_tag *tag);
|
2017-11-02 04:40:01 -04:00
|
|
|
|
2017-11-05 01:47:51 -04:00
|
|
|
static unsigned char print_multiboot_tag_cmdline(struct KernelMQ_Info *kinfo, const struct multiboot_tag_string *tag);
|
|
|
|
static unsigned char print_multiboot_tag_module (struct KernelMQ_Info *kinfo, const struct multiboot_tag_module *tag);
|
|
|
|
static unsigned char print_multiboot_tag_mmap (struct KernelMQ_Info *kinfo, const struct multiboot_tag_mmap *tag);
|
2017-11-02 04:49:55 -04:00
|
|
|
|
2017-11-04 07:07:04 -04:00
|
|
|
unsigned char multiboot_parse(struct KernelMQ_Info *kinfo, unsigned long addr)
|
2017-11-01 08:57:56 -04:00
|
|
|
{
|
2017-11-04 07:07:04 -04:00
|
|
|
if (!kinfo) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unaligned address
|
|
|
|
if (addr & 7) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-11-01 08:57:56 -04:00
|
|
|
for (
|
2017-11-04 06:51:03 -04:00
|
|
|
struct multiboot_tag *tag = (struct multiboot_tag*)(addr + 8);
|
2017-11-01 08:57:56 -04:00
|
|
|
tag->type != MULTIBOOT_TAG_TYPE_END;
|
2017-11-01 12:01:02 -04:00
|
|
|
tag = (struct multiboot_tag*)((unsigned char*)tag + ((tag->size + 7) & ~7))
|
|
|
|
) {
|
2017-11-04 07:43:55 -04:00
|
|
|
if (!print_multiboot_tag(kinfo, tag)) {
|
|
|
|
return 0;
|
|
|
|
}
|
2017-11-02 04:40:01 -04:00
|
|
|
}
|
2017-11-04 07:07:04 -04:00
|
|
|
|
|
|
|
return 1;
|
2017-11-02 04:40:01 -04:00
|
|
|
}
|
2017-11-01 09:54:53 -04:00
|
|
|
|
2017-11-04 07:43:55 -04:00
|
|
|
unsigned char print_multiboot_tag(struct KernelMQ_Info *kinfo, const struct multiboot_tag *const tag)
|
2017-11-02 04:40:01 -04:00
|
|
|
{
|
|
|
|
switch (tag->type)
|
|
|
|
{
|
|
|
|
case MULTIBOOT_TAG_TYPE_CMDLINE:
|
2017-11-04 07:43:55 -04:00
|
|
|
return print_multiboot_tag_cmdline(kinfo, (struct multiboot_tag_string*)tag);
|
2017-11-02 04:40:01 -04:00
|
|
|
|
|
|
|
case MULTIBOOT_TAG_TYPE_MODULE:
|
2017-11-04 07:43:55 -04:00
|
|
|
return print_multiboot_tag_module(kinfo, (struct multiboot_tag_module*)tag);
|
2017-11-02 04:40:01 -04:00
|
|
|
|
|
|
|
case MULTIBOOT_TAG_TYPE_MMAP:
|
2017-11-04 07:43:55 -04:00
|
|
|
return print_multiboot_tag_mmap(kinfo, (struct multiboot_tag_mmap*)tag);
|
2017-11-01 08:57:56 -04:00
|
|
|
}
|
2017-11-04 07:43:55 -04:00
|
|
|
|
|
|
|
return 1;
|
2017-11-01 08:57:56 -04:00
|
|
|
}
|
|
|
|
|
2017-11-04 07:43:55 -04:00
|
|
|
unsigned char print_multiboot_tag_cmdline(struct KernelMQ_Info *kinfo, const struct multiboot_tag_string *const tag)
|
2017-11-02 04:49:55 -04:00
|
|
|
{
|
2017-11-04 07:43:55 -04:00
|
|
|
unsigned int length = kstrlen(tag->string);
|
|
|
|
|
|
|
|
if (length >= KERNELMQ_INFO_CMDLINE_SIZE_MAX) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
kstrncpy(kinfo->cmdline, tag->string, length);
|
|
|
|
|
|
|
|
return 1;
|
2017-11-02 04:49:55 -04:00
|
|
|
}
|
|
|
|
|
2017-11-04 07:43:55 -04:00
|
|
|
unsigned char print_multiboot_tag_module(struct KernelMQ_Info *kinfo, const struct multiboot_tag_module *const tag)
|
2017-11-02 04:49:55 -04:00
|
|
|
{
|
2017-11-04 07:43:55 -04:00
|
|
|
if (kinfo->modules_count >= KERNELMQ_INFO_MODULES_MAX) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int cmdline_length = kstrlen(tag->cmdline);
|
|
|
|
|
|
|
|
if (cmdline_length >= KERNELMQ_INFO_CMDLINE_SIZE_MAX) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct KernelMQ_Info_Module *module = &kinfo->modules[kinfo->modules_count];
|
|
|
|
|
|
|
|
kstrncpy(module->cmdline, tag->cmdline, cmdline_length);
|
|
|
|
|
|
|
|
module->base = tag->mod_start;
|
|
|
|
module->limit = tag->mod_end;
|
|
|
|
module->size = module->limit - module->base + 1;
|
|
|
|
|
|
|
|
++kinfo->modules_count;
|
|
|
|
|
2017-11-04 10:03:45 -04:00
|
|
|
kinfo->modules_total_size += module->size;
|
|
|
|
|
2017-11-04 07:43:55 -04:00
|
|
|
return 1;
|
2017-11-02 04:49:55 -04:00
|
|
|
}
|
|
|
|
|
2017-11-04 07:43:55 -04:00
|
|
|
unsigned char print_multiboot_tag_mmap(struct KernelMQ_Info *kinfo, const struct multiboot_tag_mmap *const tag)
|
2017-11-02 04:49:55 -04:00
|
|
|
{
|
|
|
|
for (
|
2017-11-02 04:53:14 -04:00
|
|
|
const multiboot_memory_map_t *mmap = tag->entries;
|
|
|
|
(unsigned char*)mmap < (unsigned char*)tag + tag->size;
|
|
|
|
mmap = (multiboot_memory_map_t*)((unsigned long) mmap + tag->entry_size)
|
2017-11-02 04:49:55 -04:00
|
|
|
) {
|
2017-11-04 07:43:55 -04:00
|
|
|
if (kinfo->areas_count >= KERNELMQ_INFO_AREAS_MAX) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct KernelMQ_Info_Area *area = &kinfo->areas[kinfo->areas_count];
|
|
|
|
|
|
|
|
area->base = mmap->addr;
|
|
|
|
area->size = mmap->len;
|
|
|
|
area->limit = area->base + area->size - 1;
|
|
|
|
|
|
|
|
area->is_available = mmap->type == MULTIBOOT_MEMORY_AVAILABLE;
|
|
|
|
|
|
|
|
++kinfo->areas_count;
|
2017-11-02 04:49:55 -04:00
|
|
|
}
|
2017-11-04 07:43:55 -04:00
|
|
|
|
|
|
|
return 1;
|
2017-11-02 04:49:55 -04:00
|
|
|
}
|