Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

110550110 lab3 #174

Open
wants to merge 4 commits into
base: 110550110
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added lab2/bcm2710-rpi-3-b-plus.dtb
Binary file not shown.
27 changes: 27 additions & 0 deletions lab2/bootloader/booting.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.section ".text.boot" // Start a new section named ".text.boot"
.global _start // Declare _start symbol as global

_start: // Start of the _start block
// read cpu id, stop slave cores
mrs x1, mpidr_el1 // Read Multiprocessor Affinity Register into x1
and x1, x1, #3 // Mask the lower 2 bits (CPU core ID) from x1
cbz x1, setting // If x1 is zero, jump to setting label

halt: wfe // Wait for Event instruction
b halt // Branch (jump) to halt (infinite loop)

setting: // Setting label
ldr x1, =_start // Load the address of _start into x1
mov sp, x1 // Move the value of x1 into the Stack Pointer (sp)
ldr x1, =__bss_start // Load the address of __bss_start into x1
ldr w2, =__bss_size // Load the value of __bss_size into w2

clear_bss: // Clear BSS segment loop label
cbz w2, kernel_main // If w2 (BSS size) is zero, jump to kernel_main
str xzr, [x1], #8 // Store zero (xzr) at the address pointed by x1, then increment x1 by 8
sub w2, w2, #1 // Decrement w2 (BSS size) by 1
cbnz w2, clear_bss // If w2 is not zero, jump back to clear_bss

kernel_main: // Label for the start of kernel_main function
bl main // Branch with link (call) to main function
b halt // Branch to halt (infinite loop)
64 changes: 64 additions & 0 deletions lab2/bootloader/bootloader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include"header/bootloader.h"
#include"header/uart.h"
#include"header/utils.h"
// from linker script
extern char _start;
extern char _end;
void relocate(char *arg)
{
unsigned long bootloader_size = (&_end - &_start);
char *oldbootloader = (char *)&_start; //0x80000
char *newbootloader = (char *)0x60000;

unsigned long bl_ptr = 0;
// copying
while (bootloader_size--)
{
newbootloader[bl_ptr] = oldbootloader[bl_ptr];
++bl_ptr;
}
// run kernel in 0x60000
void (*run)(char *) = (void (*)(char *))newbootloader;
run(arg);
}
// can be verifying in gdb
void load_img(char *dtb_base) {
// kernel start
char *kernel = (char *)(0x80000);
int kn_ptr = 0;

// size
int idx = 0;
char sz[50] = {};
char c;

// receiving str size
while(1) {
c = uart_get_char();
// receive size end
if(c == '\n') {
sz[idx] = '\0';
break;
}
sz[idx++] = c;
}
// get kernel image size
int size = atoi(sz);
uart_send_str(sz);

// receive kernel img
while (size--)
kernel[kn_ptr++] = uart_get_img_char();
// test message
uart_binary_to_hex((unsigned int) dtb_base);
uart_send_str("\nKernel received\n");
int r = 1000;
while(r--){
asm volatile("nop");
}
// run kernel and pass dtb base
void (*run)(char *) = (void *)kernel;
// get dtb loading address
// run("0x60000");
run(dtb_base);
}
2 changes: 2 additions & 0 deletions lab2/bootloader/header/bootloader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
void load_img();
void relocate(char *arg);
7 changes: 7 additions & 0 deletions lab2/bootloader/header/reboot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef _REBOOT_H_
#define _REBOOT_H_

void set(long addr, unsigned int value);
void reset(int tick);
void cancel_reset();
#endif
3 changes: 3 additions & 0 deletions lab2/bootloader/header/shell.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
void ls();
void cat();
void shell();
44 changes: 44 additions & 0 deletions lab2/bootloader/header/uart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef _UART_H_
#define _UART_H_
#define MMIO_BASE 0x3f000000

#define GPFSEL0 ((volatile unsigned int *)(MMIO_BASE + 0x00200000))
#define GPFSEL1 ((volatile unsigned int *)(MMIO_BASE + 0x00200004))
#define GPFSEL2 ((volatile unsigned int *)(MMIO_BASE + 0x00200008))
#define GPFSEL3 ((volatile unsigned int *)(MMIO_BASE + 0x0020000C))
#define GPFSEL4 ((volatile unsigned int *)(MMIO_BASE + 0x00200010))
#define GPFSEL5 ((volatile unsigned int *)(MMIO_BASE + 0x00200014))
#define GPSET0 ((volatile unsigned int *)(MMIO_BASE + 0x0020001C))
#define GPSET1 ((volatile unsigned int *)(MMIO_BASE + 0x00200020))
#define GPCLR0 ((volatile unsigned int *)(MMIO_BASE + 0x00200028))
#define GPLEV0 ((volatile unsigned int *)(MMIO_BASE + 0x00200034))
#define GPLEV1 ((volatile unsigned int *)(MMIO_BASE + 0x00200038))
#define GPEDS0 ((volatile unsigned int *)(MMIO_BASE + 0x00200040))
#define GPEDS1 ((volatile unsigned int *)(MMIO_BASE + 0x00200044))
#define GPHEN0 ((volatile unsigned int *)(MMIO_BASE + 0x00200064))
#define GPHEN1 ((volatile unsigned int *)(MMIO_BASE + 0x00200068))
#define GPPUD ((volatile unsigned int *)(MMIO_BASE + 0x00200094))
#define GPPUDCLK0 ((volatile unsigned int *)(MMIO_BASE + 0x00200098))
#define GPPUDCLK1 ((volatile unsigned int *)(MMIO_BASE + 0x0020009C))

