Merge branch 'filesystem' into 'master'
Improve file system code See merge request bslathi19/super6502!15
This commit is contained in:
@@ -2,11 +2,11 @@ default:
|
||||
tags:
|
||||
- docker
|
||||
|
||||
build-sw:
|
||||
build-kernel:
|
||||
stage: build
|
||||
image: a2geek/cc65-pipeline
|
||||
script:
|
||||
- cd sw/
|
||||
- cd sw/kernel
|
||||
- make
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ test-sw:
|
||||
stage: test
|
||||
image: a2geek/cc65-pipeline
|
||||
script:
|
||||
- cd sw/
|
||||
- cd sw/kernel
|
||||
- make test
|
||||
|
||||
test_mm:
|
||||
|
||||
73
sw/fat.c
73
sw/fat.c
@@ -1,73 +0,0 @@
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fat.h"
|
||||
#include "sd_card.h"
|
||||
|
||||
uint8_t fat_buf[512];
|
||||
|
||||
static full_bpb_t bpb;
|
||||
|
||||
static uint32_t data_region_start;
|
||||
|
||||
void fat_print_pbp_info(ebpb_t* epbp){
|
||||
cprintf("Bytes per sector: %d\n", epbp->bpb3.bpb2.bytes_per_sector);
|
||||
cprintf("Sectors per cluster: %d\n", epbp->bpb3.bpb2.sectors_per_cluster);
|
||||
cprintf("Reserved Sectors: %d\n", epbp->bpb3.bpb2.reserved_sectors);
|
||||
cprintf("Fat Count: %d\n", epbp->bpb3.bpb2.fat_count);
|
||||
cprintf("Max Dir Entries: %d\n", epbp->bpb3.bpb2.max_dir_entries);
|
||||
cprintf("Total Sector Count: %d\n", epbp->bpb3.bpb2.total_sector_count);
|
||||
cprintf("Media Descriptor: 0x%x\n", epbp->bpb3.bpb2.media_descriptor);
|
||||
cprintf("Sectors per Fat: %d\n", epbp->bpb3.bpb2.sectors_per_fat);
|
||||
cprintf("\n");
|
||||
|
||||
cprintf("Sectors per track: %d\n", epbp->bpb3.sectors_per_track);
|
||||
cprintf("Head Count: %d\n", epbp->bpb3.head_count);
|
||||
cprintf("Hidden Sector Count: %ld\n", epbp->bpb3.hidden_sector_count);
|
||||
cprintf("Logical Sector Count: %ld\n", epbp->bpb3.logical_sector_count);
|
||||
cprintf("Sectors per Fat: %ld\n", epbp->bpb3.sectors_per_fat);
|
||||
cprintf("Extended Flags: 0x%x\n", epbp->bpb3.extended_flags);
|
||||
cprintf("Version: %d\n", epbp->bpb3.version);
|
||||
cprintf("Root Cluster: 0x%lx\n", epbp->bpb3.root_cluster);
|
||||
cprintf("System Information: 0x%x\n", epbp->bpb3.system_information);
|
||||
cprintf("Backup Boot Sector: 0x%x\n", epbp->bpb3.backup_boot_sector);
|
||||
cprintf("\n");
|
||||
|
||||
cprintf("Drive Number: %d\n", epbp->drive_num);
|
||||
cprintf("Extended Signature: 0x%x\n", epbp->extended_signature);
|
||||
cprintf("Volume ID: 0x%lx\n", epbp->volume_id);
|
||||
cprintf("Partition Label: %.11s\n", &epbp->partition_label);
|
||||
cprintf("Partition Label: %.8s\n", &epbp->filesystem_type);
|
||||
cprintf("\n");
|
||||
}
|
||||
|
||||
void fat_init(){
|
||||
sd_readblock(0, fat_buf);
|
||||
|
||||
memcpy(&bpb, &fat_buf[11], sizeof(ebpb_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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -15,7 +15,7 @@ LISTS=lists
|
||||
TESTS=tests
|
||||
|
||||
SRCS=$(wildcard *.s) $(wildcard *.c)
|
||||
SRCS+=$(wildcard usb/*.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)))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include "sd_card.h"
|
||||
#include "devices/sd_card.h"
|
||||
|
||||
void sd_init() {
|
||||
uint32_t resp;
|
||||
@@ -2,8 +2,8 @@
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fat.h"
|
||||
#include "o65.h"
|
||||
#include "filesystem/fat.h"
|
||||
#include "filesystem/o65.h"
|
||||
|
||||
void exec(char* filename) {
|
||||
o65_header_t* header;
|
||||
246
sw/kernel/filesystem/fat.c
Normal file
246
sw/kernel/filesystem/fat.c
Normal file
@@ -0,0 +1,246 @@
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
@@ -5,6 +5,15 @@
|
||||
|
||||
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;
|
||||
@@ -87,7 +96,7 @@ typedef struct {
|
||||
uint8_t checksum;
|
||||
uint16_t filename1[6];
|
||||
uint16_t reserved;
|
||||
uint16_t filename[2];
|
||||
uint16_t filename2[2];
|
||||
} vfat_dentry_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -104,8 +113,10 @@ typedef struct {
|
||||
uint32_t file_size;
|
||||
} dos_dentry_t;
|
||||
|
||||
void fat_print_pbp_info(ebpb_t* epbp);
|
||||
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);
|
||||
|
||||
#endif
|
||||
@@ -2,8 +2,8 @@
|
||||
#include <stdint.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include "interrupt.h"
|
||||
#include "uart.h"
|
||||
#include "devices/interrupt.h"
|
||||
#include "devices/uart.h"
|
||||
|
||||
char lastchar;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#include <stdint.h>
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "board_io.h"
|
||||
#include "uart.h"
|
||||
#include "mapper.h"
|
||||
#include "sd_card.h"
|
||||
#include "fat.h"
|
||||
#include "o65.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"
|
||||
|
||||
uint8_t buf[512];
|
||||
@@ -15,6 +15,7 @@ uint8_t buf[512];
|
||||
int main() {
|
||||
int i;
|
||||
uint16_t rca;
|
||||
char* filename;
|
||||
|
||||
clrscr();
|
||||
cprintf("Hello, world!\n");
|
||||
@@ -35,7 +36,17 @@ int main() {
|
||||
sd_select_card(rca);
|
||||
|
||||
fat_init();
|
||||
exec("/test.o65");
|
||||
|
||||
filename = (char*)malloc(FAT_MAX_FILE_NAME);
|
||||
|
||||
for(;;) {
|
||||
cprintf("Filename: ");
|
||||
cscanf("%s", filename);
|
||||
cprintf("\n");
|
||||
fat_parse_path_to_cluster(filename);
|
||||
}
|
||||
|
||||
//exec("/test.o65");
|
||||
|
||||
cprintf("Done!\n");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "board_io.h"
|
||||
#include "uart.h"
|
||||
#include "interrupt.h"
|
||||
#include "devices/board_io.h"
|
||||
#include "devices/uart.h"
|
||||
#include "devices/interrupt.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Reference in New Issue
Block a user