bios/boot: rework netboot/flashboot for VexRiscv in linux variant
authorMateusz Holenko <mholenko@antmicro.com>
Thu, 11 Jul 2019 08:14:27 +0000 (10:14 +0200)
committerMateusz Holenko <mholenko@antmicro.com>
Mon, 15 Jul 2019 14:02:58 +0000 (16:02 +0200)
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

index be7c9278da4c166bc6d3727fccece2e81c959a13..b79eed9039e5dade0b1b123a4ccc87fe092f68cb 100644 (file)
@@ -224,55 +224,73 @@ const char *filename, char *buffer)
 
 static const unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
 
-void netboot(void)
+#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)
 {
-       int size;
-       unsigned int ip;
        unsigned long tftp_dst_addr;
-       unsigned short tftp_port;
-
-       printf("Booting from network...\n");
-       printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4);
-       printf("Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
-
-       ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
-
-       microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
-
-       tftp_port = TFTP_SERVER_PORT;
-       printf("Fetching from: UDP/%d\n", tftp_port);
+       int size;
 
-#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");
-               return;
+               return 0;
        }
 
-       tftp_dst_addr = MAIN_RAM_BASE + 0x00800000;
+       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;
+               return 0;
        }
 
-       tftp_dst_addr = MAIN_RAM_BASE + 0x01000000;
+       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;
+               return 0;
        }
 
-       tftp_dst_addr = EMULATOR_RAM_BASE;
+       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;
+               return 0;
        }
 
-       boot(0, 0, 0, EMULATOR_RAM_BASE);
-#else
+       return 1;
+}
+#endif
+
+void netboot(void)
+{
+       int size;
+       unsigned int ip;
+       unsigned long tftp_dst_addr;
+       unsigned short tftp_port;
+
+       printf("Booting from network...\n");
+       printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4);
+       printf("Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
+
+       ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
+
+       microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
+
+       tftp_port = TFTP_SERVER_PORT;
+       printf("Fetching from: UDP/%d\n", tftp_port);
+
+#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;
+       }
+#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