#define AUX_ENABLE ((volatile unsigned int *)(MMIO_BASE + 0x00215004))
#define AUX_MU_IO ((volatile unsigned int *)(MMIO_BASE + 0x00215040))
#define AUX_MU_IER ((volatile unsigned int *)(MMIO_BASE + 0x00215044))
#define AUX_MU_IIR ((volatile unsigned int *)(MMIO_BASE + 0x00215048))
#define AUX_MU_LCR ((volatile unsigned int *)(MMIO_BASE + 0x0021504C))
#define AUX_MU_MCR ((volatile unsigned int *)(MMIO_BASE + 0x00215050))
#define AUX_MU_LSR ((volatile unsigned int *)(MMIO_BASE + 0x00215054))
#define AUX_MU_MSR ((volatile unsigned int *)(MMIO_BASE + 0x00215058))
#define AUX_MU_SCRATCH ((volatile unsigned int *)(MMIO_BASE + 0x0021505C))
#define AUX_MU_CNTL ((volatile unsigned int *)(MMIO_BASE + 0x00215060))
#define AUX_MU_STAT ((volatile unsigned int *)(MMIO_BASE + 0x00215064))
#define AUX_MU_BAUD ((volatile unsigned int *)(MMIO_BASE + 0x00215068))

#endif

void uart_init();
void uart_send_char(unsigned int c);
char uart_get_char();
void uart_send_str(char *s);
void uart_binary_to_hex(unsigned int d);
char uart_get_img_char();
2 changes: 2 additions & 0 deletions lab2/bootloader/header/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
int string_compare(char *a, char *b);
int atoi(char *str);
24 changes: 24 additions & 0 deletions lab2/bootloader/linker.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
SECTIONS
{
. = 0x80000; /* Set the memory address to 0x80000 (start point)*/

.text : { /* Define the .text section, which contains executable code*/
KEEP(*(.text.boot)) /* Keep all .text.boot sections*/
*(.text) /* Keep all other .text sections*/
}

.rodata : { *(.rodata) } /* Define the .rodata section, which contains read-only data*/

.data : { *(.data) } /* Define the .data section, which contains initialized data*/

.bss () : { /* Define the .bss section, which contains uninitialized data*/
__bss_start = .; /* Define __bss_start symbol as the current memory address*/
*(.bss) /* Keep all .bss sections*/
*(COMMON) /* Keep all common symbols*/
__bss_end = .; /* Define __bss_end symbol as the current memory address*/
}

_end = .; /* Define _end symbol as the current memory address*/
}

__bss_size = (__bss_end - __bss_start) >> 3; /* Calculate the size of the .bss section in bytes*/
20 changes: 20 additions & 0 deletions lab2/bootloader/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include"header/uart.h"
#include"header/bootloader.h"
#include"header/shell.h"
char *dtb_base;
int relocated = 1;
void main(char *arg)
{
uart_init();

// register x0
dtb_base = arg;

// relocate copies bootloader program from 0x80000 to 0x60000
if (relocated) {
relocated = 0;
relocate(arg);
}
uart_send_str("\x1b[2J\x1b[H");
shell(dtb_base);
}
31 changes: 31 additions & 0 deletions lab2/bootloader/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
CFLAGS = -Wall -ffreestanding -nostdinc -nostdlib -nostartfiles -fno-stack-protector -g
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)

ASMS = $(wildcard *.S)
ASM_OBJS = $(ASMS:.S=.o)

all:: clean_img flash clean

%.o: %.S
aarch64-linux-gnu-gcc $(CFLAGS) -c $< -o $@


%.o: %.c
aarch64-linux-gnu-gcc $(CFLAGS) -c $< -o $@

flash: $(ASM_OBJS) $(OBJS)
aarch64-linux-gnu-ld $(ASM_OBJS) $(OBJS) -T linker.ld -o kernel8.elf
aarch64-linux-gnu-objcopy kernel8.elf -O binary kernel8.img
clean:
rm -f $(ASM_OBJS) $(OBJS)

