Merge pull request #305 from FrankBuss/master

adding support to flash an FBI image
This commit is contained in:
enjoy-digital 2019-11-08 23:51:49 +01:00 committed by GitHub
commit 2d6100bdbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 16 deletions

View File

@ -8,6 +8,7 @@
// License: BSD // License: BSD
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <console.h> #include <console.h>
#include <uart.h> #include <uart.h>
#include <system.h> #include <system.h>
@ -23,6 +24,10 @@
#include <net/tftp.h> #include <net/tftp.h>
#endif #endif
#ifdef CSR_SPIFLASH_BASE
#include <spiflash.h>
#endif
#include "sfl.h" #include "sfl.h"
#include "boot.h" #include "boot.h"
@ -95,6 +100,14 @@ static int check_ack(void)
return ACK_TIMEOUT; return ACK_TIMEOUT;
} }
static uint32_t get_uint32(unsigned char* data)
{
return ((uint32_t) data[0] << 24) |
((uint32_t) data[1] << 16) |
((uint32_t) data[2] << 8) |
(uint32_t) data[3];
}
#define MAX_FAILED 5 #define MAX_FAILED 5
/* Returns 1 if other boot methods should be tried */ /* Returns 1 if other boot methods should be tried */
@ -165,11 +178,7 @@ int serialboot(void)
char *writepointer; char *writepointer;
failed = 0; failed = 0;
writepointer = (char *)( writepointer = (char *) get_uint32(&frame.payload[0]);
((unsigned long)frame.payload[0] << 24)
|((unsigned long)frame.payload[1] << 16)
|((unsigned long)frame.payload[2] << 8)
|((unsigned long)frame.payload[3] << 0));
for(i=4;i<frame.length;i++) for(i=4;i<frame.length;i++)
*(writepointer++) = frame.payload[i]; *(writepointer++) = frame.payload[i];
if (frame.cmd == SFL_CMD_LOAD) if (frame.cmd == SFL_CMD_LOAD)
@ -177,17 +186,39 @@ int serialboot(void)
break; break;
} }
case SFL_CMD_JUMP: { case SFL_CMD_JUMP: {
unsigned long addr; uint32_t addr;
failed = 0; failed = 0;
addr = ((unsigned long)frame.payload[0] << 24) addr = get_uint32(&frame.payload[0]);
|((unsigned long)frame.payload[1] << 16)
|((unsigned long)frame.payload[2] << 8)
|((unsigned long)frame.payload[3] << 0);
uart_write(SFL_ACK_SUCCESS); uart_write(SFL_ACK_SUCCESS);
boot(0, 0, 0, addr); boot(0, 0, 0, addr);
break; break;
} }
case SFL_CMD_FLASH: {
#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE)
uint32_t addr;
failed = 0;
addr = get_uint32(&frame.payload[0]);
for (i = 4; i < frame.length; i++) {
// erase page at sector boundaries before writing
if ((addr & (SPIFLASH_SECTOR_SIZE - 1)) == 0) {
erase_flash_sector(addr);
}
write_to_flash(addr, &frame.payload[i], 1);
addr++;
}
uart_write(SFL_ACK_SUCCESS);
#endif
break;
}
case SFL_CMD_REBOOT:
#ifdef CSR_CTRL_BASE
uart_write(SFL_ACK_SUCCESS);
ctrl_reset_write(1);
#endif
break;
default: default:
failed++; failed++;
if(failed == MAX_FAILED) { if(failed == MAX_FAILED) {

View File

@ -20,6 +20,8 @@ struct sfl_frame {
#define SFL_CMD_LOAD 0x01 #define SFL_CMD_LOAD 0x01
#define SFL_CMD_JUMP 0x02 #define SFL_CMD_JUMP 0x02
#define SFL_CMD_LOAD_NO_CRC 0x03 #define SFL_CMD_LOAD_NO_CRC 0x03
#define SFL_CMD_FLASH 0x04
#define SFL_CMD_REBOOT 0x05
/* Replies */ /* Replies */
#define SFL_ACK_SUCCESS 'K' #define SFL_ACK_SUCCESS 'K'

View File

@ -59,6 +59,8 @@ sfl_cmd_abort = b"\x00"
sfl_cmd_load = b"\x01" sfl_cmd_load = b"\x01"
sfl_cmd_load_no_crc = b"\x03" sfl_cmd_load_no_crc = b"\x03"
sfl_cmd_jump = b"\x02" sfl_cmd_jump = b"\x02"
sfl_cmd_flash = b"\x04"
sfl_cmd_reboot = b"\x05"
# Replies # Replies
sfl_ack_success = b"K" sfl_ack_success = b"K"
@ -127,7 +129,7 @@ class SFLFrame:
class LiteXTerm: class LiteXTerm:
def __init__(self, serial_boot, kernel_image, kernel_address, json_images, no_crc): def __init__(self, serial_boot, kernel_image, kernel_address, json_images, no_crc, flash):
self.serial_boot = serial_boot self.serial_boot = serial_boot
assert not (kernel_image is not None and json_images is not None) assert not (kernel_image is not None and json_images is not None)
self.mem_regions = {} self.mem_regions = {}
@ -140,6 +142,8 @@ class LiteXTerm:
self.boot_address = self.mem_regions[list(self.mem_regions.keys())[-1]] self.boot_address = self.mem_regions[list(self.mem_regions.keys())[-1]]
f.close() f.close()
self.no_crc = no_crc self.no_crc = no_crc
self.flash = flash
self.ignore_download = False
self.reader_alive = False self.reader_alive = False
self.writer_alive = False self.writer_alive = False
@ -197,6 +201,10 @@ class LiteXTerm:
f.seek(0, 2) f.seek(0, 2)
length = f.tell() length = f.tell()
f.seek(0, 0) f.seek(0, 0)
if self.flash:
print("[LXTERM] Flashing {} ({} bytes)...".format(filename, length))
current_address = 0
else:
print("[LXTERM] Uploading {} to 0x{:08x} ({} bytes)...".format(filename, address, length)) print("[LXTERM] Uploading {} to 0x{:08x} ({} bytes)...".format(filename, address, length))
current_address = address current_address = address
position = 0 position = 0
@ -209,6 +217,9 @@ class LiteXTerm:
sys.stdout.flush() sys.stdout.flush()
frame = SFLFrame() frame = SFLFrame()
frame_data = f.read(min(remaining, sfl_payload_length)) frame_data = f.read(min(remaining, sfl_payload_length))
if self.flash:
frame.cmd = sfl_cmd_flash
else:
frame.cmd = sfl_cmd_load if not self.no_crc else sfl_cmd_load_no_crc frame.cmd = sfl_cmd_load if not self.no_crc else sfl_cmd_load_no_crc
frame.payload = current_address.to_bytes(4, "big") frame.payload = current_address.to_bytes(4, "big")
frame.payload += frame_data frame.payload += frame_data
@ -230,6 +241,12 @@ class LiteXTerm:
frame.payload = int(self.boot_address, 16).to_bytes(4, "big") frame.payload = int(self.boot_address, 16).to_bytes(4, "big")
self.send_frame(frame) self.send_frame(frame)
def reboot(self):
print("[LXTERM] Rebooting the device.")
frame = SFLFrame()
frame.cmd = sfl_cmd_reboot
self.send_frame(frame)
def detect_prompt(self, data): def detect_prompt(self, data):
if len(data): if len(data):
self.prompt_detect_buffer = self.prompt_detect_buffer[1:] + data self.prompt_detect_buffer = self.prompt_detect_buffer[1:] + data
@ -249,11 +266,19 @@ class LiteXTerm:
return False return False
def answer_magic(self): def answer_magic(self):
if self.ignore_download:
self.ignore_download = False
return
print("[LXTERM] Received firmware download request from the device.") print("[LXTERM] Received firmware download request from the device.")
if(len(self.mem_regions)): if(len(self.mem_regions)):
self.port.write(sfl_magic_ack) self.port.write(sfl_magic_ack)
for filename, base in self.mem_regions.items(): for filename, base in self.mem_regions.items():
self.upload(filename, int(base, 16)) self.upload(filename, int(base, 16))
if self.flash:
# ignore next download request to do a reboot to the flashed image
self.ignore_download = True
self.reboot()
else:
self.boot() self.boot()
print("[LXTERM] Done."); print("[LXTERM] Done.");
@ -334,14 +359,16 @@ def _get_args():
parser.add_argument("--kernel-adr", default="0x40000000", help="kernel address") parser.add_argument("--kernel-adr", default="0x40000000", help="kernel address")
parser.add_argument("--images", default=None, help="json description of the images to load to memory") parser.add_argument("--images", default=None, help="json description of the images to load to memory")
parser.add_argument("--no-crc", default=False, action='store_true', help="disable CRC check (speedup serialboot)") parser.add_argument("--no-crc", default=False, action='store_true', help="disable CRC check (speedup serialboot)")
parser.add_argument("--flash", default=False, action='store_true', help="flash data with serialboot command")
return parser.parse_args() return parser.parse_args()
def main(): def main():
args = _get_args() args = _get_args()
term = LiteXTerm(args.serial_boot, args.kernel, args.kernel_adr, args.images, args.no_crc) term = LiteXTerm(args.serial_boot, args.kernel, args.kernel_adr, args.images, args.no_crc, args.flash)
term.open(args.port, int(float(args.speed))) term.open(args.port, int(float(args.speed)))
term.console.configure() term.console.configure()
term.start() term.start()
term.join(True) term.join(True)