Merge pull request #216 from antmicro/booting_vexriscv_linux

Rework booting Linux on VexRiscv
This commit is contained in:
enjoy-digital 2019-07-22 11:44:20 +02:00 committed by GitHub
commit 7d9cf1d2bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 132 additions and 68 deletions

View File

@ -245,6 +245,7 @@ class SoCCore(Module):
# Add CPU # Add CPU
self.config["CPU_TYPE"] = str(cpu_type).upper() self.config["CPU_TYPE"] = str(cpu_type).upper()
self.config["CPU_VARIANT"] = str(cpu_variant).upper()
if cpu_type is not None: if cpu_type is not None:
# CPU selection / instance # CPU selection / instance
if cpu_type == "lm32": if cpu_type == "lm32":
@ -535,6 +536,8 @@ class SoCCore(Module):
self._constants.append(((name + "_" + constant.name).upper(), constant.value.value)) self._constants.append(((name + "_" + constant.name).upper(), constant.value.value))
for name, value in sorted(self.config.items(), key=itemgetter(0)): for name, value in sorted(self.config.items(), key=itemgetter(0)):
self._constants.append(("CONFIG_" + name.upper(), value)) self._constants.append(("CONFIG_" + name.upper(), value))
if isinstance(value, str):
self._constants.append(("CONFIG_" + name.upper() + "_" + value, 1))
# Connect interrupts # Connect interrupts
if hasattr(self, "cpu"): if hasattr(self, "cpu"):

View File

@ -224,6 +224,48 @@ const char *filename, char *buffer)
static const unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00}; 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) void netboot(void)
{ {
int size; int size;
@ -242,37 +284,13 @@ void netboot(void)
tftp_port = TFTP_SERVER_PORT; tftp_port = TFTP_SERVER_PORT;
printf("Fetching from: UDP/%d\n", tftp_port); printf("Fetching from: UDP/%d\n", tftp_port);
#ifdef NETBOOT_LINUX_VEXRISCV #if defined(CONFIG_CPU_TYPE_VEXRISCV) && defined(CONFIG_CPU_VARIANT_LINUX)
tftp_dst_addr = MAIN_RAM_BASE; if(try_get_kernel_rootfs_dtb_emulator(ip, tftp_port))
size = tftp_get_v(ip, tftp_port, "Image", (void *)tftp_dst_addr); {
if (size <= 0) { boot(0, 0, 0, MAIN_RAM_BASE + EMULATOR_IMAGE_RAM_OFFSET);
printf("Network boot failed\n");
return; return;
} }
#endif
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
tftp_dst_addr = MAIN_RAM_BASE; tftp_dst_addr = MAIN_RAM_BASE;
size = tftp_get_v(ip, tftp_port, "boot.bin", (void *)tftp_dst_addr); size = tftp_get_v(ip, tftp_port, "boot.bin", (void *)tftp_dst_addr);
if (size <= 0) { if (size <= 0) {
@ -281,34 +299,10 @@ void netboot(void)
} }
boot(0, 0, 0, MAIN_RAM_BASE); boot(0, 0, 0, MAIN_RAM_BASE);
#endif
} }
#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 #ifdef FLASH_BOOT_ADDRESS
/* On systems with exernal SDRAM we copy out of the SPI flash into the SDRAM /* 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)) #define FIRMWARE_BASE_ADDRESS (FLASH_BOOT_ADDRESS + 2 * sizeof(unsigned int))
#endif #endif
void flashboot(void) static unsigned int check_image_in_flash(unsigned int *base_address)
{ {
unsigned int *flashbase;
unsigned int length; unsigned int length;
unsigned int crc; unsigned int crc;
unsigned int got_crc; unsigned int got_crc;
printf("Booting from flash...\n"); length = *base_address++;
flashbase = (unsigned int *)FLASH_BOOT_ADDRESS;
length = *flashbase++;
crc = *flashbase++;
if((length < 32) || (length > 4*1024*1024)) { 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; return;
} }
#ifdef MAIN_RAM_BASE #ifdef MAIN_RAM_BASE
printf("Loading %d bytes from flash...\n", length); 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 #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); boot(0, 0, 0, FIRMWARE_BASE_ADDRESS);
} }
#endif #endif
#endif
#ifdef ROM_BOOT_ADDRESS #ifdef ROM_BOOT_ADDRESS
/* When firmware is small enough, it can be interesting to run code from an /* When firmware is small enough, it can be interesting to run code from an
embedded blockram memory (faster and not impacted by memory controller embedded blockram memory (faster and not impacted by memory controller