Merge pull request #818 from JacobPease/main

Added true bootloader to fpga/zsbl directory.
This commit is contained in:
Rose Thompson 2024-05-31 15:34:08 -05:00 committed by GitHub
commit 9ed78b5f08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 505 additions and 438 deletions

View File

@ -16,7 +16,7 @@ OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS))
TARGETDIR := bin
TARGET := $(TARGETDIR)/fpga-test-sdc
TARGET := $(TARGETDIR)/boot
ROOT := ..
LIBRARY_DIRS :=
LIBRARY_FILES :=
@ -24,11 +24,13 @@ LIBRARY_FILES :=
MARCH :=-march=rv64imfdc_zifencei
MABI :=-mabi=lp64d
LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles
LINKER :=linker.x
LINKER :=linker1000.x
AFLAGS =$(MARCH) $(MABI) -W
CFLAGS =$(MARCH) $(MABI) -mcmodel=medany -O2
# Override directive allows us to prepend other options on the command line
# e.g. $ make CFLAGS=-g
override CFLAGS +=$(MARCH) $(MABI) -mcmodel=medany -O2 -g
AS=riscv64-unknown-elf-as
CC=riscv64-unknown-elf-gcc
AR=riscv64-unknown-elf-ar
@ -104,7 +106,7 @@ $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT)
# convert to hex
$(TARGET).memfile: $(TARGET)
@echo 'Making object dump file.'
@riscv64-unknown-elf-objdump -D $< > $<.objdump
riscv64-unknown-elf-objdump -DS $< > $<.objdump
@echo 'Making memory file'
riscv64-unknown-elf-elf2hex --bit-width 64 --input $^ --output $@
extractFunctionRadix.sh $<.objdump

View File

@ -49,7 +49,12 @@ _start:
# set the stack pointer to the top of memory - 8 bytes (pointer size)
li sp, 0x87FFFFF8
jal ra, main
li a0, 0x00000000
li a1, 0x80000000
#li a2, 128*1024*1024/512 # copy 128MB
li a2, 127*1024*1024/512 # copy 127MB upper 1MB contains the return address (ra)
#li a2, 800 # copy 400KB
jal ra, copyFlash
fence.i
# now toggle led so we know the copy completed.
@ -81,18 +86,16 @@ delay2:
# now that the card is copied and the led toggled we
# jump to the copied contents of the sd card.
jumpToLinux:
csrr a0, mhartid
li s0, 0x80000000
la a1, _dtb
jr s0
jumpToLinux:
csrrs a0, 0xF14, x0 # copy hart ID to a0
li a1, 0x87000000 # end of memory? not 100% sure on this but it's 112MB
la a2, end_of_bios
li t0, 0x80000000 # start of code
jalr x0, t0, 0
end_of_bios:
.section .rodata
.globl _dtb
.align 4, 0
_dtb:
#.incbin "wally-vcu118.dtb"

422
fpga/zsbl/boot.c Normal file
View File

