Skip to content

312551071 lab2 #158

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

Open
wants to merge 1 commit into
base: 312551071
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
743 changes: 743 additions & 0 deletions lab2/.clang-format

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions lab2/bootloader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
CC = aarch64-linux-gnu-gcc
LD = aarch64-linux-gnu-ld
AR = aarch64-linux-gnu-ar
OBJCOPY = aarch64-linux-gnu-objcopy
LINKER_SCRIPT = linker.ld
START = start
IMG_NAME = bootloader
BUILD = ../build

CFLAGS := -fno-stack-protector -I ../include/

all: $(BUILD)/$(IMG_NAME).img

$(BUILD)/$(START).o: $(START).S
$(CC) $(CFLAGS) -c $(START).S -o $(BUILD)/$(START).o

OBJS := \
bootloader.o \
uart.o \
string.o


OBJS := $(addprefix $(BUILD)/, $(OBJS))

$(BUILD)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

$(BUILD)/$(IMG_NAME).img: $(BUILD)/$(START).o $(OBJS)
$(LD) $(BUILD)/$(START).o $(OBJS) -T $(LINKER_SCRIPT) -o $(BUILD)/$(IMG_NAME).elf
$(OBJCOPY) -O binary $(BUILD)/$(IMG_NAME).elf $(BUILD)/$(IMG_NAME).img

clean:
rm -f $(BUILD)/$(IMG_NAME).elf $(BUILD)/$(IMG_NAME).img $(BUILD)/*.o

run:
qemu-system-aarch64 -M raspi3b -kernel $(BUILD)/$(IMG_NAME).img -serial null -serial stdio
69 changes: 69 additions & 0 deletions lab2/bootloader/bootloader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <stddef.h>

#include "uart.h"
#include "string.h"

#define MAX_BUFFER_LEN 1024

void bootloader_main(void *dtb)
{
char buffer[MAX_BUFFER_LEN];
size_t buffer_index = 0;
char ch;

uart_init();
uart_puts("Starting the shell!\r\n");

while (1) {
uart_puts("# ");
buffer_index = 0;
buffer[0] = '\0';

while (1) {
ch = uart_getc();
if (buffer_index + 1 >= sizeof(buffer)) {
uart_puts(
"ERROR: Exceed buffer length limit!\r\n");
buffer_index = 0;
buffer[0] = '\0';
break;
}
if (ch == '\n') {
uart_puts("\r\n");
buffer[buffer_index] = '\0';
break;
}
uart_send(ch);
buffer[buffer_index++] = ch;
}
// dispatch_cmd(buffer);

if (strcmp(buffer, "boot") == 0) {
unsigned int size = 0;
unsigned char *size_buffer = (unsigned char *)&size;

uart_puts("Use send_loader.py to load kernel\r\n");
for (int i = 0; i < 4; i++)
size_buffer[i] = uart_getc();
uart_puts("Start receiving kernel\r\n");

char *kernel = (char *)0x80000; // load kernel in 0x80000
while (size--)
*kernel++ = uart_getc();

uart_puts("kernel loaded!\r\n");

void (*kernel_entry)(void) = (void (*)(void))0x80000;
kernel_entry();

return;
} else {
uart_puts("ERROR: Unrecognized command!\r\n");
}
}

// echo everything back
while (1) {
uart_send(uart_getc());
}
}
3 changes: 3 additions & 0 deletions lab2/bootloader/config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kernel=bootloader.img
arm_64bit=1
initramfs initramfs.cpio 0x20000000
22 changes: 22 additions & 0 deletions lab2/bootloader/linker.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
SECTIONS
{
. = 0x60000; /*start loading from 0x60000*/

