diff --git a/sw/Makefile b/sw/Makefile index d362cdb..ee3f485 100644 --- a/sw/Makefile +++ b/sw/Makefile @@ -1,14 +1,11 @@ -.PHONY: all install bios bootloader kernel clean +.PHONY: all install bootloader kernel clean -all: bios bootloader kernel +all: bootloader kernel install: all sh script/format_disk.sh sh script/copy_files.sh -bios: - @$(MAKE) -C bios - bootloader: @$(MAKE) -C bootloader @@ -17,6 +14,5 @@ kernel: clean: - @$(MAKE) -C bios --no-print-directory $@ @$(MAKE) -C bootloader --no-print-directory $@ @$(MAKE) -C kernel --no-print-directory $@ \ No newline at end of file diff --git a/sw/bios/Makefile b/sw/bios/Makefile deleted file mode 100644 index caa77c0..0000000 --- a/sw/bios/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -CC=cl65 -CFLAGS=-T -t none -I. --cpu "65C02" -test: CFLAGS=-T -t sim65c02 -I. -LDFLAGS=-C link.ld -m $(NAME).map -NAME=bios - -BIN=$(NAME).bin -HEX=$(NAME).hex - -LISTS=lists - -SRCS=$(wildcard *.s) $(wildcard *.c) -SRCS+=$(filter-out $(wildcard tests/*), $(wildcard **/*.s)) $(filter-out $(wildcard tests/*), $(wildcard **/*.c)) -OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) -OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) - -all: $(HEX) - -$(HEX): $(BIN) - objcopy --input-target=binary --output-target=ihex $(BIN) $(HEX) - - -$(BIN): $(OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ - -%.o: %.c $(LISTS) - $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ - -%.o: %.s $(LISTS) - $(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@ - -$(LISTS): - mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) - -.PHONY: clean -clean: - rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map - diff --git a/sw/bios/boot.s b/sw/bios/boot.s deleted file mode 100644 index 4a26770..0000000 --- a/sw/bios/boot.s +++ /dev/null @@ -1,14 +0,0 @@ -.include "zeropage.inc" - -.segment "STARTUP" - -.export _init -.import _load_bootsect - -_init: ldx #$ff - txs - cld - - jsr _load_bootsect - jmp $1000 - \ No newline at end of file diff --git a/sw/bios/devices/interrupt.s b/sw/bios/devices/interrupt.s deleted file mode 100644 index f555c1c..0000000 --- a/sw/bios/devices/interrupt.s +++ /dev/null @@ -1,55 +0,0 @@ -.include "io.inc65" - -.export _irq_int, _nmi_int - -.importzp sreg, ptr1 - -.segment "CODE" - -; IRQ -_irq_int: - jmp (irqmap,x) - -_nmi_int: - rti - -irqmap: - .addr handle_invalid - .addr handle_sd_read - -handle_invalid: - rti - -; sreg is the pointer to store the data -; a/y is the block address -; send command 17 with the block address of 00/y/a -handle_sd_read: - sta SD_ARG ; send command - sty SD_ARG+1 - stz SD_ARG+2 - stz SD_ARG+3 - lda #$11 - sta SD_CMD - -@1: lda SD_CMD ; wait for status flag - and #$01 - beq @1 - -@2: lda SD_CMD ; wait for data - and #$02 - beq @2 - - ldy #$00 -@loop: lda SD_DATA ; copy first 256 bytes - sta (sreg),y - iny - bne @loop - - ldy #$00 ; copy second 256 bytes - inc sreg+1 -@loop2: lda SD_DATA - sta (sreg),y - iny - bne @loop2 - - rti \ No newline at end of file diff --git a/sw/bios/devices/io.inc65 b/sw/bios/devices/io.inc65 deleted file mode 120000 index 14ef1f5..0000000 --- a/sw/bios/devices/io.inc65 +++ /dev/null @@ -1 +0,0 @@ -../../kernel/devices/io.inc65 \ No newline at end of file diff --git a/sw/bios/devices/sd_card.c b/sw/bios/devices/sd_card.c deleted file mode 120000 index c20d8c7..0000000 --- a/sw/bios/devices/sd_card.c +++ /dev/null @@ -1 +0,0 @@ -../../kernel/devices/sd_card.c \ No newline at end of file diff --git a/sw/bios/devices/sd_card.h b/sw/bios/devices/sd_card.h deleted file mode 120000 index 7955199..0000000 --- a/sw/bios/devices/sd_card.h +++ /dev/null @@ -1 +0,0 @@ -../../kernel/devices/sd_card.h \ No newline at end of file diff --git a/sw/bios/devices/sd_card_asm.s b/sw/bios/devices/sd_card_asm.s deleted file mode 120000 index a25313c..0000000 --- a/sw/bios/devices/sd_card_asm.s +++ /dev/null @@ -1 +0,0 @@ -../../kernel/devices/sd_card_asm.s \ No newline at end of file diff --git a/sw/bios/link.ld b/sw/bios/link.ld deleted file mode 100644 index 0fe59b7..0000000 --- a/sw/bios/link.ld +++ /dev/null @@ -1,19 +0,0 @@ -MEMORY -{ - ZP: start = $0, size = $100, type = rw, define = yes; - SDRAM: start = $1000, size = $6ef0, type = rw, define = yes; - ROM: start = $8000, size = $8000, fill = yes, fillval = $ff, file = %O; -} - -SEGMENTS { - ZEROPAGE: load = ZP, type = zp, define = yes; - DATA: load = ROM, type = rw, define = yes, run = SDRAM; - BSS: load = SDRAM, type = bss, define = yes; - HEAP: load = SDRAM, type = bss, optional = yes; - STARTUP: load = ROM, type = ro; - ONCE: load = ROM, type = ro, optional = yes; - CODE: load = ROM, type = ro; - RODATA: load = ROM, type = ro; - VECTORS: load = ROM, type = ro, start = $FFFA; -} - diff --git a/sw/bios/load_bootsect.c b/sw/bios/load_bootsect.c deleted file mode 100644 index 6fe0ba2..0000000 --- a/sw/bios/load_bootsect.c +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#include "devices/sd_card.h" - -#define BOOTSECTOR_LOAD_ADDRESS 0x1000 - -#define BOOTSIG_0 0x55 -#define BOOTSIG_1 0xaa - -//Should probably do this in asm -void load_bootsect() { - uint32_t rca; - uint8_t sig[2]; - - sd_init(); - rca = sd_get_rca(); - sd_select_card(rca); - - sd_readblock(0, (uint8_t*)BOOTSECTOR_LOAD_ADDRESS); - - sig[0] = ((uint8_t*)BOOTSECTOR_LOAD_ADDRESS)[510]; - sig[1] = ((uint8_t*)BOOTSECTOR_LOAD_ADDRESS)[511]; - - if (sig[0] != BOOTSIG_0 || sig[1] != BOOTSIG_1) { - for(;;); //maybe figure out a way to have an error message here - } - - return; -} \ No newline at end of file diff --git a/sw/bootloader/Makefile b/sw/bootloader/Makefile index 3e4a963..bd08961 100644 --- a/sw/bootloader/Makefile +++ b/sw/bootloader/Makefile @@ -7,18 +7,31 @@ SIMARGS=-v -c -x 1000000 NAME=bootloader +TEST_BIN=test.bin BIN=$(NAME).bin HEX=$(NAME).hex LISTS=lists +TESTS=tests SRCS=$(wildcard *.s) $(wildcard *.c) SRCS+=$(filter-out $(wildcard tests/*), $(wildcard **/*.s)) $(filter-out $(wildcard tests/*), $(wildcard **/*.c)) OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS))) OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS))) +TEST_SRCS=$(wildcard $(TESTS)/*.s) $(wildcard $(TESTS)/*.c) +TEST_OBJS+=$(patsubst %.s,%.o,$(filter %s,$(TEST_SRCS))) +TEST_OBJS+=$(patsubst %.c,%.o,$(filter %c,$(TEST_SRCS))) +TEST_OBJS+=$(filter-out boot.o,$(filter-out main.o,$(filter-out vectors.o,$(OBJS)))) + all: $(HEX) +test: $(TEST_BIN) + $(SIM) $(SIMARGS) $(TEST_BIN) + +$(TEST_BIN): $(OBJS) $(TEST_OBJS) + $(CC) $(CFLAGS) $(TEST_OBJS) -o $@ + $(HEX): $(BIN) objcopy --input-target=binary --output-target=ihex $(BIN) $(HEX) @@ -34,8 +47,10 @@ $(BIN): $(OBJS) $(LISTS): mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS)))) + mkdir $(LISTS)/$(sort $(dir $(TEST_SRCS))) .PHONY: clean clean: rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map + rm -rf $(TEST_OBJS) $(TEST_BIN) diff --git a/sw/bootloader/bios_calls b/sw/bootloader/bios_calls deleted file mode 100644 index e69de29..0000000 diff --git a/sw/bootloader/bios_calls.h b/sw/bootloader/bios_calls.h deleted file mode 100644 index 88ed750..0000000 --- a/sw/bootloader/bios_calls.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _BIOS_CALLS_H -#define _BIOS_CALLS_H - -#include - -void sd_readblock(uint16_t addr, void* buf); - -#endif \ No newline at end of file diff --git a/sw/bootloader/bios_calls.s b/sw/bootloader/bios_calls.s deleted file mode 100644 index a1964a3..0000000 --- a/sw/bootloader/bios_calls.s +++ /dev/null @@ -1,23 +0,0 @@ -.export _sd_readblock - -.autoimport - -.importzp sreg - -; sreg is the pointer to store the data -; a/y is the block address -; send command 17 with the block address of 00/y/a - -; void sd_readblock(uint16_t addr, void* buf); - -_sd_readblock: - sta sreg ; move buf pointer to sreg - stx sreg+1 - - jsr popax ; move addr to a/y - tya - - ldx #$1 ; call interrupt 1 - brk - - rts \ No newline at end of file diff --git a/sw/bootloader/boot.s b/sw/bootloader/boot.s index 47eaf07..00b87b1 100644 --- a/sw/bootloader/boot.s +++ b/sw/bootloader/boot.s @@ -1,26 +1,54 @@ -; We need to to read the boot sector from the -; SD card, verify the last 2 bytes, then jump to the -; beginning of it. +; --------------------------------------------------------------------------- +; crt0.s +; --------------------------------------------------------------------------- +; +; Startup code for cc65 (Single Board Computer version) -.include "zeropage.inc" +.export _init, _exit +.import _main -.import _load_bootsect +.export __STARTUP__ : absolute = 1 ; Mark as startup +.import __SDRAM_START__, __SDRAM_SIZE__ ; Linker generated -.export _init, _boot +.import copydata, zerobss, initlib, donelib -.segment "STARTUP" +.include "zeropage.inc" -_init: jmp _boot +; --------------------------------------------------------------------------- +; Place the startup code in a special segment -.segment "CODE" +.segment "STARTUP" -_boot: ldx #$ff - txs - cld +; --------------------------------------------------------------------------- +; A little light 6502 housekeeping - jsr _load_bootsect - jmp $1000 +_init: LDX #$FF ; Initialize stack pointer to $01FF + TXS + CLD ; Clear decimal mode -.segment "SIGN" -.byte $55 -.byte $aa +; --------------------------------------------------------------------------- +; Set cc65 argument stack pointer + + LDA #<(__SDRAM_START__ + __SDRAM_SIZE__) + STA sp + LDA #>(__SDRAM_START__ + __SDRAM_SIZE__) + STA sp+1 + +; --------------------------------------------------------------------------- +; Initialize memory storage + + JSR zerobss ; Clear BSS segment + JSR copydata ; Initialize DATA segment + JSR initlib ; Run constructors + +; --------------------------------------------------------------------------- +; Call main() + cli + JSR _main + jmp ($fffc) + +; --------------------------------------------------------------------------- +; Back from main (this is also the _exit entry): force a software break + +_exit: JSR donelib ; Run destructors + BRK diff --git a/sw/bootloader/devices/board_io.h b/sw/bootloader/devices/board_io.h new file mode 100644 index 0000000..c55c7a5 --- /dev/null +++ b/sw/bootloader/devices/board_io.h @@ -0,0 +1,16 @@ +#ifndef _BOARD_IO_H +#define _BOARD_IO_H + +#include + +uint8_t hex_set_8(uint8_t val, uint8_t idx); +uint8_t hex_set_16(uint16_t val); +uint8_t hex_set_24(uint32_t val); + +void hex_enable(uint8_t mask); + +uint8_t sw_read(); + +void led_set(uint8_t val); + +#endif \ No newline at end of file diff --git a/sw/bootloader/devices/board_io.s b/sw/bootloader/devices/board_io.s new file mode 100644 index 0000000..95656fe --- /dev/null +++ b/sw/bootloader/devices/board_io.s @@ -0,0 +1,71 @@ +.include "io.inc65" + +.importzp sp, sreg + +.export _hex_set_8 +.export _hex_set_16 +.export _hex_set_24 +.export _hex_enable +.export _sw_read +.export _led_set + +.autoimport on + +.code + +; @in A: idx Stack[0]: val +; @out A: 0 for success, 1 for failure. +; Sets one of the 3 pairs of hex digits. +_hex_set_8: + phx + cmp #$3 ; If idx >= 3 then fail + bcc @1 + plx + lda #$1 + rts +@1: tax ; Move idx into x + jsr popa ; put val into a + sta SEVEN_SEG,x ; write to val + lda #$0 + plx + rts + +; @in A/X: val +; @out A: 0 for success, 1 for failure +; Sets the low 2 pairs of hex digits +_hex_set_16: + sta SEVEN_SEG + stx SEVEN_SEG+1 + lda #$0 + rts + +; @in A/X/sreg: val +; @out A: 0 for success, 1 for failure +; Sets the 3 pairs of hex digits for a 24 bit value +_hex_set_24: + sta SEVEN_SEG + stx SEVEN_SEG+1 + lda sreg + sta SEVEN_SEG+2 + lda #$0 + rts + +; @in A: mask +; Set the mask for seven seg enables +_hex_enable: + sta SEVEN_SEG+3 + rts + +; @out A: The Value of the switches +; Reads the current values of the switches. +_sw_read: + lda SW + ldx #$0 + rts + +; @in A: val +; @out A: 0 for success, 1 for failure +; Sets the LEDs +_led_set: + sta LED + rts \ No newline at end of file diff --git a/sw/bootloader/devices/conio.s b/sw/bootloader/devices/conio.s new file mode 100644 index 0000000..30b4d6a --- /dev/null +++ b/sw/bootloader/devices/conio.s @@ -0,0 +1,60 @@ +.importzp sp, sreg + +.import _uart_txb_block +.import _lastchar + +.export _cputc +.export gotoxy +.export _clrscr +.export _cgetc + +.autoimport on + +.code + +; void __fastcall__ cputc (char c); +_cputc: + jsr _uart_txb_block + cmp #$0a + bne @1 + lda #$0d + jsr _uart_txb_block +@1: rts + +; void __fastcall__ gotoxy (unsigned char x, unsigned char y); +gotoxy: + phx + phy + tay ; Move y position to y + lda (sp) + tax ; Move x position to x + lda #$1b + jsr _uart_txb_block + lda #'[' + jsr _uart_txb_block + tya + jsr _uart_txb_block + lda #';' + jsr _uart_txb_block + txa + jsr _uart_txb_block + lda #'H' + jsr _uart_txb_block + ply + plx + rts + +_clrscr: + phx + lda #$1b + jsr _uart_txb_block + lda #'c' + jsr _uart_txb_block + pla + rts + +_cgetc: +@2: lda _lastchar + beq @2 + stz _lastchar + rts \ No newline at end of file diff --git a/sw/bootloader/devices/interrupt.h b/sw/bootloader/devices/interrupt.h new file mode 100644 index 0000000..d0231aa --- /dev/null +++ b/sw/bootloader/devices/interrupt.h @@ -0,0 +1,15 @@ +#ifndef _INTERRUPT_H +#define _INTERRUPT_H + +#include + +#define BUTTON (1 << 0) +#define UART (1 << 1) + +void irq_int(); +void nmi_int(); + +uint8_t irq_get_status(); +void irq_set_status(uint8_t); + +#endif \ No newline at end of file diff --git a/sw/bootloader/devices/interrupt.s b/sw/bootloader/devices/interrupt.s new file mode 100644 index 0000000..f87f81d --- /dev/null +++ b/sw/bootloader/devices/interrupt.s @@ -0,0 +1,58 @@ +; --------------------------------------------------------------------------- +; interrupt.s +; --------------------------------------------------------------------------- +; +; Interrupt handler. +; +; Checks for a BRK instruction and returns from all valid interrupts. + +.import _handle_irq + +.export _irq_int, _nmi_int +.export _irq_get_status, _irq_set_status + +.include "io.inc65" + +.segment "CODE" + +.PC02 ; Force 65C02 assembly mode + +; --------------------------------------------------------------------------- +; Non-maskable interrupt (NMI) service routine + +_nmi_int: RTI ; Return from all NMI interrupts + +; --------------------------------------------------------------------------- +; Maskable interrupt (IRQ) service routine + +_irq_int: PHX ; Save X register contents to stack + TSX ; Transfer stack pointer to X + PHA ; Save accumulator contents to stack + INX ; Increment X so it points to the status + INX ; register value saved on the stack + LDA $100,X ; Load status register contents + AND #$10 ; Isolate B status bit + BNE break ; If B = 1, BRK detected + +; --------------------------------------------------------------------------- +; IRQ detected, return + +irq: PLA ; Restore accumulator contents + PLX ; Restore X register contents + jsr _handle_irq ; Handle the IRQ + RTI ; Return from all IRQ interrupts + +; --------------------------------------------------------------------------- +; BRK detected, stop + +break: JMP break ; If BRK is detected, something very bad + ; has happened, so stop running + +_irq_get_status: + lda IRQ_STATUS + ldx #$00 + rts + +_irq_set_status: + sta IRQ_STATUS + rts \ No newline at end of file diff --git a/sw/bootloader/devices/io.inc65 b/sw/bootloader/devices/io.inc65 new file mode 100644 index 0000000..bad732c --- /dev/null +++ b/sw/bootloader/devices/io.inc65 @@ -0,0 +1,18 @@ +SEVEN_SEG = $7ff0 + +UART = $7ff4 +UART_TXB = UART +UART_RXB = UART +UART_STATUS = UART + 1 + +LED = $7ff6 +SW = LED + +MM_CTRL = $7ff7 +MM_DATA = $7fe0 + +SD_ARG = $7ff8 +SD_CMD = $7ffc +SD_DATA = $7ffd + +IRQ_STATUS = $7fff diff --git a/sw/bootloader/devices/mapper.h b/sw/bootloader/devices/mapper.h new file mode 100644 index 0000000..8276b60 --- /dev/null +++ b/sw/bootloader/devices/mapper.h @@ -0,0 +1,12 @@ +#ifndef _MAPPER_H +#define _MAPPER_H + +#include + +void mapper_enable(uint8_t en); + +uint8_t mapper_read(uint8_t addr); +void mapper_write(uint8_t data, uint8_t addr); + +#endif + diff --git a/sw/bootloader/devices/mapper.s b/sw/bootloader/devices/mapper.s new file mode 100644 index 0000000..2ed1bc0 --- /dev/null +++ b/sw/bootloader/devices/mapper.s @@ -0,0 +1,32 @@ +.include "io.inc65" + +.importzp sp, sreg + +.export _mapper_enable +.export _mapper_read, _mapper_write + +.autoimport on + +.code + + +; void mapper_enable(uint8_t en) +_mapper_enable: + sta MM_CTRL + rts + +_mapper_read: + phx + tax + lda MM_DATA,x + ldx #$00 + rts + +_mapper_write: + phx + tax + jsr popa + sta MM_DATA,x + plx + rts + diff --git a/sw/bootloader/devices/sd_card.c b/sw/bootloader/devices/sd_card.c new file mode 100644 index 0000000..752cd0e --- /dev/null +++ b/sw/bootloader/devices/sd_card.c @@ -0,0 +1,75 @@ +#include +#include + +#include "devices/sd_card.h" + +void sd_init() { + uint32_t resp; + sd_card_command(0, 0); + + sd_card_command(0x000001aa, 8); + sd_card_resp(&resp); + cprintf("CMD8: %lx\n", resp); + + sd_card_command(0, 55); + sd_card_command(0x40180000, 41); + sd_card_resp(&resp); + cprintf("CMD41: %lx\n", resp); + + sd_card_command(0, 55); + sd_card_command(0x40180000, 41); + sd_card_resp(&resp); + cprintf("CMD41: %lx\n", resp); + + sd_card_command(0, 2); + sd_card_resp(&resp); + cprintf("CMD2: %lx\n", resp); +} + +uint16_t sd_get_rca() { + uint32_t resp; + + sd_card_command(0, 3); + resp = 0; + sd_card_resp(&resp); + + //cprintf("CMD3: %lx\n", resp); + + return resp >> 16; +} + +uint16_t sd_select_card(uint16_t rca) { + uint32_t resp; + + sd_card_command((uint32_t)rca << 16, 7); + sd_card_resp(&resp); + + return (uint16_t) resp; +} + +uint16_t sd_get_status(uint16_t rca) { + uint32_t resp; + + sd_card_command((uint32_t)rca << 16, 13); + sd_card_resp(&resp); + + return (uint16_t) resp; +} + +void sd_readblock(uint32_t addr, void* buf) { + uint32_t resp; + int i; + + sd_card_command(addr, 17); + sd_card_resp(&resp); + //cprintf("CMD17: %lx\n", resp); + + sd_card_wait_for_data(); + + //cprintf("Read data: \n"); + for (i = 0; i < 512; i++){ + ((uint8_t*)buf)[i] = sd_card_read_byte(); + } + + //cprintf("\n"); +} diff --git a/sw/bootloader/devices/sd_card.h b/sw/bootloader/devices/sd_card.h new file mode 100644 index 0000000..7e3cb00 --- /dev/null +++ b/sw/bootloader/devices/sd_card.h @@ -0,0 +1,18 @@ +#ifndef _SD_CARD_H +#define _SD_CARD_H + +#include + +void sd_init(); +uint16_t sd_get_rca(); +uint16_t sd_select_card(uint16_t rca); +uint16_t sd_get_status(uint16_t rca); +void sd_readblock(uint32_t addr, void* buf); + +void sd_card_command(uint32_t arg, uint8_t cmd); + +void sd_card_resp(uint32_t* resp); +uint8_t sd_card_read_byte(); +void sd_card_wait_for_data(); + +#endif diff --git a/sw/bootloader/devices/sd_card_asm.s b/sw/bootloader/devices/sd_card_asm.s new file mode 100644 index 0000000..fe4f4e2 --- /dev/null +++ b/sw/bootloader/devices/sd_card_asm.s @@ -0,0 +1,66 @@ +.include "io.inc65" + +.importzp sp, sreg, ptr1 + +.export _sd_card_command +.export _sd_card_resp +.export _sd_card_read_byte +.export _sd_card_wait_for_data + +.autoimport on + +.code + +; Send sd card command. +; command is in A register, the args are on the stack +; I think the order is high byte first? +_sd_card_command: + pha + + jsr popeax + sta SD_ARG + stx SD_ARG+1 + lda sreg + sta SD_ARG+2 + lda sreg+1 + sta SD_ARG+3 + + pla + sta SD_CMD + rts + +; void sd_card_resp(uint32_t* resp); +_sd_card_resp: + phy + sta ptr1 ; store pointer + stx ptr1+1 +@1: lda SD_CMD ; wait for status flag + and #$01 + beq @1 + lda SD_ARG + ldy #$0 + sta (ptr1),y + lda SD_ARG+1 + iny + sta (ptr1),y + lda SD_ARG+2 + iny + sta (ptr1),y + lda SD_ARG+3 + iny + sta (ptr1),y + ply + rts + +_sd_card_read_byte: + lda SD_DATA + ldx #$00 + rts + +_sd_card_wait_for_data: + pha +@1: lda SD_CMD ; wait for status flag + and #$02 + beq @1 + pla + rts \ No newline at end of file diff --git a/sw/bootloader/devices/uart.h b/sw/bootloader/devices/uart.h new file mode 100644 index 0000000..e8f06db --- /dev/null +++ b/sw/bootloader/devices/uart.h @@ -0,0 +1,13 @@ +#ifndef _UART_H +#define _UART_H + +#include + +void uart_txb(uint8_t val); +void uart_txb_block(uint8_t val); + +uint8_t uart_rxb(); + +uint8_t uart_status(); + +#endif \ No newline at end of file diff --git a/sw/bootloader/devices/uart.s b/sw/bootloader/devices/uart.s new file mode 100644 index 0000000..c852f7e --- /dev/null +++ b/sw/bootloader/devices/uart.s @@ -0,0 +1,36 @@ +.include "io.inc65" + +.importzp sp, sreg + +.export _uart_txb, _uart_txb_block +.export _uart_rxb +.export _uart_status + +.autoimport on + +.code + +; @in A: byte to transmit +; Transmits a byte over the UART +_uart_txb: + sta UART_TXB ; Just write value, don't wait + rts + +_uart_txb_block: + pha + sta UART_TXB ; Write value +@1: lda UART_STATUS ; Wait for status[0] to be 0 + bit #$01 + bne @1 + pla + rts + +_uart_rxb: + lda UART_RXB ; Read value + ldx #$00 + rts + +_uart_status: + lda UART_STATUS + ldx #$00 + rts diff --git a/sw/bootloader/exec.c b/sw/bootloader/exec.c new file mode 100644 index 0000000..0824eb6 --- /dev/null +++ b/sw/bootloader/exec.c @@ -0,0 +1,61 @@ +#include +#include +#include + +#include "filesystem/fat.h" +#include "filesystem/o65.h" + +void exec(char* filename) { + o65_header_t* header; + o65_opt_t* o65_opt; + uint8_t* seg_ptr; + + uint8_t* code_base; + uint8_t* data_base; + uint16_t code_len; + uint16_t data_len; + + uint8_t (*exec)(void); + uint8_t ret; + + fat_read(filename, fat_buf); + + header = (o65_header_t*)fat_buf; + + if (header->c64_marker == O65_NON_C64 && + header->magic[0] == O65_MAGIC_0 && + header->magic[1] == O65_MAGIC_1 && + header->magic[2] == O65_MAGIC_2) { + + code_base = (uint8_t*)header->tbase; + data_base = (uint8_t*)header->dbase; + code_len = header->tlen; + data_len = header->dlen; + + + o65_opt = (o65_opt_t*)(fat_buf + sizeof(o65_header_t)); + while (o65_opt->olen) + { + o65_print_option(o65_opt); + o65_opt = (o65_opt_t*)((uint8_t*)o65_opt + o65_opt->olen); + } + + seg_ptr = (uint8_t*)o65_opt + 1; + + memcpy((uint8_t*)code_base, seg_ptr, code_len); + + seg_ptr+=code_len; + + memcpy((uint8_t*)data_base, seg_ptr, data_len); + + exec = (uint8_t (*)(void))code_base; + + ret = 0; + + ret = (*exec)(); + + cprintf("ret: %x\n", ret); + + + } +} diff --git a/sw/bootloader/exec.h b/sw/bootloader/exec.h new file mode 100644 index 0000000..9ed3941 --- /dev/null +++ b/sw/bootloader/exec.h @@ -0,0 +1,6 @@ +#ifndef _EXEC_H +#define _EXEC_H + +void exec(char* filename); + +#endif diff --git a/sw/bootloader/filesystem/fat.c b/sw/bootloader/filesystem/fat.c new file mode 100644 index 0000000..bd353d1 --- /dev/null +++ b/sw/bootloader/filesystem/fat.c @@ -0,0 +1,260 @@ +#include +#include +#include + +#include "fat.h" +#include "devices/sd_card.h" + +uint8_t fat_buf[512]; + +static uint32_t fat_end_of_chain; + +static full_bpb_t bpb; + +static uint32_t data_region_start; + +void fat_print_pbp_info(full_bpb_t* bpb){ + cprintf("Bytes per sector: %d\n", bpb->bytes_per_sector); + cprintf("Sectors per cluster: %d\n", bpb->sectors_per_cluster); + cprintf("Reserved Sectors: %d\n", bpb->reserved_sectors); + cprintf("Fat Count: %d\n", bpb->fat_count); + cprintf("Max Dir Entries: %d\n", bpb->max_dir_entries); + cprintf("Total Sector Count: %d\n", bpb->total_sector_count); + cprintf("Media Descriptor: 0x%x\n", bpb->media_descriptor); + cprintf("Sectors per Fat: %d\n", bpb->sectors_per_fat_16); + cprintf("\n"); + + cprintf("Sectors per track: %d\n", bpb->sectors_per_track); + cprintf("Head Count: %d\n", bpb->head_count); + cprintf("Hidden Sector Count: %ld\n", bpb->hidden_sector_count); + cprintf("Logical Sector Count: %ld\n", bpb->logical_sector_count); + cprintf("Sectors per Fat: %ld\n", bpb->sectors_per_fat_32); + cprintf("Extended Flags: 0x%x\n", bpb->extended_flags); + cprintf("Version: %d\n", bpb->version); + cprintf("Root Cluster: 0x%lx\n", bpb->root_cluster); + cprintf("System Information: 0x%x\n", bpb->system_information); + cprintf("Backup Boot Sector: 0x%x\n", bpb->backup_boot_sector); + cprintf("\n"); + + cprintf("Drive Number: %d\n", bpb->drive_num); + cprintf("Extended Signature: 0x%x\n", bpb->extended_signature); + cprintf("Volume ID: 0x%lx\n", bpb->volume_id); + cprintf("Partition Label: %.11s\n", &bpb->partition_label); + cprintf("Partition Label: %.8s\n", &bpb->filesystem_type); + cprintf("\n"); +} + +void fat_init(){ + int i; + + sd_readblock(0, fat_buf); + + memcpy(&bpb, &fat_buf[11], sizeof(full_bpb_t)); + + sd_readblock(1, fat_buf); + sd_readblock(32, fat_buf); + + fat_print_pbp_info(&bpb); + + data_region_start = bpb.reserved_sectors + bpb.fat_count*bpb.sectors_per_fat_32; + + sd_readblock(bpb.reserved_sectors, fat_buf); + + //uncomment to view start of FAT + + /* + for (i = 0; i < FAT_CLUSTERS_PER_SECTOR; i++) { + cprintf("%lx ", ((uint32_t*)fat_buf)[i]); + } + cprintf("\n\n"); + */ + + fat_end_of_chain = ((uint32_t*)fat_buf)[1] & FAT_EOC_CLUSTERMASK; + cprintf("End of chain indicator: %lx\n", fat_end_of_chain); +} + +void fat_read(char* filename, void* buf) { + vfat_dentry_t* vfat_dentry; + dos_dentry_t* dos_dentry; + uint32_t cluster; + + (void)filename; //just ignore filename + + sd_readblock(data_region_start, buf); + + vfat_dentry = (vfat_dentry_t*)buf; + while(vfat_dentry->sequence_number == 0xe5) + vfat_dentry++; + + dos_dentry = (dos_dentry_t*)(vfat_dentry + 1); + + cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l; + + sd_readblock(data_region_start + (cluster - 2) * 8, buf); +} + +// make sure you have enough space. +void fat_read_cluster(uint16_t cluster, uint8_t* buf) { + uint8_t i; + + for (i = 0; i < bpb.sectors_per_cluster; i++) { + sd_readblock(data_region_start + i + (cluster - 2) * 8, buf+i*bpb.bytes_per_sector); + } +} + +uint32_t fat_get_chain_value(uint16_t cluster) { + sd_readblock(bpb.reserved_sectors, fat_buf); + return ((uint32_t*)fat_buf)[cluster]; +} + +//the dentry is a double pointer because we need to increment it. +void fat_parse_vfat_filenamename(vfat_dentry_t** vfat_dentry, char* name, uint32_t cluster) { + uint8_t i; + uint8_t overflows; + uint8_t done; + char* shift_name; + uint8_t sequence_number = (*vfat_dentry)->sequence_number; + overflows = 0; + + for (;;){ + shift_name = name + 13*((sequence_number & FAT_LFN_ENTRY_MASK) - 1); + + done = 0; + for(i = 0; i < 5; i++) { + shift_name[i] = (*vfat_dentry)->filename0[i]; + if (!shift_name[i]) { + done = 1; + break; + } + } + + if (!done) { + for(i = 0; i < 6; i++) { + shift_name[i+5] = (*vfat_dentry)->filename1[i]; + if (!shift_name[i+5]) { + done = 1; + break; + } + } + } + + if (!done) { + for(i = 0; i < 2; i++) { + shift_name[i+11] = (*vfat_dentry)->filename2[i]; + if (!shift_name[i+11]) { + done = 1; + break; + } + } + } + + if ((sequence_number & FAT_LFN_ENTRY_MASK) == 1) { + break; + } else { + do { + (*vfat_dentry)++; + if ((uint8_t*)*vfat_dentry >= fat_buf + sizeof(fat_buf)) { + overflows++; + if (overflows == bpb.sectors_per_cluster) { + cprintf("Too many overflows, go back to fat!\n"); //TODO this + return; + } + sd_readblock(data_region_start + (cluster - 2) * 8 + overflows, fat_buf); + *vfat_dentry = (vfat_dentry_t*)fat_buf; + } + } while((*vfat_dentry)->sequence_number == 0xe5); + sequence_number = (*vfat_dentry)->sequence_number; + } + } + +} + +uint32_t fat_find_cluster_num(char* name, uint32_t cluster) { + vfat_dentry_t* vfat_dentry; + dos_dentry_t* dos_dentry; + char* vfat_name; + + cprintf("Looking for file %s\n", name); + + sd_readblock(data_region_start + (cluster - 2) * 8, fat_buf); + vfat_dentry = (vfat_dentry_t*)fat_buf; + + vfat_name = (char*)malloc(FAT_MAX_FILE_NAME); + + while(vfat_dentry->sequence_number == 0xe5) + vfat_dentry++; + + vfat_name[0] = '\0'; + + while(vfat_dentry->sequence_number) { + fat_parse_vfat_filenamename(&vfat_dentry, vfat_name, cluster); + cprintf("Parsed filename: %s\n", vfat_name); + + if (!strcmp(vfat_name, name)) { //TODO this is probably unsafe, use strncmp + cprintf("Found file %s\n", vfat_name); + break; + } else { + vfat_dentry += 2; + while(vfat_dentry->sequence_number == 0xe5) + vfat_dentry++; + } + } + + free(vfat_name); + + if (!vfat_dentry->sequence_number) { + cprintf("File not found.\n"); + return -1; + } + + dos_dentry = (dos_dentry_t*) vfat_dentry + 1; //dos entry follows last vfat entry + + cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l; + cprintf("Cluster: %ld\n", cluster); + + return cluster; +} + +uint16_t fat_parse_path_to_cluster(char* filename) { + //basically start at the root folder and search through it + int i; + int len; + uint8_t dirs = 0; + + char* spaced_filename; + char* fragment; + + uint32_t cluster = 2; //root chain is chain 2 + + if (filename[0] != '/') { + cprintf("Filename does not begin with '/'\n"); + return 0; + } + + filename++; + len = strlen(filename); + spaced_filename = (char*)malloc(len+1); //need to account for null byte + + for (i = 0; i <= len; i++) { + if (filename[i] == '/') { + spaced_filename[i] = '\0'; + dirs++; + } else { + spaced_filename[i] = filename[i]; + } + } + + fragment = spaced_filename; + + cprintf("Dirs: %d\n", dirs); + + for (i = 0; i <= dirs; i++) { + cprintf("Fragment: %s\n", fragment); + cluster = fat_find_cluster_num(fragment, cluster); + fragment = spaced_filename + strlen(fragment) + 1; + } + + free(spaced_filename); + + return cluster; +} diff --git a/sw/bootloader/filesystem/fat.h b/sw/bootloader/filesystem/fat.h new file mode 100644 index 0000000..732e179 --- /dev/null +++ b/sw/bootloader/filesystem/fat.h @@ -0,0 +1,124 @@ +#ifndef _FAT_H +#define _FAT_H + +#include + +extern uint8_t fat_buf[]; + +#define FAT_MAX_FILE_NAME 255 +#define FAT_CLUSTERS_PER_SECTOR 128 + +#define FAT_CLUSTERMASK 0x0fffffff +#define FAT_EOC_CLUSTERMASK 0x0ffffff8 + +#define FAT_LAST_LFN_MASK (1 << 6) +#define FAT_LFN_ENTRY_MASK 0x1f + +typedef struct { + uint16_t bytes_per_sector; + uint8_t sectors_per_cluster; + uint16_t reserved_sectors; + uint8_t fat_count; + uint16_t max_dir_entries; + uint16_t total_sector_count; + uint8_t media_descriptor; + uint16_t sectors_per_fat; +} dos_2_bpb_t; + +typedef struct { + dos_2_bpb_t bpb2; + uint16_t sectors_per_track; + uint16_t head_count; + uint32_t hidden_sector_count; + uint32_t logical_sector_count; + uint32_t sectors_per_fat; + uint16_t extended_flags; + uint16_t version; + uint32_t root_cluster; + uint16_t system_information; + uint16_t backup_boot_sector; + uint8_t reserved[12]; +} dos_3_bpb_t; + +typedef struct { + dos_3_bpb_t bpb3; + uint8_t drive_num; + uint8_t reserved; + uint8_t extended_signature; + uint32_t volume_id; + uint8_t partition_label[11]; + uint8_t filesystem_type[8]; +} ebpb_t; + +typedef struct { + uint16_t bytes_per_sector; + uint8_t sectors_per_cluster; + uint16_t reserved_sectors; + uint8_t fat_count; + uint16_t max_dir_entries; + uint16_t total_sector_count; + uint8_t media_descriptor; + uint16_t sectors_per_fat_16; + uint16_t sectors_per_track; + uint16_t head_count; + uint32_t hidden_sector_count; + uint32_t logical_sector_count; + uint32_t sectors_per_fat_32; + uint16_t extended_flags; + uint16_t version; + uint32_t root_cluster; + uint16_t system_information; + uint16_t backup_boot_sector; + uint8_t reserved[12]; + uint8_t drive_num; + uint8_t reserved2; + uint8_t extended_signature; + uint32_t volume_id; + uint8_t partition_label[11]; + uint8_t filesystem_type[8]; +} full_bpb_t; + +typedef struct { + uint32_t sig; + uint8_t reserved[480]; + uint32_t sig2; + uint32_t free_data_clusters; + uint32_t last_allocated_data_cluster; + uint32_t reserved2; + uint32_t sig3; +} fs_info_sector_t; + +typedef struct { + uint8_t sequence_number; + uint16_t filename0[5]; + uint8_t attributes; + uint8_t type; + uint8_t checksum; + uint16_t filename1[6]; + uint16_t reserved; + uint16_t filename2[2]; +} vfat_dentry_t; + +typedef struct { + uint8_t filename[8]; + uint8_t extension[3]; + uint8_t attributes; + uint8_t reserved; + uint8_t create_time_10ms; + uint32_t create_date; + uint16_t access_date; + uint16_t first_cluster_h; + uint32_t modify_cluster; + uint16_t first_cluster_l; + uint32_t file_size; +} dos_dentry_t; + +void fat_print_pbp_info(full_bpb_t* bpb); +void fat_init(); +void fat_read(char* filename, void* buf); + +uint16_t fat_parse_path_to_cluster(char* filename); +void fat_read_cluster(uint16_t cluster, uint8_t* buf); +uint32_t fat_get_chain_value(uint16_t cluster); + +#endif diff --git a/sw/bootloader/filesystem/o65.c b/sw/bootloader/filesystem/o65.c new file mode 100644 index 0000000..9e76dc0 --- /dev/null +++ b/sw/bootloader/filesystem/o65.c @@ -0,0 +1,28 @@ +#include + +#include "o65.h" + +void o65_print_option(o65_opt_t* opt) { + int i; + + cprintf("Option Length: %d\n", opt->olen); + cprintf("Option Type: %x ", opt->type); + + switch (opt->type) { + case O65_OPT_FILENAME: cprintf("Filename\n"); break; + case O65_OPT_OS: cprintf("OS\n"); break; + case O65_OPT_ASSEMBLER: cprintf("Assembler\n"); break; + case O65_OPT_AUTHOR: cprintf("Author\n"); break; + case O65_OPT_DATE: cprintf("Creation Date\n"); break; + default: cprintf("Invalid\n"); break; + } + + if (opt->type != O65_OPT_OS) { + for (i = 0; i < opt->olen - 2; i++) { + cprintf("%c", opt->data[i]); + } + } else { + cprintf("%x", opt->data[0]); + } + cprintf("\n\n"); +} diff --git a/sw/bootloader/filesystem/o65.h b/sw/bootloader/filesystem/o65.h new file mode 100644 index 0000000..719305c --- /dev/null +++ b/sw/bootloader/filesystem/o65.h @@ -0,0 +1,65 @@ +#ifndef _O65_H +#define _O65_H + +#include + +#define O65_NON_C64 0x0001 +#define O65_MAGIC_0 0x6f +#define O65_MAGIC_1 0x36 +#define O65_MAGIC_2 0x35 + +#define O65_OPT_FILENAME 0 +#define O65_OPT_OS 1 +#define O65_OPT_ASSEMBLER 2 +#define O65_OPT_AUTHOR 3 +#define O65_OPT_DATE 4 + +#define O65_OS_OSA65 1 +#define O65_OS_LUNIX 2 +#define O65_OS_CC65 3 +#define O65_OS_OPENCBM 4 +#define O65_OS_SUPER6502 5 + +typedef union { + struct { + int cpu : 1; + int reloc : 1; + int size : 1; + int obj : 1; + int simple : 1; + int chain : 1; + int bsszero : 1; + int cpu2 : 4; + int align : 2; + }; + uint16_t _mode; +} o65_mode_t; + +typedef struct { + uint16_t c64_marker; + uint8_t magic[3]; + uint8_t version; + + o65_mode_t mode; + + uint16_t tbase; + uint16_t tlen; + uint16_t dbase; + uint16_t dlen; + uint16_t bbase; + uint16_t blen; + uint16_t zbase; + uint16_t zlen; + uint16_t stack; + +} o65_header_t; + +typedef struct { + uint8_t olen; + uint8_t type; + uint8_t data[1]; //This is actually variable length +} o65_opt_t; + +void o65_print_option(o65_opt_t* opt); + +#endif diff --git a/sw/bootloader/io.inc65 b/sw/bootloader/io.inc65 deleted file mode 120000 index 52851e4..0000000 --- a/sw/bootloader/io.inc65 +++ /dev/null @@ -1 +0,0 @@ -../kernel/devices/io.inc65 \ No newline at end of file diff --git a/sw/bootloader/irq.c b/sw/bootloader/irq.c new file mode 100644 index 0000000..4d2c0d8 --- /dev/null +++ b/sw/bootloader/irq.c @@ -0,0 +1,24 @@ + +#include +#include + +#include "devices/interrupt.h" +#include "devices/uart.h" + +char lastchar; + + +void handle_irq() { + uint8_t status; + + status = irq_get_status(); + + if (status & BUTTON) { + cputs("Button Interrupt!\n"); + irq_set_status(status & ~BUTTON); + } + if (status & UART) { + lastchar = uart_rxb(); + irq_set_status(status & ~UART); + } +} \ No newline at end of file diff --git a/sw/bootloader/link.ld b/sw/bootloader/link.ld index 6860602..46ee428 100644 --- a/sw/bootloader/link.ld +++ b/sw/bootloader/link.ld @@ -1,17 +1,35 @@ MEMORY { ZP: start = $0, size = $100, type = rw, define = yes; - BOOTSECT: start = $1000, size = $200, file = %O; + SDRAM: start = $200, size = $7cf0, type = rw, define = yes; + ROM: start = $8000, size = $8000, file = %O; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, define = yes; - DATA: load = BOOTSECT, type = rw, define = yes; - BSS: load = BOOTSECT, type = bss, define = yes; - HEAP: load = BOOTSECT, type = bss, optional = yes; - STARTUP: load = BOOTSECT, type = ro, start = $1000; - CODE: load = BOOTSECT, type = ro, start = $105a; - RODATA: load = BOOTSECT, type = ro; - SIGN: load = BOOTSECT, type = ro, start = $11fe; + DATA: load = ROM, type = rw, define = yes, run = SDRAM; + BSS: load = SDRAM, type = bss, define = yes; + HEAP: load = SDRAM, type = bss, optional = yes; + STARTUP: load = ROM, type = ro; + ONCE: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro; + RODATA: load = ROM, type = ro; + VECTORS: load = ROM, type = ro, start = $FFFA; } +FEATURES { + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: value = $0200, type = weak; + __STACKSTART__: type = weak, value = $0800; # 2k stack +} diff --git a/sw/bootloader/main.c b/sw/bootloader/main.c index e69fb86..66d399f 100644 --- a/sw/bootloader/main.c +++ b/sw/bootloader/main.c @@ -1,11 +1,63 @@ #include +#include +#include +#include -#include "bios_calls.h" -#include "uart.h" +#include "devices/board_io.h" +#include "devices/uart.h" +#include "devices/mapper.h" +#include "devices/sd_card.h" +#include "filesystem/fat.h" +#include "exec.h" -//Should probably do this in asm -void load_bootsect() { - uart_txb_block('A'); - for (;;); - return; -} \ No newline at end of file +#define KERNEL_LOAD_ADDR 0xD000 + +uint8_t buf[512]; + +int main() { + int i; + uint16_t rca; + char* filename; + uint32_t cluster; + uint8_t* kernel_load; + + clrscr(); + cprintf("boot\n"); + + for (i = 0; i < 16; i++){ + //cprintf("Mapping %1xxxx to %2xxxx\n", i, i); + mapper_write(i, i); + } + + cprintf("Enabling Mapper\n"); + mapper_enable(1); + + mapper_write(0x10, 0xd); + mapper_write(0x11, 0xe); + mapper_write(0x12, 0xf); + + sd_init(); + + rca = sd_get_rca(); + cprintf("rca: %x\n", rca); + + sd_select_card(rca); + + fat_init(); + + filename = (char*)malloc(FAT_MAX_FILE_NAME); + + cluster = fat_parse_path_to_cluster("/kernel.bin"); + for (kernel_load = (uint8_t*)KERNEL_LOAD_ADDR; cluster < FAT_CLUSTERMASK; kernel_load+=(8*512)) { + cprintf("cluster: %lx\n", cluster); + cprintf("Writing to %p\n", kernel_load); + fat_read_cluster(cluster, kernel_load); + cluster = fat_get_chain_value(cluster); + } + + cprintf("Done!\n"); + + cprintf("Reset vector: %x\n", *((uint16_t*)0xfffc)); + + return 0; +} diff --git a/sw/bootloader/tests/test_main.c b/sw/bootloader/tests/test_main.c new file mode 100644 index 0000000..99e3dd8 --- /dev/null +++ b/sw/bootloader/tests/test_main.c @@ -0,0 +1,89 @@ +#include + +#include "devices/board_io.h" +#include "devices/uart.h" +#include "devices/interrupt.h" + +int main(void) +{ + int retval = 0; + + int i; + + printf("\nStarting tests...\n\n"); + + printf("Testing hex_set_8...\n"); + for (i = 0; i < 3; i++) { + if (hex_set_8(i+1, i)) { + printf("Failed to write to idx %d!\n", i); + retval++; + } + if (*(uint8_t*)0x7ff0+i != i+1) { + printf("Incorrect value at idx %d!\n", i); + retval++; + } + } + + if (!hex_set_8(0xab, 3)) { + printf("Writing to idx 3 should fail!\n"); + retval++; + } + printf("Done!\n\n"); + + printf("Testing hex_set_16...\n"); + if (hex_set_16(0xabcd)){ + printf("Failed to write!\n"); + } + if (*(uint16_t*)0x7ff0 != 0xabcd) { + printf("Incorrect value!\n", i); + retval++; + } + printf("Done!\n\n"); + + printf("Testing hex_set_24...\n"); + if (hex_set_24(0xabcdef)){ + printf("Failed to write!\n"); + } + if (*(uint16_t*)0x7ff0 != 0xcdef && *(uint8_t*)0x7ff2 != 0xab) { + printf("Incorrect value!\n", i); + retval++; + } + printf("Done!\n\n"); + + printf("Testing hex_enable...\n"); + hex_enable(0xa5); + if (*(uint8_t*)0x7ff3 != 0xa5) { + printf("Incorrect value!\n", i); + retval++; + } + printf("Done!\n\n"); + + printf("Testing uart_txb_block...\n"); + *(uint8_t*)0x7ff5 = 0; + uart_txb_block(0xa5); + if (*(uint8_t*)0x7ff4 != 0xa5) { + printf("Incorrect value!\n", i); + retval++; + } + printf("Done!\n\n"); + + printf("Testing uart_status...\n"); + *(uint8_t*)0x7ff5 = 0xa5; + if (uart_status() != 0xa5) { + printf("Incorrect value!\n", i); + retval++; + } + printf("Done!\n\n"); + + + printf("Testing irq_get_status...\n"); + *(uint8_t*)0x7fff = 0xa5; + if (irq_get_status() != 0xa5) { + printf("Incorrect value!\n", i); + retval++; + } + printf("Done!\n\n"); + + + return retval != 0; +} \ No newline at end of file diff --git a/sw/bootloader/uart.h b/sw/bootloader/uart.h deleted file mode 120000 index bdfeb82..0000000 --- a/sw/bootloader/uart.h +++ /dev/null @@ -1 +0,0 @@ -../kernel/devices/uart.h \ No newline at end of file diff --git a/sw/bootloader/uart.s b/sw/bootloader/uart.s deleted file mode 120000 index aa91b87..0000000 --- a/sw/bootloader/uart.s +++ /dev/null @@ -1 +0,0 @@ -../kernel/devices/uart.s \ No newline at end of file diff --git a/sw/bios/vectors.s b/sw/bootloader/vectors.s similarity index 100% rename from sw/bios/vectors.s rename to sw/bootloader/vectors.s