@ -0,0 +1,422 @@
#include <stddef.h>
#include "boot.h"
#include "gpt.h"
/* Card type flags (card_type) */
#define CT_MMC 0x01 /* MMC ver 3 */
#define CT_SD1 0x02 /* SD ver 1 */
#define CT_SD2 0x04 /* SD ver 2 */
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK 0x08 /* Block addressing */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND */
#define CMD2 (2) /* SEND_CID */
#define CMD3 (3) /* RELATIVE_ADDR */
#define CMD4 (4)
#define CMD5 (5) /* SLEEP_WAKE (SDC) */
#define CMD6 (6) /* SWITCH_FUNC */
#define CMD7 (7) /* SELECT */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD11 (11)
#define CMD12 (12) /* STOP_TRANSMISSION */
#define CMD13 (13)
#define CMD15 (15)
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD19 (19)
#define CMD20 (20)
#define CMD23 (23)
#define CMD24 (24)
#define CMD25 (25)
#define CMD27 (27)
#define CMD28 (28)
#define CMD29 (29)
#define CMD30 (30)
#define CMD32 (32)
#define CMD33 (33)
#define CMD38 (38)
#define CMD42 (42)
#define CMD55 (55) /* APP_CMD */
#define CMD56 (56)
#define ACMD6 (0x80+6) /* define the data bus width */
#define ACMD41 (0x80+41) /* SEND_OP_COND (ACMD) */
// Capability bits
#define SDC_CAPABILITY_SD_4BIT 0x0001
#define SDC_CAPABILITY_SD_RESET 0x0002
#define SDC_CAPABILITY_ADDR 0xff00
// Control bits
#define SDC_CONTROL_SD_4BIT 0x0001
#define SDC_CONTROL_SD_RESET 0x0002
// Card detect bits
#define SDC_CARD_INSERT_INT_EN 0x0001
#define SDC_CARD_INSERT_INT_REQ 0x0002
#define SDC_CARD_REMOVE_INT_EN 0x0004
#define SDC_CARD_REMOVE_INT_REQ 0x0008
// Command status bits
#define SDC_CMD_INT_STATUS_CC 0x0001 // Command complete
#define SDC_CMD_INT_STATUS_EI 0x0002 // Any error
#define SDC_CMD_INT_STATUS_CTE 0x0004 // Timeout
#define SDC_CMD_INT_STATUS_CCRC 0x0008 // CRC error
#define SDC_CMD_INT_STATUS_CIE 0x0010 // Command code check error
// Data status bits
#define SDC_DAT_INT_STATUS_TRS 0x0001 // Transfer complete
#define SDC_DAT_INT_STATUS_ERR 0x0002 // Any error
#define SDC_DAT_INT_STATUS_CTE 0x0004 // Timeout
#define SDC_DAT_INT_STATUS_CRC 0x0008 // CRC error
#define SDC_DAT_INT_STATUS_CFE 0x0010 // Data FIFO underrun or overrun
#define ERR_EOF 30
#define ERR_NOT_ELF 31
#define ERR_ELF_BITS 32
#define ERR_ELF_ENDIANNESS 33
#define ERR_CMD_CRC 34
#define ERR_CMD_CHECK 35
#define ERR_DATA_CRC 36
#define ERR_DATA_FIFO 37
#define ERR_BUF_ALIGNMENT 38
#define FR_DISK_ERR 39
#define FR_TIMEOUT 40
struct sdc_regs {
volatile uint32_t argument;
volatile uint32_t command;
volatile uint32_t response1;
volatile uint32_t response2;
volatile uint32_t response3;
volatile uint32_t response4;
volatile uint32_t data_timeout;
volatile uint32_t control;
volatile uint32_t cmd_timeout;
volatile uint32_t clock_divider;
volatile uint32_t software_reset;
volatile uint32_t power_control;
volatile uint32_t capability;
volatile uint32_t cmd_int_status;
volatile uint32_t cmd_int_enable;
volatile uint32_t dat_int_status;
volatile uint32_t dat_int_enable;
volatile uint32_t block_size;
volatile uint32_t block_count;
volatile uint32_t card_detect;
volatile uint32_t res_50;
volatile uint32_t res_54;
volatile uint32_t res_58;
volatile uint32_t res_5c;
volatile uint64_t dma_addres;
};
#define MAX_BLOCK_CNT 0x1000
#define SDC 0x00013000;
// static struct sdc_regs * const regs __attribute__((section(".rodata"))) = (struct sdc_regs *)0x00013000;
// static int errno __attribute__((section(".bss")));
// static DSTATUS drv_status __attribute__((section(".bss")));
// static BYTE card_type __attribute__((section(".bss")));
// static uint32_t response[4] __attribute__((section(".bss")));
// static int alt_mem __attribute__((section(".bss")));
/*static const char * errno_to_str(void) {
switch (errno) {
case ERR_EOF: return "Unexpected EOF";
case ERR_NOT_ELF: return "Not an ELF file";
case ERR_ELF_BITS: return "Wrong ELF word size";
case ERR_ELF_ENDIANNESS: return "Wrong ELF endianness";
case ERR_CMD_CRC: return "Command CRC error";
case ERR_CMD_CHECK: return "Command code check error";
case ERR_DATA_CRC: return "Data CRC error";
case ERR_DATA_FIFO: return "Data FIFO error";
case ERR_BUF_ALIGNMENT: return "Bad buffer alignment";
case FR_DISK_ERR: return "Disk error";
case FR_TIMEOUT: return "Timeout";
}
return "Unknown error code";
}*/
static void usleep(unsigned us) {
uintptr_t cycles0;
uintptr_t cycles1;
asm volatile ("csrr %0, 0xB00" : "=r" (cycles0));
for (;;) {
asm volatile ("csrr %0, 0xB00" : "=r" (cycles1));
if (cycles1 - cycles0 >= us * 100) break;
}
}
static int sdc_cmd_finish(unsigned cmd, uint32_t * response) {
struct sdc_regs * regs = (struct sdc_regs *)SDC;
while (1) {
unsigned status = regs->cmd_int_status;
if (status) {
// clear interrupts
regs->cmd_int_status = 0;
while (regs->software_reset != 0) {}
if (status == SDC_CMD_INT_STATUS_CC) {
// get response
response[0] = regs->response1;
response[1] = regs->response2;
response[2] = regs->response3;
response[3] = regs->response4;
return 0;
}
/* errno = FR_DISK_ERR;
if (status & SDC_CMD_INT_STATUS_CTE) errno = FR_TIMEOUT;
if (status & SDC_CMD_INT_STATUS_CCRC) errno = ERR_CMD_CRC;
if (status & SDC_CMD_INT_STATUS_CIE) errno = ERR_CMD_CHECK;*/
break;
}
}
return -1;
}
static int sdc_data_finish(void) {
int status;
struct sdc_regs * regs = (struct sdc_regs *)SDC;
while ((status = regs->dat_int_status) == 0) {}
regs->dat_int_status = 0;
while (regs->software_reset != 0) {}
if (status == SDC_DAT_INT_STATUS_TRS) return 0;
/* errno = FR_DISK_ERR;
if (status & SDC_DAT_INT_STATUS_CTE) errno = FR_TIMEOUT;
if (status & SDC_DAT_INT_STATUS_CRC) errno = ERR_DATA_CRC;
if (status & SDC_DAT_INT_STATUS_CFE) errno = ERR_DATA_FIFO;*/
return -1;
}
static int send_data_cmd(unsigned cmd, unsigned arg, void * buf, unsigned blocks, uint32_t * response) {
struct sdc_regs * regs = (struct sdc_regs *)SDC;
unsigned command = (cmd & 0x3f) << 8;
switch (cmd) {
case CMD0:
case CMD4:
case CMD15:
// No responce
break;
case CMD11:
case CMD13:
case CMD16:
case CMD17:
case CMD18:
case CMD19:
case CMD23:
case CMD24:
case CMD25:
case CMD27:
case CMD30:
case CMD32:
case CMD33:
case CMD42:
case CMD55:
case CMD56:
case ACMD6:
// R1
command |= 1; // 48 bits
command |= 1 << 3; // resp CRC
command |= 1 << 4; // resp OPCODE
break;
case CMD7:
case CMD12:
case CMD20:
case CMD28:
case CMD29:
case CMD38:
// R1b
command |= 1; // 48 bits
command |= 1 << 2; // busy
command |= 1 << 3; // resp CRC
command |= 1 << 4; // resp OPCODE
break;
case CMD2:
case CMD9:
case CMD10:
// R2
command |= 2; // 136 bits
command |= 1 << 3; // resp CRC
break;
case ACMD41:
// R3
command |= 1; // 48 bits
break;
case CMD3:
// R6
command |= 1; // 48 bits
command |= 1 << 2; // busy
command |= 1 << 3; // resp CRC
command |= 1 << 4; // resp OPCODE
break;
case CMD8:
// R7
command |= 1; // 48 bits
command |= 1 << 3; // resp CRC
command |= 1 << 4; // resp OPCODE
break;
}
if (blocks) {
command |= 1 << 5;
if ((intptr_t)buf & 3) {
// errno = ERR_BUF_ALIGNMENT;
return -1;
}
regs->dma_addres = (uint64_t)(intptr_t)buf;
regs->block_size = 511;
regs->block_count = blocks - 1;
regs->data_timeout = 0x1FFFFFF;
}
regs->command = command;
regs->cmd_timeout = 0xFFFFF;
regs->argument = arg;
if (sdc_cmd_finish(cmd, response) < 0) return -1;
if (blocks) return sdc_data_finish();
return 0;
}
#define send_cmd(cmd, arg, response) send_data_cmd(cmd, arg, NULL, 0, response)
static BYTE ini_sd(void) {
struct sdc_regs * regs = (struct sdc_regs *)SDC;
unsigned rca;
BYTE card_type;
uint32_t response[4];
/* Reset controller */
regs->software_reset = 1;
while ((regs->software_reset & 1) == 0) {}
// This clock divider is meant to initialize the card at
// 400kHz
// 22MHz/400kHz = 55 (base 10) = 0x37 - 0x01 = 0x36
regs->clock_divider = 0x36;
regs->software_reset = 0;
while (regs->software_reset) {}
usleep(5000);
card_type = 0;
// drv_status = STA_NOINIT;
if (regs->capability & SDC_CAPABILITY_SD_RESET) {
/* Power cycle SD card */
regs->control |= SDC_CONTROL_SD_RESET;
usleep(1000000);
regs->control &= ~SDC_CONTROL_SD_RESET;
usleep(100000);
}
/* Enter Idle state */
send_cmd(CMD0, 0, response);
card_type = CT_SD1;
if (send_cmd(CMD8, 0x1AA, response) == 0) {
if ((response[0] & 0xfff) != 0x1AA) {
// errno = ERR_CMD_CHECK;
return -1;
}
card_type = CT_SD2;
}
/* Wait for leaving idle state (ACMD41 with HCS bit) */
while (1) {
/* ACMD41, Set Operating Conditions: Host High Capacity & 3.3V */
if (send_cmd(CMD55, 0, response) < 0 || send_cmd(ACMD41, 0x40300000, response) < 0) return -1;
if (response[0] & (1 << 31)) {
if (response[0] & (1 << 30)) card_type |= CT_BLOCK;
break;
}
}
/* Enter Identification state */
if (send_cmd(CMD2, 0, response) < 0) return -1;
/* Get RCA (Relative Card Address) */
rca = 0x1234;
if (send_cmd(CMD3, rca << 16, response) < 0) return -1;
rca = response[0] >> 16;
/* Select card */
if (send_cmd(CMD7, rca << 16, response) < 0) return -1;
/* Clock 25MHz */
// 22Mhz/2 = 11Mhz
regs->clock_divider = 1;
usleep(10000);
/* Bus width 1-bit */
regs->control = 0;
if (send_cmd(CMD55, rca << 16, response) < 0 || send_cmd(ACMD6, 0, response) < 0) return -1;
/* Set R/W block length to 512 */
if (send_cmd(CMD16, 512, response) < 0) return -1;
// drv_status &= ~STA_NOINIT;
return card_type;
}
int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type) {
/* This is not needed. This has everything to do with the FAT
filesystem stuff that I'm not including. All I need to do is
initialize the SD card and read from it. Anything in here that is
checking for potential errors, I'm going to have to temporarily
do without.
*/
// if (!count) return RES_PARERR;
/* if (drv_status & STA_NOINIT) return RES_NOTRDY; */
uint32_t response[4];
struct sdc_regs * regs = (struct sdc_regs *)SDC;
/* Convert LBA to byte address if needed */
if (!(card_type & CT_BLOCK)) sector *= 512;
while (count > 0) {
UINT bcnt = count > MAX_BLOCK_CNT ? MAX_BLOCK_CNT : count;
unsigned bytes = bcnt * 512;
if (send_data_cmd(bcnt == 1 ? CMD17 : CMD18, sector, buf, bcnt, response) < 0) return 1;
if (bcnt > 1 && send_cmd(CMD12, 0, response) < 0) return 1;
sector += (card_type & CT_BLOCK) ? bcnt : bytes;
count -= bcnt;
buf += bytes;
}
return 0;;
}
void copyFlash(QWORD address, QWORD * Dst, DWORD numBlocks) {
BYTE card_type;
int ret = 0;
card_type = ini_sd();
// BYTE * buf = (BYTE *)Dst;
// if (disk_read(buf, (LBA_t)address, (UINT)numBlocks, card_type) < 0) /* UART Print function?*/;
ret = gpt_load_partitions(card_type);
}
/*
int main() {
ini_sd();
return 0;
}
*/

