From 005c07769b317a64ce79b9cd903e882bb4183cdf Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Thu, 11 Jul 2019 10:13:28 +0200 Subject: [PATCH 1/3] soc_core: include information about cpu variant in csv and headers --- litex/soc/integration/soc_core.py | 1 + 1 file changed, 1 insertion(+) diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 5de233c78..1fd7917f1 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -239,6 +239,7 @@ class SoCCore(Module): # Add CPU self.config["CPU_TYPE"] = str(cpu_type).upper() + self.config["CPU_VARIANT"] = str(cpu_variant).upper() if cpu_type is not None: # CPU selection / instance if cpu_type == "lm32": From a19bdd0e6a0952ddaba0d6fa4c50f2fc489c7819 Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Thu, 11 Jul 2019 10:13:54 +0200 Subject: [PATCH 2/3] soc_core: generate extra string-based config defines C preprocessor does not allow to compare strings, so the current defines are not usable at the compile time. This adds new defines that can be ifdefed. --- litex/soc/integration/soc_core.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 1fd7917f1..50ff64efb 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -530,6 +530,8 @@ class SoCCore(Module): self._constants.append(((name + "_" + constant.name).upper(), constant.value.value)) for name, value in sorted(self.config.items(), key=itemgetter(0)): self._constants.append(("CONFIG_" + name.upper(), value)) + if isinstance(value, str): + self._constants.append(("CONFIG_" + name.upper() + "_" + value, 1)) # Connect interrupts if hasattr(self, "cpu"): From 8335f13fb15080852bf1928ad669b98f7e4c51ea Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Thu, 11 Jul 2019 10:14:27 +0200 Subject: [PATCH 3/3] bios/boot: rework netboot/flashboot for VexRiscv in linux variant Get rid of NETBOOT_LINUX_VEXRISCV/FLASHBOOT_LINUX_VEXRISCV defines and use information about CPU_TYPE and CPU_VARIANT instead. Use common kernel/rootfs/device tree/emulator images layout when booting over network and from flash. --- litex/soc/software/bios/boot.c | 197 +++++++++++++++++++++------------ 1 file changed, 129 insertions(+), 68 deletions(-) diff --git a/litex/soc/software/bios/boot.c b/litex/soc/software/bios/boot.c index be7c9278d..b79eed903 100644 --- a/litex/soc/software/bios/boot.c +++ b/litex/soc/software/bios/boot.c @@ -224,6 +224,48 @@ const char *filename, char *buffer) static const unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00}; +#define ROOTFS_IMAGE_RAM_OFFSET 0x00800000 +#define DEVICE_TREE_IMAGE_RAM_OFFSET 0x01000000 +#define EMULATOR_IMAGE_RAM_OFFSET 0x02000000 + +#if defined(CONFIG_CPU_TYPE_VEXRISCV) && defined(CONFIG_CPU_VARIANT_LINUX) +static int try_get_kernel_rootfs_dtb_emulator(unsigned int ip, unsigned short tftp_port) +{ + unsigned long tftp_dst_addr; + int size; + + tftp_dst_addr = MAIN_RAM_BASE; + size = tftp_get_v(ip, tftp_port, "Image", (void *)tftp_dst_addr); + if (size <= 0) { + printf("Network boot failed\n"); + return 0; + } + + tftp_dst_addr = MAIN_RAM_BASE + ROOTFS_IMAGE_RAM_OFFSET; + size = tftp_get_v(ip, tftp_port, "rootfs.cpio", (void *)tftp_dst_addr); + if(size <= 0) { + printf("No rootfs.cpio found\n"); + return 0; + } + + tftp_dst_addr = MAIN_RAM_BASE + DEVICE_TREE_IMAGE_RAM_OFFSET; + size = tftp_get_v(ip, tftp_port, "rv32.dtb", (void *)tftp_dst_addr); + if(size <= 0) { + printf("No rv32.dtb found\n"); + return 0; + } + + tftp_dst_addr = MAIN_RAM_BASE + EMULATOR_IMAGE_RAM_OFFSET; + size = tftp_get_v(ip, tftp_port, "emulator.bin", (void *)tftp_dst_addr); + if(size <= 0) { + printf("No emulator.bin found\n"); + return 0; + } + + return 1; +} +#endif + void netboot(void) { int size; @@ -242,37 +284,13 @@ void netboot(void) tftp_port = TFTP_SERVER_PORT; printf("Fetching from: UDP/%d\n", tftp_port); -#ifdef NETBOOT_LINUX_VEXRISCV - tftp_dst_addr = MAIN_RAM_BASE; - size = tftp_get_v(ip, tftp_port, "Image", (void *)tftp_dst_addr); - if (size <= 0) { - printf("Network boot failed\n"); +#if defined(CONFIG_CPU_TYPE_VEXRISCV) && defined(CONFIG_CPU_VARIANT_LINUX) + if(try_get_kernel_rootfs_dtb_emulator(ip, tftp_port)) + { + boot(0, 0, 0, MAIN_RAM_BASE + EMULATOR_IMAGE_RAM_OFFSET); return; } - - tftp_dst_addr = MAIN_RAM_BASE + 0x00800000; - size = tftp_get_v(ip, tftp_port, "rootfs.cpio", (void *)tftp_dst_addr); - if(size <= 0) { - printf("No rootfs.cpio found\n"); - return; - } - - tftp_dst_addr = MAIN_RAM_BASE + 0x01000000; - size = tftp_get_v(ip, tftp_port, "rv32.dtb", (void *)tftp_dst_addr); - if(size <= 0) { - printf("No rv32.dtb found\n"); - return; - } - - tftp_dst_addr = EMULATOR_RAM_BASE; - size = tftp_get_v(ip, tftp_port, "emulator.bin", (void *)tftp_dst_addr); - if(size <= 0) { - printf("No emulator.bin found\n"); - return; - } - - boot(0, 0, 0, EMULATOR_RAM_BASE); -#else +#endif tftp_dst_addr = MAIN_RAM_BASE; size = tftp_get_v(ip, tftp_port, "boot.bin", (void *)tftp_dst_addr); if (size <= 0) { @@ -281,34 +299,10 @@ void netboot(void) } boot(0, 0, 0, MAIN_RAM_BASE); -#endif - } #endif -#ifdef FLASHBOOT_LINUX_VEXRISCV - -/* TODO: add configurable flash mapping, improve integration */ - -void flashboot(void) -{ - printf("Loading Image from flash...\n"); - memcpy((void *)MAIN_RAM_BASE + 0x00000000, (void *)0x50400000, 0x400000); - - printf("Loading rootfs.cpio from flash...\n"); - memcpy((void *)MAIN_RAM_BASE + 0x00800000, (void *)0x50800000, 0x700000); - - printf("Loading rv32.dtb from flash...\n"); - memcpy((void *)MAIN_RAM_BASE + 0x01000000, (void *)0x50f00000, 0x001000); - - printf("Loading emulator.bin from flash...\n"); - memcpy((void *)EMULATOR_RAM_BASE + 0x00000000, (void *)0x50f80000, 0x004000); - - boot(0, 0, 0, EMULATOR_RAM_BASE); -} -#else - #ifdef FLASH_BOOT_ADDRESS /* On systems with exernal SDRAM we copy out of the SPI flash into the SDRAM @@ -321,38 +315,105 @@ void flashboot(void) #define FIRMWARE_BASE_ADDRESS (FLASH_BOOT_ADDRESS + 2 * sizeof(unsigned int)) #endif -void flashboot(void) +static unsigned int check_image_in_flash(unsigned int *base_address) { - unsigned int *flashbase; unsigned int length; unsigned int crc; unsigned int got_crc; - printf("Booting from flash...\n"); - flashbase = (unsigned int *)FLASH_BOOT_ADDRESS; - length = *flashbase++; - crc = *flashbase++; + length = *base_address++; if((length < 32) || (length > 4*1024*1024)) { - printf("Error: Invalid flash boot image length 0x%08x\n", length); + printf("Error: Invalid image length 0x%08x\n", length); + return 0; + } + + crc = *base_address++; + got_crc = crc32((unsigned char *)base_address, length); + if(crc != got_crc) { + printf("CRC failed (expected %08x, got %08x)\n", crc, got_crc); + return 0; + } + + return length; +} + +#if defined(MAIN_RAM_BASE) && defined(CONFIG_CPU_TYPE_VEXRISCV) && defined(CONFIG_CPU_VARIANT_LINUX) +static int copy_image_from_flash_to_ram(unsigned int *flash_address, unsigned int *ram_address) +{ + unsigned int length; + + length = check_image_in_flash(flash_address); + if(length > 0) { + // skip length and crc + memcpy((void *)ram_address, (void *)(flash_address + 2), length); + return 1; + } + + return 0; +} +#endif + +#define KERNEL_IMAGE_FLASH_OFFSET 0x00000000 // 0MB +#define ROOTFS_IMAGE_FLASH_OFFSET 0x00400000 // 4MB +#define DEVICE_TREE_IMAGE_FLASH_OFFSET 0x00B00000 // 11MB +#define EMULATOR_IMAGE_FLASH_OFFSET 0x00B01000 // 11MB + 4KB + +void flashboot(void) +{ + unsigned int length; + +#if defined(MAIN_RAM_BASE) && defined(CONFIG_CPU_TYPE_VEXRISCV) && defined(CONFIG_CPU_VARIANT_LINUX) + unsigned int result; + + printf("Loading emulator.bin from flash...\n"); + result = copy_image_from_flash_to_ram( + (unsigned int *)(FLASH_BOOT_ADDRESS + EMULATOR_IMAGE_FLASH_OFFSET), + (unsigned int *)(MAIN_RAM_BASE + EMULATOR_IMAGE_RAM_OFFSET)); + + if(result) { + printf("Loading Image from flash...\n"); + result &= copy_image_from_flash_to_ram( + (unsigned int *)FLASH_BOOT_ADDRESS + KERNEL_IMAGE_FLASH_OFFSET, + (unsigned int *)MAIN_RAM_BASE); + } + + if(result) { + printf("Loading rootfs.cpio from flash...\n"); + result &= copy_image_from_flash_to_ram( + (unsigned int *)(FLASH_BOOT_ADDRESS + ROOTFS_IMAGE_FLASH_OFFSET), + (unsigned int *)(MAIN_RAM_BASE + ROOTFS_IMAGE_RAM_OFFSET)); + } + + if(result) { + printf("Loading rv32.dtb from flash...\n"); + result &= copy_image_from_flash_to_ram( + (unsigned int *)(FLASH_BOOT_ADDRESS + DEVICE_TREE_IMAGE_FLASH_OFFSET), + (unsigned int *)(MAIN_RAM_BASE + DEVICE_TREE_IMAGE_RAM_OFFSET)); + } + + if(result) { + boot(0, 0, 0, MAIN_RAM_BASE + EMULATOR_IMAGE_RAM_OFFSET); + return; + } +#endif + + printf("Booting from flash...\n"); + length = check_image_in_flash((unsigned int *)FLASH_BOOT_ADDRESS); + if(!length) + { return; } #ifdef MAIN_RAM_BASE printf("Loading %d bytes from flash...\n", length); - memcpy((void *)MAIN_RAM_BASE, flashbase, length); + // skip length and crc + memcpy((void *)MAIN_RAM_BASE, (unsigned int *)(FLASH_BOOT_ADDRESS + 2 * sizeof(unsigned int)), length); #endif - got_crc = crc32((unsigned char *)FIRMWARE_BASE_ADDRESS, length); - if(crc != got_crc) { - printf("CRC failed (expected %08x, got %08x)\n", crc, got_crc); - return; - } boot(0, 0, 0, FIRMWARE_BASE_ADDRESS); } #endif -#endif - #ifdef ROM_BOOT_ADDRESS /* When firmware is small enough, it can be interesting to run code from an embedded blockram memory (faster and not impacted by memory controller