clean_img:
rm -f kernel8.elf
rm -f kernel8.img
test:
qemu-system-aarch64 -machine raspi3b -kernel kernel8.img -display none -serial null -serial stdio -initrd ../rootfs/initramfs.cpio
test_pty:
qemu-system-aarch64 -machine raspi3b -kernel kernel8.img -display none -serial null -serial pty
screen:
sudo screen /dev/ttyUSB0 115200
20 changes: 20 additions & 0 deletions lab2/bootloader/reboot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include"header/reboot.h"

#define PM_PASSWORD 0x5a000000
#define PM_RSTC 0x3F10001c
#define PM_WDOG 0x3F100024

void set(long addr, unsigned int value) {
volatile unsigned int* point = (unsigned int*)addr;
*point = value;
}

void reset(int tick) { // reboot after watchdog timer expire
set(PM_RSTC, PM_PASSWORD | 0x20); // full reset
set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick
}

void cancel_reset() {
set(PM_RSTC, PM_PASSWORD | 0); // full reset
set(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick
}
59 changes: 59 additions & 0 deletions lab2/bootloader/shell.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include"header/shell.h"
#include"header/uart.h"
#include"header/utils.h"
#include"header/reboot.h"
#include"header/bootloader.h"

void shell(char *dtb_base){
char cmd[256];
char *cur;
while (1)
{
char *s = "# ";
uart_send_str(s);
cur = cmd;
char receive;
while (1)
{
receive = uart_get_char();
if(receive == '\n'){
*cur = '\0';
break;
}
else if(receive == 127){
if(cur == cmd){
*cur = '\0';
continue;
}
*cur = '\0';
cur--;
uart_send_str("\b \b");
continue;
}
*cur = receive;
uart_send_char(receive);
cur++;
}
cur = cmd;
if(string_compare(cur,"help")){
uart_send_str("\nhelp\t\t:print this help menu\r\n");
uart_send_str("hello\t\t:print Hello World!\r\n");
uart_send_str("load\t\t:load kernel image through uart\r\n");
uart_send_str("reboot\t\t:reboot the device\r\n");
}
else if(string_compare(cur,"hello")){
uart_send_str("\nHello World!\n");
}
else if(string_compare(cur,"load")){
uart_send_str("\nload kernel...\n");
load_img(dtb_base);
}
else if (string_compare(cur,"reboot")) {
uart_send_str("\nRebooting....\n");
reset(1000);

}
else
uart_send_str("\n");
}
}
74 changes: 74 additions & 0 deletions lab2/bootloader/uart.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include"header/uart.h"

void uart_init(){

*AUX_ENABLE |= 1;
*AUX_MU_CNTL = 0;
*AUX_MU_IER = 0;
*AUX_MU_LCR = 3;
*AUX_MU_MCR = 0;
*AUX_MU_BAUD = 270;

register unsigned int r;

//???
r =* GPFSEL1;
r &= ~((7 << 12) | (7 << 15)); // gpio14, gpio15 innitial
r |= (2 << 12) | (2 << 15); // alt5
*GPFSEL1 = r;
*GPPUD = 0; // enable pins 14 and 15
r = 150; while(r--) { asm volatile("nop"); }
*GPPUDCLK0 = (1 << 14) | (1 << 15);
r = 150; while(r--) { asm volatile("nop"); }
*GPPUDCLK0 = 0; // flush GPIO setup

*AUX_MU_IIR = 6;
*AUX_MU_CNTL = 3;
}

void uart_send_char(unsigned int c){
do{asm volatile("nop");}while(!(*AUX_MU_LSR & 0x20)); // This bit is set if the transmit FIFO can accept at least one byte.
/* write the character to the buffer */
*AUX_MU_IO = c;
}

char uart_get_char(){
char r;
/* wait until something is in the buffer */
//bit 0 is set if the receive FIFO holds at least 1 symbol.
do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01));
/* read it and return */
r=(char)(*AUX_MU_IO);
/* convert carriage return to newline */
return r=='\r'?'\n':r;
}
char uart_get_img_char(){
char r;
/* wait until something is in the buffer */
//bit 0 is set if the receive FIFO holds at least 1 symbol.
do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01));
/* read it and return */
r=(char)(*AUX_MU_IO);
return r;
}
void uart_send_str(char *s){
while(*s) {
/* convert newline to carriage return + newline */
if(*s=='\n')
uart_send_char('\r');
uart_send_char(*s++);
}
}

void uart_binary_to_hex(unsigned int d) {
unsigned int n;
int c;
uart_send_str("0x");
for(c=28;c>=0;c-=4) {
// get highest tetrad
n=(d>>c)&0xF;
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
n+=n>9?0x37:0x30;
uart_send_char(n);
}
}
Loading