Espresso 0.0.1b
This commit is contained in:
@ -5,24 +5,24 @@
|
||||
#include <fs/fat32.h>
|
||||
|
||||
struct __attribute__((packed)) fat32_bpb {
|
||||
uint8_t jmp[3];
|
||||
uint8_t oem[8];
|
||||
uint16_t bytes_per_sector;
|
||||
uint8_t sectors_per_cluster;
|
||||
uint16_t reserved_sector_count;
|
||||
uint8_t num_fats;
|
||||
uint16_t root_entry_count;
|
||||
uint16_t total_sectors_16;
|
||||
uint8_t media;
|
||||
uint16_t fat_size_16;
|
||||
uint16_t sectors_per_track;
|
||||
uint16_t num_heads;
|
||||
uint32_t hidden_sectors;
|
||||
uint32_t total_sectors_32;
|
||||
uint32_t fat_size_32;
|
||||
uint16_t ext_flags;
|
||||
uint16_t fs_version;
|
||||
uint32_t root_cluster;
|
||||
uint8_t jmp[3];
|
||||
uint8_t oem[8];
|
||||
uint16_t bytes_per_sector;
|
||||
uint8_t sectors_per_cluster;
|
||||
uint16_t reserved_sector_count;
|
||||
uint8_t num_fats;
|
||||
uint16_t root_entry_count;
|
||||
uint16_t total_sectors_16;
|
||||
uint8_t media;
|
||||
uint16_t fat_size_16;
|
||||
uint16_t sectors_per_track;
|
||||
uint16_t num_heads;
|
||||
uint32_t hidden_sectors;
|
||||
uint32_t total_sectors_32;
|
||||
uint32_t fat_size_32;
|
||||
uint16_t ext_flags;
|
||||
uint16_t fs_version;
|
||||
uint32_t root_cluster;
|
||||
};
|
||||
|
||||
static int32_t fat32_drive = 0;
|
||||
@ -37,9 +37,10 @@ int32_t fat32_init(int32_t drive)
|
||||
{
|
||||
fat32_drive = drive;
|
||||
int err = ide_read48(drive, 0, 1, sector);
|
||||
if (err != 0) {
|
||||
printf("ide_read48 failed on sector 0 (err = %d)\n", err);
|
||||
return -1;
|
||||
if (err != 0)
|
||||
{
|
||||
printf("ide_read48 failed on sector 0 (err = %d)\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&bpb, sector, sizeof(bpb));
|
||||
@ -47,56 +48,79 @@ int32_t fat32_init(int32_t drive)
|
||||
fat_start_lba = bpb.reserved_sector_count;
|
||||
cluster_heap_lba = fat_start_lba + bpb.num_fats * bpb.fat_size_32;
|
||||
current_directory_cluster = bpb.root_cluster;
|
||||
printf("========= Start FAT info =========\n");
|
||||
printf("Bytes per sector: %u\n", bpb.bytes_per_sector);
|
||||
printf("Sectors per cluster: %u\n", bpb.sectors_per_cluster);
|
||||
printf("Reserved sectors: %u\n", bpb.reserved_sector_count);
|
||||
printf("Number of FATs: %u\n", bpb.num_fats);
|
||||
printf("FAT size (32): %u\n", bpb.fat_size_32);
|
||||
printf("Root cluster: %u\n", bpb.root_cluster);
|
||||
printf("========= End FAT info =========\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_83(const char *s) {
|
||||
for (int i = 0; i < 11; i++) {
|
||||
char c = s[i];
|
||||
if (c >= 32 && c <= 126) {
|
||||
printf("%c", c); // or your kernel's character output function
|
||||
} else {
|
||||
printf("\\x%02X", (unsigned char)c); // hex-escape non-printables
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
static uint32_t cluster_to_lba(uint32_t cluster)
|
||||
{
|
||||
printf("cluster_heap_lba: %u\n", cluster_heap_lba);
|
||||
return cluster_heap_lba + (cluster - 2) * bpb.sectors_per_cluster;
|
||||
}
|
||||
|
||||
static void format_83_name(const char *input, char out[11]) {
|
||||
memset(out, ' ', 11);
|
||||
int i = 0, j = 0;
|
||||
void format_83_name(const char* input, char* output)
|
||||
{
|
||||
printf("Input name: %s, Input length: %i\n", input, strlen(input));
|
||||
|
||||
// Copy name part (up to 8 chars)
|
||||
while (input[i] && input[i] != '.' && j < 8) {
|
||||
out[j++] = toupper((unsigned char)input[i++]);
|
||||
memset(output, ' ', 11);
|
||||
int32_t i = 0, j = 0;
|
||||
while (input[i] && j < 11)
|
||||
{
|
||||
if (input[i] == '.')
|
||||
{
|
||||
j = 8;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip dot
|
||||
if (input[i] == '.') i++;
|
||||
|
||||
// Copy extension (up to 3 chars)
|
||||
int k = 8;
|
||||
while (input[i] && j < 11) {
|
||||
out[k++] = toupper((unsigned char)input[i++]);
|
||||
j++;
|
||||
if (j < 11)
|
||||
{
|
||||
output[j++] = toupper((unsigned char)input[i++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t find_free_cluster() {
|
||||
// Read FAT sectors one by one
|
||||
for (uint32_t cluster = 2; cluster < bpb.total_sectors_32; cluster++) {
|
||||
uint32_t fat_sector = fat_start_lba + (cluster * 4) / 512;
|
||||
uint32_t fat_offset = (cluster * 4) % 512;
|
||||
|
||||
if (ide_read48(fat32_drive, fat_sector, 1, sector) != 0)
|
||||
return 0;
|
||||
static uint32_t find_free_cluster(void)
|
||||
{
|
||||
/* Read FAT sectors one by one */
|
||||
for (uint32_t cluster = 2; cluster < bpb.total_sectors_32; cluster++)
|
||||
{
|
||||
uint32_t fat_sector = fat_start_lba + (cluster * 4) / 512;
|
||||
uint32_t fat_offset = (cluster * 4) % 512;
|
||||
|
||||
uint32_t entry = *(uint32_t *)(sector + fat_offset) & 0x0FFFFFFF;
|
||||
if (entry == 0x00000000) {
|
||||
return cluster;
|
||||
}
|
||||
if (ide_read48(fat32_drive, fat_sector, 1, sector) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 0; // No free cluster found
|
||||
|
||||
uint32_t entry = *(uint32_t *)(sector + fat_offset) & 0x0FFFFFFF;
|
||||
if (entry == 0x00000000)
|
||||
{
|
||||
return cluster;
|
||||
}
|
||||
}
|
||||
return 0; // No free cluster found
|
||||
}
|
||||
|
||||
|
||||
@ -148,70 +172,336 @@ int32_t fat32_list_root(void)
|
||||
|
||||
int32_t fat32_read_file(const char *name, uint8_t *buffer, uint32_t max_len)
|
||||
{
|
||||
uint32_t lba = cluster_to_lba(current_directory_cluster);
|
||||
if (ide_read48(fat32_drive, lba, 1, sector) != 0)
|
||||
char formatted[11];
|
||||
memset(formatted, 0xAB, sizeof(formatted));
|
||||
format_83_name(name, formatted);
|
||||
|
||||
uint32_t dir_cluster = current_directory_cluster;
|
||||
|
||||
while (dir_cluster < 0x0FFFFFF8)
|
||||
{
|
||||
uint32_t lba = cluster_to_lba(dir_cluster);
|
||||
|
||||
for (uint8_t sector_idx = 0; sector_idx < bpb.sectors_per_cluster; sector_idx++)
|
||||
{
|
||||
if (ide_read48(fat32_drive, lba + sector_idx, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < 512; i += 32)
|
||||
{
|
||||
char *entry = (char *)§or[i];
|
||||
if ((uint8_t)entry[0] == 0x00)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((uint8_t)entry[0] == 0xE5 || (uint8_t)entry[11] == 0x0F)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("here\n");
|
||||
|
||||
char entry_name[12] = { '\0' };
|
||||
memcpy((void*)entry_name, (void*)entry, 11);
|
||||
|
||||
int32_t err = memcmp(entry_name, formatted, (size_t)11);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
printf("memcmp: %i\n", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* File found */
|
||||
uint32_t cluster = (*(uint16_t *)(entry + 26)) | ((*(uint16_t *)(entry + 20)) << 16);
|
||||
uint32_t size = *(uint32_t *)(entry + 28);
|
||||
uint32_t bytes_read = 0;
|
||||
|
||||
while (cluster < 0x0FFFFFF8 && bytes_read < max_len && bytes_read < size)
|
||||
{
|
||||
uint32_t file_lba = cluster_to_lba(cluster);
|
||||
if (ide_read48(fat32_drive, file_lba, bpb.sectors_per_cluster, buffer + bytes_read) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes_read += bpb.sectors_per_cluster * 512;
|
||||
|
||||
uint32_t fat_sector = cluster * 4 / 512;
|
||||
uint32_t fat_offset = cluster * 4 % 512;
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cluster = *(uint32_t *)(sector + fat_offset) & 0x0FFFFFFF;
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
/* Next directory cluster */
|
||||
uint32_t fat_sector = dir_cluster * 4 / 512;
|
||||
uint32_t fat_offset = dir_cluster * 4 % 512;
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir_cluster = *(uint32_t *)(sector + fat_offset) & 0x0FFFFFFF;
|
||||
}
|
||||
|
||||
return -2; /* File not found */
|
||||
}
|
||||
|
||||
|
||||
int32_t fat32_write_file(const char *name, const uint8_t *buffer, uint32_t len)
|
||||
{
|
||||
uint8_t fat_sector_buf[512];
|
||||
|
||||
char formatted[11];
|
||||
memset(formatted, 0xAB, sizeof(formatted));
|
||||
format_83_name(name, formatted);
|
||||
|
||||
uint32_t dir_cluster = current_directory_cluster;
|
||||
|
||||
while (dir_cluster < 0x0FFFFFF8)
|
||||
{
|
||||
uint32_t lba = cluster_to_lba(dir_cluster);
|
||||
|
||||
for (uint8_t sector_idx = 0; sector_idx < bpb.sectors_per_cluster; sector_idx++)
|
||||
{
|
||||
// Read directory sector
|
||||
if (ide_read48(fat32_drive, lba + sector_idx, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find matching entry offset inside this sector
|
||||
int32_t entry_offset = -1;
|
||||
for (int32_t i = 0; i < 512; i += 32)
|
||||
{
|
||||
char *entry = (char *)§or[i];
|
||||
if ((uint8_t)entry[0] == 0x00)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((uint8_t)entry[0] == 0xE5 || (uint8_t)entry[11] == 0x0F)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
char entry_name[12] = {0};
|
||||
memcpy(entry_name, entry, 11);
|
||||
|
||||
if (memcmp(entry_name, formatted, 11) == 0)
|
||||
{
|
||||
entry_offset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry_offset == -1)
|
||||
{
|
||||
// Not found in this sector, continue to next
|
||||
continue;
|
||||
}
|
||||
|
||||
// Entry found, write file data clusters
|
||||
uint8_t *entry = §or[entry_offset];
|
||||
uint32_t cluster = (*(uint16_t *)(entry + 26)) | ((*(uint16_t *)(entry + 20)) << 16);
|
||||
uint32_t bytes_written = 0;
|
||||
|
||||
while (cluster < 0x0FFFFFF8 && bytes_written < len)
|
||||
{
|
||||
uint32_t file_lba = cluster_to_lba(cluster);
|
||||
if (ide_write48(fat32_drive, file_lba, bpb.sectors_per_cluster, buffer + bytes_written) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes_written += bpb.sectors_per_cluster * 512;
|
||||
|
||||
if (bytes_written < len)
|
||||
{
|
||||
// Read FAT sector for current cluster
|
||||
uint32_t fat_sector = cluster * 4 / 512;
|
||||
uint32_t fat_offset = cluster * 4 % 512;
|
||||
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, fat_sector_buf) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t next_cluster = find_free_cluster();
|
||||
if (next_cluster == 0)
|
||||
{
|
||||
return -3; // No free cluster
|
||||
}
|
||||
|
||||
*(uint32_t *)(fat_sector_buf + fat_offset) = next_cluster & 0x0FFFFFFF;
|
||||
|
||||
if (ide_write48(fat32_drive, fat_start_lba + fat_sector, 1, fat_sector_buf) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cluster = next_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mark end of cluster chain
|
||||
uint32_t fat_sector = cluster * 4 / 512;
|
||||
uint32_t fat_offset = cluster * 4 % 512;
|
||||
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, fat_sector_buf) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(uint32_t *)(fat_sector_buf + fat_offset) = 0x0FFFFFFF;
|
||||
|
||||
if (ide_write48(fat32_drive, fat_start_lba + fat_sector, 1, fat_sector_buf) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// **Re-read the directory sector before updating file size**
|
||||
if (ide_read48(fat32_drive, lba + sector_idx, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Update file size in directory entry again after re-read
|
||||
entry = §or[entry_offset];
|
||||
*(uint32_t *)(entry + 28) = len;
|
||||
|
||||
// Write back updated directory sector
|
||||
if (ide_write48(fat32_drive, lba + sector_idx, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Debug print updated directory entry
|
||||
printf("Directory entry after write (offset %d):\n", entry_offset);
|
||||
for (int j = 0; j < 32; j++) {
|
||||
uint8_t b = (uint8_t)entry[j];
|
||||
printf("%02X ", b);
|
||||
if ((j + 1) % 16 == 0) printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
for (int j = 0; j < 32; j++) {
|
||||
char c = entry[j];
|
||||
printf("%c", (c >= 32 && c <= 126) ? c : '.');
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
// Move to next cluster of the directory
|
||||
uint32_t fat_sector = dir_cluster * 4 / 512;
|
||||
uint32_t fat_offset = dir_cluster * 4 % 512;
|
||||
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir_cluster = *(uint32_t *)(sector + fat_offset) & 0x0FFFFFFF;
|
||||
}
|
||||
|
||||
return -2; // File not found
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t fat32_create_file(const char *name)
|
||||
{
|
||||
uint8_t dir_sector[512];
|
||||
uint8_t fat_sector_buf[512];
|
||||
|
||||
uint32_t root_lba = cluster_to_lba(current_directory_cluster);
|
||||
|
||||
if (ide_read48(fat32_drive, root_lba, 1, dir_sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
char formatted_name[11];
|
||||
format_83_name(name, formatted_name);
|
||||
|
||||
for (int32_t i = 0; i < 512; i += 32)
|
||||
{
|
||||
char *entry = (char *)§or[i];
|
||||
if ((uint8_t)entry[0] == 0x00)
|
||||
uint8_t *entry = &dir_sector[i];
|
||||
if (entry[0] == 0x00 || entry[0] == 0xE5)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if ((uint8_t)entry[0] == 0xE5)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
printf("Writing entry at offset %d\n", i);
|
||||
memset(entry, 0, 32);
|
||||
memcpy(entry, formatted_name, 11);
|
||||
entry[11] = 0x20;
|
||||
|
||||
char entry_name[12];
|
||||
memcpy(entry_name, entry, 11);
|
||||
entry_name[11] = 0;
|
||||
for (int32_t j = 0; j < 11; j++)
|
||||
{
|
||||
if (entry_name[j] == ' ')
|
||||
uint32_t free_cluster = find_free_cluster();
|
||||
if (free_cluster == 0)
|
||||
{
|
||||
entry_name[j] = 0;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(entry_name, name, 11) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
uint32_t fat_sector = fat_start_lba + (free_cluster * 4) / 512;
|
||||
uint32_t fat_offset = (free_cluster * 4) % 512;
|
||||
|
||||
uint32_t cluster = (*(uint16_t *)(entry + 26)) | ((*(uint16_t *)(entry + 20)) << 16);
|
||||
uint32_t size = *(uint32_t *)(entry + 28);
|
||||
uint32_t bytes_read = 0;
|
||||
|
||||
while (cluster < 0x0FFFFFF8 && bytes_read < max_len && bytes_read < size)
|
||||
{
|
||||
uint32_t lba = cluster_to_lba(cluster);
|
||||
if (ide_read48(fat32_drive, lba, bpb.sectors_per_cluster, buffer + bytes_read) != 0)
|
||||
if (ide_read48(fat32_drive, fat_sector, 1, fat_sector_buf) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes_read += bpb.sectors_per_cluster * 512;
|
||||
*(uint32_t *)(fat_sector_buf + fat_offset) = 0x0FFFFFFF;
|
||||
|
||||
uint32_t fat_sector = cluster * 4 / 512;
|
||||
uint32_t fat_offset = cluster * 4 % 512;
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
if (ide_write48(fat32_drive, fat_sector, 1, fat_sector_buf) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cluster = *(uint32_t *)(sector + fat_offset) & 0x0FFFFFFF;
|
||||
/* Set first cluster */
|
||||
entry[20] = (free_cluster >> 16) & 0xFF;
|
||||
entry[21] = (free_cluster >> 24) & 0xFF;
|
||||
entry[26] = free_cluster & 0xFF;
|
||||
entry[27] = (free_cluster >> 8) & 0xFF;
|
||||
|
||||
/* File size = 0 */
|
||||
memset(entry + 28, 0, 4);
|
||||
|
||||
if (ide_write48(fat32_drive, root_lba, 1, dir_sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t temp[512];
|
||||
ide_read48(fat32_drive, cluster_to_lba(bpb.root_cluster), 1, temp);
|
||||
printf("Root directory cluster 2 dump (first 64 bytes):\n");
|
||||
for (int i = 0; i < 64; i++) {
|
||||
printf("%02X ", temp[i]);
|
||||
if ((i + 1) % 16 == 0) printf("\n");
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
return -2;
|
||||
|
||||
return -8;
|
||||
}
|
||||
|
||||
int32_t fat32_write_file(const char *name, const uint8_t *buffer, uint32_t len)
|
||||
int32_t fat32_create_directory(const char *name)
|
||||
{
|
||||
uint32_t lba = cluster_to_lba(current_directory_cluster);
|
||||
if (ide_read48(fat32_drive, lba, 1, sector) != 0)
|
||||
@ -222,206 +512,90 @@ int32_t fat32_write_file(const char *name, const uint8_t *buffer, uint32_t len)
|
||||
for (int32_t i = 0; i < 512; i += 32)
|
||||
{
|
||||
char *entry = (char *)§or[i];
|
||||
if ((uint8_t)entry[0] == 0x00) break;
|
||||
if ((uint8_t)entry[0] == 0xE5) continue;
|
||||
|
||||
char entry_name[12];
|
||||
memcpy(entry_name, entry, 11);
|
||||
entry_name[11] = 0;
|
||||
for (int j = 0; j < 11; j++)
|
||||
if ((uint8_t)entry[0] == 0x00 || (uint8_t)entry[0] == 0xE5)
|
||||
{
|
||||
if (entry_name[j] == ' ')
|
||||
{
|
||||
entry_name[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(entry_name, name, 11) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
memset(entry, 0, 32);
|
||||
memcpy(entry, name, strlen(name) > 11 ? 11 : strlen(name));
|
||||
entry[11] = FAT32_ATTR_DIRECTORY;
|
||||
|
||||
uint32_t cluster = (*(uint16_t *)(entry + 26)) | ((*(uint16_t *)(entry + 20)) << 16);
|
||||
uint32_t bytes_written = 0;
|
||||
uint32_t cluster = 6;
|
||||
*(uint16_t *)(entry + 26) = cluster & 0xFFFF;
|
||||
*(uint16_t *)(entry + 20) = (cluster >> 16) & 0xFFFF;
|
||||
*(uint32_t *)(entry + 28) = 0;
|
||||
|
||||
while (cluster < 0x0FFFFFF8 && bytes_written < len)
|
||||
{
|
||||
uint32_t lba = cluster_to_lba(cluster);
|
||||
if (ide_write48(fat32_drive, lba, bpb.sectors_per_cluster, buffer + bytes_written) != 0)
|
||||
if (ide_write48(fat32_drive, lba, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes_written += bpb.sectors_per_cluster * 512;
|
||||
|
||||
if (bytes_written < len)
|
||||
{
|
||||
uint32_t fat_sector = cluster * 4 / 512;
|
||||
uint32_t fat_offset = cluster * 4 % 512;
|
||||
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t next_cluster = find_free_cluster();
|
||||
if (next_cluster == 0)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
*(uint32_t *)(sector + fat_offset) = next_cluster & 0x0FFFFFFF;
|
||||
|
||||
if (ide_write48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
cluster = next_cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t fat_sector = cluster * 4 / 512;
|
||||
uint32_t fat_offset = cluster * 4 % 512;
|
||||
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(uint32_t *)(sector + fat_offset) = 0x0FFFFFFF;
|
||||
|
||||
if (ide_write48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
*(uint32_t *)(entry + 28) = len;
|
||||
if (ide_write48(fat32_drive, lba, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int32_t fat32_create_file(const char *name) {
|
||||
uint32_t root_lba = cluster_to_lba(bpb.root_cluster);
|
||||
int32_t fat32_change_directory(const char *name)
|
||||
{
|
||||
uint32_t dir_cluster = current_directory_cluster;
|
||||
|
||||
// Read root directory cluster sector (assuming 1 sector here for simplicity)
|
||||
if (ide_read48(fat32_drive, root_lba, 1, sector) != 0)
|
||||
while (dir_cluster < 0x0FFFFFF8)
|
||||
{
|
||||
uint32_t lba = cluster_to_lba(dir_cluster);
|
||||
|
||||
for (uint8_t sector_idx = 0; sector_idx < bpb.sectors_per_cluster; sector_idx++)
|
||||
{
|
||||
if (ide_read48(fat32_drive, lba + sector_idx, 1, sector) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
char formatted_name[11];
|
||||
format_83_name(name, formatted_name);
|
||||
|
||||
for (int32_t i = 0; i < 512; i += 32) {
|
||||
uint8_t *entry = §or[i];
|
||||
if (entry[0] == 0x00 || entry[0] == 0xE5) {
|
||||
// Found free directory entry, clear it
|
||||
memset(entry, 0, 32);
|
||||
|
||||
// Copy formatted filename
|
||||
memcpy(entry, formatted_name, 11);
|
||||
|
||||
// Set attributes to Archive (normal file)
|
||||
entry[11] = 0x20;
|
||||
|
||||
// Allocate first cluster for the file
|
||||
uint32_t free_cluster = find_free_cluster();
|
||||
if (free_cluster == 0) {
|
||||
return -2; // No free cluster
|
||||
}
|
||||
|
||||
// Mark cluster as end-of-chain in FAT
|
||||
uint32_t fat_sector = fat_start_lba + (free_cluster * 4) / 512;
|
||||
uint32_t fat_offset = (free_cluster * 4) % 512;
|
||||
if (ide_read48(fat32_drive, fat_sector, 1, sector) != 0)
|
||||
return -1;
|
||||
|
||||
*(uint32_t *)(sector + fat_offset) = 0x0FFFFFFF; // end of cluster chain
|
||||
if (ide_write48(fat32_drive, fat_sector, 1, sector) != 0)
|
||||
return -1;
|
||||
|
||||
// Set first cluster in directory entry (split high and low 16 bits)
|
||||
entry[20] = (free_cluster >> 16) & 0xFF;
|
||||
entry[21] = (free_cluster >> 24) & 0xFF;
|
||||
entry[26] = free_cluster & 0xFF;
|
||||
entry[27] = (free_cluster >> 8) & 0xFF;
|
||||
|
||||
// Set file size = 0
|
||||
entry[28] = 0;
|
||||
entry[29] = 0;
|
||||
entry[30] = 0;
|
||||
entry[31] = 0;
|
||||
|
||||
// Write back directory sector
|
||||
if (ide_write48(fat32_drive, root_lba, 1, sector) != 0)
|
||||
return -1;
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
}
|
||||
|
||||
return -3; // No free directory entry found
|
||||
}
|
||||
|
||||
int32_t fat32_create_directory(const char *name) {
|
||||
uint32_t lba = cluster_to_lba(current_directory_cluster);
|
||||
if (ide_read48(fat32_drive, lba, 1, sector) != 0)
|
||||
return -1;
|
||||
|
||||
for (int32_t i = 0; i < 512; i += 32) {
|
||||
for (int32_t i = 0; i < 512; i += 32)
|
||||
{
|
||||
char *entry = (char *)§or[i];
|
||||
if ((uint8_t)entry[0] == 0x00 || (uint8_t)entry[0] == 0xE5) {
|
||||
memset(entry, 0, 32);
|
||||
memcpy(entry, name, strlen(name) > 11 ? 11 : strlen(name));
|
||||
entry[11] = FAT32_ATTR_DIRECTORY;
|
||||
|
||||
uint32_t cluster = 6;
|
||||
*(uint16_t *)(entry + 26) = cluster & 0xFFFF;
|
||||
*(uint16_t *)(entry + 20) = (cluster >> 16) & 0xFFFF;
|
||||
*(uint32_t *)(entry + 28) = 0;
|
||||
|
||||
if (ide_write48(fat32_drive, lba, 1, sector) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
if ((uint8_t)entry[0] == 0x00)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((uint8_t)entry[0] == 0xE5)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int32_t fat32_change_directory(const char *name) {
|
||||
uint32_t lba = cluster_to_lba(current_directory_cluster);
|
||||
if (ide_read48(fat32_drive, lba, 1, sector) != 0)
|
||||
return -1;
|
||||
|
||||
for (int32_t i = 0; i < 512; i += 32) {
|
||||
char *entry = (char *)§or[i];
|
||||
if ((uint8_t)entry[0] == 0x00) break;
|
||||
if ((uint8_t)entry[0] == 0xE5) continue;
|
||||
|
||||
char entry_name[12];
|
||||
memcpy(entry_name, entry, 11);
|
||||
entry_name[11] = 0;
|
||||
for (int32_t j = 0; j < 11; j++)
|
||||
if (entry_name[j] == ' ') entry_name[j] = 0;
|
||||
|
||||
if (strncmp(entry_name, name, 11) != 0) continue;
|
||||
for (int j = 0; j < 11; j++)
|
||||
{
|
||||
if (entry_name[j] == ' ')
|
||||
{
|
||||
entry_name[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(entry_name, name, 11) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(entry[11] & FAT32_ATTR_DIRECTORY))
|
||||
return -2;
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
current_directory_cluster = (*(uint16_t *)(entry + 26)) | ((*(uint16_t *)(entry + 20)) << 16);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -3;
|
||||
|
||||
uint32_t fat_sector = dir_cluster * 4 / 512;
|
||||
uint32_t fat_offset = dir_cluster * 4 % 512;
|
||||
if (ide_read48(fat32_drive, fat_start_lba + fat_sector, 1, sector) != 0)
|
||||
return -1;
|
||||
|
||||
dir_cluster = *(uint32_t *)(sector + fat_offset) & 0x0FFFFFFF;
|
||||
}
|
||||
|
||||
return -3;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user