From 9c60b66f71bef55a6f0e048737cab9c5766cfc5a Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Sat, 12 Oct 2024 19:39:11 +0300 Subject: [PATCH] AARCH64: Allow for embedding an initramfs This actually breaks the armv7 port. It has to be revisited in the future, since it not only is not compilable right now, but also cannot boot linux properly. TODO Also introduce a new C-based __memcpy_optimized that does not cause an exception on some devices when copying the initramfs. This issue has to be debugged further. Signed-off-by: Ivaylo Ivanov --- .gitignore | 1 + Kconfig | 7 ++++++ Makefile | 5 +++-- arch/aarch64/linker.lds.S | 7 ++++++ arch/aarch64/start.S | 2 ++ blob/ramdisk | 0 board/Kconfig | 4 ++++ include/main.h | 1 + lib/unic/string.h | 45 ++++++++++++++++++++++++++++++++++++++- main/main.c | 3 ++- 10 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 blob/ramdisk diff --git a/.gitignore b/.gitignore index fd907f17..931d6bf4 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ boot.img blob/Image blob/dtb drivers/*.a +blob/ramdisk diff --git a/Kconfig b/Kconfig index 260b7674..1b9080a0 100644 --- a/Kconfig +++ b/Kconfig @@ -36,6 +36,13 @@ menu "Building options" default blob/dtb help Path to the device tree, which is going to get embedded to uniLoader + + config RAMDISK_PATH + string "Path to ramdisk image" + depends on EMBED_LINUX + default blob/ramdisk + help + Path to the ramdisk, which is going to get embedded to uniLoader endmenu source "lib/Kconfig" diff --git a/Makefile b/Makefile index 139f6eab..1a3b6a1e 100644 --- a/Makefile +++ b/Makefile @@ -103,6 +103,7 @@ export srctree objtree VPATH CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) KERNEL_PATH ?= $(CONFIG_KERNEL_PATH:"%"=%) DT_PATH ?= $(CONFIG_DT_PATH:"%"=%) +RAMDISK_PATH ?= $(CONFIG_RAMDISK_PATH:"%"=%) TEXT_BASE ?= $(CONFIG_TEXT_BASE:"%"=%) KCONFIG_CONFIG ?= .config @@ -371,8 +372,8 @@ uniLoader-all := $(uniLoader-objs) $(uniLoader-libs) quiet_cmd_uniLoader = LD $@.o cmd_uniLoader = $(LD) $(main-y) $(arch-libs-y) $(uniLoader-libs) -o $@.o --script=arch/$(ARCH)/linker.lds -arch/$(ARCH)/linker.lds: arch/$(ARCH)/linker.lds.S $(KERNEL_PATH) - $(CPP) $< -DTEXT_BASE=$(TEXT_BASE) -DKERNEL_PATH=$(KERNEL_PATH) -DDTB_PATH=$(DT_PATH) -P -o $@ +arch/$(ARCH)/linker.lds: arch/$(ARCH)/linker.lds.S $(KERNEL_PATH) $(RAMDISK_PATH) + $(CPP) $< -DTEXT_BASE=$(TEXT_BASE) -DKERNEL_PATH=$(KERNEL_PATH) -DDTB_PATH=$(DT_PATH) -DRAMDISK_PATH=$(RAMDISK_PATH) -P -o $@ uniLoader: $(uniLoader-all) $(call if_changed,uniLoader) diff --git a/arch/aarch64/linker.lds.S b/arch/aarch64/linker.lds.S index 187ae30a..0b92e162 100644 --- a/arch/aarch64/linker.lds.S +++ b/arch/aarch64/linker.lds.S @@ -9,6 +9,7 @@ TARGET(binary) INPUT(KERNEL_PATH) INPUT(DTB_PATH) +INPUT(RAMDISK_PATH) SECTIONS { @@ -41,5 +42,11 @@ SECTIONS KERNEL_PATH } + .ramdisk ALIGN(4096) : { + ramdisk = .; + RAMDISK_PATH + } + kernel_size = SIZEOF(.kernel); + ramdisk_size = SIZEOF(.ramdisk); } diff --git a/arch/aarch64/start.S b/arch/aarch64/start.S index 30666aa6..4abdae81 100644 --- a/arch/aarch64/start.S +++ b/arch/aarch64/start.S @@ -18,6 +18,8 @@ ENTRY(_start) add x0, x0, #:lo12:dtb /* Add offset within the page */ adrp x1, kernel /* Load page of kernel */ add x1, x1, #:lo12:kernel /* Add offset within the page */ + adrp x2, ramdisk /* Load page of kernel */ + add x2, x2, #:lo12:ramdisk /* Add offset within the page */ bl main END(_start) diff --git a/blob/ramdisk b/blob/ramdisk new file mode 100644 index 00000000..e69de29b diff --git a/board/Kconfig b/board/Kconfig index a315d728..0a9d138b 100644 --- a/board/Kconfig +++ b/board/Kconfig @@ -97,6 +97,10 @@ menu "Device Specific Addresses" default 0x090000000 if SAMSUNG_J5LTE default 0x090000000 if SAMSUNG_GTA4XL + config RAMDISK_ENTRY + hex "Ramdisk Entry Address" + default 0x082000000 if SAMSUNG_DREAMLTE + config FRAMEBUFFER_BASE hex "Framebuffer Base Address (for SimpleFB)" depends on SIMPLE_FB diff --git a/include/main.h b/include/main.h index dbbab736..584678eb 100644 --- a/include/main.h +++ b/include/main.h @@ -9,6 +9,7 @@ #define MAIN_H_ extern unsigned long kernel_size; +extern unsigned long ramdisk_size; extern void load_kernel(void* dtb, void* x1, void* x2, void* x3, void* kernel); extern void soc_init(void); diff --git a/lib/unic/string.h b/lib/unic/string.h index 4ef58584..14103348 100644 --- a/lib/unic/string.h +++ b/lib/unic/string.h @@ -9,7 +9,7 @@ #include "stddef.h" #define LBLOCKSIZE (sizeof(long)) -#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) +#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) // C-driven unoptimized functions @@ -30,6 +30,49 @@ void writel (unsigned int value, void* address); // C-driven optimized functions void *memset (void *m, int c, size_t n); +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED_CPY(X, Y) (((long)X & (sizeof (long) - 1)) | \ + ((long)Y & (sizeof (long) - 1))) + +/* How many bytes are copied each iteration of the 4X unrolled loop. */ +#define BIGBLOCKSIZE (sizeof(long) << 2) + +static void *__optimized_memcpy (void *dst0, const void *src0, size_t len0) +{ + char *dst = dst0; + const char *src = src0; + long *aligned_dst; + const long *aligned_src; + + /* If the size is small, or either SRC or DST is unaligned, + then punt into the byte copy loop. This should be rare. */ + if (!(((len0) < BIGBLOCKSIZE)) && !UNALIGNED_CPY (src, dst)) { + aligned_dst = (long*)dst; + aligned_src = (long*)src; + /* Copy 4X long words at a time if possible. */ + while (len0 >= BIGBLOCKSIZE) { + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + len0 -= BIGBLOCKSIZE; + } + /* Copy one long word at a time if possible. */ + while (len0 >= LBLOCKSIZE) { + *aligned_dst++ = *aligned_src++; + len0 -= LBLOCKSIZE; + } + + /* Pick up any residual with a byte copier. */ + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while (len0--) + *dst++ = *src++; + return dst0; +} + // Assembly-driven functions #ifdef __aarch64__ void *memcpy (void *__restrict, const void *__restrict, size_t); diff --git a/main/main.c b/main/main.c index 8c889db8..7e3775de 100644 --- a/main/main.c +++ b/main/main.c @@ -23,7 +23,7 @@ struct board_data board = { } }; -void main(void* dt, void* kernel) +void main(void* dt, void* kernel, void* ramdisk) { /* Initialize SoC and Board specific peripherals/quirks */ init_board_funcs(&board); @@ -46,6 +46,7 @@ void main(void* dt, void* kernel) printk(-1, "Booting linux...\n"); memcpy((void*)CONFIG_PAYLOAD_ENTRY, kernel, (unsigned long) &kernel_size); + __optimized_memcpy((void*)CONFIG_RAMDISK_ENTRY, ramdisk, (unsigned long) &ramdisk_size); load_kernel(dt, 0, 0, 0, (void*)CONFIG_PAYLOAD_ENTRY); /* We shouldn't get there */