11860face3
The "framebuf" driver was an incomplete driver expecting _clients_ to implement missing functionality (i.e. init and device definition) outside of the driver. This pattern of scattering driver code throughout the tree is not common (if used at all). If certain drivers share functionality, one can create a common module within the subsystem (see e.g. ILI9XXX drivers). The _generic_ framebuffer code was only used to implement the Intel Multiboot framebuffer driver. This patch centralizes all the scattered code in the subsystem and adjusts the driver name to "intel_multibootfb" to make things clear. If there's ever another framebuffer driver that shares code, it can be split into multiple modules. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
133 lines
3.3 KiB
C
133 lines
3.3 KiB
C
/*
|
|
* Copyright (c) 2019 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <string.h>
|
|
#include <zephyr/arch/x86/multiboot.h>
|
|
#include <zephyr/arch/x86/memmap.h>
|
|
|
|
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_pa)
|
|
{
|
|
struct multiboot_info *info;
|
|
|
|
#if defined(CONFIG_ARCH_MAPS_ALL_RAM) || !defined(CONFIG_X86_MMU)
|
|
/*
|
|
* Since the struct from bootloader resides in memory
|
|
* and all memory is mapped, there is no need to
|
|
* manually map it before accessing.
|
|
*
|
|
* Without MMU, all memory are identity-mapped already
|
|
* so there is no need to map them again.
|
|
*/
|
|
info = info_pa;
|
|
#else
|
|
z_phys_map((uint8_t **)&info, POINTER_TO_UINT(info_pa),
|
|
sizeof(*info_pa), K_MEM_CACHE_NONE);
|
|
#endif /* CONFIG_ARCH_MAPS_ALL_RAM */
|
|
|
|
if (info == NULL) {
|
|
return;
|
|
}
|
|
|
|
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)) {
|
|
uintptr_t address;
|
|
uintptr_t address_end;
|
|
struct multiboot_mmap *mmap;
|
|
int index = 0;
|
|
uint32_t type;
|
|
|
|
#if defined(CONFIG_ARCH_MAPS_ALL_RAM) || !defined(CONFIG_X86_MMU)
|
|
address = info->mmap_addr;
|
|
#else
|
|
uint8_t *address_va;
|
|
|
|
z_phys_map(&address_va, info->mmap_addr, info->mmap_length,
|
|
K_MEM_CACHE_NONE);
|
|
|
|
address = POINTER_TO_UINT(address_va);
|
|
#endif /* CONFIG_ARCH_MAPS_ALL_RAM */
|
|
|
|
address_end = address + info->mmap_length;
|
|
|
|
while ((address < address_end) &&
|
|
(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 */
|
|
}
|