13 #include <lib/string.h>
15 #include "drv/disk/dpm.h"
17 #include "lib/utf_conversion.h"
20 #include "io/rgb_image.h"
21 #include "lib/libstring/string.h"
22 #include "lib/php/pathinfo.h"
24 size_t fs_fat32_read(
char Disk,
const char* Path,
size_t Offset,
size_t Size,
void* Buffer){
25 size_t clust = fs_fat32_evaluate(Disk, Path,
true);
31 char* filename = pathinfo(Path, PATHINFO_BASENAME);
35 fs_fat32_read_file_from_dir(Disk, clust, Offset, Size, filename, Buffer);
42 size_t fs_fat32_write(
char Disk,
const char* Path,
size_t Offset,
size_t Size,
void* Buffer){
46 FSM_FILE fs_fat32_info(
char Disk,
const char* Path) {
50 size_t clust = fs_fat32_evaluate(Disk, Path,
true);
53 qemu_err(
"File does not exist");
57 char* filename = pathinfo(Path, PATHINFO_BASENAME);
59 qemu_warn(
"Path: %s; Filename: %s;", Path, filename);
64 if(info.filename[0] == 0) {
68 memset(file.Name, 0, 1024);
69 memcpy(file.Name, info.filename, 256);
71 file.Size = info.size;
77 qemu_ok(
"%s %d", file.Name, file.Size);
84 FSM_DIR* fs_fat32_dir(
char Disk,
const char* Path) {
87 qemu_note(
"Given path is: %s", Path);
88 size_t clust = fs_fat32_evaluate(Disk, Path,
true);
90 qemu_warn(
"Got cluster: %d", clust);
92 FSM_DIR *Dir = kcalloc(
sizeof(FSM_DIR), 1);
105 FSM_FILE *Files = kcalloc(
sizeof(FSM_FILE), 1);
107 size_t cluster_count = fs_fat32_get_cluster_count(Disk, clust);
108 char* cluster_data = kcalloc(desc->cluster_size, cluster_count);
110 fs_fat32_read_clusters_to_memory(Disk, clust, cluster_data);
113 size_t file_count = 0;
114 size_t directory_count = 0;
119 if(file.advanced_info.short_file_name[0] == 0)
122 size_t len =
strlen(file.filename);
123 size_t skip_lfns_count = (len / 13);
124 size_t skip_lfns_remiander = (len % 13);
126 if(skip_lfns_remiander > 0)
130 offset +=
sizeof(LFN_t) * skip_lfns_count;
132 offset +=
sizeof(fat_object_info_t);
134 Files = krealloc(Files,
sizeof(FSM_FILE) * (file_count + directory_count + 1));
136 Files[directory_count + file_count].LastTime.year = 1980 + ((file.advanced_info.last_modif_date >> 9) & 0b1111111);
137 Files[directory_count + file_count].LastTime.month = (file.advanced_info.last_modif_date >> 5) & 0b1111;
138 Files[directory_count + file_count].LastTime.day = (file.advanced_info.last_modif_date >> 0) & 0b11111;
140 Files[directory_count + file_count].LastTime.hour = ((file.advanced_info.last_modif_time >> 11) & 0b11111);
141 Files[directory_count + file_count].LastTime.minute = ((file.advanced_info.last_modif_time >> 5) & 0b111111);
142 Files[directory_count + file_count].LastTime.second = ((file.advanced_info.last_modif_time >> 0) & 0b11111);
144 memset(Files[directory_count + file_count].Name, 0, 1024);
145 memcpy(Files[directory_count + file_count].Name, file.filename,
strlen(file.filename));
146 Files[directory_count + file_count].Size = file.size;
147 Files[directory_count + file_count].Ready = 1;
149 qemu_note(
"File: %s, Size: %d", Files[directory_count + file_count].Name, Files[directory_count + file_count].Size);
151 if(file.advanced_info.attributes & ATTR_DIRECTORY) {
152 Files[directory_count + file_count].Type = 5;
156 Files[directory_count + file_count].Type = 0;
165 Dir->Count = file_count + directory_count;
166 Dir->CountFiles = file_count;
167 Dir->CountDir = directory_count;
174 int fs_fat32_create(
char Disk,
const char* Path,
int Mode){
178 int fs_fat32_delete(
char Disk,
const char* Path,
int Mode){
182 void fs_fat32_label(
char Disk,
char* Label){
185 memcpy(Label, desc->info.volume_label, 11);
188 vector_t* fs_fat32_get_clusters(
char Disk,
size_t cluster_number) {
193 uint32_t cur_cluster = cluster_number;
196 uint32_t old_cluster = cur_cluster;
198 cur_cluster = desc->fat_table[cur_cluster];
201 vector_push_back(container, old_cluster);
202 }
while(!(cur_cluster == 0x0fffffff || cur_cluster == 0x0ffffff8));
207 void fs_fat32_read_entire_fat(
char Disk) {
210 if(desc->fat_table) {
211 qemu_err(
"Reading FAT second time is not allowed");
215 desc->fat_table = kcalloc(1, desc->fat_size);
217 dpm_read(Disk, 0, desc->fat_offset, desc->fat_size, desc->fat_table);
221 void fs_fat32_read_clusters_to_memory(
char Disk,
size_t cluster_number,
void* buffer) {
224 vector_t* cluster_list = fs_fat32_get_clusters(Disk, cluster_number);
226 for(
int i = 0; i < cluster_list->size; i++) {
227 size_t current_cluster = vector_get(cluster_list, i).element;
229 size_t addr = ((desc->info.reserved_sectors + (desc->info.fat_size_in_sectors * 2)) \
230 + ((current_cluster - 2) * desc->info.sectors_per_cluster)) * desc->info.bytes_per_sector;
232 dpm_read(Disk, 0, addr, desc->cluster_size, (
void*)(((size_t)buffer) + (i * desc->cluster_size)));
235 vector_destroy(cluster_list);
241 size_t old = vector_get(cluster_list, 0).element;
242 size_t start = vector_get(cluster_list, 0).element;
244 for(
int i = 1; i < cluster_list->size; i++) {
245 size_t current = vector_get(cluster_list, i).element;
247 if (current - 1 != old) {
248 vector_push_back(lists, start);
249 vector_push_back(lists, old);
257 vector_push_back(lists, start);
258 vector_push_back(lists, old);
263 void fs_fat32_read_clusters_to_memory_precise(
char Disk,
size_t cluster_number,
void *buffer,
size_t byte_offset,
267 qemu_log(
"Reading cluster chain...");
268 vector_t* cluster_list = fs_fat32_get_clusters(Disk, cluster_number);
270 #if FAT32_LINEAR_OPTIMIZATION==1
271 vector_t* optimized = fs_fat32_optimize(cluster_list);
275 for(
int i = 0; i < optimized->size; i++) {
276 qemu_printf(
"%u ", vector_get(optimized, i).element);
281 vector_destroy(cluster_list);
283 cluster_list = optimized;
286 qemu_log(
"Byte offset: %d; Size of read: %d; Cluster size: %d", byte_offset, len, desc->cluster_size);
288 size_t starting_cluster = byte_offset / desc->cluster_size;
289 size_t read_clutser_count = len / desc->cluster_size;
291 if(len % desc->cluster_size > 0) {
292 read_clutser_count++;
295 qemu_log(
"Calculated: Starting cluster: %d; Cluster count: %d", starting_cluster, read_clutser_count);
296 qemu_log(
"Reading file data...");
298 #if FAT32_LINEAR_OPTIMIZATION==1
299 size_t buffer_index = 0;
301 for(
int i = 0; i < cluster_list->size; i+=2) {
302 size_t start_cluster = vector_get(cluster_list, i).element;
303 size_t end_cluster = vector_get(cluster_list, i + 1).element;
304 size_t count = end_cluster - start_cluster + 1;
306 qemu_note(
"START: %u; END: %u; COUNT: %u", start_cluster, end_cluster, count);
309 qemu_note(
"BUFFER INDEX: %u", buffer_index);
310 qemu_note(
"STARTING_CLUSTER: %u", starting_cluster);
312 size_t addr = ((desc->info.reserved_sectors + (desc->info.fat_size_in_sectors * 2)) \
313 + ((start_cluster - 2) * desc->info.sectors_per_cluster)) * desc->info.bytes_per_sector;
317 qemu_note(
"LEN: %u", MIN(desc->cluster_size * count, len));
318 qemu_note(
"LOAD TO: %x", (
size_t)buffer);
324 MIN(desc->cluster_size * count, len),
325 (
void*)(((
size_t)buffer) + (buffer_index * desc->cluster_size))
328 len -= MIN(desc->cluster_size * count, len);
329 buffer_index += count;
332 qemu_log(
"Remaining: %u", len);
334 for(
size_t i = starting_cluster; i < starting_cluster + read_clutser_count; i++) {
335 size_t buffer_index = i - starting_cluster;
337 size_t current_cluster = vector_get(cluster_list, i).element;
339 size_t addr = ((desc->info.reserved_sectors + (desc->info.fat_size_in_sectors * 2)) \
340 + ((current_cluster - 2) * desc->info.sectors_per_cluster)) * desc->info.bytes_per_sector;
346 MIN(desc->cluster_size, len),
347 (
void*)(((
size_t)buffer) + (buffer_index * desc->cluster_size))
350 len -= desc->cluster_size;
354 vector_destroy(cluster_list);
358 size_t fs_fat32_get_cluster_count(
char Disk,
size_t cluster_number) {
359 vector_t* clusters = fs_fat32_get_clusters(Disk, cluster_number);
361 size_t cluster_count = clusters->size;
363 vector_destroy(clusters);
365 return cluster_count;
368 size_t fs_fat32_read_lfn(
char* data,
char* out) {
369 size_t encoded_characters = 0;
371 uint16_t* chunk = kcalloc(
sizeof(uint16_t), 13);
377 memcpy(&lfn, data,
sizeof lfn);
381 uint8_t lfn_num = lfn.attr_number & ~LFN_LAST_ENTRY;
383 if(lfn.reserved != 0 || lfn_num > 20 || lfn.attribute != 0x0F) {
389 memcpy(chunk, lfn.first_name_chunk, 10);
390 memcpy(chunk + 5, lfn.second_name_chunk, 12);
391 memcpy(chunk + 11, lfn.third_name_chunk, 4);
393 uint16_t* prepared_chunk = kcalloc(
sizeof(uint16_t), 13);
395 for(
int i = 0; i < 13; i++) {
396 if(chunk[i] == 0xffff) {
399 prepared_chunk[i] = chunk[i];
400 encoded_characters += 2;
404 char* x = kcalloc(1, encoded_characters);
406 utf16_to_utf8((
short*)prepared_chunk,
407 (
int)encoded_characters / 2,
413 kfree(prepared_chunk);
424 return encoded_characters;
430 size_t ecc = fs_fat32_read_lfn(data, info.filename);
432 size_t byte_count = ecc / 2;
434 size_t div = byte_count / 13, rem = byte_count % 13;
439 data +=
sizeof(LFN_t) * div;
441 memcpy(&info.advanced_info, data,
sizeof info.advanced_info);
443 if(
strlen(info.filename) == 0) {
444 for(
int i = 0; i < 11; i++) {
448 info.filename[i] = info.advanced_info.short_file_name[i];
456 info.starting_cluster = (info.advanced_info.first_cluster_high << 16) | info.advanced_info.first_cluster_low;
457 info.size = info.advanced_info.file_size_in_bytes;
462 fat_file_info_t fs_fat32_get_object_info(
char Disk,
const char* filename,
size_t directory_cluster) {
465 size_t cluster_count = fs_fat32_get_cluster_count(Disk, directory_cluster);
467 char* cluster_data = kcalloc(desc->cluster_size, cluster_count);
469 fs_fat32_read_clusters_to_memory(Disk, directory_cluster, cluster_data);
476 if(info.advanced_info.short_file_name[0] == 0)
479 size_t len =
strlen(info.filename);
480 size_t skip_lfns_count = (len / 13);
481 size_t skip_lfns_remiander = (len % 13);
483 if(skip_lfns_remiander > 0)
487 offset +=
sizeof(LFN_t) * skip_lfns_count;
489 offset +=
sizeof(fat_object_info_t);
491 if(
strcmp(info.filename, filename) == 0) {
503 void fs_fat32_read_file_from_dir(
char Disk,
size_t directory_cluster,
size_t byte_offset,
size_t length,
char *filename,
507 size_t cluster_count = fs_fat32_get_cluster_count(Disk, directory_cluster);
508 char* cluster_data = kcalloc(desc->cluster_size, cluster_count);
510 fs_fat32_read_clusters_to_memory(Disk, directory_cluster, cluster_data);
517 if(file.advanced_info.short_file_name[0] == 0)
520 size_t len =
strlen(file.filename);
521 size_t skip_lfns_count = (len / 13);
522 size_t skip_lfns_remiander = (len % 13);
524 if(skip_lfns_remiander > 0)
528 offset +=
sizeof(LFN_t) * skip_lfns_count;
530 offset +=
sizeof(fat_object_info_t);
532 if(
memcmp(file.filename, filename, len) == 0) {
533 qemu_ok(
"File found!");
536 fs_fat32_read_clusters_to_memory_precise(Disk, file.starting_cluster, out, byte_offset, length);
544 void fs_fat32_scan_directory(
char Disk,
size_t directory_cluster) {
547 size_t cluster_count = fs_fat32_get_cluster_count(Disk, directory_cluster);
548 char* cluster_data = kcalloc(desc->cluster_size, cluster_count);
550 fs_fat32_read_clusters_to_memory(Disk, directory_cluster, cluster_data);
558 if(file.advanced_info.short_file_name[0] == 0)
561 size_t len =
strlen(file.filename);
562 size_t skip_lfns_count = (len / 13);
563 size_t skip_lfns_remiander = (len % 13);
565 if(skip_lfns_remiander > 0)
569 offset +=
sizeof(LFN_t) * skip_lfns_count;
571 offset +=
sizeof(fat_object_info_t);
573 qemu_note(
"%s %d", file.filename, file.size);
582 size_t fs_fat32_evaluate(
char Disk,
const char* path,
bool error_on_file) {
583 size_t current_cluster = 2;
584 size_t old_cluster = 2;
587 return current_cluster;
590 string_t* strpath = string_from_charptr(path);
591 vector_t* pieces = string_split(strpath,
"/");
595 for(
int i = 0; i < pieces->size; i++) {
596 char* value = ADDR2STRING(pieces->data[i])->data;
597 qemu_note(
"%s", value);
602 if(
strcmp(value,
".") == 0)
605 if(
strcmp(value,
"..") == 0) {
606 current_cluster = old_cluster;
610 temp_info = fs_fat32_get_object_info(Disk, value, current_cluster);
612 if(temp_info.filename[0] == 0) {
613 string_split_free(pieces);
614 string_destroy(strpath);
619 if(~temp_info.advanced_info.attributes & ATTR_DIRECTORY) {
621 qemu_err(
"That's not a directory, can't go on...");
623 string_split_free(pieces);
624 string_destroy(strpath);
626 return current_cluster;
628 string_split_free(pieces);
629 string_destroy(strpath);
631 return temp_info.starting_cluster;
635 old_cluster = current_cluster;
636 current_cluster = temp_info.starting_cluster;
639 string_split_free(pieces);
640 string_destroy(strpath);
642 return current_cluster;
645 int fs_fat32_detect(
char Disk) {
654 dpm_read(Disk, 0, 0,
sizeof(fat_info_t), &fat_system->info);
656 qemu_warn(
"Trying FAT32...");
658 bool is_fat_bootcode = (
unsigned char)fat_system->info.bootcode[0] == 0xEB
659 && (
unsigned char)fat_system->info.bootcode[1] == 0x58
660 && (
unsigned char)fat_system->info.bootcode[2] == 0x90;
662 bool is_fat_fsname =
memcmp(fat_system->info.fs_type,
"FAT32", 0) == 0;
664 if(is_fat_bootcode && is_fat_fsname) {
665 qemu_note(
"FAT filesystem found!");
666 qemu_note(
"Disk label: %.11s", fat_system->info.volume_label);
669 fat_system->cluster_size = fat_system->info.bytes_per_sector * fat_system->info.sectors_per_cluster;
670 fat_system->fat_offset = fat_system->info.reserved_sectors * fat_system->info.bytes_per_sector;
671 fat_system->fat_size = fat_system->info.fat_size_in_sectors * fat_system->info.bytes_per_sector;
672 fat_system->reserved_fat_offset = (fat_system->info.reserved_sectors + fat_system->info.fat_size_in_sectors) * fat_system->info.bytes_per_sector;
673 fat_system->root_directory_offset = ((fat_system->info.reserved_sectors + (fat_system->info.fat_size_in_sectors * 2)) + ((fat_system->info.root_directory_offset_in_clusters - 2) * fat_system->info.sectors_per_cluster)) * fat_system->info.bytes_per_sector;
675 qemu_note(
"Cluster size: %d", fat_system->cluster_size);
676 qemu_note(
"FAT offset: %d", fat_system->fat_offset);
677 qemu_note(
"FAT size: %d", fat_system->fat_size);
678 qemu_note(
"Reserved FAT offset: %d", fat_system->reserved_fat_offset);
679 qemu_note(
"Root directory offset: %d", fat_system->root_directory_offset);
682 dpm_metadata_write(Disk, (uint32_t) fat_system);
684 qemu_log(
"Reading FAT32 FAT table to memory, it may take a while...");
685 fs_fat32_read_entire_fat(Disk);
687 vector_t* root_directory = fs_fat32_get_clusters(Disk, 2);
689 qemu_note(
"[%d] Root occupies folllwing clusters:", root_directory->size);
690 for(
int i = 0; i < root_directory->size; i++) {
691 qemu_note(
"Cluster: %d", vector_get(root_directory, i).element);
694 vector_destroy(root_directory);
696 qemu_warn(
"SCANNING ROOT DIRECTORY");
697 fs_fat32_scan_directory(Disk, 2);
698 qemu_warn(
"END SCANNING ROOT DIRECTORY");
Основные определения ядра
size_t dpm_read(char Letter, uint64_t high_offset, uint64_t low_offset, size_t Size, void *Buffer)
[DPM] Считывание данных с диска
size_t strlen(const char *str)
Возращает длину строки
int strcmp(const char *s1, const char *s2)
Сравнение строк
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
int32_t memcmp(const char *s1, const char *s2, size_t n)
Сравнение массивов
void * memmove(void *dest, void *src, size_t count)
Копирование массивов (в том числе пересекающихся)
void qemu_printf(const char *text,...)
Вывод QEMU через COM1 информации