multiboot2: Support load_addr == -1
diff --git a/common/protos/multiboot2.c b/common/protos/multiboot2.c
index 2720ac10..3139ccca 100644
--- a/common/protos/multiboot2.c
+++ b/common/protos/multiboot2.c
@@ -203,22 +203,34 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
uint64_t ranges_count;
if (addresstag != NULL) {
- if (addresstag->load_addr > addresstag->header_addr)
- panic(true, "multiboot2: Illegal load address");
+ size_t header_offset = (size_t)header - (size_t)kernel;
- size_t load_size;
- if (addresstag->load_end_addr)
- load_size = addresstag->load_end_addr - addresstag->load_addr;
- else
- load_size = kernel_file_size;
+ uintptr_t load_src, load_addr;
+ if (addresstag->load_addr != (uint32_t)-1) {
+ if (addresstag->load_addr > addresstag->header_addr) {
+ panic(true, "multiboot2: Illegal load address");
+ }
- size_t header_offset = (size_t)header - (size_t)kernel;
+ load_src = header_offset - (addresstag->header_addr - addresstag->load_addr);
+ load_addr = addresstag->load_addr;
+ } else {
+ load_src = 0;
+ load_addr = addresstag->header_addr - header_offset;
+ }
- uint32_t bss_size = 0;
- if (addresstag->bss_end_addr) {
- uintptr_t bss_addr = addresstag->load_addr + load_size;
- if (addresstag->bss_end_addr < bss_addr)
+ size_t load_size;
+ if (addresstag->load_end_addr != 0) {
+ load_size = addresstag->load_end_addr - load_addr;
+ } else {
+ load_size = kernel_file_size - load_src;
+ }
+
+ size_t bss_size = 0;
+ if (addresstag->bss_end_addr != 0) {
+ uintptr_t bss_addr = load_addr + load_size;
+ if (addresstag->bss_end_addr < bss_addr) {
panic(true, "multiboot2: Illegal bss end address");
+ }
bss_size = addresstag->bss_end_addr - bss_addr;
}
@@ -227,8 +239,7 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
void *elsewhere = ext_mem_alloc(full_size);
- memcpy(elsewhere, kernel + (header_offset
- - (addresstag->header_addr - addresstag->load_addr)), load_size);
+ memcpy(elsewhere, kernel + load_src, load_size);
if (entry_point == 0xffffffff) {
panic(true, "multiboot2: Using address tag but entry address tag missing");
@@ -238,7 +249,7 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
ranges = ext_mem_alloc(sizeof(struct elsewhere_range));
ranges->elsewhere = (uintptr_t)elsewhere;
- ranges->target = addresstag->load_addr;
+ ranges->target = load_addr;
ranges->length = full_size;
} else {
uint64_t e;
