Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | /* * Copyright (c) 2019 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <kernel.h> #include <string.h> #include <arch/x86/multiboot.h> #include <arch/x86/memmap.h> #ifdef CONFIG_MULTIBOOT_INFO struct multiboot_info multiboot_info; /* * called very early in the boot process to fetch data out of the multiboot * info struct. we need to grab the relevant data before any dynamic memory * allocation takes place, lest the struct itself or any data it points to * be overwritten before we read it. */ static inline void clear_memmap(int index) { while (index < CONFIG_X86_MEMMAP_ENTRIES) { x86_memmap[index].type = X86_MEMMAP_ENTRY_UNUSED; ++index; } } void z_multiboot_init(struct multiboot_info *info) { if (info != NULL) { memcpy(&multiboot_info, info, sizeof(*info)); } #ifdef CONFIG_MULTIBOOT_MEMMAP /* * If the extended map (basically, the equivalent of * the BIOS E820 map) is available, then use that. */ if ((info->flags & MULTIBOOT_INFO_FLAGS_MMAP) && (x86_memmap_source < X86_MEMMAP_SOURCE_MULTIBOOT_MMAP)) { u32_t address = info->mmap_addr; struct multiboot_mmap *mmap; int index = 0; u32_t type; while ((address < (info->mmap_addr + info->mmap_length)) && (index < CONFIG_X86_MEMMAP_ENTRIES)) { mmap = UINT_TO_POINTER(address); x86_memmap[index].base = mmap->base; x86_memmap[index].length = mmap->length; switch (mmap->type) { case MULTIBOOT_MMAP_RAM: type = X86_MEMMAP_ENTRY_RAM; break; case MULTIBOOT_MMAP_ACPI: type = X86_MEMMAP_ENTRY_ACPI; break; case MULTIBOOT_MMAP_NVS: type = X86_MEMMAP_ENTRY_NVS; break; case MULTIBOOT_MMAP_DEFECTIVE: type = X86_MEMMAP_ENTRY_DEFECTIVE; break; default: type = X86_MEMMAP_ENTRY_UNKNOWN; } x86_memmap[index].type = type; ++index; address += mmap->size + sizeof(mmap->size); } x86_memmap_source = X86_MEMMAP_SOURCE_MULTIBOOT_MMAP; clear_memmap(index); } /* If no extended map is available, fall back to the basic map. */ if ((info->flags & MULTIBOOT_INFO_FLAGS_MEM) && (x86_memmap_source < X86_MEMMAP_SOURCE_MULTIBOOT_MEM)) { x86_memmap[0].base = 0; x86_memmap[0].length = info->mem_lower * 1024ULL; x86_memmap[0].type = X86_MEMMAP_ENTRY_RAM; if (CONFIG_X86_MEMMAP_ENTRIES > 1) { x86_memmap[1].base = 1048576U; /* 1MB */ x86_memmap[1].length = info->mem_upper * 1024ULL; x86_memmap[1].type = X86_MEMMAP_ENTRY_RAM; clear_memmap(2); } x86_memmap_source = X86_MEMMAP_SOURCE_MULTIBOOT_MEM; } #endif /* CONFIG_MULTIBOOT_MEMMAP */ } #ifdef CONFIG_MULTIBOOT_FRAMEBUF #include <display/framebuf.h> static struct framebuf_dev_data multiboot_framebuf_data = { .width = CONFIG_MULTIBOOT_FRAMEBUF_X, .height = CONFIG_MULTIBOOT_FRAMEBUF_Y }; static int multiboot_framebuf_init(struct device *dev) { struct framebuf_dev_data *data = FRAMEBUF_DATA(dev); struct multiboot_info *info = &multiboot_info; if ((info->flags & MULTIBOOT_INFO_FLAGS_FB) && (info->fb_width >= CONFIG_MULTIBOOT_FRAMEBUF_X) && (info->fb_height >= CONFIG_MULTIBOOT_FRAMEBUF_Y) && (info->fb_bpp == 32) && (info->fb_addr_hi == 0)) { /* * We have a usable multiboot framebuffer - it is 32 bpp * and at least as large as the requested dimensions. Compute * the pitch and adjust the start address center our canvas. */ u16_t adj_x; u16_t adj_y; u32_t *buffer; adj_x = info->fb_width - CONFIG_MULTIBOOT_FRAMEBUF_X; adj_y = info->fb_height - CONFIG_MULTIBOOT_FRAMEBUF_Y; data->pitch = (info->fb_pitch / 4) + adj_x; adj_x /= 2; adj_y /= 2; buffer = (uint32_t *) (uintptr_t) info->fb_addr_lo; buffer += adj_x; buffer += adj_y * data->pitch; data->buffer = buffer; return 0; } else { return -ENOTSUP; } } DEVICE_AND_API_INIT(multiboot_framebuf, "FRAMEBUF", multiboot_framebuf_init, &multiboot_framebuf_data, NULL, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &framebuf_display_api); #endif /* CONFIG_MULTIBOOT_FRAMEBUF */ #endif /* CONFIG_MULTIBOOT_INFO */ |