bios/boot: make Ethernet boot mode flexible (now also using boot.json similarly to SDCard boot).
Example of boot.json: { "Image": "0x40000000", "rootfs.cpio": "0x40800000", "rv32.dtb": "0x41000000", "emulator.bin": "0x41100000" }
This commit is contained in:
parent
c2ae22eeb6
commit
f4abdd3f2c
|
@ -241,23 +241,6 @@ int serialboot(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_VARIANT_LINUX)
|
|
||||||
|
|
||||||
#ifndef KERNEL_IMAGE_RAM_OFFSET
|
|
||||||
#define KERNEL_IMAGE_RAM_OFFSET 0x00000000
|
|
||||||
#endif
|
|
||||||
#ifndef ROOTFS_IMAGE_RAM_OFFSET
|
|
||||||
#define ROOTFS_IMAGE_RAM_OFFSET 0x00800000
|
|
||||||
#endif
|
|
||||||
#ifndef DEVICE_TREE_IMAGE_RAM_OFFSET
|
|
||||||
#define DEVICE_TREE_IMAGE_RAM_OFFSET 0x01000000
|
|
||||||
#endif
|
|
||||||
#ifndef EMULATOR_IMAGE_RAM_OFFSET
|
|
||||||
#define EMULATOR_IMAGE_RAM_OFFSET 0x01100000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CSR_ETHMAC_BASE
|
#ifdef CSR_ETHMAC_BASE
|
||||||
|
|
||||||
#ifndef LOCALIP1
|
#ifndef LOCALIP1
|
||||||
|
@ -274,138 +257,100 @@ int serialboot(void)
|
||||||
#define REMOTEIP4 100
|
#define REMOTEIP4 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_TFTP_SERVER_PORT 69 /* IANA well known port: UDP/69 */
|
|
||||||
#ifndef TFTP_SERVER_PORT
|
#ifndef TFTP_SERVER_PORT
|
||||||
#define TFTP_SERVER_PORT DEFAULT_TFTP_SERVER_PORT
|
#define TFTP_SERVER_PORT 69
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int tftp_get_v(unsigned int ip, unsigned short server_port,
|
|
||||||
const char *filename, char *buffer)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = tftp_get(ip, server_port, filename, buffer);
|
|
||||||
if(r > 0)
|
|
||||||
printf("Downloaded %d bytes from %s over TFTP to 0x%08x\n", r, filename, buffer);
|
|
||||||
else
|
|
||||||
printf("Unable to download %s over TFTP\n", filename);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
|
static const unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_TYPE_MOR1KX) && defined(CONFIG_CPU_VARIANT_LINUX)
|
static int copy_file_from_tftp_to_ram(unsigned int ip, unsigned short server_port,
|
||||||
static int try_get_kernel_rootfs_dtb(unsigned int ip, unsigned short tftp_port)
|
const char *filename, char *buffer)
|
||||||
{
|
{
|
||||||
unsigned long tftp_dst_addr;
|
|
||||||
int size;
|
int size;
|
||||||
|
printf("Copying %s to 0x%08x... ", filename, buffer);
|
||||||
tftp_dst_addr = MAIN_RAM_BASE + KERNEL_IMAGE_RAM_OFFSET;
|
size = tftp_get(ip, server_port, filename, buffer);
|
||||||
size = tftp_get_v(ip, tftp_port, "Image", (void *)tftp_dst_addr);
|
if(size > 0)
|
||||||
if (size <= 0) {
|
printf("(%d bytes)", size);
|
||||||
printf("Network boot failed\n");
|
printf("\n");
|
||||||
return 0;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
tftp_dst_addr = MAIN_RAM_BASE + DEVICE_TREE_IMAGE_RAM_OFFSET;
|
static void netboot_from_json(const char * filename, unsigned int ip, unsigned short tftp_port)
|
||||||
size = tftp_get_v(ip, tftp_port, "mor1kx.dtb", (void *)tftp_dst_addr);
|
|
||||||
if(size <= 0) {
|
|
||||||
printf("No mor1kx.dtb found\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 (optional)\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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;
|
int size;
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t count;
|
||||||
|
|
||||||
tftp_dst_addr = MAIN_RAM_BASE + KERNEL_IMAGE_RAM_OFFSET;
|
/* FIXME: modify/increase if too limiting */
|
||||||
size = tftp_get_v(ip, tftp_port, "Image", (void *)tftp_dst_addr);
|
char json_buffer[256];
|
||||||
if (size <= 0) {
|
char image_filename[32];
|
||||||
printf("Network boot failed\n");
|
char image_address[32];
|
||||||
return 0;
|
uint8_t image_found;
|
||||||
|
|
||||||
|
/* Read JSON file */
|
||||||
|
size = tftp_get(ip, tftp_port, filename, json_buffer);
|
||||||
|
if (size <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Parse JSON file */
|
||||||
|
jsmntok_t t[16];
|
||||||
|
jsmn_parser p;
|
||||||
|
jsmn_init(&p);
|
||||||
|
image_found = 0;
|
||||||
|
count = jsmn_parse(&p, json_buffer, strlen(json_buffer), t, sizeof(t)/sizeof(*t));
|
||||||
|
for (i=0; i<count-1; i++) {
|
||||||
|
/* Images are JSON strings with 1 children */
|
||||||
|
if ((t[i].type == JSMN_STRING) && (t[i].size == 1)) {
|
||||||
|
/* Get Image filename */
|
||||||
|
memset(image_filename, 0, sizeof(image_filename));
|
||||||
|
memcpy(image_filename, json_buffer+t[i].start, t[i].end - t[i].start);
|
||||||
|
/* Get Image address */
|
||||||
|
memset(image_address, 0, sizeof(image_address));
|
||||||
|
memcpy(image_address, json_buffer+t[i+1].start, t[i+1].end - t[i+1].start);
|
||||||
|
/* Copy Image from Network to address */
|
||||||
|
size = copy_file_from_tftp_to_ram(ip, tftp_port, image_filename, (void *)strtoul(image_address, NULL, 0));
|
||||||
|
if (size <= 0)
|
||||||
|
return;
|
||||||
|
image_found = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tftp_dst_addr = MAIN_RAM_BASE + ROOTFS_IMAGE_RAM_OFFSET;
|
/* Boot to last Image address */
|
||||||
size = tftp_get_v(ip, tftp_port, "rootfs.cpio", (void *)tftp_dst_addr);
|
if (image_found)
|
||||||
if(size <= 0) {
|
boot(0, 0, 0, strtoul(image_address, NULL, 0));
|
||||||
printf("No rootfs.cpio found\n");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tftp_dst_addr = MAIN_RAM_BASE + DEVICE_TREE_IMAGE_RAM_OFFSET;
|
static void netboot_from_bin(const char * filename, unsigned int ip, unsigned short tftp_port)
|
||||||
size = tftp_get_v(ip, tftp_port, "rv32.dtb", (void *)tftp_dst_addr);
|
{
|
||||||
if(size <= 0) {
|
int size;
|
||||||
printf("No rv32.dtb found\n");
|
size = copy_file_from_tftp_to_ram(ip, tftp_port, filename, (void *)MAIN_RAM_BASE);
|
||||||
return 0;
|
if (size <= 0)
|
||||||
|
return;
|
||||||
|
boot(0, 0, 0, MAIN_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 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void netboot(void)
|
void netboot(void)
|
||||||
{
|
{
|
||||||
int size;
|
|
||||||
unsigned int ip;
|
unsigned int ip;
|
||||||
unsigned long tftp_dst_addr;
|
|
||||||
unsigned short tftp_port;
|
|
||||||
|
|
||||||
printf("Booting from network...\n");
|
printf("Booting from network...\n");
|
||||||
printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4);
|
printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4);
|
||||||
printf("Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
|
printf("Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
|
||||||
|
|
||||||
ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
|
ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
|
||||||
|
|
||||||
udp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
|
udp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
|
||||||
|
|
||||||
tftp_port = TFTP_SERVER_PORT;
|
/* Boot from boot.json */
|
||||||
printf("Fetching from: UDP/%d\n", tftp_port);
|
printf("Booting from boot.json...\n");
|
||||||
|
netboot_from_json("boot.json", ip, TFTP_SERVER_PORT);
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_TYPE_VEXRISCV) && defined(CONFIG_CPU_VARIANT_LINUX)
|
/* Boot from boot.bin */
|
||||||
if(try_get_kernel_rootfs_dtb_emulator(ip, tftp_port))
|
printf("Booting from boot.bin...\n");
|
||||||
{
|
netboot_from_bin("boot.bin", ip, TFTP_SERVER_PORT);
|
||||||
boot(0, 0, 0, MAIN_RAM_BASE + EMULATOR_IMAGE_RAM_OFFSET);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
printf("Unable to download Linux images, falling back to boot.bin\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_TYPE_MOR1KX) && defined(CONFIG_CPU_VARIANT_LINUX)
|
/* Boot failed if we are here... */
|
||||||
if(try_get_kernel_rootfs_dtb(ip, tftp_port))
|
printf("Network boot failed.\n");
|
||||||
{
|
|
||||||
boot(MAIN_RAM_BASE + DEVICE_TREE_IMAGE_RAM_OFFSET, 0, 0, MAIN_RAM_BASE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
printf("Unable to download Linux images, falling back to boot.bin\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tftp_dst_addr = MAIN_RAM_BASE;
|
|
||||||
size = tftp_get_v(ip, tftp_port, "boot.bin", (void *)tftp_dst_addr);
|
|
||||||
if (size <= 0) {
|
|
||||||
printf("Network boot failed\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boot(0, 0, 0, MAIN_RAM_BASE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -472,6 +417,19 @@ static int copy_image_from_flash_to_ram(unsigned int flash_address, unsigned int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef KERNEL_IMAGE_RAM_OFFSET
|
||||||
|
#define KERNEL_IMAGE_RAM_OFFSET 0x00000000
|
||||||
|
#endif
|
||||||
|
#ifndef ROOTFS_IMAGE_RAM_OFFSET
|
||||||
|
#define ROOTFS_IMAGE_RAM_OFFSET 0x00800000
|
||||||
|
#endif
|
||||||
|
#ifndef DEVICE_TREE_IMAGE_RAM_OFFSET
|
||||||
|
#define DEVICE_TREE_IMAGE_RAM_OFFSET 0x01000000
|
||||||
|
#endif
|
||||||
|
#ifndef EMULATOR_IMAGE_RAM_OFFSET
|
||||||
|
#define EMULATOR_IMAGE_RAM_OFFSET 0x01100000
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef KERNEL_IMAGE_FLASH_OFFSET
|
#ifndef KERNEL_IMAGE_FLASH_OFFSET
|
||||||
#define KERNEL_IMAGE_FLASH_OFFSET 0x00000000 // 0MB
|
#define KERNEL_IMAGE_FLASH_OFFSET 0x00000000 // 0MB
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue