diff --git a/README.md b/README.md new file mode 100644 index 000000000..c56b9b76e --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# OSC2023 + +| Github Account | Student ID | Name | +|----------------|------------|---------------| +| Haoze0102 | A122542 | Hao-Ze Wang | + +## Requirements + +* a cross-compiler for aarch64 +* (optional) qemu-system-arm + +## Build + +``` +make kernel.img +``` + +## Test With QEMU + +``` +qemu-system-aarch64 -M raspi3b -kernel kernel.img -initrd initramfs.cpio -serial null -serial stdio -dtb bcm2710-rpi-3-b-plus.dtb +``` \ No newline at end of file diff --git a/README.org b/README.org index a77151714..a0cfbf2fa 100644 --- a/README.org +++ b/README.org @@ -1,79 +1,22 @@ -#+TITLE: Operating Systems Capstone 2023 -#+OPTIONS: toc:nil +# OSC2023 -This repository is used for homework submission. +| Github Account | Student ID | Name | +|----------------|------------|---------------| +| psychicalcoder | 0816171 | Tsung-Han Liu | -*To protect your rights, please create a pull request (PR) before the demo and* -*make sure the TA merges your PR after the demo.* +## Requirements -* How To Submit Homework +* a cross-compiler for aarch64 +* (optional) qemu-system-arm -** Overview -For those who are familiar with git. -1. TA creates a branch named your student ID. -2. You fork this repo. -3. Base on the == branch, you do your labs and put your code in the - forked repo. -4. Create a PR to the == branch in this repo to submit the homework. -5. TA merges the PR as a proof that you have demo the lab. +## Build -** Fork The Repo -Fork the repository on Github. +``` +make kernel.img +``` -[[./images/fork_button.jpg]] +## Test With QEMU -Uncheck the "Copy the =main= branch only". - -[[./images/create_fork.jpg]] - -If you don't want to see a lot of redundant branches in the forked repo, keep -the checkbox checked and follow the [[./git-usage.org][guide]] to fetch your own branch. - -** Clone To Your Computer -Clone the forked repo and switch to the branch named your student id. -If you cannot find your branch, ask TAs for help. - -[[./images/clone_url.jpg]] - -#+BEGIN_SRC shell - git clone - cd osc2023 - git checkout --track origin/ -#+END_SRC - -** Specify Personal Information -Write down the following info in your =README.md= (or =README.org=, =README.rst= -etc.) -+ Github account name -+ Student ID -+ Your name -+ Any other information you want - -Here is an example [[https://github.com/psychicalcoder/osc2023/blob/0816171/README.md][README.md]]. - -** Implement Your Kernel -Design and implement your kernel in the forked repository. -#+BEGIN_QUOTE - Make good use of =.gitignore=. In the git history, we do not want to see - binaries, objective files, __MACOSX, python caches, super large test files, - or any files that can be compiled from your source code. -#+END_QUOTE - -** Create a PR -Create a Github pull request before your demo. Once the PR is created, you can -always push additional commits to your forked repo before the PR is merged. The -changes will automatically appear within the PR. - -1. Click the =New pull request= buttom in your repo. - [[./images/pr_button.jpg]] -2. Choose the branch with your student ID as the base branch. - [[./images/pr_base_selection.jpg]] -3. Type a title and some information about the PR. - [[./images/pr_desc.jpg]] - -Here is a [[https://github.com/oscapstone/osc2023/pull/1][PR example]]. - -* Happy Coding ~ -As long as you meet the above requirements and the PR can be merged without -conflicts, we do not care about what the forked repo look like. You can rename -your branch, change the default branch, or do whatever you want. +``` +qemu-system-aarch64 -M raspi3b -kernel kernel.img -initrd initramfs.cpio -serial null -serial stdio -dtb bcm2710-rpi-3-b-plus.dtb +``` \ No newline at end of file diff --git a/lab1/.gitignore b/lab1/.gitignore new file mode 100644 index 000000000..d0238014a --- /dev/null +++ b/lab1/.gitignore @@ -0,0 +1,5 @@ +.vscode +gen.py +build/ +kernel8.img +kernel8.elf \ No newline at end of file diff --git a/lab1/Makefile b/lab1/Makefile new file mode 100644 index 000000000..3fe0d0de7 --- /dev/null +++ b/lab1/Makefile @@ -0,0 +1,141 @@ +BUILD_DIR = ./build +# Lib +LIB_SRC_DIR = ./lib + +# LIB_SRC = \ +# $(LIB_SRC_DIR)/mbox.c \ +# $(LIB_SRC_DIR)/mmio.c \ +# $(LIB_SRC_DIR)/shell.c \ +# $(LIB_SRC_DIR)/string.c \ +# $(LIB_SRC_DIR)/uart.c \ +# $(LIB_SRC_DIR)/utils.c \ + +LIB_SRC = \ + $(LIB_SRC_DIR)/mmio.c \ + $(LIB_SRC_DIR)/mbox.c \ + $(LIB_SRC_DIR)/shell.c \ + $(LIB_SRC_DIR)/uart.c \ + +LIB_INCLUDES = \ + -I $(LIB_SRC_DIR)/include \ + +LIB_BUILD_DIR = $(BUILD_DIR)/lib +LIB_OBJS := $(patsubst %.c,$(LIB_BUILD_DIR)/%.o,$(notdir $(LIB_SRC))) + +# Application +APP_SRC_DIR = . + +APP_SRC = \ + $(APP_SRC_DIR)/main.c \ + +APP_ASM = \ + $(APP_SRC_DIR)/boot.S \ + +APP_INCLUDES = \ + -I ./ \ + $(LIB_INCLUDES) \ + +APP_BUILD_DIR = $(BUILD_DIR)/app +APP_OBJS := $(patsubst %.c,$(APP_BUILD_DIR)/%.o,$(notdir $(APP_SRC))) +APP_OBJS += $(patsubst %.S,$(APP_BUILD_DIR)/%.o,$(notdir $(APP_ASM))) + +VPATH += \ + $(LIB_SRC_DIR) \ + $(APP_SRC_DIR) \ + +# ARM toolchain +CROSS = aarch64-linux-gnu +CC = $(CROSS)-gcc +AS = $(CROSS)-as +LD = $(CROSS)-ld +OC = $(CROSS)-objcopy +OD = $(CROSS)-objdump +SP = $(CROSS)-strip + +# Project +OUT_OBJS = \ + $(LIB_OBJS) \ + $(APP_OBJS) \ + +BUILD_DIRECTORIES = \ + $(LIB_BUILD_DIR) \ + $(APP_BUILD_DIR) \ + +PROJ = kernel8 +OUT_ELF = ./$(PROJ).elf +OUT_IMG = ./$(PROJ).img +LINKER_FILE = linker.ld + +CCFLAGS = -Wall -O0 -fno-stack-protector +LDFLAGS = -T$(LINKER_FILE) -nostdlib + +.PHONY: clean directories out_elf run docker_cp +all: directories $(OUT_OBJS) $(OUT_ELF) $(OUT_IMG) +directories: $(BUILD_DIRECTORIES) +out_elf: directories $(OUT_ELF) +out_img: directories $(OUT_IMG) + +# Compile Object Files --------------------------------------------------------- +$(APP_BUILD_DIR)/%.o : %.c + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + @echo "[+] Building: $<" + $(CC) $(CCFLAGS) $(APP_INCLUDES) -g -o $@ -c $< + @echo "[+] Finished Building: $<" + @echo '' + +$(APP_BUILD_DIR)/%.o : %.S + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + @echo "[+] Building: $<" + $(CC) $(ASMFLAGS) $(APP_INCLUDES) -g -o $@ -c $< + @echo "[+] Finished Building: $<" + @echo '' + +$(LIB_BUILD_DIR)/%.o : %.c + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + @echo "[+] Building: $<" + $(CC) $(CCFLAGS) $(LIB_INCLUDES) -g -o $@ -c $< + @echo "[+] Finished Building: $<" + @echo '' + +# Generate ELF ----------------------------------------------------------------- +$(OUT_ELF): $(OUT_OBJS) + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + $(LD) $(LDFLAGS) -o $@ $(OUT_OBJS) + $(OD) -d $@ > $(BUILD_DIR)/$(PROJ).objdump + # $(SP) $@ + @echo '[+] Finished building target: $@' + @echo ' ' + +# Generate IMG ----------------------------------------------------------------- +$(OUT_IMG): $(OUT_ELF) + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + $(OC) -O binary $(OUT_ELF) $@ + @echo '[+] Finished building target: $@' + @echo ' ' + +$(BUILD_DIRECTORIES): + mkdir -p $@ + +run: + qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -serial null -serial stdio + +debug: + qemu-system-aarch64 -M raspi3b -kernel kernel8.img -display none -serial null -serial stdio -s -S + +docker_cp: + docker cp kernel8.elf my_kali:/ + +clean: + rm -rf *.elf + rm -rf *.img + rm -rf $(BUILD_DIR) \ No newline at end of file diff --git a/lab1/boot.S b/lab1/boot.S new file mode 100644 index 000000000..633875f8a --- /dev/null +++ b/lab1/boot.S @@ -0,0 +1,30 @@ +.section ".text.boot" + +.global _start + +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, 2f + // 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 + mov sp, x1 + + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size +3: cbz w2, 4f + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, 3b + + // jump to C code, should not return +4: bl kernel_main + // for failsafe, halt this core too + b 1b \ No newline at end of file diff --git a/lab1/boot.o b/lab1/boot.o new file mode 100644 index 000000000..605353a83 Binary files /dev/null and b/lab1/boot.o differ diff --git a/lab1/lib/include/aux.h b/lab1/lib/include/aux.h new file mode 100644 index 000000000..7fca3f1ec --- /dev/null +++ b/lab1/lib/include/aux.h @@ -0,0 +1,33 @@ +#ifndef __AUX_H__ +#define __AUX_H__ + +#include "mmio.h" +/* Ref: https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf + * Page: 8 +*/ +#define AUX_BASE (MMIO_BASE + 0x00215000) +#define AUX_IRQ (AUX_BASE + 0x0) +#define AUX_ENABLES (AUX_BASE + 0x4) +#define AUX_MU_IO_REG (AUX_BASE + 0x40) +#define AUX_MU_IER_REG (AUX_BASE + 0x44) +#define AUX_MU_IIR_REG (AUX_BASE + 0x48) +#define AUX_MU_LCR_REG (AUX_BASE + 0x4c) +#define AUX_MU_MCR_REG (AUX_BASE + 0x50) +#define AUX_MU_LSR_REG (AUX_BASE + 0x54) +#define AUX_MU_MSR_REG (AUX_BASE + 0x58) +#define AUX_MU_SCRATCH (AUX_BASE + 0x5c) +#define AUX_MU_CNTL_REG (AUX_BASE + 0x60) +#define AUX_MU_STAT_REG (AUX_BASE + 0x64) +#define AUX_MU_BAUD_REG (AUX_BASE + 0x68) +#define AUX_SPI0_CNTL0_REG (AUX_BASE + 0x80) +#define AUX_SPI0_CNTL1_REG (AUX_BASE + 0x84) +#define AUX_SPI0_STAT_REG (AUX_BASE + 0x88) +#define AUX_SPI0_IO_REG (AUX_BASE + 0x90) +#define AUX_SPI0_PEEK_REG (AUX_BASE + 0x94) +#define AUX_SPI1_CNTL0_REG (AUX_BASE + 0xc0) +#define AUX_SPI1_CNTL1_REG (AUX_BASE + 0xc4) +#define AUX_SPI1_STAT_REG (AUX_BASE + 0xc8) +#define AUX_SPI1_IO_REG (AUX_BASE + 0xd0) +#define AUX_SPI1_PEEK_REG (AUX_BASE + 0xd4) + +#endif \ No newline at end of file diff --git a/lab1/lib/include/gpio.h b/lab1/lib/include/gpio.h new file mode 100644 index 000000000..b4322f8db --- /dev/null +++ b/lab1/lib/include/gpio.h @@ -0,0 +1,35 @@ +#ifndef __GPIO_H__ +#define __GPIO_H__ + +#define GPIO_BASE 0x3f200000 +#define GPFSEL0 (GPIO_BASE + 0x0) +#define GPFSEL1 (GPIO_BASE + 0x4) +#define GPFSEL2 (GPIO_BASE + 0x8) +#define GPFSEL3 (GPIO_BASE + 0xc) +#define GPFSEL4 (GPIO_BASE + 0x10) +#define GPFSEL5 (GPIO_BASE + 0x14) +#define GPSET0 (GPIO_BASE + 0x1c) +#define GPSET1 (GPIO_BASE + 0x20) +#define GPCLR0 (GPIO_BASE + 0x28) +#define GPCLR1 (GPIO_BASE + 0x2c) +#define GPLEV0 (GPIO_BASE + 0x34) +#define GPLEV1 (GPIO_BASE + 0x38) +#define GPEDS0 (GPIO_BASE + 0x40) +#define GPEDS1 (GPIO_BASE + 0x44) +#define GPREN0 (GPIO_BASE + 0x4c) +#define GPREN1 (GPIO_BASE + 0x50) +#define GPFEN0 (GPIO_BASE + 0x58) +#define GPFEN1 (GPIO_BASE + 0x5c) +#define GPHEN0 (GPIO_BASE + 0x64) +#define GPHEN1 (GPIO_BASE + 0x68) +#define GPLEN0 (GPIO_BASE + 0x70) +#define GPLEN1 (GPIO_BASE + 0x74) +#define GPAREN0 (GPIO_BASE + 0x7c) +#define GPAREN1 (GPIO_BASE + 0x80) +#define GPAFEN0 (GPIO_BASE + 0x88) +#define GPAFEN1 (GPIO_BASE + 0x8c) +#define GPPUD (GPIO_BASE + 0x94) +#define GPPUDCLK0 (GPIO_BASE + 0x98) +#define GPPUDCLK1 (GPIO_BASE + 0x9c) + +#endif \ No newline at end of file diff --git a/lab1/lib/include/mbox.h b/lab1/lib/include/mbox.h new file mode 100644 index 000000000..8dc9ed9fc --- /dev/null +++ b/lab1/lib/include/mbox.h @@ -0,0 +1,111 @@ +#ifndef __MBOX_H__ +#define __MBOX_H__ + +#include "mmio.h" + +#define VIDEOCORE_MBOX_BASE (MMIO_BASE + 0x0000B880) +#define MBOX_READ (VIDEOCORE_MBOX_BASE + 0x00) +#define MBOX_POLL (VIDEOCORE_MBOX_BASE + 0x10) +#define MBOX_SENDER (VIDEOCORE_MBOX_BASE + 0x14) +#define MBOX_STATUS (VIDEOCORE_MBOX_BASE + 0x18) +#define MBOX_CONFIG (VIDEOCORE_MBOX_BASE + 0x1C) +#define MBOX_WRITE (VIDEOCORE_MBOX_BASE + 0x20) +#define MBOX_RESPONSE (0x80000000) +#define MBOX_FULL (0x80000000) +#define MBOX_EMPTY (0x40000000) + +#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) + +#define MAIL_BODY_BUF_LEN (4) +#define MAIL_BUF_SIZE (MAIL_BODY_BUF_LEN << 2) +#define MAIL_PACKET_SIZE (MAIL_BUF_SIZE + 24) + +#define REQUEST_CODE 0x00000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 +#define TAG_REQUEST_CODE 0x00000000 +#define END_TAG 0x00000000 + +/* Tags */ +#define GET_FIRMWARE_REVISION 0x00000001 +#define GET_BOARD_MODEL 0x00010001 +#define GET_BOARD_REVISION 0x00010002 +#define GET_BOARD_MAC_ADDR 0x00010003 +#define GET_BOARD_SERIAL 0x00010004 +#define GET_ARM_MEMORY 0x00010005 +#define GET_VC_MEMORY 0x00010006 +#define GET_CLOCKS 0x00010007 + +#define GET_COMMAND_LINE 0x00050001 + +#define GET_DMA_CHANNELS 0x00060001 + +#define GET_POWER_STATE 0x00020001 +#define GET_TIMING 0x00020002 +#define SET_POWER_STATE 0x00028001 + +// and so on... + +/* Unique Device ID */ +#define DEVICE_ID_SD_CARD 0x00000000 +#define DEVICE_ID_UART0 0x00000001 +#define DEVICE_ID_UART1 0x00000002 +#define DEVICE_ID_USB_HCD 0x00000003 +#define DEVICE_ID_I2C0 0x00000004 +#define DEVICE_ID_I2C1 0x00000005 +#define DEVICE_ID_I2C2 0x00000006 +#define DEVICE_ID_SPI 0x00000007 +#define DEVICE_ID_CCP2TX 0x00000008 +#define DEVICE_ID_UNKNOWN 0x00000009 +#define DEVICE_ID_UNKNOWN 0x0000000a + +/* Unique Clock ID */ +#define CLOCK_ID_RESERVED 0x000000000 +#define CLOCK_ID_EMMC 0x000000001 +#define CLOCK_ID_UART 0x000000002 +#define CLOCK_ID_ARM 0x000000003 +#define CLOCK_ID_CORE 0x000000004 +#define CLOCK_ID_V3D 0x000000005 +#define CLOCK_ID_H264 0x000000006 +#define CLOCK_ID_ISP 0x000000007 +#define CLOCK_ID_SDRAM 0x000000008 +#define CLOCK_ID_PIXEL 0x000000009 +#define CLOCK_ID_PWM 0x00000000a +#define CLOCK_ID_HEVC 0x00000000b +#define CLOCK_ID_EMMC2 0x00000000c +#define CLOCK_ID_M2MC 0x00000000d +#define CLOCK_ID_PIXEL_BVB 0x00000000e + +struct mail_header { + uint32_t packet_size; + uint32_t code; +}; + +struct mail_body { + uint32_t id; + uint32_t buf_size; + uint32_t code; + uint32_t buf[MAIL_BODY_BUF_LEN]; + uint32_t end; +}; + +typedef struct mail_t { + struct mail_header header; + struct mail_body body; +} mail_t __attribute__((aligned(16))); + +int mbox_call(mail_t* mbox, uint8_t ch); +void get_board_revision(uint32_t* board_revision); +void get_memory_info(uint32_t* mem_base, uint32_t* mem_size); +void get_board_serial(uint32_t* msb, uint32_t* lsb); + + +#endif \ No newline at end of file diff --git a/lab1/lib/include/mmio.h b/lab1/lib/include/mmio.h new file mode 100644 index 000000000..efbccf3c9 --- /dev/null +++ b/lab1/lib/include/mmio.h @@ -0,0 +1,14 @@ +#ifndef __MMIO_H__ +#define __MMIO_H__ +// #include +#include "stdint.h" + +#define PHY_BASE 0x3F000000 +#define BUS_BASE 0x7f000000 + +#define MMIO_BASE PHY_BASE + +void mmio_write(uint32_t reg, uint32_t data); // MMIO write +uint32_t mmio_read(uint32_t reg); // MMIO read + +#endif \ No newline at end of file diff --git a/lab1/lib/include/reset.h b/lab1/lib/include/reset.h new file mode 100644 index 000000000..b12aa1945 --- /dev/null +++ b/lab1/lib/include/reset.h @@ -0,0 +1,19 @@ +#ifndef __RESET_H__ +#define __RESET_H__ + +#include "mmio.h" +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 + +void reset(int tick) { // reboot after watchdog timer expire + mmio_write(PM_RSTC, PM_PASSWORD | 0x20); // full reset + mmio_write(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick +} + +void cancel_reset() { + mmio_write(PM_RSTC, PM_PASSWORD | 0); // full reset + mmio_write(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} + +#endif \ No newline at end of file diff --git a/lab1/lib/include/shell.h b/lab1/lib/include/shell.h new file mode 100644 index 000000000..88ae05f88 --- /dev/null +++ b/lab1/lib/include/shell.h @@ -0,0 +1,32 @@ +#ifndef __SHELL_H__ +#define __SHELL_H__ +#include "mbox.h" +#include "stdint.h" +#include "reset.h" +#include "string.h" +// #include "uart.h" + +struct func { + char *name; + void (*ptr)(); + char *desc; +}; + +void welcome_msg(); +void shell(); +void read_cmd(); +void exec_cmd(); + +void cmd_help(); +void cmd_hello(); +void cmd_reboot(); +void cmd_sysinfo(); +void cmd_unknown(); + +struct func func_list[] = { + {.name = "help", .ptr = cmd_help, .desc = "print this help menu"}, + {.name = "hello", .ptr = cmd_hello, .desc = "print Hello World!"}, + {.name = "reboot", .ptr = cmd_reboot, .desc = "reboot the device"}, + {.name = "sysinfo", .ptr = cmd_sysinfo, .desc = "get system info"}}; + +#endif \ No newline at end of file diff --git a/lab1/lib/include/stdint.h b/lab1/lib/include/stdint.h new file mode 100644 index 000000000..4b76cee21 --- /dev/null +++ b/lab1/lib/include/stdint.h @@ -0,0 +1,13 @@ +#ifndef __STDINT_H__ +#define __STDINT_H__ + +#define int8_t signed char +#define int16_t signed short int +#define int32_t signed int +#define int64_t signed long int +#define uint8_t unsigned char +#define uint16_t unsigned short int +#define uint32_t unsigned int +#define uint64_t unsigned long int + +#endif \ No newline at end of file diff --git a/lab1/lib/include/string.h b/lab1/lib/include/string.h new file mode 100644 index 000000000..fde569986 --- /dev/null +++ b/lab1/lib/include/string.h @@ -0,0 +1,20 @@ +#ifndef __STRING_H__ +#define __STRING_H__ + +#include "stdint.h" + +#define ENDL "\r\n" + +int strcmp(const char *a, const char *b) { + uint32_t i = 0; + while (a[i] == b[i] && a[i] != '\0' && b[i] != '\0') i++; + return a[i] - b[i]; +} + +uint32_t strlen(const char *a) { + for (uint32_t i = 0;; i++) + if (a[i] == '\0') return i; + return 0; +} + +#endif \ No newline at end of file diff --git a/lab1/lib/include/uart.h b/lab1/lib/include/uart.h new file mode 100644 index 000000000..a5e3b59c0 --- /dev/null +++ b/lab1/lib/include/uart.h @@ -0,0 +1,19 @@ +#ifndef __UART_H__ +#define __UART_H__ + +#include "aux.h" +#include "gpio.h" +#include "mmio.h" + +void uart_init(); +void uart_write(char c); +char uart_read(); +void uart_flush(); +void uart_write_string(char* str); +void uart_puth(uint32_t d); +void delay(uint32_t t) { + for (uint32_t i = 0; i < t; i++) + asm volatile("nop"); +} + +#endif \ No newline at end of file diff --git a/lab1/lib/mbox.c b/lab1/lib/mbox.c new file mode 100644 index 000000000..0b63e94db --- /dev/null +++ b/lab1/lib/mbox.c @@ -0,0 +1,98 @@ +#include "mbox.h" + +int mbox_call(mail_t* mbox, uint8_t ch) { + uint32_t addr_channel; + + // 1. Combine the message address (upper 28 bits) with channel number (lower 4 bits) + addr_channel = (((uint32_t)(uint64_t)mbox) & 0xFFFFFFF0) | (ch & 0xF); + + // 2. Read the status register until the empty flag is not set, then break while + while (mmio_read(MBOX_STATUS) & MBOX_FULL) asm volatile("nop"); + + // 3. If not, then you can write to Mailbox 1 Read/Write register. + mmio_write(MBOX_WRITE, addr_channel); + + // 4. Check if Mailbox 0 status register’s empty flag is set. + // 5. Read from Mailbox 0 Read/Write register. + do { + while (mmio_read(MBOX_STATUS) & MBOX_EMPTY) asm volatile("nop"); + } while (mmio_read(MBOX_READ) != addr_channel); + + + // 6. And check if the value is the same as you wrote in step 1. + // 0x80000000: request successfu + return mbox->header.code == MBOX_RESPONSE; +} + +void get_board_revision(uint32_t* board_revision) { + // Create a mailbox structure and initialize its fields + mail_t mbox = { + .header.packet_size = MAIL_PACKET_SIZE, // Set the packet size in the header + .header.code = REQUEST_CODE, // Set the code in the header to indicate a request + .body.id = GET_BOARD_REVISION, // Set the ID of the body to get board revision + .body.buf_size = MAIL_BUF_SIZE, // Set the size of the buffer in the body + .body.code = TAG_REQUEST_CODE, // Set the code in the body to indicate a tag request + .body.end = END_TAG, // Set the end tag in the body + }; + + // Initialize the buffer in the body to 0 + for (uint32_t i = 0; i < MAIL_BODY_BUF_LEN; i++) { + mbox.body.buf[i] = 0; + } + + // Call the mailbox function to send the request and receive the response + // MBOX_CH_PROP means chennel 8 + mbox_call(&mbox, MBOX_CH_PROP); + + // Extract the board revision information from the response buffer and assign it to board_revision + *board_revision = mbox.body.buf[0]; +} + + +// Get ARM memory Response:Length: 8 +void get_memory_info(uint32_t* mem_base, uint32_t* mem_size) { + mail_t mbox = { + .header.packet_size = MAIL_PACKET_SIZE, + .header.code = REQUEST_CODE, + .body.id = GET_ARM_MEMORY, + .body.buf_size = MAIL_BUF_SIZE, + .body.code = TAG_REQUEST_CODE, + .body.end = END_TAG, + }; + + for (uint32_t i = 0; i < MAIL_BODY_BUF_LEN; i++) mbox.body.buf[i] = 0; + + if (mbox_call(&mbox, MBOX_CH_PROP)) { + *mem_base = mbox.body.buf[0]; // u32: base address in bytes + *mem_size = mbox.body.buf[1]; // u32: size in bytes + + } else { + *mem_size = 0xFFFFFFFF; + *mem_base = 0xFFFFFFFF; + } +} + + +// Get board serial : Response:Length: 8 u64: board serial +void get_board_serial(uint32_t* msb, uint32_t* lsb) { + mail_t mbox = { + .header.packet_size = MAIL_PACKET_SIZE, + .header.code = REQUEST_CODE, + .body.id = GET_BOARD_SERIAL, + .body.buf_size = MAIL_BUF_SIZE, + .body.code = TAG_REQUEST_CODE, + .body.end = END_TAG, + }; + + for (uint32_t i = 0; i < MAIL_BODY_BUF_LEN; i++) mbox.body.buf[i] = 0; + + if (mbox_call(&mbox, MBOX_CH_PROP)) { + *msb = mbox.body.buf[1]; + *lsb = mbox.body.buf[0]; + } else { + *msb = 0xFFFFFFFF; + *lsb = 0xFFFFFFFF; + } +} + + diff --git a/lab1/lib/mmio.c b/lab1/lib/mmio.c new file mode 100644 index 000000000..ef9ba0d36 --- /dev/null +++ b/lab1/lib/mmio.c @@ -0,0 +1,11 @@ +#include "mmio.h" + +#include "stdint.h" + +void mmio_write(uint32_t reg, uint32_t data) { + *(volatile uint32_t*)(reg) = data; +} + +uint32_t mmio_read(uint32_t reg) { + return *(volatile uint32_t*)(reg); +} diff --git a/lab1/lib/shell.c b/lab1/lib/shell.c new file mode 100644 index 000000000..236954b22 --- /dev/null +++ b/lab1/lib/shell.c @@ -0,0 +1,113 @@ +#include "shell.h" + +char buf[0x100]; + +void welcome_msg() { + uart_write_string( + ENDL + " ____ _____ _____ ___ ___ ___ _ _" ENDL + " / __ \\ / ____| / ____| |__ \\ / _ \\ |__ \\ | || |" ENDL + " | | | || (___ | | ) || | | | ) || || |_" ENDL + " | | | | \\___ \\ | | / / | | | | / / |__ _|" ENDL + " | |__| | ____) || |____ / /_ | |_| | / /_ | | "ENDL + " \\____/ |_____/ \\_____| |____| \\___/ |____| |_|" ENDL); +} + +void read_cmd() { + char tmp; + uart_write_string("# "); + for (uint32_t i = 0; tmp = uart_read();) { + uart_write(tmp); + switch (tmp) { + case '\r': + case '\n': + buf[i++] = '\0'; + return; + case 127: // Backspace + if (i > 0) { + i--; + buf[i] = '\0'; + uart_write_string("\b \b"); + } + break; + default: + buf[i++] = tmp; + break; + } + } +} + +void exec_cmd() { + if (!strlen(buf)) return; + for (uint32_t i = 0; i < sizeof(func_list) / sizeof(struct func); i++) { + if (!strcmp(buf, func_list[i].name)) { + func_list[i].ptr(); + return; + } + } + cmd_unknown(); +} + +void cmd_help() { + for (uint32_t i = 0; i < sizeof(func_list) / sizeof(struct func); i++) { + uart_write_string(func_list[i].name); + for (uint32_t j = 0; j < (10 - strlen(func_list[i].name)); j++) uart_write(' '); + uart_write_string(": "); + uart_write_string(func_list[i].desc); + uart_write_string(ENDL); + } +} + +void cmd_hello() { + uart_write_string("Hello World!" ENDL); +} + + + +void cmd_sysinfo() { + uint32_t *board_revision; + uint32_t *board_serial_msb, *board_serial_lsb; + uint32_t *mem_base, *mem_size; + const int padding = 20; + + // Board Revision + get_board_revision(board_revision); + uart_write_string("Board Revision : 0x"); + uart_puth(*board_revision); + uart_write_string(ENDL); + + + // Memory Info + get_memory_info(mem_base, mem_size); + uart_write_string("Memroy Base Address : 0x"); + uart_puth(*mem_base); + uart_write_string(ENDL); + + uart_write_string("Memory Size : 0x"); + uart_puth(*mem_size); + uart_write_string(ENDL); +} + +void cmd_reboot() { + uart_write_string("Rebooting...."ENDL); + reset(10); +} + +void cmd_unknown() { + uart_write_string("Unknown command: "); + uart_write_string(buf); + uart_write_string(ENDL); +} + +void shell() { + welcome_msg(); + do { + read_cmd(); + + uart_write_string("# "); + uart_write_string(buf); + uart_write_string(ENDL); + + exec_cmd(); + } while (1); +} \ No newline at end of file diff --git a/lab1/lib/uart.c b/lab1/lib/uart.c new file mode 100644 index 000000000..490fc53d9 --- /dev/null +++ b/lab1/lib/uart.c @@ -0,0 +1,102 @@ +#include "uart.h" + +#include "mmio.h" +// #include "stdint.h" + +void uart_init() { + uint32_t t; + + /* Init GPIO */ + // mini UART -> set ALT5 + // Configure GPFSELn register to change alternate function + t = mmio_read(GPFSEL1); + t &= ~(7 << 12); // clean gpio14 + t |= (2 << 12); // set alt5 ,decimal(2) = binary(101) + t &= ~(7 << 15); // clean gpio15 + t |= (2 << 15); // set alt5 ,2 = 101 + mmio_write(GPFSEL1, t); + + /* Configure pull up/down register to disable GPIO pull up/down */ + /* P.101 + The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on + the respective GPIO pins. These registers must be used in conjunction with the GPPUD + register to effect GPIO Pull-up/down changes. The following sequence of events is + required: + 1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither + to remove the current Pull-up/down) + 2. Wait 150 cycles – this provides the required set-up time for the control signal + 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to + modify – NOTE only the pads which receive a clock will be modified, all others will + retain their previous state. + 4. Wait 150 cycles – this provides the required hold time for the control signal + 5. Write to GPPUD to remove the control signal + 6. Write to GPPUDCLK0/1 to remove the clock + */ + mmio_write(GPPUD, 0); + delay(150); + mmio_write(GPPUDCLK0, (1 << 14) | (1 << 15)); + delay(150); + mmio_write(GPPUDCLK0, 0); + + /* Init mini UART */ + // 0. The MMIO area base address is 0x3F000000 on raspi3 + // 1. Set AUXENB register to enable mini UART. Then mini UART register can be accessed. + t = mmio_read(AUX_ENABLES); + mmio_write(AUX_ENABLES, t | 1); + + // 2. Set AUX_MU_CNTL_REG to 0. Disable transmitter and receiver during configuration. + mmio_write(AUX_MU_CNTL_REG, 0); + + // 3. Set AUX_MU_IER_REG to 0. Disable interrupt because currently you don’t need interrupt. + mmio_write(AUX_MU_IER_REG, 0); + + // 4. Set AUX_MU_LCR_REG to 3. Set the data size to 8 bit. + mmio_write(AUX_MU_LCR_REG, 3); + + // 5. Set AUX_MU_MCR_REG to 0. Don’t need auto flow control. + mmio_write(AUX_MU_MCR_REG, 0); + + // 6. Set AUX_MU_BAUD to 270. Set baud rate to 115200 + mmio_write(AUX_MU_BAUD_REG, 270); + + // 7. Set AUX_MU_IIR_REG to 6. No FIFO. + mmio_write(AUX_MU_IIR_REG, 6); + + // 8. Set AUX_MU_CNTL_REG to 3. Enable the transmitter and receiver. + mmio_write(AUX_MU_CNTL_REG, 3); + + // clear rx data + //uart_flush(); +} + +void uart_write(char c) { + while (!(mmio_read(AUX_MU_LSR_REG) & (1 << 5))) delay(1); + mmio_write(AUX_MU_IO_REG, c); +} + +char uart_read() { + while (!(mmio_read(AUX_MU_LSR_REG) & 1)) delay(1); + return (mmio_read(AUX_MU_IO_REG) & 0xff); +} + +void uart_flush() { + while (mmio_read(AUX_MU_LSR_REG) & 1) mmio_read(AUX_MU_IO_REG); +} + +void uart_write_string(char* str) { + for (uint32_t i = 0; str[i] != '\0'; i++) { + uart_write((char)str[i]); + } +} + +void uart_puth(uint32_t d) { + uint32_t c; + + for (int i = 28; i >= 0; i -= 4) { + /* Highest 4 bits */ + c = (d >> i) & 0xF; + /* Translate to hex */ + c = (c > 9) ? (0x37 + c) : (0x30 + c); + uart_write(c); + } +} \ No newline at end of file diff --git a/lab1/linker.ld b/lab1/linker.ld new file mode 100644 index 000000000..f51a65fe3 --- /dev/null +++ b/lab1/linker.ld @@ -0,0 +1,48 @@ +/* entry point */ +ENTRY(_start) + +SECTIONS +{ + /* start at LOADER_ADDR */ + . = 0x80000; + + __start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + . = ALIGN(4096); /* align to page size */ + __text_end = .; + + . = ALIGN(4096); /* align to page size */ + .rodata : + { + *(.rodata) + } + __rodata_end = .; + + __data_start = .; + .data : + { + *(.data) + } + . = ALIGN(4096); /* align to page size */ + __data_end = .; + + __bss_start = .; + .bss : + { + bss = .; + *(.bss) + } + . = ALIGN(4096); /* align to page size */ + __bss_end = .; + __bss_size = __bss_end - __bss_start; + + . = 0x200000; + _estack = .; + + __end = .; +} \ No newline at end of file diff --git a/lab1/main.c b/lab1/main.c new file mode 100644 index 000000000..1ae5aede3 --- /dev/null +++ b/lab1/main.c @@ -0,0 +1,9 @@ +// #include "shell.h" +#include "stdint.h" +// #include "uart.h" + +void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) { + // initialize UART for Raspi2 + uart_init(); + shell(); +} \ No newline at end of file diff --git a/lab1/main.o b/lab1/main.o new file mode 100644 index 000000000..6395c8c5a Binary files /dev/null and b/lab1/main.o differ diff --git a/lab2/.gitignore b/lab2/.gitignore new file mode 100644 index 000000000..d0238014a --- /dev/null +++ b/lab2/.gitignore @@ -0,0 +1,5 @@ +.vscode +gen.py +build/ +kernel8.img +kernel8.elf \ No newline at end of file diff --git a/lab2/1.cpp b/lab2/1.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/lab2/Makefile b/lab2/Makefile new file mode 100644 index 000000000..3fe0d0de7 --- /dev/null +++ b/lab2/Makefile @@ -0,0 +1,141 @@ +BUILD_DIR = ./build +# Lib +LIB_SRC_DIR = ./lib + +# LIB_SRC = \ +# $(LIB_SRC_DIR)/mbox.c \ +# $(LIB_SRC_DIR)/mmio.c \ +# $(LIB_SRC_DIR)/shell.c \ +# $(LIB_SRC_DIR)/string.c \ +# $(LIB_SRC_DIR)/uart.c \ +# $(LIB_SRC_DIR)/utils.c \ + +LIB_SRC = \ + $(LIB_SRC_DIR)/mmio.c \ + $(LIB_SRC_DIR)/mbox.c \ + $(LIB_SRC_DIR)/shell.c \ + $(LIB_SRC_DIR)/uart.c \ + +LIB_INCLUDES = \ + -I $(LIB_SRC_DIR)/include \ + +LIB_BUILD_DIR = $(BUILD_DIR)/lib +LIB_OBJS := $(patsubst %.c,$(LIB_BUILD_DIR)/%.o,$(notdir $(LIB_SRC))) + +# Application +APP_SRC_DIR = . + +APP_SRC = \ + $(APP_SRC_DIR)/main.c \ + +APP_ASM = \ + $(APP_SRC_DIR)/boot.S \ + +APP_INCLUDES = \ + -I ./ \ + $(LIB_INCLUDES) \ + +APP_BUILD_DIR = $(BUILD_DIR)/app +APP_OBJS := $(patsubst %.c,$(APP_BUILD_DIR)/%.o,$(notdir $(APP_SRC))) +APP_OBJS += $(patsubst %.S,$(APP_BUILD_DIR)/%.o,$(notdir $(APP_ASM))) + +VPATH += \ + $(LIB_SRC_DIR) \ + $(APP_SRC_DIR) \ + +# ARM toolchain +CROSS = aarch64-linux-gnu +CC = $(CROSS)-gcc +AS = $(CROSS)-as +LD = $(CROSS)-ld +OC = $(CROSS)-objcopy +OD = $(CROSS)-objdump +SP = $(CROSS)-strip + +# Project +OUT_OBJS = \ + $(LIB_OBJS) \ + $(APP_OBJS) \ + +BUILD_DIRECTORIES = \ + $(LIB_BUILD_DIR) \ + $(APP_BUILD_DIR) \ + +PROJ = kernel8 +OUT_ELF = ./$(PROJ).elf +OUT_IMG = ./$(PROJ).img +LINKER_FILE = linker.ld + +CCFLAGS = -Wall -O0 -fno-stack-protector +LDFLAGS = -T$(LINKER_FILE) -nostdlib + +.PHONY: clean directories out_elf run docker_cp +all: directories $(OUT_OBJS) $(OUT_ELF) $(OUT_IMG) +directories: $(BUILD_DIRECTORIES) +out_elf: directories $(OUT_ELF) +out_img: directories $(OUT_IMG) + +# Compile Object Files --------------------------------------------------------- +$(APP_BUILD_DIR)/%.o : %.c + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + @echo "[+] Building: $<" + $(CC) $(CCFLAGS) $(APP_INCLUDES) -g -o $@ -c $< + @echo "[+] Finished Building: $<" + @echo '' + +$(APP_BUILD_DIR)/%.o : %.S + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + @echo "[+] Building: $<" + $(CC) $(ASMFLAGS) $(APP_INCLUDES) -g -o $@ -c $< + @echo "[+] Finished Building: $<" + @echo '' + +$(LIB_BUILD_DIR)/%.o : %.c + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + @echo "[+] Building: $<" + $(CC) $(CCFLAGS) $(LIB_INCLUDES) -g -o $@ -c $< + @echo "[+] Finished Building: $<" + @echo '' + +# Generate ELF ----------------------------------------------------------------- +$(OUT_ELF): $(OUT_OBJS) + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + $(LD) $(LDFLAGS) -o $@ $(OUT_OBJS) + $(OD) -d $@ > $(BUILD_DIR)/$(PROJ).objdump + # $(SP) $@ + @echo '[+] Finished building target: $@' + @echo ' ' + +# Generate IMG ----------------------------------------------------------------- +$(OUT_IMG): $(OUT_ELF) + @echo '============================================================' + @echo ' Building target: $@' + @echo '============================================================' + $(OC) -O binary $(OUT_ELF) $@ + @echo '[+] Finished building target: $@' + @echo ' ' + +$(BUILD_DIRECTORIES): + mkdir -p $@ + +run: + qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -serial null -serial stdio + +debug: + qemu-system-aarch64 -M raspi3b -kernel kernel8.img -display none -serial null -serial stdio -s -S + +docker_cp: + docker cp kernel8.elf my_kali:/ + +clean: + rm -rf *.elf + rm -rf *.img + rm -rf $(BUILD_DIR) \ No newline at end of file diff --git a/lab2/boot.S b/lab2/boot.S new file mode 100644 index 000000000..633875f8a --- /dev/null +++ b/lab2/boot.S @@ -0,0 +1,30 @@ +.section ".text.boot" + +.global _start + +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, 2f + // 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 + mov sp, x1 + + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size +3: cbz w2, 4f + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, 3b + + // jump to C code, should not return +4: bl kernel_main + // for failsafe, halt this core too + b 1b \ No newline at end of file diff --git a/lab2/boot.o b/lab2/boot.o new file mode 100644 index 000000000..605353a83 Binary files /dev/null and b/lab2/boot.o differ diff --git a/lab2/bootloader/boot.S b/lab2/bootloader/boot.S new file mode 100644 index 000000000..dc2aef711 --- /dev/null +++ b/lab2/bootloader/boot.S @@ -0,0 +1,58 @@ +.section ".text.boot" + +.global _start + +// x0 register stores address to dtb +_start: + // Load the current location into register x20 (address of the current instruction) + adr x20, . + + // Load the size of the bootloader (_bl_size) into register x21 + ldr x21, =_bl_size + + // Calculate the end address of the bootloader by adding _bl_size to the current location + add x21, x21, x20 + + // Load the start address of the text section (_text_start) into register x22 + ldr x22, =_text_start + + // Copy the value of _text_start into register x19 for later use (initializing the stack pointer) + mov x19, x22 + + // Relocate the bootloader itself from 0x80000 to 0x60000. + // This loop copies the instructions of the bootloader from the current location (0x80000) to the new location (0x60000) +1: + cmp x20, x21 // Compare the current location (x20) with the end address of the bootloader (x21) + b.eq 2f // If they are equal, jump to label 2f (end of relocation) + ldr x23, [x20] // Load a 64-bit word from the current location (instruction of the bootloader) + str x23, [x22] // Store the loaded word to the new location (relocate the instruction) + add x20, x20, #8 // Move to the next instruction (increment by 8 bytes) + add x22, x22, #8 // Move to the next location to store the instruction + b 1b // Branch back to label 1 (continue relocation) + +2: + // Jump to the ".text._bl" section after relocation + ldr x1, =_bl_start // Load the address of the start of the bootloader section + br x1 // Branch to the start of the bootloader code + +.section ".text._bl" + // Initialize stack pointer (sp) to the start address of the text section + mov sp, x19 // Load the value of x19 (start address of text section) into the stack pointer (sp) + + // Clear the BSS section + ldr x20, =_bss_start // Load the start address of the BSS section + ldr x21, =_bss_size // Load the size of the BSS section + add x21, x21, x20 // Calculate the end address of the BSS section +3: + cmp x20, x21 // Compare the current location with the end address of the BSS section + b.eq 4f // If equal, exit loop + str xzr, [x20] // Store zero to the current location (clearing BSS) + add x20, x20, #8 // Move to the next location in the BSS section + b 3b // Branch back to label 3 (continue clearing BSS) + +4: + // Jump to the bootloader main function + bl bootloader_main // Call the bootloader main function +5: + // Failsafe loop to halt the core in case the main function returns + b 5b // Branch back to label 5 (infinite loop) diff --git a/lab2/bootloader/linker.ld b/lab2/bootloader/linker.ld new file mode 100644 index 000000000..9249f78da --- /dev/null +++ b/lab2/bootloader/linker.ld @@ -0,0 +1,47 @@ +/* entry point */ +ENTRY(_start) + +SECTIONS +{ + /* Move boot.S itslef from 0x80000 to 0x60000 */ + . = 0x60000; + + _text_start = .; + .text : + { + KEEP(*(.text.boot)) + _bl_start = .; + *(.text._bl) + *(.text) + } + . = ALIGN(0x1000); /* align to page size */ + _text_end = .; + + _data_start = .; + .data : + { + *(.data) + } + . = ALIGN(0x1000); /* align to page size */ + _data_end = .; + + _bss_start = .; + .bss : + { + bss = .; + *(.bss) + } + . = ALIGN(0x1000); /* align to page size */ + _bss_end = .; + _bss_size = _bss_end - _bss_start; + + . = 0x70000; + _stack_start = .; + + . = 0x80000; + _kernel_start = .; + + // Calculate the size of the bootloader by subtracting the start of the text section (_text_start) from the end of the BSS section (_bss_end). + // The bootloader includes the text, data, and BSS sections, hence the calculation. + _bl_size = _bss_end - _text_start; /* size of bootloader */ +}w \ No newline at end of file diff --git a/lab2/lib/include/aux.h b/lab2/lib/include/aux.h new file mode 100644 index 000000000..7fca3f1ec --- /dev/null +++ b/lab2/lib/include/aux.h @@ -0,0 +1,33 @@ +#ifndef __AUX_H__ +#define __AUX_H__ + +#include "mmio.h" +/* Ref: https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf + * Page: 8 +*/ +#define AUX_BASE (MMIO_BASE + 0x00215000) +#define AUX_IRQ (AUX_BASE + 0x0) +#define AUX_ENABLES (AUX_BASE + 0x4) +#define AUX_MU_IO_REG (AUX_BASE + 0x40) +#define AUX_MU_IER_REG (AUX_BASE + 0x44) +#define AUX_MU_IIR_REG (AUX_BASE + 0x48) +#define AUX_MU_LCR_REG (AUX_BASE + 0x4c) +#define AUX_MU_MCR_REG (AUX_BASE + 0x50) +#define AUX_MU_LSR_REG (AUX_BASE + 0x54) +#define AUX_MU_MSR_REG (AUX_BASE + 0x58) +#define AUX_MU_SCRATCH (AUX_BASE + 0x5c) +#define AUX_MU_CNTL_REG (AUX_BASE + 0x60) +#define AUX_MU_STAT_REG (AUX_BASE + 0x64) +#define AUX_MU_BAUD_REG (AUX_BASE + 0x68) +#define AUX_SPI0_CNTL0_REG (AUX_BASE + 0x80) +#define AUX_SPI0_CNTL1_REG (AUX_BASE + 0x84) +#define AUX_SPI0_STAT_REG (AUX_BASE + 0x88) +#define AUX_SPI0_IO_REG (AUX_BASE + 0x90) +#define AUX_SPI0_PEEK_REG (AUX_BASE + 0x94) +#define AUX_SPI1_CNTL0_REG (AUX_BASE + 0xc0) +#define AUX_SPI1_CNTL1_REG (AUX_BASE + 0xc4) +#define AUX_SPI1_STAT_REG (AUX_BASE + 0xc8) +#define AUX_SPI1_IO_REG (AUX_BASE + 0xd0) +#define AUX_SPI1_PEEK_REG (AUX_BASE + 0xd4) + +#endif \ No newline at end of file diff --git a/lab2/lib/include/gpio.h b/lab2/lib/include/gpio.h new file mode 100644 index 000000000..b4322f8db --- /dev/null +++ b/lab2/lib/include/gpio.h @@ -0,0 +1,35 @@ +#ifndef __GPIO_H__ +#define __GPIO_H__ + +#define GPIO_BASE 0x3f200000 +#define GPFSEL0 (GPIO_BASE + 0x0) +#define GPFSEL1 (GPIO_BASE + 0x4) +#define GPFSEL2 (GPIO_BASE + 0x8) +#define GPFSEL3 (GPIO_BASE + 0xc) +#define GPFSEL4 (GPIO_BASE + 0x10) +#define GPFSEL5 (GPIO_BASE + 0x14) +#define GPSET0 (GPIO_BASE + 0x1c) +#define GPSET1 (GPIO_BASE + 0x20) +#define GPCLR0 (GPIO_BASE + 0x28) +#define GPCLR1 (GPIO_BASE + 0x2c) +#define GPLEV0 (GPIO_BASE + 0x34) +#define GPLEV1 (GPIO_BASE + 0x38) +#define GPEDS0 (GPIO_BASE + 0x40) +#define GPEDS1 (GPIO_BASE + 0x44) +#define GPREN0 (GPIO_BASE + 0x4c) +#define GPREN1 (GPIO_BASE + 0x50) +#define GPFEN0 (GPIO_BASE + 0x58) +#define GPFEN1 (GPIO_BASE + 0x5c) +#define GPHEN0 (GPIO_BASE + 0x64) +#define GPHEN1 (GPIO_BASE + 0x68) +#define GPLEN0 (GPIO_BASE + 0x70) +#define GPLEN1 (GPIO_BASE + 0x74) +#define GPAREN0 (GPIO_BASE + 0x7c) +#define GPAREN1 (GPIO_BASE + 0x80) +#define GPAFEN0 (GPIO_BASE + 0x88) +#define GPAFEN1 (GPIO_BASE + 0x8c) +#define GPPUD (GPIO_BASE + 0x94) +#define GPPUDCLK0 (GPIO_BASE + 0x98) +#define GPPUDCLK1 (GPIO_BASE + 0x9c) + +#endif \ No newline at end of file diff --git a/lab2/lib/include/mbox.h b/lab2/lib/include/mbox.h new file mode 100644 index 000000000..8dc9ed9fc --- /dev/null +++ b/lab2/lib/include/mbox.h @@ -0,0 +1,111 @@ +#ifndef __MBOX_H__ +#define __MBOX_H__ + +#include "mmio.h" + +#define VIDEOCORE_MBOX_BASE (MMIO_BASE + 0x0000B880) +#define MBOX_READ (VIDEOCORE_MBOX_BASE + 0x00) +#define MBOX_POLL (VIDEOCORE_MBOX_BASE + 0x10) +#define MBOX_SENDER (VIDEOCORE_MBOX_BASE + 0x14) +#define MBOX_STATUS (VIDEOCORE_MBOX_BASE + 0x18) +#define MBOX_CONFIG (VIDEOCORE_MBOX_BASE + 0x1C) +#define MBOX_WRITE (VIDEOCORE_MBOX_BASE + 0x20) +#define MBOX_RESPONSE (0x80000000) +#define MBOX_FULL (0x80000000) +#define MBOX_EMPTY (0x40000000) + +#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) + +#define MAIL_BODY_BUF_LEN (4) +#define MAIL_BUF_SIZE (MAIL_BODY_BUF_LEN << 2) +#define MAIL_PACKET_SIZE (MAIL_BUF_SIZE + 24) + +#define REQUEST_CODE 0x00000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 +#define TAG_REQUEST_CODE 0x00000000 +#define END_TAG 0x00000000 + +/* Tags */ +#define GET_FIRMWARE_REVISION 0x00000001 +#define GET_BOARD_MODEL 0x00010001 +#define GET_BOARD_REVISION 0x00010002 +#define GET_BOARD_MAC_ADDR 0x00010003 +#define GET_BOARD_SERIAL 0x00010004 +#define GET_ARM_MEMORY 0x00010005 +#define GET_VC_MEMORY 0x00010006 +#define GET_CLOCKS 0x00010007 + +#define GET_COMMAND_LINE 0x00050001 + +#define GET_DMA_CHANNELS 0x00060001 + +#define GET_POWER_STATE 0x00020001 +#define GET_TIMING 0x00020002 +#define SET_POWER_STATE 0x00028001 + +// and so on... + +/* Unique Device ID */ +#define DEVICE_ID_SD_CARD 0x00000000 +#define DEVICE_ID_UART0 0x00000001 +#define DEVICE_ID_UART1 0x00000002 +#define DEVICE_ID_USB_HCD 0x00000003 +#define DEVICE_ID_I2C0 0x00000004 +#define DEVICE_ID_I2C1 0x00000005 +#define DEVICE_ID_I2C2 0x00000006 +#define DEVICE_ID_SPI 0x00000007 +#define DEVICE_ID_CCP2TX 0x00000008 +#define DEVICE_ID_UNKNOWN 0x00000009 +#define DEVICE_ID_UNKNOWN 0x0000000a + +/* Unique Clock ID */ +#define CLOCK_ID_RESERVED 0x000000000 +#define CLOCK_ID_EMMC 0x000000001 +#define CLOCK_ID_UART 0x000000002 +#define CLOCK_ID_ARM 0x000000003 +#define CLOCK_ID_CORE 0x000000004 +#define CLOCK_ID_V3D 0x000000005 +#define CLOCK_ID_H264 0x000000006 +#define CLOCK_ID_ISP 0x000000007 +#define CLOCK_ID_SDRAM 0x000000008 +#define CLOCK_ID_PIXEL 0x000000009 +#define CLOCK_ID_PWM 0x00000000a +#define CLOCK_ID_HEVC 0x00000000b +#define CLOCK_ID_EMMC2 0x00000000c +#define CLOCK_ID_M2MC 0x00000000d +#define CLOCK_ID_PIXEL_BVB 0x00000000e + +struct mail_header { + uint32_t packet_size; + uint32_t code; +}; + +struct mail_body { + uint32_t id; + uint32_t buf_size; + uint32_t code; + uint32_t buf[MAIL_BODY_BUF_LEN]; + uint32_t end; +}; + +typedef struct mail_t { + struct mail_header header; + struct mail_body body; +} mail_t __attribute__((aligned(16))); + +int mbox_call(mail_t* mbox, uint8_t ch); +void get_board_revision(uint32_t* board_revision); +void get_memory_info(uint32_t* mem_base, uint32_t* mem_size); +void get_board_serial(uint32_t* msb, uint32_t* lsb); + + +#endif \ No newline at end of file diff --git a/lab2/lib/include/mmio.h b/lab2/lib/include/mmio.h new file mode 100644 index 000000000..efbccf3c9 --- /dev/null +++ b/lab2/lib/include/mmio.h @@ -0,0 +1,14 @@ +#ifndef __MMIO_H__ +#define __MMIO_H__ +// #include +#include "stdint.h" + +#define PHY_BASE 0x3F000000 +#define BUS_BASE 0x7f000000 + +#define MMIO_BASE PHY_BASE + +void mmio_write(uint32_t reg, uint32_t data); // MMIO write +uint32_t mmio_read(uint32_t reg); // MMIO read + +#endif \ No newline at end of file diff --git a/lab2/lib/include/reset.h b/lab2/lib/include/reset.h new file mode 100644 index 000000000..b12aa1945 --- /dev/null +++ b/lab2/lib/include/reset.h @@ -0,0 +1,19 @@ +#ifndef __RESET_H__ +#define __RESET_H__ + +#include "mmio.h" +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 + +void reset(int tick) { // reboot after watchdog timer expire + mmio_write(PM_RSTC, PM_PASSWORD | 0x20); // full reset + mmio_write(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick +} + +void cancel_reset() { + mmio_write(PM_RSTC, PM_PASSWORD | 0); // full reset + mmio_write(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} + +#endif \ No newline at end of file diff --git a/lab2/lib/include/shell.h b/lab2/lib/include/shell.h new file mode 100644 index 000000000..88ae05f88 --- /dev/null +++ b/lab2/lib/include/shell.h @@ -0,0 +1,32 @@ +#ifndef __SHELL_H__ +#define __SHELL_H__ +#include "mbox.h" +#include "stdint.h" +#include "reset.h" +#include "string.h" +// #include "uart.h" + +struct func { + char *name; + void (*ptr)(); + char *desc; +}; + +void welcome_msg(); +void shell(); +void read_cmd(); +void exec_cmd(); + +void cmd_help(); +void cmd_hello(); +void cmd_reboot(); +void cmd_sysinfo(); +void cmd_unknown(); + +struct func func_list[] = { + {.name = "help", .ptr = cmd_help, .desc = "print this help menu"}, + {.name = "hello", .ptr = cmd_hello, .desc = "print Hello World!"}, + {.name = "reboot", .ptr = cmd_reboot, .desc = "reboot the device"}, + {.name = "sysinfo", .ptr = cmd_sysinfo, .desc = "get system info"}}; + +#endif \ No newline at end of file diff --git a/lab2/lib/include/stdint.h b/lab2/lib/include/stdint.h new file mode 100644 index 000000000..4b76cee21 --- /dev/null +++ b/lab2/lib/include/stdint.h @@ -0,0 +1,13 @@ +#ifndef __STDINT_H__ +#define __STDINT_H__ + +#define int8_t signed char +#define int16_t signed short int +#define int32_t signed int +#define int64_t signed long int +#define uint8_t unsigned char +#define uint16_t unsigned short int +#define uint32_t unsigned int +#define uint64_t unsigned long int + +#endif \ No newline at end of file diff --git a/lab2/lib/include/string.h b/lab2/lib/include/string.h new file mode 100644 index 000000000..fde569986 --- /dev/null +++ b/lab2/lib/include/string.h @@ -0,0 +1,20 @@ +#ifndef __STRING_H__ +#define __STRING_H__ + +#include "stdint.h" + +#define ENDL "\r\n" + +int strcmp(const char *a, const char *b) { + uint32_t i = 0; + while (a[i] == b[i] && a[i] != '\0' && b[i] != '\0') i++; + return a[i] - b[i]; +} + +uint32_t strlen(const char *a) { + for (uint32_t i = 0;; i++) + if (a[i] == '\0') return i; + return 0; +} + +#endif \ No newline at end of file diff --git a/lab2/lib/include/uart.h b/lab2/lib/include/uart.h new file mode 100644 index 000000000..a5e3b59c0 --- /dev/null +++ b/lab2/lib/include/uart.h @@ -0,0 +1,19 @@ +#ifndef __UART_H__ +#define __UART_H__ + +#include "aux.h" +#include "gpio.h" +#include "mmio.h" + +void uart_init(); +void uart_write(char c); +char uart_read(); +void uart_flush(); +void uart_write_string(char* str); +void uart_puth(uint32_t d); +void delay(uint32_t t) { + for (uint32_t i = 0; i < t; i++) + asm volatile("nop"); +} + +#endif \ No newline at end of file diff --git a/lab2/lib/mbox.c b/lab2/lib/mbox.c new file mode 100644 index 000000000..0b63e94db --- /dev/null +++ b/lab2/lib/mbox.c @@ -0,0 +1,98 @@ +#include "mbox.h" + +int mbox_call(mail_t* mbox, uint8_t ch) { + uint32_t addr_channel; + + // 1. Combine the message address (upper 28 bits) with channel number (lower 4 bits) + addr_channel = (((uint32_t)(uint64_t)mbox) & 0xFFFFFFF0) | (ch & 0xF); + + // 2. Read the status register until the empty flag is not set, then break while + while (mmio_read(MBOX_STATUS) & MBOX_FULL) asm volatile("nop"); + + // 3. If not, then you can write to Mailbox 1 Read/Write register. + mmio_write(MBOX_WRITE, addr_channel); + + // 4. Check if Mailbox 0 status register’s empty flag is set. + // 5. Read from Mailbox 0 Read/Write register. + do { + while (mmio_read(MBOX_STATUS) & MBOX_EMPTY) asm volatile("nop"); + } while (mmio_read(MBOX_READ) != addr_channel); + + + // 6. And check if the value is the same as you wrote in step 1. + // 0x80000000: request successfu + return mbox->header.code == MBOX_RESPONSE; +} + +void get_board_revision(uint32_t* board_revision) { + // Create a mailbox structure and initialize its fields + mail_t mbox = { + .header.packet_size = MAIL_PACKET_SIZE, // Set the packet size in the header + .header.code = REQUEST_CODE, // Set the code in the header to indicate a request + .body.id = GET_BOARD_REVISION, // Set the ID of the body to get board revision + .body.buf_size = MAIL_BUF_SIZE, // Set the size of the buffer in the body + .body.code = TAG_REQUEST_CODE, // Set the code in the body to indicate a tag request + .body.end = END_TAG, // Set the end tag in the body + }; + + // Initialize the buffer in the body to 0 + for (uint32_t i = 0; i < MAIL_BODY_BUF_LEN; i++) { + mbox.body.buf[i] = 0; + } + + // Call the mailbox function to send the request and receive the response + // MBOX_CH_PROP means chennel 8 + mbox_call(&mbox, MBOX_CH_PROP); + + // Extract the board revision information from the response buffer and assign it to board_revision + *board_revision = mbox.body.buf[0]; +} + + +// Get ARM memory Response:Length: 8 +void get_memory_info(uint32_t* mem_base, uint32_t* mem_size) { + mail_t mbox = { + .header.packet_size = MAIL_PACKET_SIZE, + .header.code = REQUEST_CODE, + .body.id = GET_ARM_MEMORY, + .body.buf_size = MAIL_BUF_SIZE, + .body.code = TAG_REQUEST_CODE, + .body.end = END_TAG, + }; + + for (uint32_t i = 0; i < MAIL_BODY_BUF_LEN; i++) mbox.body.buf[i] = 0; + + if (mbox_call(&mbox, MBOX_CH_PROP)) { + *mem_base = mbox.body.buf[0]; // u32: base address in bytes + *mem_size = mbox.body.buf[1]; // u32: size in bytes + + } else { + *mem_size = 0xFFFFFFFF; + *mem_base = 0xFFFFFFFF; + } +} + + +// Get board serial : Response:Length: 8 u64: board serial +void get_board_serial(uint32_t* msb, uint32_t* lsb) { + mail_t mbox = { + .header.packet_size = MAIL_PACKET_SIZE, + .header.code = REQUEST_CODE, + .body.id = GET_BOARD_SERIAL, + .body.buf_size = MAIL_BUF_SIZE, + .body.code = TAG_REQUEST_CODE, + .body.end = END_TAG, + }; + + for (uint32_t i = 0; i < MAIL_BODY_BUF_LEN; i++) mbox.body.buf[i] = 0; + + if (mbox_call(&mbox, MBOX_CH_PROP)) { + *msb = mbox.body.buf[1]; + *lsb = mbox.body.buf[0]; + } else { + *msb = 0xFFFFFFFF; + *lsb = 0xFFFFFFFF; + } +} + + diff --git a/lab2/lib/mmio.c b/lab2/lib/mmio.c new file mode 100644 index 000000000..ef9ba0d36 --- /dev/null +++ b/lab2/lib/mmio.c @@ -0,0 +1,11 @@ +#include "mmio.h" + +#include "stdint.h" + +void mmio_write(uint32_t reg, uint32_t data) { + *(volatile uint32_t*)(reg) = data; +} + +uint32_t mmio_read(uint32_t reg) { + return *(volatile uint32_t*)(reg); +} diff --git a/lab2/lib/shell.c b/lab2/lib/shell.c new file mode 100644 index 000000000..236954b22 --- /dev/null +++ b/lab2/lib/shell.c @@ -0,0 +1,113 @@ +#include "shell.h" + +char buf[0x100]; + +void welcome_msg() { + uart_write_string( + ENDL + " ____ _____ _____ ___ ___ ___ _ _" ENDL + " / __ \\ / ____| / ____| |__ \\ / _ \\ |__ \\ | || |" ENDL + " | | | || (___ | | ) || | | | ) || || |_" ENDL + " | | | | \\___ \\ | | / / | | | | / / |__ _|" ENDL + " | |__| | ____) || |____ / /_ | |_| | / /_ | | "ENDL + " \\____/ |_____/ \\_____| |____| \\___/ |____| |_|" ENDL); +} + +void read_cmd() { + char tmp; + uart_write_string("# "); + for (uint32_t i = 0; tmp = uart_read();) { + uart_write(tmp); + switch (tmp) { + case '\r': + case '\n': + buf[i++] = '\0'; + return; + case 127: // Backspace + if (i > 0) { + i--; + buf[i] = '\0'; + uart_write_string("\b \b"); + } + break; + default: + buf[i++] = tmp; + break; + } + } +} + +void exec_cmd() { + if (!strlen(buf)) return; + for (uint32_t i = 0; i < sizeof(func_list) / sizeof(struct func); i++) { + if (!strcmp(buf, func_list[i].name)) { + func_list[i].ptr(); + return; + } + } + cmd_unknown(); +} + +void cmd_help() { + for (uint32_t i = 0; i < sizeof(func_list) / sizeof(struct func); i++) { + uart_write_string(func_list[i].name); + for (uint32_t j = 0; j < (10 - strlen(func_list[i].name)); j++) uart_write(' '); + uart_write_string(": "); + uart_write_string(func_list[i].desc); + uart_write_string(ENDL); + } +} + +void cmd_hello() { + uart_write_string("Hello World!" ENDL); +} + + + +void cmd_sysinfo() { + uint32_t *board_revision; + uint32_t *board_serial_msb, *board_serial_lsb; + uint32_t *mem_base, *mem_size; + const int padding = 20; + + // Board Revision + get_board_revision(board_revision); + uart_write_string("Board Revision : 0x"); + uart_puth(*board_revision); + uart_write_string(ENDL); + + + // Memory Info + get_memory_info(mem_base, mem_size); + uart_write_string("Memroy Base Address : 0x"); + uart_puth(*mem_base); + uart_write_string(ENDL); + + uart_write_string("Memory Size : 0x"); + uart_puth(*mem_size); + uart_write_string(ENDL); +} + +void cmd_reboot() { + uart_write_string("Rebooting...."ENDL); + reset(10); +} + +void cmd_unknown() { + uart_write_string("Unknown command: "); + uart_write_string(buf); + uart_write_string(ENDL); +} + +void shell() { + welcome_msg(); + do { + read_cmd(); + + uart_write_string("# "); + uart_write_string(buf); + uart_write_string(ENDL); + + exec_cmd(); + } while (1); +} \ No newline at end of file diff --git a/lab2/lib/uart.c b/lab2/lib/uart.c new file mode 100644 index 000000000..490fc53d9 --- /dev/null +++ b/lab2/lib/uart.c @@ -0,0 +1,102 @@ +#include "uart.h" + +#include "mmio.h" +// #include "stdint.h" + +void uart_init() { + uint32_t t; + + /* Init GPIO */ + // mini UART -> set ALT5 + // Configure GPFSELn register to change alternate function + t = mmio_read(GPFSEL1); + t &= ~(7 << 12); // clean gpio14 + t |= (2 << 12); // set alt5 ,decimal(2) = binary(101) + t &= ~(7 << 15); // clean gpio15 + t |= (2 << 15); // set alt5 ,2 = 101 + mmio_write(GPFSEL1, t); + + /* Configure pull up/down register to disable GPIO pull up/down */ + /* P.101 + The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on + the respective GPIO pins. These registers must be used in conjunction with the GPPUD + register to effect GPIO Pull-up/down changes. The following sequence of events is + required: + 1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither + to remove the current Pull-up/down) + 2. Wait 150 cycles – this provides the required set-up time for the control signal + 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to + modify – NOTE only the pads which receive a clock will be modified, all others will + retain their previous state. + 4. Wait 150 cycles – this provides the required hold time for the control signal + 5. Write to GPPUD to remove the control signal + 6. Write to GPPUDCLK0/1 to remove the clock + */ + mmio_write(GPPUD, 0); + delay(150); + mmio_write(GPPUDCLK0, (1 << 14) | (1 << 15)); + delay(150); + mmio_write(GPPUDCLK0, 0); + + /* Init mini UART */ + // 0. The MMIO area base address is 0x3F000000 on raspi3 + // 1. Set AUXENB register to enable mini UART. Then mini UART register can be accessed. + t = mmio_read(AUX_ENABLES); + mmio_write(AUX_ENABLES, t | 1); + + // 2. Set AUX_MU_CNTL_REG to 0. Disable transmitter and receiver during configuration. + mmio_write(AUX_MU_CNTL_REG, 0); + + // 3. Set AUX_MU_IER_REG to 0. Disable interrupt because currently you don’t need interrupt. + mmio_write(AUX_MU_IER_REG, 0); + + // 4. Set AUX_MU_LCR_REG to 3. Set the data size to 8 bit. + mmio_write(AUX_MU_LCR_REG, 3); + + // 5. Set AUX_MU_MCR_REG to 0. Don’t need auto flow control. + mmio_write(AUX_MU_MCR_REG, 0); + + // 6. Set AUX_MU_BAUD to 270. Set baud rate to 115200 + mmio_write(AUX_MU_BAUD_REG, 270); + + // 7. Set AUX_MU_IIR_REG to 6. No FIFO. + mmio_write(AUX_MU_IIR_REG, 6); + + // 8. Set AUX_MU_CNTL_REG to 3. Enable the transmitter and receiver. + mmio_write(AUX_MU_CNTL_REG, 3); + + // clear rx data + //uart_flush(); +} + +void uart_write(char c) { + while (!(mmio_read(AUX_MU_LSR_REG) & (1 << 5))) delay(1); + mmio_write(AUX_MU_IO_REG, c); +} + +char uart_read() { + while (!(mmio_read(AUX_MU_LSR_REG) & 1)) delay(1); + return (mmio_read(AUX_MU_IO_REG) & 0xff); +} + +void uart_flush() { + while (mmio_read(AUX_MU_LSR_REG) & 1) mmio_read(AUX_MU_IO_REG); +} + +void uart_write_string(char* str) { + for (uint32_t i = 0; str[i] != '\0'; i++) { + uart_write((char)str[i]); + } +} + +void uart_puth(uint32_t d) { + uint32_t c; + + for (int i = 28; i >= 0; i -= 4) { + /* Highest 4 bits */ + c = (d >> i) & 0xF; + /* Translate to hex */ + c = (c > 9) ? (0x37 + c) : (0x30 + c); + uart_write(c); + } +} \ No newline at end of file diff --git a/lab2/linker.ld b/lab2/linker.ld new file mode 100644 index 000000000..f51a65fe3 --- /dev/null +++ b/lab2/linker.ld @@ -0,0 +1,48 @@ +/* entry point */ +ENTRY(_start) + +SECTIONS +{ + /* start at LOADER_ADDR */ + . = 0x80000; + + __start = .; + __text_start = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + } + . = ALIGN(4096); /* align to page size */ + __text_end = .; + + . = ALIGN(4096); /* align to page size */ + .rodata : + { + *(.rodata) + } + __rodata_end = .; + + __data_start = .; + .data : + { + *(.data) + } + . = ALIGN(4096); /* align to page size */ + __data_end = .; + + __bss_start = .; + .bss : + { + bss = .; + *(.bss) + } + . = ALIGN(4096); /* align to page size */ + __bss_end = .; + __bss_size = __bss_end - __bss_start; + + . = 0x200000; + _estack = .; + + __end = .; +} \ No newline at end of file diff --git a/lab2/main.c b/lab2/main.c new file mode 100644 index 000000000..86e14f4a4 --- /dev/null +++ b/lab2/main.c @@ -0,0 +1,10 @@ +// #include "shell.h" +#include "stdint.h" +// #include "uart.h" + +void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags) { + // initialize UART for Raspi2 + uart_init(); + + shell(); +} \ No newline at end of file diff --git a/lab2/main.o b/lab2/main.o new file mode 100644 index 000000000..6395c8c5a Binary files /dev/null and b/lab2/main.o differ