26
fpga/zsbl/boot.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef WALLYBOOT
#define WALLYBOOT 10000
#include <stdint.h>
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR;
typedef QWORD LBA_t;
// Define memory locations of boot images =====================
// These locations are copied from the generic configuration
// of OpenSBI. These addresses can be found in:
// buildroot/output/build/opensbi-0.9/platform/generic/config.mk
#define FDT_ADDRESS 0x87000000 // FW_JUMP_FDT_ADDR
#define OPENSBI_ADDRESS 0x80000000 // FW_TEXT_START
#define KERNEL_ADDRESS 0x80200000 // FW_JUMP_ADDR
// Export disk_read
int disk_read(BYTE * buf, LBA_t sector, UINT count, BYTE card_type);
#endif // WALLYBOOT

View File

@ -1,40 +0,0 @@
///////////////////////////////////////////
// copyFlash.sv
//
// Written: Ross Thompson September 25, 2021
// Modified:
//
// Purpose: copies flash card into memory
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
#include "sdcDriver.h"
void copyFlash(long int blockAddr, long int * Dst, int numBlocks) {
setSDCCLK(4); // must be even, 1 gives no division.
waitInitSDC();
int index;
for(index = 0; index < numBlocks; index++) {
copySDC512(blockAddr+(index*512), Dst+(index*512/8));
}
}

