summaryrefslogtreecommitdiffstats
path: root/bsps/x86_64/amd64/start
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/x86_64/amd64/start')
-rw-r--r--bsps/x86_64/amd64/start/bspstart.c16
-rw-r--r--bsps/x86_64/amd64/start/efimem.c203
-rw-r--r--bsps/x86_64/amd64/start/linkcmds8
-rw-r--r--bsps/x86_64/amd64/start/multiboot2.c174
-rw-r--r--bsps/x86_64/amd64/start/page.c2
-rw-r--r--bsps/x86_64/amd64/start/start.S74
6 files changed, 471 insertions, 6 deletions
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