diff options
Diffstat (limited to '')
-rw-r--r-- | bsps/x86_64/amd64/start/bsp_specs | 0 | ||||
-rw-r--r-- | bsps/x86_64/amd64/start/bspstart.c | 16 | ||||
-rw-r--r-- | bsps/x86_64/amd64/start/efimem.c | 203 | ||||
-rw-r--r-- | bsps/x86_64/amd64/start/linkcmds | 8 | ||||
-rw-r--r-- | bsps/x86_64/amd64/start/multiboot2.c | 174 | ||||
-rw-r--r-- | bsps/x86_64/amd64/start/page.c | 2 | ||||
-rw-r--r-- | bsps/x86_64/amd64/start/start.S | 74 |
7 files changed, 471 insertions, 6 deletions
diff --git a/bsps/x86_64/amd64/start/bsp_specs b/bsps/x86_64/amd64/start/bsp_specs deleted file mode 100644 index e69de29bb2..0000000000 --- a/bsps/x86_64/amd64/start/bsp_specs +++ /dev/null diff --git a/bsps/x86_64/amd64/start/bspstart.c b/bsps/x86_64/amd64/start/bspstart.c index d1e1e4b2f2..e0e70f97bb 100644 --- a/bsps/x86_64/amd64/start/bspstart.c +++ b/bsps/x86_64/amd64/start/bspstart.c @@ -28,9 +28,21 @@ #include <bsp/bootcard.h> #include <libcpu/page.h> #include <bsp/irq-generic.h> +#include <multiboot2impl.h> + +#if defined(BSP_USE_EFI_BOOT_SERVICES) && !defined(BSP_MULTIBOOT_SUPPORT) +#error "RTEMS amd64efi BSP requires multiboot2 support!" +#endif void bsp_start(void) { - paging_init(); - bsp_interrupt_initialize(); +#ifdef BSP_MULTIBOOT_SUPPORT + process_multiboot2_info(); + if (!uefi_bootservices_running()) { +#endif + paging_init(); + bsp_interrupt_initialize(); +#ifdef BSP_MULTIBOOT_SUPPORT + } +#endif } diff --git a/bsps/x86_64/amd64/start/efimem.c b/bsps/x86_64/amd64/start/efimem.c new file mode 100644 index 0000000000..a6ec076a63 --- /dev/null +++ b/bsps/x86_64/amd64/start/efimem.c @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2023 Karel Gardas + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +#include <efi.h> +#include <efilib.h> + +#include <stdio.h> + +extern Heap_Control *RTEMS_Malloc_Heap; + +void bsp_memory_heap_extend(void); + +extern EFI_BOOT_SERVICES *BS; + +static UINT32 total_pages = 0; +static UINT32 allocated_pages = 0; +static UINT32 usable_pages = 0; +static EFI_PHYSICAL_ADDRESS physBuf; + +static int error = 0; +static int extension_steps = 0; + +#ifdef BSP_EFI_MMAP_PRINTOUT +static const char* +efi_memory_type(EFI_MEMORY_TYPE type); +#endif + +void +efi_memory_heap_extend( void ); + +static UINT64 +heap_size(void) +{ + return RTEMS_Malloc_Heap->stats.size; +} + +static UINT64 +allocate_biggest_block( void ) +{ + UINT64 sz = 0; + EFI_MEMORY_DESCRIPTOR *map = 0, *p = 0; + UINTN key = 0, dsz = 0; + UINT32 dver = 0; + EFI_STATUS status = 0; + int i, ndesc = 0; + + UINT64 to_alloc_pages = 0; + bool first_run = false; + if (total_pages == 0) + first_run = true; + // let's see available RAM + status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver); + if (status != EFI_BUFFER_TOO_SMALL) { + printf("EFI: Can't determine memory map size\n"); + return 0; + } + map = malloc(sz); + if (map == NULL) { + printf("EFI: Can't allocate memory map backing\n"); + return 0; + } + status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver); + if (EFI_ERROR(status)) { + printf("EFI: Can't read memory map\n"); + free(map); + return 0; + } + ndesc = sz / dsz; +#ifdef BSP_EFI_MMAP_PRINTOUT + if (first_run) + printf("%23s %12s %8s\n", "Type", "Physical", "#Pages"); +#endif + for (i = 0, p = map; i < ndesc; + i++, p = NextMemoryDescriptor(p, dsz)) { + if (first_run) { +#ifdef BSP_EFI_MMAP_PRINTOUT + printf("%23s %012jx %08jx\n", efi_memory_type(p->Type), + (uintmax_t)p->PhysicalStart, (uintmax_t)p->NumberOfPages); +#endif + if (p->Type != EfiReservedMemoryType) + total_pages = total_pages + p->NumberOfPages; + if (p->Type == EfiConventionalMemory) { + usable_pages = usable_pages + p->NumberOfPages; + } + } + if (p->Type == EfiConventionalMemory) { + if (to_alloc_pages < p->NumberOfPages) + to_alloc_pages = p->NumberOfPages; + } + } + status = ST->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, to_alloc_pages, &physBuf ); + if (EFI_ERROR(status)) { + /* on some UEFI implementations it is not possible to allocate biggest available block + for whatever reasons. In that case, let's go wild and attempt to allocate + half of it */ + error++; + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, (to_alloc_pages / 2), &physBuf ); + if (EFI_ERROR(status)) { + printf("EFI can't allocate: %lu pages nor half of the amount.\n", to_alloc_pages); + free(map); + return 0; + } + else { + to_alloc_pages = to_alloc_pages / 2; + } + } + allocated_pages = allocated_pages + to_alloc_pages; + sz = to_alloc_pages * 4096; + uintptr_t es = 0; + es = _Heap_Extend( RTEMS_Malloc_Heap, (void *)physBuf, sz, 0 ); + free(map); + return es; +} + +void efi_memory_heap_extend( void ) +{ + int i; + UINT64 asz = 0; + UINT64 oldsz, newsz = 0; + oldsz = heap_size(); + for (i = 0; i < 1024; i++) { + /* let's try 1k alloc attempts */ + asz = allocate_biggest_block(); + if (asz == 0) + break; + extension_steps++; + } + newsz = heap_size(); + printf("EFI: Total memory: %u pages, %u megabytes\n", total_pages, (total_pages * 4 / 1024)); + printf("EFI: Usable memory: %u pages, %u megabytes\n", usable_pages, (usable_pages * 4 / 1024)); + printf("EFI: Allocated memory: %u pages, %u megabytes\n", allocated_pages, (allocated_pages * 4 / 1024)); + printf("RTEMS: Heap extended in %u steps with %u steps failed.\n", extension_steps, error); + uint64_t s = newsz - oldsz; + printf("RTEMS: Heap extended by %lu pages, %lu megabytes\n", (s / 4096), ((s / 1024) / 1024)); +} + +#ifdef BSP_EFI_MMAP_PRINTOUT +static const char* +efi_memory_type(EFI_MEMORY_TYPE type) +{ + switch (type) { + case EfiReservedMemoryType: + return "Reserved"; + case EfiLoaderCode: + return "LoaderCode"; + case EfiLoaderData: + return "LoaderData"; + case EfiBootServicesCode: + return "BootServicesCode"; + case EfiBootServicesData: + return "BootServicesData"; + case EfiRuntimeServicesCode: + return "RuntimeServicesCode"; + case EfiRuntimeServicesData: + return "RuntimeServicesData"; + case EfiConventionalMemory: + return "ConventionalMemory"; + case EfiUnusableMemory: + return "UnusableMemory"; + case EfiACPIReclaimMemory: + return "ACPIReclaimMemory"; + case EfiACPIMemoryNVS: + return "ACPIMemoryNVS"; + case EfiMemoryMappedIO: + return "MemoryMappedIO"; + case EfiMemoryMappedIOPortSpace: + return "MemoryMappedIOPortSpace"; + case EfiPalCode: + return "PalCode"; + case EfiPersistentMemory: + return "PersistentMemory"; + default: + return "Unknown Type"; + } +} +#endif diff --git a/bsps/x86_64/amd64/start/linkcmds b/bsps/x86_64/amd64/start/linkcmds index ab6981e872..b0de91f160 100644 --- a/bsps/x86_64/amd64/start/linkcmds +++ b/bsps/x86_64/amd64/start/linkcmds @@ -28,13 +28,15 @@ RamBase = DEFINED(RamBase) ? RamBase : /* XXX: Defaulting to 1GiB. */ RamSize = DEFINED(RamSize) ? RamSize : - DEFINED(_RamSize) ? _RamSize : 0x40000000; + /* DEFINED(_RamSize) ? _RamSize : 0x2000000;*/ /* 32MB */ + DEFINED(_RamSize) ? _RamSize : 0x1000000; /* 16MB */ RamEnd = RamBase + RamSize; SECTIONS { /* Read-only sections, merged into text segment: */ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x00100000)); . = SEGMENT_START("text-segment", 0x00100000) + SIZEOF_HEADERS; +/* .multiboot2_header : { *(.multiboot2_header) }*/ .interp : { *(.interp) } .note.gnu.build-id : { *(.note.gnu.build-id) } .hash : { *(.hash) } @@ -88,6 +90,7 @@ SECTIONS .plt.sec : { *(.plt.sec) } .text : { + KEEP (*(.multiboot2_header)) *(.text.unlikely .text.*_unlikely .text.unlikely.*) *(.text.exit .text.exit.*) *(.text.startup .text.startup.*) @@ -234,8 +237,9 @@ SECTIONS _end = .; PROVIDE (end = .); .noinit (NOLOAD) : { - *(.noinit*) + *(SORT_BY_NAME (SORT_BY_ALIGNMENT (.noinit*))) } + . = ALIGN(64); .rtemsstack (NOLOAD) : { *(SORT(.rtemsstack.*)) diff --git a/bsps/x86_64/amd64/start/multiboot2.c b/bsps/x86_64/amd64/start/multiboot2.c new file mode 100644 index 0000000000..4dce74834c --- /dev/null +++ b/bsps/x86_64/amd64/start/multiboot2.c @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2023 Karel Gardas + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <bsp.h> +#include <inttypes.h> +#include <multiboot2.h> +#include <multiboot2impl.h> + +#include <rtems/score/heap.h> + +#include <efi.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef BSP_MULTIBOOT_SUPPORT +#ifdef BSP_USE_EFI_BOOT_SERVICES + +extern void +efi_console_initialize( void ); + +extern void +efi_memory_heap_extend(void); + + +extern EFI_HANDLE IH; +extern EFI_SYSTEM_TABLE *ST; +extern EFI_BOOT_SERVICES *BS; +extern EFI_RUNTIME_SERVICES *RS; +#endif +extern int _multiboot2_magic; +extern void* _multiboot2_info_ptr; +static int already_processed = 0; +#endif + +static int bootservices_running = 0; + +static char multiboot_boot_args[256]; + +extern Heap_Control *RTEMS_Malloc_Heap; + +#ifdef BSP_MULTIBOOT_SUPPORT + +void +process_multiboot2_info() +{ + struct multiboot_tag *tag; + unsigned size; + +#ifdef BSP_USE_EFI_BOOT_SERVICES + ST = 0; + RS = 0; + BS = 0; +#endif + if (already_processed) + return; + if (_multiboot2_magic == MULTIBOOT2_BOOTLOADER_MAGIC) { + if ((*(unsigned*)_multiboot2_info_ptr) & 7) { + printf("Multiboot2 info @ %p, unaligned mbi: 0x%x\n", _multiboot2_info_ptr, *(unsigned*)_multiboot2_info_ptr); + } + else { + size = *(unsigned*)_multiboot2_info_ptr; + printf("Multiboot2 info @ %p, size 0x%x\n", _multiboot2_info_ptr, size); + for (tag = (struct multiboot_tag *) (_multiboot2_info_ptr + 8); + tag->type != MULTIBOOT_TAG_TYPE_END; + tag = (struct multiboot_tag *) ((multiboot_uint8_t *) tag + ((tag->size + 7) & ~7))) { + switch (tag->type) { + case MULTIBOOT_TAG_TYPE_CMDLINE: + printf("Multiboot2 booting arguments: `%s', args len: %d\n", + ((struct multiboot_tag_string *) tag)->string, + ((struct multiboot_tag_string *) tag)->size); + strncpy(multiboot_boot_args, ((struct multiboot_tag_string*)tag)->string, ((struct multiboot_tag_string*)tag)->size); + break; + case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: + printf("Multiboot2 loader name: `%s'\n", ((struct multiboot_tag_string *) tag)->string); + break; + case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: + struct multiboot_tag_framebuffer* fbtag = (struct multiboot_tag_framebuffer*)tag; + uint64_t fbbase = fbtag->common.framebuffer_addr; + printf("Multiboot2 framebuffer @ %p, resolution: %dx%d, pitch/bpp: %d/%d, type: %d\n", + (void*)fbbase, fbtag->common.framebuffer_width, fbtag->common.framebuffer_height, + fbtag->common.framebuffer_pitch, fbtag->common.framebuffer_bpp, + fbtag->common.framebuffer_type); + break; +#ifdef BSP_USE_EFI_BOOT_SERVICES + case MULTIBOOT_TAG_TYPE_EFI64: + printf("EFI64 system table @ 0x%llx\n", ((struct multiboot_tag_efi64 *) tag)->pointer); + ST = ((EFI_SYSTEM_TABLE*)((struct multiboot_tag_efi64 *) tag)->pointer); + BS = ST->BootServices; + RS = ST->RuntimeServices; + efi_console_initialize(); + efi_memory_heap_extend(); + break; + case MULTIBOOT_TAG_TYPE_EFI_BS: + printf("GRUB: EFI boot services running.\n"); + bootservices_running = 1; + break; + case MULTIBOOT_TAG_TYPE_EFI64_IH: + printf("EFI: 64bit image handle: 0x%llx\n", ((struct multiboot_tag_efi64_ih *) tag)->pointer); + IH = (EFI_HANDLE)((struct multiboot_tag_efi64_ih *) tag)->pointer; + break; +#endif + } + } + } + } + else { + printf("So while not being booted by multiboot2, let's see what's in its magic then?: %dx\n", _multiboot2_magic); + } +} + +#endif /* BSP_MULTIBOOT_SUPPORT */ + +int +uefi_bootservices_running() +{ + return bootservices_running; +} + +const char* +boot_args() +{ + return multiboot_boot_args; +} + +int +get_boot_arg_int_value(const char* boot_args, const char* arg, int* val) +{ + int len_arg = strlen(arg); + int len_try = strlen(boot_args) - len_arg; + int len_bootargs = strlen(boot_args); + char num[10]; + for (int i = 0; i < len_try; i++) { + if (strncmp(&(boot_args[i]), arg, len_arg) == 0) { + i = i + len_arg + 1; + for (int j = 0; j < 10; j++) { + if (boot_args[i + j] != ' ' && i + j < len_bootargs) + num[j] = boot_args[i + j]; + else { + num[j] = 0; + *val = atoi(num); + return 0; + } + } + } + } + return -1; +} + diff --git a/bsps/x86_64/amd64/start/page.c b/bsps/x86_64/amd64/start/page.c index 64bdf21707..c2e3949556 100644 --- a/bsps/x86_64/amd64/start/page.c +++ b/bsps/x86_64/amd64/start/page.c @@ -83,7 +83,7 @@ uint64_t get_mask_for_bits(uint8_t start, uint8_t end) return mask; } -RTEMS_INLINE_ROUTINE void assert_0s_from_bit(uint64_t entry, uint8_t bit_pos) +static inline void assert_0s_from_bit(uint64_t entry, uint8_t bit_pos) { /* Confirm that bit_pos:64 are all 0s */ assert((entry & get_mask_for_bits(bit_pos, 64)) == 0); diff --git a/bsps/x86_64/amd64/start/start.S b/bsps/x86_64/amd64/start/start.S index e1a50e05db..b8120473be 100644 --- a/bsps/x86_64/amd64/start/start.S +++ b/bsps/x86_64/amd64/start/start.S @@ -1,7 +1,8 @@ /* * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (C) 2018 embedded brains GmbH + * Copyright (C) 2023 Karel Gardas + * Copyright (C) 2018 embedded brains GmbH & Co. KG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,6 +26,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <bspopts.h> + +#ifdef BSP_MULTIBOOT_SUPPORT +#include <multiboot2.h> +#endif + .text .section .text._start,"ax",@progbits .p2align 4,,15 @@ -36,6 +43,71 @@ _start: subq $8, %rsp .cfi_def_cfa_offset 16 xorl %edi, %edi +#ifdef BSP_MULTIBOOT_SUPPORT + mov %eax, _multiboot2_magic + mov %rbx, _multiboot2_info_ptr +#endif movabsq $boot_card, %rax call *%rax .cfi_endproc + +#ifdef BSP_MULTIBOOT_SUPPORT + +multiboot2: + ret + +_multiboot2_start: + jmp _start + + .text + .section .multiboot2_header + .p2align 4,,15 +multiboot2_header_start: + .long MULTIBOOT2_HEADER_MAGIC + .long MULTIBOOT_ARCHITECTURE_I386 + .long multiboot2_header_end - multiboot2_header_start + .long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (multiboot2_header_end - multiboot2_header_start)) +efi_bootservices_start: + .short MULTIBOOT_HEADER_TAG_EFI_BS + .short 0 + .long efi_bootservices_end - efi_bootservices_start +efi_bootservices_end: +efi64_entry_start: + .short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 + .short 0 + .long efi64_entry_end - efi64_entry_start + .long _start /* directly copied from resulting ELF */ + /* padding to 8 byte tags allignment */ + .long 0 +efi64_entry_end: +info_requests_start: + .short MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST + .short 0 + .long info_requests_end - info_requests_start + .long MULTIBOOT_TAG_TYPE_EFI64 + .long MULTIBOOT_TAG_TYPE_CMDLINE +#ifdef BSP_USE_EFI_BOOT_SERVICES + .long MULTIBOOT_TAG_TYPE_EFI_BS +#else + .long 0 +#endif + /* padding to 8 byte tags allignment */ + .long 0 +info_requests_end: + /* header end*/ + .short MULTIBOOT_HEADER_TAG_END + .short 0 + .long 8 +multiboot2_header_end: + + .data + .global _multiboot2_magic +_multiboot2_magic: + .long 0 + + .data + .global _multiboot2_info_ptr +_multiboot2_info_ptr: + .quad 0 + +#endif |