Merge pull request #216 from antmicro/booting_vexriscv_linux
Rework booting Linux on VexRiscv
This commit is contained in:
commit
7d9cf1d2bd
|
@ -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"):
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue