From 6b0caea84cc3a5856a3a3b11657c1c54de6c2ab0 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Tue, 8 Aug 2023 22:16:42 -0700 Subject: [PATCH] Link bootloader with bios to get access to symbols By doing this we don't need to call bios functions, we can just jsr directly to the addresses. This does mean that everytime the bios changes the bootloader has to change, but ideally all the bootloader does is load the bios and then get remapped out of memory. Any important drivers like file system can be loaded from the bootloader. This also means that the runtime functions are located in the bios for the bootloader, so the rom will have to stay mapped in until the kernel is started, at which point it will have its own runtime and the rom and bootloader are no longer needed. --- hw/efinix_fpga/super6502.xml | 2 +- sw/bios/Makefile | 2 +- sw/bios/bootloader.s | 41 +++++++ sw/bios/filesystem/fat.c | 208 ----------------------------------- sw/bios/filesystem/fat.h | 122 -------------------- sw/bios/filesystem/o65.c | 28 ----- sw/bios/filesystem/o65.h | 65 ----------- sw/bios/link.ld | 3 +- sw/bios/main.c | 1 - sw/bootloader/Makefile | 38 ------- sw/bootloader/bootloader.s | 27 ----- sw/bootloader/link.ld | 8 -- sw/script/format_disk.sh | 2 +- 13 files changed, 46 insertions(+), 501 deletions(-) create mode 100644 sw/bios/bootloader.s delete mode 100644 sw/bios/filesystem/fat.c delete mode 100644 sw/bios/filesystem/fat.h delete mode 100644 sw/bios/filesystem/o65.c delete mode 100644 sw/bios/filesystem/o65.h delete mode 100644 sw/bootloader/Makefile delete mode 100644 sw/bootloader/bootloader.s delete mode 100644 sw/bootloader/link.ld diff --git a/hw/efinix_fpga/super6502.xml b/hw/efinix_fpga/super6502.xml index 6bb6682..8098232 100644 --- a/hw/efinix_fpga/super6502.xml +++ b/hw/efinix_fpga/super6502.xml @@ -1,5 +1,5 @@ - + diff --git a/sw/bios/Makefile b/sw/bios/Makefile index 65a5116..e5efbe0 100644 --- a/sw/bios/Makefile +++ b/sw/bios/Makefile @@ -11,7 +11,7 @@ LISTS=lists TESTS=tests SRCS=$(wildcard *.s) $(wildcard *.c) -SRCS+=$(filter-out $(wildcard tests/*), $(wildcard **/*.s)) $(filter-out $(wildcard tests/*) $(wildcard filesystem/*), $(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))) diff --git a/sw/bios/bootloader.s b/sw/bios/bootloader.s new file mode 100644 index 0000000..47ef646 --- /dev/null +++ b/sw/bios/bootloader.s @@ -0,0 +1,41 @@ +.importzp sp, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3 + +.autoimport on + +.feature string_escapes + +.MACPACK generic + +_console_clear = $0 +_console_read_char = $2 +_console_write_char = $4 +_sd_readblock = $6 + +.segment "BOOTSECTOR" + +_start: + jmp _main + +.byte "SUPR6502" + +_main: + lda #str + jsr _cputs +@end: bra @end + + +str: .asciiz "Hello from the bootloader!\r\n" + +_end: + +.res (446+_start-_end) + +.res 16 +.res 16 +.res 16 +.res 16 + +.byte $55 +.byte $AA + diff --git a/sw/bios/filesystem/fat.c b/sw/bios/filesystem/fat.c deleted file mode 100644 index fbbd50f..0000000 --- a/sw/bios/filesystem/fat.c +++ /dev/null @@ -1,208 +0,0 @@ -#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_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); - - 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); -} - - -// 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/bios/filesystem/fat.h b/sw/bios/filesystem/fat.h deleted file mode 100644 index 2f7a640..0000000 --- a/sw/bios/filesystem/fat.h +++ /dev/null @@ -1,122 +0,0 @@ -#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_init(); - -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/bios/filesystem/o65.c b/sw/bios/filesystem/o65.c deleted file mode 100644 index 9e76dc0..0000000 --- a/sw/bios/filesystem/o65.c +++ /dev/null @@ -1,28 +0,0 @@ -#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/bios/filesystem/o65.h b/sw/bios/filesystem/o65.h deleted file mode 100644 index 719305c..0000000 --- a/sw/bios/filesystem/o65.h +++ /dev/null @@ -1,65 +0,0 @@ -#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/bios/link.ld b/sw/bios/link.ld index 53ef73c..25ad7c2 100644 --- a/sw/bios/link.ld +++ b/sw/bios/link.ld @@ -2,7 +2,7 @@ MEMORY { ZP: start = $0, size = $100, type = rw, define = yes; SDRAM: start = $200, size = $7e00, type = rw, define = yes; - BOOTLOADER: start = $8000, size = $1000, type = rw, define = yes; + BOOTLOADER: start = $8000, size = $1000, type = rw, define = yes, file = "bootloader.bin"; ROM: start = $F000, size = $1000, file = %O; } @@ -16,6 +16,7 @@ SEGMENTS { CODE: load = ROM, type = ro; RODATA: load = ROM, type = ro; VECTORS: load = ROM, type = ro, start = $FFFA; + BOOTSECTOR: load = BOOTLOADER, type = rw, start = $8000; } FEATURES { diff --git a/sw/bios/main.c b/sw/bios/main.c index 75dff9f..27a701d 100644 --- a/sw/bios/main.c +++ b/sw/bios/main.c @@ -7,7 +7,6 @@ #include "devices/uart.h" #include "devices/sd_card.h" #include "devices/sd_print.h" -#include "filesystem/fat.h" #define KERNEL_LOAD_ADDR 0xD000 diff --git a/sw/bootloader/Makefile b/sw/bootloader/Makefile deleted file mode 100644 index 006cf3a..0000000 --- a/sw/bootloader/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -CC=../cc65/bin/cl65 -CFLAGS=-T -t none -I. --cpu "65C02" -LDFLAGS=-C link.ld -m $(NAME).map - -NAME=bootloader - -BIN=$(NAME).bin -HEX=$(NAME).hex - -LISTS=lists - -SRCS=$(wildcard *.s) $(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/bootloader/bootloader.s b/sw/bootloader/bootloader.s deleted file mode 100644 index f05685e..0000000 --- a/sw/bootloader/bootloader.s +++ /dev/null @@ -1,27 +0,0 @@ -.segment "BOOTSECTOR" - - -_start: - jmp _main - -.byte "SUPR6502" - -_main: - ldx #$04 - lda #'A' - brk - nop ; This byte available for something - @1: jmp @1 - -_end: - -.res (446+_start-_end) - -.res 16 -.res 16 -.res 16 -.res 16 - -.byte $55 -.byte $AA - diff --git a/sw/bootloader/link.ld b/sw/bootloader/link.ld deleted file mode 100644 index d0725d6..0000000 --- a/sw/bootloader/link.ld +++ /dev/null @@ -1,8 +0,0 @@ -MEMORY -{ - BOOT: start = $8000, size = $200, file = %O; -} - -SEGMENTS { - BOOTSECTOR: load = BOOT, start = $8000; -} diff --git a/sw/script/format_disk.sh b/sw/script/format_disk.sh index 9cd6c8f..9aed55d 100644 --- a/sw/script/format_disk.sh +++ b/sw/script/format_disk.sh @@ -1,6 +1,6 @@ #!/bin/bash -BOOTLOADER=../bootloader/bootloader.bin +BOOTLOADER=../bios/bootloader.bin DEVICE=/dev/mmcblk0 TMPBOOTSECT=/tmp/bootsect TMPMOUNT=/tmp/sd