Move code out of main and into their own files

All of the SD card commands are moved into their own file, with
functions sd_init, sd_get_rca, sd_select_card, sd_get_status, and
sd_readblock.

The FAT functions are movied into fat.c and give functions fat_init and
fat_read. Note that the filename is ignored for now, it always reads the
first file in the root directory.

The loading of o65 files is done in o65.c, and executing is done in
exec.c

This cleans up the main file signifigantly and leaves the project open
to expansion.
This commit is contained in:
Byron Lathi
2022-04-16 20:52:50 -05:00
parent c02d03bd99
commit f1e71a9461
9 changed files with 293 additions and 292 deletions

61
sw/exec.c Normal file
View File

@@ -0,0 +1,61 @@
#include <stdint.h>
#include <conio.h>
#include <string.h>
#include "fat.h"
#include "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);
}
}

6
sw/exec.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _EXEC_H
#define _EXEC_H
void exec(char* filename);
#endif

73
sw/fat.c Normal file
View File

@@ -0,0 +1,73 @@
#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);
}

View File

@@ -3,6 +3,8 @@
#include <stdint.h>
extern uint8_t fat_buf[];
typedef struct {
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
@@ -39,6 +41,34 @@ typedef struct {
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];
@@ -74,4 +104,8 @@ typedef struct {
uint32_t file_size;
} dos_dentry_t;
void fat_print_pbp_info(ebpb_t* epbp);
void fat_init();
void fat_read(char* filename, void* buf);
#endif

300
sw/main.c
View File

@@ -8,96 +8,13 @@
#include "sd_card.h"
#include "fat.h"
#include "o65.h"
#include "exec.h"
uint8_t buf[512];
void sd_readblock(uint32_t addr) {
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++){
buf[i] = sd_card_read_byte();
}
/*
for (i = 0; i < 512; i++){
if (i % 16 == 0)
cprintf("\n %2x: ", i);
cprintf("%2x ", buf[i]);
}
*/
cprintf("\n");
}
void 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");
}
int main() {
int i;
uint8_t sw;
uint32_t resp;
ebpb_t* epbp;
fs_info_sector_t* fsis;
vfat_dentry_t* vfat_dentry;
dos_dentry_t* dos_dentry;
uint32_t cluster;
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;
uint16_t reserved_count;
uint32_t sectors_per_fat;
uint8_t fat_count;
uint32_t data_region_start;
char s[16];
s[15] = 0;
uint16_t rca;
clrscr();
cprintf("Hello, world!\n");
@@ -110,218 +27,17 @@ int main() {
cprintf("Enabling Mapper\n");
mapper_enable(1);
sd_init();
// This will read a 512 block from the sd card.
// The RCA is hard coded for the one that I have on hand as responses
// are not implemented yet.
sd_card_command(0, 0);
rca = sd_get_rca();
cprintf("rca: %x\n", rca);
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);
sd_card_command(0, 3);
sd_card_resp(&resp);
cprintf("CMD3: %lx\n", resp);
sd_card_command(0x59b40000, 7);
sd_card_resp(&resp);
cprintf("CMD7: %lx\n", resp);
sd_card_command(0x59b41000, 13);
sd_card_resp(&resp);
cprintf("CMD13: %lx\n", resp);
sd_readblock(0);
epbp = (ebpb_t*)&buf[11];
print_pbp_info(epbp);
cprintf("Boot Signature: %x %x\n", buf[510], buf[511]);
reserved_count = epbp->bpb3.bpb2.reserved_sectors;
fat_count = epbp->bpb3.bpb2.fat_count;
sectors_per_fat = epbp->bpb3.sectors_per_fat;
sd_readblock(1);
fsis = (fs_info_sector_t*)&buf[0];
cprintf("Free Data clusters: %ld\n", fsis->free_data_clusters);
cprintf("Last allocated data cluster: %ld\n", fsis->last_allocated_data_cluster);
cprintf("32 reserved sectors, reading from sector 32...\n");
sd_readblock(32);
cprintf("CLUST_0: %08lx\n", *(uint32_t*)&buf[0]);
cprintf("CLUST_1: %08lx\n", *(uint32_t*)&buf[1*4]);
cprintf("Root cluster: %08lx\n", *(uint32_t*)&buf[2*4]);
data_region_start = reserved_count + fat_count*sectors_per_fat;
cprintf("Data Region starting sector: %lx\n", data_region_start);
cprintf("Reading root directory entry...\n");
cprintf("%ld\n", data_region_start*512);
sd_readblock(data_region_start);
vfat_dentry = (vfat_dentry_t*)buf;
while(vfat_dentry->sequence_number == 0xe5)
vfat_dentry++;
cprintf("Sequence: %x\n", vfat_dentry->sequence_number);
cprintf("Name: ");
for (i = 0;; i++) { // this will not work for proper vfat names
if (i < 5) {
if (!vfat_dentry->filename0[i])
break;
cprintf("%c", vfat_dentry->filename0[i]);
} else if (i < 11) {
if (!vfat_dentry->filename0[i])
break;
cprintf("%c", vfat_dentry->filename1[i-5]);
} else {
break;
}
}
cprintf("\n");
dos_dentry = (dos_dentry_t*)(vfat_dentry + 1);
cprintf("DOS name: %.8s.%.3s\n", &dos_dentry->filename, &dos_dentry->extension);
cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l;
cprintf("Cluster: %ld\n", cluster);
cprintf("File location: %lx\n", data_region_start + (cluster - 2) * 8);
sd_readblock(data_region_start + (cluster - 2) * 8);
header = (o65_header_t*)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) {
cprintf("Found a valid o65 file!\n\n");
cprintf("tbase: %x\n", header->tbase);
cprintf("tlen: %x\n", header->tlen);
cprintf("dbase: %x\n", header->dbase);
cprintf("dlen: %x\n", header->dlen);
cprintf("bbase: %x\n", header->bbase);
cprintf("blen: %x\n", header->blen);
cprintf("zbase: %x\n", header->zbase);
cprintf("zlen: %x\n", header->zlen);
cprintf("stack: %x\n", header->stack);
cprintf("\n");
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*)(buf + sizeof(o65_header_t));
while (o65_opt->olen)
{
cprintf("Option Length: %d\n", o65_opt->olen);
cprintf("Option Type: %x ", o65_opt->type);
switch (o65_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 (o65_opt->type != O65_OPT_OS) {
for (i = 0; i < o65_opt->olen - 2; i++) {
cprintf("%c", o65_opt->data[i]);
}
} else {
cprintf("%x", o65_opt->data[0]);
}
cprintf("\n\n");
o65_opt = (o65_opt_t*)((uint8_t*)o65_opt + o65_opt->olen);
}
seg_ptr = (uint8_t*)o65_opt + 1;
cprintf("Code: \n");
for (i = 0; i < code_len; i++) {
cprintf("%x ", seg_ptr[i]);
}
cprintf("\n\n");
memcpy((uint8_t*)code_base, seg_ptr, code_len);
seg_ptr+=code_len;
cprintf("Data: \n");
for (i = 0; i < data_len; i++) {
cprintf("%x ", seg_ptr[i]);
}
cprintf("\n\n");
memcpy((uint8_t*)data_base, seg_ptr, data_len);
cprintf("Memory Copied!\n");
cprintf("Code: \n");
for (i = 0; i < code_len; i++) {
cprintf("%x ", code_base[i]);
}
cprintf("\n\n");
cprintf("Data: \n");
for (i = 0; i < data_len; i++) {
cprintf("%x ", data_base[i]);
}
cprintf("\n\n");
exec = (uint8_t (*)(void))code_base;
ret = 0;
ret = (*exec)();
cprintf("ret: %x\n", ret);
}
sd_select_card(rca);
fat_init();
exec("/test.o65");
cprintf("Done!\n");
while (1) {
sw = sw_read();
led_set(sw);
cscanf("%15s", s);
cprintf("\n");
for (i = 0; i < 16; i++)
cprintf("s[%d]=%c ", i, s[i]);
cprintf("\n");
cprintf("Read string: %s\n", s);
}
return 0;
}

28
sw/o65.c Normal file
View File

@@ -0,0 +1,28 @@
#include <conio.h>
#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");
}

View File

@@ -60,6 +60,8 @@ typedef struct {
uint8_t data[1]; //This is actually variable length
} o65_opt_t;
void o65_print_option(o65_opt_t* opt);
#endif

75
sw/sd_card.c Normal file
View File

@@ -0,0 +1,75 @@
#include <stdint.h>
#include <conio.h>
#include "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");
}

View File

@@ -3,6 +3,12 @@
#include <stdint.h>
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);