From 05403a7b813fa89dfa0164d1b2705ec2ce157e5f Mon Sep 17 00:00:00 2001
From: Mattia Rizzi <mattia.rizzi@cern.ch>
Date: Thu, 21 Jan 2021 19:09:18 +0100
Subject: [PATCH] Bootloader code

---
 software/bootldr/Makefile   |  42 ++++++++++
 software/bootldr/bootldr.ld |  75 ++++++++++++++++++
 software/bootldr/crt0.S     |  81 +++++++++++++++++++
 software/bootldr/main.c     | 154 ++++++++++++++++++++++++++++++++++++
 software/bootldr/riscv.h    |  37 +++++++++
 5 files changed, 389 insertions(+)
 create mode 100644 software/bootldr/Makefile
 create mode 100644 software/bootldr/bootldr.ld
 create mode 100644 software/bootldr/crt0.S
 create mode 100644 software/bootldr/main.c
 create mode 100644 software/bootldr/riscv.h

diff --git a/software/bootldr/Makefile b/software/bootldr/Makefile
new file mode 100644
index 0000000..277c9d9
--- /dev/null
+++ b/software/bootldr/Makefile
@@ -0,0 +1,42 @@
+#CROSS_COMPILE_TARGET ?= /home/mattia/riscv-toolchain/riscv/bin/riscv32-elf-
+
+CROSS_COMPILE_TARGET ?= /home/mattia/riscv32-nanolib/gnu-mcu-eclipse/riscv-none-gcc/8.1.0-2-20181019-0952/bin/riscv-none-embed-
+CFLAGS += -mabi=ilp32 -march=rv32im  -Os -ffunction-sections -fdata-sections --specs=nano.specs --specs=nosys.specs -lgcc -lc -Wl,--gc-sections
+
+
+CC =		$(CROSS_COMPILE_TARGET)gcc
+LD =		$(CROSS_COMPILE_TARGET)ld
+OBJDUMP =	$(CROSS_COMPILE_TARGET)objdump
+OBJCOPY =	$(CROSS_COMPILE_TARGET)objcopy
+SIZE =		$(CROSS_COMPILE_TARGET)size
+STRIP =	$(CROSS_COMPILE_TARGET)strip
+
+
+
+all: bootloader.hex
+
+crt0.o: crt0.S
+	$(CC) -c -o $@ $(CFLAGS) $<
+
+irq.o: irq.S
+	$(CC) -c -o $@ $(CFLAGS) $<
+
+eth_config.o: eth_config.c
+	$(CC) -c -o $@ $(CFLAGS) $<
+
+refresh.o: refresh.s
+	$(CC) -c -o $@ $(CFLAGS) $<
+
+main: main.o crt0.o  bootldr.ld 
+	$(CC)  -o $@ -nostartfiles $(CFLAGS) crt0.o main.o -T bootldr.ld
+
+main-text.bin: main
+	riscv32-elf-objcopy -j .text -j .loader -O binary $< $@
+
+bootloader.hex: main-text.bin
+	riscv32-elf-objcopy -I binary -O ihex $< $@
+
+clean:
+	rm main
+	rm main-text.*	
+	rm bootloader.*
diff --git a/software/bootldr/bootldr.ld b/software/bootldr/bootldr.ld
new file mode 100644
index 0000000..9f4c489
--- /dev/null
+++ b/software/bootldr/bootldr.ld
@@ -0,0 +1,75 @@
+OUTPUT_FORMAT("elf32-littleriscv")
+ENTRY(_start)
+
+MEMORY
+{
+   iram : ORIGIN = 0x00000000, LENGTH = 512
+   ldr  : ORIGIN = 0x00000200, LENGTH = 512
+   dram : ORIGIN = 0x00010000, LENGTH = 64K
+
+}
+
+
+SECTIONS
+{
+
+  /* Begining of code and text segment */
+  . = 0x00000000;
+  /* text: Program code section */
+  .text :
+  {
+    *(.boot)
+    *(.text)
+    *(.text.*)
+    *(.gnu.linkonce.t.*)
+
+  } > iram
+  .loader :
+  {
+    *(.launcher)
+    *(.launcher.*)
+    *(.launcher_call)
+  } > ldr
+
+  /* rodata: Read-only data */
+  .data :
+  {
+    *(.rdata)
+    *(.rodata)
+    *(.rodata.*)
+    *(.gnu.linkonce.r.*)
+    *(.data)
+    *(.data.*)
+    
+    *(.gnu.linkonce.d.*)
+    _edata = .;
+
+    /* Have _gp point to middle of sdata/sbss to maximize displacement range */
+    . = ALIGN(16);
+    _gp = . + 0x800;
+
+    *(.sdata)
+    *(.sdata.*)
+    *(.srodata.*)
+    *(.gnu.linkonce.s.*)
+
+    . = ALIGN(8);
+    _fbss = .;
+
+    *(.sbss)
+    *(.sbss.*)
+    *(.gnu.linkonce.sb.*)
+
+    _bss_start = .;
+
+    *(.bss)
+    *(.bss.*)
+    *(.gnu.linkonce.b.*)
+    *(COMMON)
+
+    _end = ALIGN(8);
+  } > dram
+
+ PROVIDE(_fstack = ORIGIN(dram) + LENGTH(dram) - 0x100);
+
+}
diff --git a/software/bootldr/crt0.S b/software/bootldr/crt0.S
new file mode 100644
index 0000000..798083d
--- /dev/null
+++ b/software/bootldr/crt0.S
@@ -0,0 +1,81 @@
+  .section    .boot, "ax", @progbits
+
+.global _start
+_start:
+    j _entry
+
+.org 0x8
+
+
+
+_entry:
+	
+
+	
+  lui ra, 0
+  lui sp, 0
+  lui gp, 0
+  lui tp, 0
+  lui s0, 0
+  lui s1, 0
+  lui s2, 0
+  lui s3, 0
+  lui s4, 0
+  lui s5, 0
+  lui s6, 0
+  lui s7, 0
+  lui s8, 0
+  lui s9, 0
+  lui s10, 0
+  lui s11, 0
+  lui t0, 0
+  lui t1, 0
+  lui t2, 0
+  lui t3, 0
+  lui t4, 0
+  lui t5, 0
+  lui t6, 0 
+  lui a0, 0
+  lui a1, 0
+  lui a2, 0
+  lui a3, 0
+  lui a4, 0
+  lui a5, 0
+  lui a6, 0
+  lui a7, 0
+
+  li t1, 0xffff
+1:
+
+  sw zero, 0(t0)
+  addi t0, t0, 4
+  and t0, t0, t1
+  bne t0, zero, 1b
+  lui t0, 0
+  lui t1, 0
+  
+  la gp, _gp                 /* Initialize global pointer */
+  la sp, _fstack
+
+/*  la t0, _fexception_stack
+  csrrw t0, mscratch, t0 */
+
+  /* clear the bss segment */
+  la t0, _fbss
+  la t1, _end
+1:
+#ifdef __riscv64
+  sd zero,0(t0)
+  addi t0, t0, 8
+#else
+  sw zero,0(t0)
+  addi t0, t0, 4
+
+#endif
+  bltu t0, t1, 1b
+  call main
+1:
+  j     1b
+
+	.data
+_recov_data:	.long 0
diff --git a/software/bootldr/main.c b/software/bootldr/main.c
new file mode 100644
index 0000000..bc3665b
--- /dev/null
+++ b/software/bootldr/main.c
@@ -0,0 +1,154 @@
+// TO DO: check integrity of the image before executing it
+
+
+#include <stdio.h>
+//#include <string.h>
+#include "riscv.h"
+
+#define IRAM_SIZE       65536
+#define LOADER_SIZE     512
+#define APP_IMAGE_TEXT	0x60000000
+#define APP_IMAGE_DATA	0x60020000
+#define LOADER_IMAGE    0x60012200
+
+#define print_line() print_char('\n');print_char('\r')
+
+typedef struct uart_reg  {
+  uint32_t flags;
+  uint32_t buffer;
+} uart_reg;
+
+void  __attribute__((__section__(".launcher_call"))) print_string (char * str, unsigned char len) {
+ 
+	for (char i=0; i < len; i++) 
+		print_char(str[i]);
+        
+	
+}
+
+void   __attribute__((always_inline)) print_char (char c)  {
+	volatile uart_reg * uart_tx = (uart_reg *) 0x82000000;
+	while (!uart_tx->flags);
+	uart_tx->buffer = c;
+	uart_tx->flags = 2;
+
+}
+
+
+void  __attribute__((__section__(".launcher_call"))) print_word (uint32_t  word) {
+	int8_t i;
+	uint8_t disp;
+	uint32_t temp;
+	char c;
+	
+	for (i=7; i >= 0; i--) {
+
+	  disp = ((word >> (i<<2)) & 0xf);
+		if (disp <= 9 )
+			c = '0'+ disp;
+		else
+			c = 'A' + disp - 10; 
+ 
+		print_char (c);
+	}
+
+}
+
+
+uint32_t  __attribute__((__section__(".launcher_call"))) envm_read (uint32_t * addr) {
+
+	volatile uint32_t * wb_envm_dev = 0x87000000;
+
+	while (wb_envm_dev[0] & 0x1);
+	wb_envm_dev[1] = addr;
+	while (*wb_envm_dev & 0x1);
+
+	return wb_envm_dev[2];
+}
+
+
+void  __attribute__((__section__(".launcher"))) iram_write (uint32_t * addr, uint32_t data) {
+
+	volatile uint32_t * wb_iram_dev = 0x87000010;
+
+	
+	wb_iram_dev[0] = addr;
+	wb_iram_dev[1] = data;
+	asm ("nop");
+	//	asm("nop");
+	//	asm("nop");
+	//  asm("nop");
+
+}
+
+
+
+
+void load_image ();
+
+
+void main(void)
+{
+
+	
+   const char boot_logo [5] = {'b','o','o','t'};
+	
+
+	volatile char  * p_wd = 0x81000000;
+	void (*func)(void) = IRAM_SIZE - LOADER_SIZE + (&load_image - 0x200) ;
+	uint32_t i, data = 0;
+
+
+	//print_line();
+	print_string (boot_logo, 4);
+	print_line();
+
+
+
+	for (i=1024; i < (1<<16); i=i+4)
+		iram_write(i, 0);
+
+	for (i=0; i < 1024; i=i+4) {
+		data = envm_read (LOADER_IMAGE + i);
+		iram_write(IRAM_SIZE-LOADER_SIZE+i, data);
+	}
+
+	*p_wd = 1;
+
+	(*func)();	// jump to (relocated) load_image()
+
+
+
+	while(1);
+//	*p_wd = 1; //watchdog
+
+
+
+}
+
+
+void __attribute__((__section__(".launcher")))  load_image () {
+	const char done [5] = {'D','o','n', 'e'};
+	uint32_t i, data = 0;
+	uint32_t * dram = 0;
+	void (*func)(void) = 0 ;
+
+	for (i=0; i < IRAM_SIZE-LOADER_SIZE; i=i+4) {
+		data = envm_read (APP_IMAGE_TEXT + i);
+		iram_write (i, data);
+	}
+
+	for (i=0; i < (1<<16)-1024; i=i+4) {
+		data = envm_read (APP_IMAGE_DATA + i);
+		*dram++ = data;
+	}
+	print_string(done, 4);
+	
+
+	(*func)(); // run app
+
+	while(1);
+	
+	
+}
+
diff --git a/software/bootldr/riscv.h b/software/bootldr/riscv.h
new file mode 100644
index 0000000..75d2ab9
--- /dev/null
+++ b/software/bootldr/riscv.h
@@ -0,0 +1,37 @@
+#ifndef __RISCV_H
+#define __RISCV_H
+
+#ifdef __GNUC__
+
+#define riscv_read_csr(reg) ({ unsigned long __tmp; \
+  asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
+  __tmp; })
+
+#define riscv_write_csr(reg, val) \
+  asm volatile ("csrw " #reg ", %0" :: "r"(val))
+
+#define riscv_swap_csr(reg, val) ({ long __tmp; \
+  asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \
+  __tmp; })
+
+#define riscv_set_csr(reg, bit) ({ unsigned long __tmp; \
+  if (__builtin_constant_p(bit) && (bit) < 32) \
+    asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
+  else \
+    asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
+  __tmp; })
+
+#define riscv_clear_csr(reg, bit) ({ unsigned long __tmp; \
+  if (__builtin_constant_p(bit) && (bit) < 32) \
+    asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
+  else \
+    asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
+  __tmp; })
+
+#define riscv_rdtime() riscv_read_csr(time)
+#define riscv_rdcycle() riscv_read_csr(cycle)
+#define riscv_rdinstret() riscv_read_csr(instret)
+
+#endif
+
+#endif
-- 
GitLab