.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
PROVIDE(_data = .); /* let _data = current address */
.data : { *(.data .data.* .gnu.linkonce.d*) }
.bss (NOLOAD) : { /*don't require space in executable*/
. = ALIGN(16); /*align with 16 bit for efficiency*/
/*put all .bss, .bss. segments and other segments into .bss */
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
_end = .;

/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
__bss_size = (__bss_end - __bss_start)>>3; /* bss size for start.S */
__bootloader_size = (_end - 0x60000)>>3;
31 changes: 31 additions & 0 deletions lab2/bootloader/send_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
import os.path
import argparse
import time

# Set up argument parser
parser = argparse.ArgumentParser(description='Send a file over serial connection.')
parser.add_argument('-s', '--serial_path', default='/dev/ttyUSB0', help='The path to the serial device (default: /dev/ttyUSB0)')
parser.add_argument('-f', '--file_path', default='kernel8.img', help='The file to send (default: kernel8.img)')
args = parser.parse_args()

# Check if file exists
if not os.path.exists(args.file_path):
print(f"File {args.file_path} not found.")
exit(1)

# Get file size
size = os.stat(args.file_path).st_size
size_bytes = size.to_bytes(4, "little") #little endian to fit the environment (8bit 8bit 8bit 8bit)

# Open serial connection write binary
with open(args.serial_path, "wb", buffering=0) as tty:
# Send file size
tty.write(size_bytes)
print("wrote data")
time.sleep(3)
print("sending kernel")

# Open and send the file
with open(args.file_path, "rb") as f:
tty.write(f.read())
48 changes: 48 additions & 0 deletions lab2/bootloader/start.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.section ".text.boot"

.global _start

_start:
// relocate bootloader
mov x28, x0
ldr x1, =0x80000 //64 bits for address, 0x1 = 1 byte
ldr x2, =0x60000 //ldr: put address to register
ldr w3, =__bootloader_size //size, 32 bit is enough

relocate: //since its 64-bit architecture, move 8 bytes every time
ldr x4,[x1],#8 //store value from x1 to x4, then mov x1 ([] means read value in the address)
str x4,[x2],#8 //store value from x4 to x2, then mov x2 ([] means write value in the address)
sub w3,w3,#1 //size is >>3, so 1 means 8 bytes
cbnz w3,relocate //keep relocate if size is not 0

init_cpu:
// read cpu id, stop slave cores
mrs x1, mpidr_el1 //get cpu num
and x1, x1, #3 //see if cpu num is 0
cbz x1, 2f //cpu 0 jump to 2f (others wfe)
// cpu id > 0, stop

1: wfe
b 1b

2: // cpu id == 0

// set top of stack just before our code (stack grows to a lower address per AAPCS64)
ldr x1, =_start //ldr: load Register
mov sp, x1 //stack pointer before _start

// clear bss
ldr x1, =__bss_start
ldr w2, =__bss_size

3: cbz w2, 4f //see if bss is cleared, if cleared go to 4
str xzr, [x1], #8 //xzr means zero, clear to zzero from start
sub w2, w2, #1 //1 count means 8bit
cbnz w2, 3b //if not zero go back

// jump to C code, should not return

4: mov x0, x28
bl bootloader_main-0x20000
// for failsafe, halt this core too
b 1b
9 changes: 9 additions & 0 deletions lab2/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

rm ./build/*
cd kernel
make
cd ..
rm ./build/start.o
cd bootloader
make
25 changes: 25 additions & 0 deletions lab2/include/cpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

struct cpio_newc_header {
//file metadata
char c_magic[6]; // Magic number identifying the CPIO format
char c_ino[8]; // Inode number
char c_mode[8]; // File mode and type
char c_uid[8]; // User ID of file owner
char c_gid[8]; // Group ID of file owner
char c_nlink[8]; // Number of hard links
char c_mtime[8]; // Modification time of file
char c_filesize[8]; // Size of file (in hexadecimal)
char c_devmajor[8]; // Major device number (for device files)
char c_devminor[8]; // Minor device number (for device files)
char c_rdevmajor
[8]; // Major device number for the device file node referenced by the symlink
char c_rdevminor
[8]; // Minor device number for the device file node referenced by the symlink
char c_namesize[8]; // Size of filename (in hexadecimal)
char c_check[8]; // Checksum
};
// Link: https://manpages.ubuntu.com/manpages/bionic/man5/cpio.5.html

void cpio_ls();
void cpio_cat();
45 changes: 45 additions & 0 deletions lab2/include/gpio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
*
* 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.
*
*/

#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))
52 changes: 52 additions & 0 deletions lab2/include/mbox.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
*
* 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.
*
*/

/* a properly aligned buffer */
extern volatile unsigned int mbox[36];

#define MBOX_REQUEST 0

/* channels */
#define MBOX_CH_POWER 0
#define MBOX_CH_FB 1
#define MBOX_CH_VUART 2
#define MBOX_CH_VCHIQ 3
#define MBOX_CH_LEDS 4
#define MBOX_CH_BTNS 5
#define MBOX_CH_TOUCH 6
#define MBOX_CH_COUNT 7
#define MBOX_CH_PROP 8

/* tags */
#define TAG_REQUEST_CODE 0x00000000
#define MBOX_TAG_GETSERIAL 0x10004
#define MBOX_TAG_GETBOARD 0x00010002
#define MBOX_TAG_GETARMMEM 0x00010005
#define MBOX_TAG_LAST 0

int mbox_call(unsigned char ch);
void get_board_revision();
void get_serial_number();
void get_arm_mem();
20 changes: 20 additions & 0 deletions lab2/include/memory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <stddef.h>

#define MEMORY_SIZE 1024

static char memory_pool[MEMORY_SIZE];
static char *memory_ptr = memory_pool;

void *simple_alloc(size_t size)
{
void *allocated = memory_ptr;

if (memory_ptr + size - memory_pool > MEMORY_SIZE)
return NULL;

memory_ptr += size;

return allocated;
}
5 changes: 5 additions & 0 deletions lab2/include/reset.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

void set(long addr, unsigned int value);
void reset(int tick);
void cancel_reset();
5 changes: 5 additions & 0 deletions lab2/include/shell.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#define MAX_BUFFER_LEN 1024

void shell();
3 changes: 3 additions & 0 deletions lab2/include/string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

int strcmp(const char *s1, const char *s2);
Loading