View File

@ -1,119 +1,46 @@
#include "gpt.h"
#include "sdcDriver.h"
#include "uart.h"
#include "boot.h"
#include <stddef.h>
int gpt_find_boot_partition(long int* dest, uint32_t size)
{
//int ret = init_sd();
int ret;
setSDCCLK(4); // must be even, 1 gives no division.
waitInitSDC();
ret = 0;
if (ret != 0) {
print_uart("could not initialize sd... exiting\r\n");
return -1;
}
/* PSUEDOCODE
print_uart("sd initialized!\r\n");
Need to load GPT LBA 1 and read through the partition entries.
I need to find each of the relevant partition entries, possibly
by their partition names.
*/
// load LBA1
size_t block_size = 512/8;
long int lba1_buf[block_size];
int gpt_load_partitions(BYTE card_type) {
// In this version of the GPT partition code
// I'm going to assume that the SD card is already initialized.
//int res = sd_copy(lba1_buf, 1, 1);
int res;
copySDC512(1, lba1_buf);
res = 0;
// size_t block_size = 512/8;
// long int lba1_buf[block_size];
if (res != 0)
{
print_uart("SD card failed!\r\n");
print_uart("sd copy return value: ");
print_uart_addr(res);
print_uart("\r\n");
return -2;
}
BYTE lba1_buf[512];
int ret = 0;
//ret = disk_read(/* BYTE * buf, LBA_t sector, UINT count, BYTE card_type */);
ret = disk_read(lba1_buf, 1, 1, card_type);
gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf;
/* Possible error handling with UART message
if ( ret != 0 ) {
}*/
print_uart("gpt partition table header:");
print_uart("\r\n\tsignature:\t");
print_uart_addr(lba1->signature);
print_uart("\r\n\trevision:\t");
print_uart_int(lba1->revision);
print_uart("\r\n\tsize:\t\t");
print_uart_int(lba1->header_size);
print_uart("\r\n\tcrc_header:\t");
print_uart_int(lba1->crc_header);
print_uart("\r\n\treserved:\t");
print_uart_int(lba1->reserved);
print_uart("\r\n\tcurrent lba:\t");
print_uart_addr(lba1->current_lba);
print_uart("\r\n\tbackup lda:\t");
print_uart_addr(lba1->backup_lba);
print_uart("\r\n\tpartition entries lba: \t");
print_uart_addr(lba1->partition_entries_lba);
print_uart("\r\n\tnumber partition entries:\t");
print_uart_int(lba1->nr_partition_entries);
print_uart("\r\n\tsize partition entries: \t");
print_uart_int(lba1->size_partition_entry);
print_uart("\r\n");
gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf;
long int lba2_buf[block_size];
BYTE lba2_buf[512];
ret = disk_read(lba2_buf, (LBA_t)lba1->partition_entries_lba, 1, card_type);
//res = sd_copy(lba2_buf, lba1->partition_entries_lba, 1);
copySDC512(lba1->partition_entries_lba, lba2_buf);
res = 0;
// Load parition entries for the relevant boot partitions.
partition_entries_t *fdt = (partition_entries_t *)(lba2_buf);
partition_entries_t *opensbi = (partition_entries_t *)(lba2_buf + 128);
partition_entries_t *kernel = (partition_entries_t *)(lba2_buf + 256);
if (res != 0)
{
print_uart("SD card failed!\r\n");
print_uart("sd copy return value: ");
print_uart_addr(res);
print_uart("\r\n");
return -2;
}
ret = disk_read((BYTE *)FDT_ADDRESS, fdt->first_lba, fdt->last_lba - fdt->first_lba + 1, card_type);
ret = disk_read((BYTE *)OPENSBI_ADDRESS, opensbi->first_lba, opensbi->last_lba - opensbi->first_lba + 1, card_type);
ret = disk_read((BYTE *)KERNEL_ADDRESS, kernel->first_lba,kernel->last_lba - kernel->first_lba + 1, card_type);
for (int i = 0; i < 4; i++)
{
partition_entries_t *part_entry = (partition_entries_t *)(lba2_buf + (i * 128));
print_uart("gpt partition entry ");
print_uart_byte(i);
print_uart("\r\n\tpartition type guid:\t");
for (int j = 0; j < 16; j++)
print_uart_byte(part_entry->partition_type_guid[j]);
print_uart("\r\n\tpartition guid: \t");
for (int j = 0; j < 16; j++)
print_uart_byte(part_entry->partition_guid[j]);
print_uart("\r\n\tfirst lba:\t");
print_uart_addr(part_entry->first_lba);
print_uart("\r\n\tlast lba:\t");
print_uart_addr(part_entry->last_lba);
print_uart("\r\n\tattributes:\t");
print_uart_addr(part_entry->attributes);
print_uart("\r\n\tname:\t");
for (int j = 0; j < 72; j++)
print_uart_byte(part_entry->name[j]);
print_uart("\r\n");
}
partition_entries_t *boot = (partition_entries_t *)(lba2_buf);
print_uart("copying boot image ");
//res = sd_copy(dest, boot->first_lba, boot->last_lba - boot->first_lba + 1);
copyFlash(boot->first_lba, dest, boot->last_lba - boot->first_lba + 1);
if (res != 0)
{
print_uart("SD card failed!\r\n");
print_uart("sd copy return value: ");
print_uart_addr(res);
print_uart("\r\n");
return -2;
}
print_uart(" done!\r\n");
return 0;
return 0;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <stdint.h>
#include "boot.h"
// LBA 0: Protective MBR
// ignored here
@ -36,4 +37,4 @@ typedef struct partition_entries
} partition_entries_t;
// Find boot partition and load it to the destination
int gpt_find_boot_partition(long int* dest, uint32_t size);
int gpt_load_partitions(BYTE card_type);

View File

@ -7,7 +7,7 @@ SECTIONS
{
/* Read-only sections, merged into text segment: */
/* init segment to ensure we get a consistent start routine*/
. = 0x0000000000000000;
. = 0x0000000000001000;
. = ALIGN(0x0);
.init : {
*(.init)
@ -72,6 +72,7 @@ SECTIONS
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
. = 0x0000000000002000;
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.sdata2 :

View File

@ -1,26 +0,0 @@
#include "uart.h"
#include "sdcDriver.h"
#include "gpt.h"
int main()
{
init_uart(30000000, 115200);
print_uart("Hello World!\r\n");
int res = gpt_find_boot_partition((long int *)0x80000000UL, 2 * 16384);
if (res == 0)
{
return 0;
}
while (1)
{
// do nothing
}
}
void handle_trap(void)
{
// print_uart("trap\r\n");
}

View File

@ -1,69 +0,0 @@
///////////////////////////////////////////
// SDC.sv
//
// Written: Rose Thompson September 25, 2021
// Modified:
//
// Purpose: driver for sdc reader.
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
#include "sdcDriver.h"
#define SDC_MAIL_BOX 0x12100
void copySDC512(long int blockAddr, long int * Dst) {
waitInitSDC();
volatile long int * mailBoxAddr;
volatile int * mailBoxCmd;
volatile int * mailBoxStatus;
volatile long int * mailBoxReadData;
mailBoxStatus = (int *) (SDC_MAIL_BOX + 0x4);
mailBoxCmd = (int *) (SDC_MAIL_BOX + 0x8);
mailBoxAddr = (long int *) (SDC_MAIL_BOX + 0x10);
mailBoxReadData = (long int *) (SDC_MAIL_BOX + 0x18);
// write the SDC address register with the blockAddr
*mailBoxAddr = blockAddr;
*mailBoxCmd = 0x4;
// wait until the mailbox has valid data
// this occurs when status[1] = 0
while((*mailBoxStatus & 0x2) == 0x2);
int index;
for(index = 0; index < 512/8; index++) {
Dst[index] = *mailBoxReadData;
}
}
volatile void waitInitSDC(){
volatile int * mailBoxStatus;
mailBoxStatus = (int *) (SDC_MAIL_BOX + 0x4);
while((*mailBoxStatus & 0x1) != 0x1);
}
void setSDCCLK(int divider){
divider = (1 - (divider >> 1));
volatile int * mailBoxCLK;
mailBoxCLK = (int *) (SDC_MAIL_BOX + 0x0);
*mailBoxCLK = divider;
}

View File

@ -1,10 +0,0 @@
#ifndef __SDCDRIVER_H
#define __SDCDRIVER_H
void copySDC512(long int, long int *);
volatile void waitInitSDC();
void setSDCCLK(int);
void copyFlash(long int, long int *, int);
#endif

View File

@ -1,52 +0,0 @@
#pragma once
// The hart that non-SMP tests should run on
#ifndef NONSMP_HART
#define NONSMP_HART 0
#endif
// The maximum number of HARTs this code supports
#define CLINT_CTRL_ADDR 0x2000000
#ifndef MAX_HARTS
#define MAX_HARTS 256
#endif
#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS * 4)
/* If your test needs to temporarily block multiple-threads, do this:
* smp_pause(reg1, reg2)
* ... single-threaded work ...
* smp_resume(reg1, reg2)
* ... multi-threaded work ...
*/
#define smp_pause(reg1, reg2) \
li reg2, 0x8; \
csrw mie, reg2; \
li reg1, NONSMP_HART; \
csrr reg2, mhartid; \
bne reg1, reg2, 42f
#define smp_resume(reg1, reg2) \
li reg1, CLINT_CTRL_ADDR; \
41:; \
li reg2, 1; \
sw reg2, 0(reg1); \
addi reg1, reg1, 4; \
li reg2, CLINT_END_HART_IPI; \
blt reg1, reg2, 41b; \
42:; \
wfi; \
csrr reg2, mip; \
andi reg2, reg2, 0x8; \
beqz reg2, 42b; \
li reg1, CLINT_CTRL_ADDR; \
csrr reg2, mhartid; \
slli reg2, reg2, 2; \
add reg2, reg2, reg1; \
sw zero, 0(reg2); \
41:; \
lw reg2, 0(reg1); \
bnez reg2, 41b; \
addi reg1, reg1, 4; \
li reg2, CLINT_END_HART_IPI; \
blt reg1, reg2, 41b

View File

@ -1,91 +0,0 @@
#include "uart.h"
void write_reg_u8(uintptr_t addr, uint8_t value)
{
volatile uint8_t *loc_addr = (volatile uint8_t *)addr;
*loc_addr = value;
}
uint8_t read_reg_u8(uintptr_t addr)
{
return *(volatile uint8_t *)addr;
}
int is_transmit_empty()
{
return read_reg_u8(UART_LINE_STATUS) & 0x20;
}
void write_serial(char a)
{
while (is_transmit_empty() == 0) {};
write_reg_u8(UART_THR, a);
}
void init_uart(uint32_t freq, uint32_t baud)
{
uint32_t divisor = freq / (baud << 4);
write_reg_u8(UART_INTERRUPT_ENABLE, 0x00); // Disable all interrupts
write_reg_u8(UART_LINE_CONTROL, 0x80); // Enable DLAB (set baud rate divisor)
write_reg_u8(UART_DLAB_LSB, divisor); // divisor (lo byte)
write_reg_u8(UART_DLAB_MSB, (divisor >> 8) & 0xFF); // divisor (hi byte)
write_reg_u8(UART_LINE_CONTROL, 0x03); // 8 bits, no parity, one stop bit
write_reg_u8(UART_FIFO_CONTROL, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
write_reg_u8(UART_MODEM_CONTROL, 0x20); // Autoflow mode
}
void print_uart(const char *str)
{
const char *cur = &str[0];
while (*cur != '\0')
{
write_serial((uint8_t)*cur);
++cur;
}
}
uint8_t bin_to_hex_table[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
void bin_to_hex(uint8_t inp, uint8_t res[2])
{
res[1] = bin_to_hex_table[inp & 0xf];
res[0] = bin_to_hex_table[(inp >> 4) & 0xf];
return;
}
void print_uart_int(uint32_t addr)
{
int i;
for (i = 3; i > -1; i--)
{
uint8_t cur = (addr >> (i * 8)) & 0xff;
uint8_t hex[2];
bin_to_hex(cur, hex);
write_serial(hex[0]);
write_serial(hex[1]);
}
}
void print_uart_addr(uint64_t addr)
{
int i;
for (i = 7; i > -1; i--)
{
uint8_t cur = (addr >> (i * 8)) & 0xff;
uint8_t hex[2];
bin_to_hex(cur, hex);
write_serial(hex[0]);
write_serial(hex[1]);
}
}
void print_uart_byte(uint8_t byte)
{
uint8_t hex[2];
bin_to_hex(byte, hex);
write_serial(hex[0]);
write_serial(hex[1]);
}

View File

@ -1,27 +0,0 @@
#pragma once
#include <stdint.h>
#define UART_BASE 0x10000000
#define UART_RBR UART_BASE + 0
#define UART_THR UART_BASE + 0
#define UART_INTERRUPT_ENABLE UART_BASE + 4
#define UART_INTERRUPT_IDENT UART_BASE + 8
#define UART_FIFO_CONTROL UART_BASE + 8
#define UART_LINE_CONTROL UART_BASE + 12
#define UART_MODEM_CONTROL UART_BASE + 16
#define UART_LINE_STATUS UART_BASE + 20
#define UART_MODEM_STATUS UART_BASE + 24
#define UART_DLAB_LSB UART_BASE + 0
#define UART_DLAB_MSB UART_BASE + 4
void init_uart();
void print_uart(const char* str);
void print_uart_int(uint32_t addr);
void print_uart_addr(uint64_t addr);
void print_uart_byte(uint8_t byte);