COBE 0.1 ALPHA
|
00001 #include <fat.h> 00002 #include <stdint.h> 00003 #include <fdc.h> 00004 #include <stdio.h> 00005 #include <pic.h> 00006 #include <pmm.h> 00007 00013 00014 boot_fat_table_t* table; 00016 uint32_t sec_actdir; //----------Der Sektor des aktuellen Verzeichnis---------- 00018 uint8_t act_drive;//----------Das aktuelle Laufwerk (Floppy)---------- 00020 char curr_dir[90]; //----------Der aktuelle Verzeichnispfad---------- 00022 directory_t* first_dir = NULL; //----------Das erste Listenteil der Verzeichnisliste---------- 00024 directory_t* curr_dir_t = NULL; //----------Das aktuelle Listenteil der Verzeichnisliste---------- 00026 uint32_t first_data; //----------Der erste Datensektor nach dem Bootsektor und reservierten Sektoren---------- 00028 uint32_t start_dir_list; //----------Adresse der neu anzulegenenden Verzeichnisliste---------- 00030 uint32_t dir_size; 00031 uint8_t boot_run; 00033 uint8_t long_file_name_set; 00034 extern uint8_t booted; 00036 00043 void init_fat() { 00044 fat_get_boot(table); //----------Schreibe die Informationen aus dem Bootsektor in die Tabelle---------- 00045 sec_actdir = (uint32_t)(table->reserved_sectors + (table->sectors_of_fat * table->num_of_fats)); //----------Berechne den Sektor des Wurzelverzeichnis---------- 00046 first_data = sec_actdir + (table->max_entry_workdirectory / (512 / 32)); //----------Setze den Sektor des Wurzelverzeichnis als ersten Datensektor(, was er auch ist bei FAT12/16)---------- 00047 act_drive = 0; //----------Setze das erste Laufwerk als aktuelles Laufwerk---------- 00048 kstrcpy("/",curr_dir); //----------Setze das Wurzelverzeichnis als ersten Verzeichnispfad---------- 00049 start_dir_list = (uint32_t)pmm_alloc(); //----------Reserviere einen Speicherblock für die Listen---------- 00050 first_dir->next = NULL;//----------Setze den das nächste Listenteil des ersten voerst auf NULL---------- 00051 dir_size = table->max_entry_workdirectory; 00052 long_file_name_set = 0; 00053 //fat_show_directory(); 00054 } 00056 00066 void fat_show_directory() { 00068 char long_name[255]; 00069 uint8_t dir_entry[512]; //----------Lege Daten für den Verzeichniseintrag an(ein Sektor groß)---------- 00070 fat_copy_act_sector((void*)dir_entry,sec_actdir,false); 00071 char* header = "__NAME__ __ART__ __GROESSE__"; 00072 long_file_name_set = 0; 00073 uint8_t first = 0; 00074 long_name[0] = '\0'; 00075 first_dir->next = NULL;//----------Setze den das nächste Listenteil des ersten voerst auf NULL---------- 00076 uint16_t toread_sectors = dir_size / 16; if(toread_sectors == 0) toread_sectors = 1; 00077 00078 kprintf("\n\t%s\n",header); //----------Header der Anzeige---------- 00079 for(uint16_t k = 0; k < toread_sectors; k++) { //----------Führe das ganze für jeden belegten Sektor aus---------- 00080 00081 for(uint16_t i = 1; i < 16+1; i++) { //----------Füre dies für 16 Einträge aus---------- 00082 00083 char name[9]; //----------Lege ein Array für den Namen an---------- 00084 char ext[4]; //----------Lege ein Array für die Dateiendung an---------- 00085 00086 if(dir_entry[(i*32)+0x0B] == 0x0F){ //----------Wenn es sich um ein LongFileName Eintrag handelt, kopiere nur den Dateinamen heraus---------- 00087 for(signed short j = 1; j < 11; j += 2) { 00088 if(dir_entry[(i*32)+j] == 0x0) { long_name[((j+1)/2)-1] = 0x20; continue; } 00089 long_name[((j+1)/2)-1] = dir_entry[(i*32)+j]; 00090 } name[11] = '\0'; 00091 for(signed short j = 0x0C; j < 13+0x0E; j += 2) { 00092 if(dir_entry[(i*32)+j] == 0x0) {long_name[((j+1)/2)-1] = 0x20; continue; } 00093 long_name[((j+1)/2)-1] = dir_entry[(i*32)+j]; 00094 } name[23] = '\0'; 00095 long_file_name_set = 1; 00096 continue; //----------Überspringe den Rest!---------- 00097 } 00098 else { 00099 if(long_file_name_set == 0) for(uint8_t j = 0; j < 8; j++) long_name[j] = dir_entry[(i*32)+j]; long_name[8] = '\0'; //----------Schreibe den Namen aus dem Array in das Namen-Array---------- 00100 if(long_name[0] == 0x0) return; 00101 if(long_name[0] == 0xE5 || long_name[0] == 0x0E) continue; //----------Dateinamen die mit 0x0, 0x0E oder 0xE5 anfangen sind keine Verzeichniseinträge---------- 00102 for(uint8_t j = 0; j < 3; j++) ext[j] = dir_entry[(i*32)+8+j]; ext[3] = '\0'; //----------Schreibe die Dateiendung aus dem Array in das Dateiendung-Array---------- 00103 long_file_name_set = 0; 00104 } 00105 00106 uint8_t type = dir_entry[(i*32)+0x0B]; //----------Hole den Dateityp aus dem Array---------- 00107 up_to_low(long_name); 00108 00109 if(type == 0x10) { //----------Wenn es ein Verzeichnis ist, mache ein neues Listenelement---------- 00110 directory_t* new_dir = (void*)start_dir_list; //----------Lege ein Listenelement im reservierten Speicherblock an---------- 00111 start_dir_list += sizeof(directory_t); //----------Erhöhre die Adresse für die nächste Liste--------- 00112 kstrcpy(long_name,new_dir->name); //----------Setze den Namen des Verzeichnis---------- 00113 delete_rep_character(new_dir->name,' ',true); 00114 new_dir->cluster = dir_entry[(i*32)+0x1B]; //----------Lies den Startcluster des Verzeichniseintrags aus---------- 00115 new_dir->cluster = new_dir->cluster << 8; 00116 new_dir->cluster += dir_entry[(i*32)+0x1A]; 00117 00118 if(first != 0) curr_dir_t->next = new_dir; //----------Setze den Nachfolger des aktuellen Eintrags auf diesen Eintrag---------- 00119 curr_dir_t = new_dir; //----------Setze den aktuellen auf diesen Eintrag---------- 00120 if(first == 0) first_dir->next = new_dir; //----------Wenn das erste Element noch keinen Nachfolger hat, ist dies der erste---------- 00121 first = 1; //----------Alle folgenden Einträge werden direkt mit einem next belegt---------- 00122 curr_dir_t->next = NULL; //----------Setze den Nachfolger auf NULL, da es noch keinen gibt---------- 00123 } 00124 00125 uint32_t size = dir_entry[(i*32)+0x1F]; //----------Hole die Größe des Verzeichnis(Datei) aus dem Array---------- 00126 size = size << 8; 00127 size += dir_entry[(i*32)+0x1E]; 00128 size = size << 8; 00129 size += dir_entry[(i*32)+0x1D]; 00130 size = size << 8; 00131 size += dir_entry[(i*32)+0x1C]; 00132 00133 if(booted == 0) return; 00134 if(long_name[0] != 0xE5) kprintf("\n\t%s",long_name); position_x = 14; //----------Gib den Namen des Verzeichnis(Datei) aus---------- 00135 for(uint16_t i = 0; i < 255; i++) long_name[i] = 0x0; 00136 switch(type) 00137 { 00138 case 0x10: kprintf("DIR");break; //----------Gib die Art des Eintrages an (0x10 ist ein Verzeichnis)---------- 00139 default: kprintf("%s",ext);break; 00140 } 00141 00142 position_x = 22; 00143 if(type != 0x10) { if(size / 1000 > 0) kprintf("%d KByte", size / 1000); else kprintf("%d Byte", size); }//----------Gib die Größe des Verzeichnis(Datei) aus---------- 00144 } 00145 sec_actdir++; //----------Erhöhre den Sektor und lies den nächsten aus---------- 00146 fat_copy_act_sector((void*)dir_entry,sec_actdir,false); 00147 } 00148 00149 sec_actdir -= 13; 00150 } 00151 00153 00161 void fat_change_directory(char* new_dir) { 00162 curr_dir_t = first_dir; //----------Setze am Anfang das erste als aktuelle Listenteil---------- 00163 while(curr_dir_t->next != NULL) { //----------Solange das nächste Listenteil nicht NULL ist, mach weiter---------- 00164 curr_dir_t = curr_dir_t->next; //----------Setze das nächste Listenteil als aktuelles---------- 00165 if(!kstrcmp(curr_dir_t->name,new_dir)) { //----------Wenn das Verzeichnis in der Liste gefunden wurde, errechne den Sektor und setze diesen---------- 00166 sec_actdir = ((curr_dir_t->cluster - 2) * table->cluster_size) + first_data; 00167 dir_size = 1; 00168 char* slash = "/"; 00169 kstrcpy(curr_dir_t->name, (char*)(&curr_dir+kstrlen(curr_dir)+1)); kstrcpy(slash, (char*)(&curr_dir+kstrlen(curr_dir)+1)); 00170 kprintf("\n Ordner gewechselt in %s", curr_dir_t->name); 00171 return; 00172 } 00173 } 00174 kprintf("\n Ordner nicht gefunden!"); 00175 } 00176 00178 00190 void fat_mkdir(char* name) { 00191 uint8_t dir_entry[512]; //----------Lege Daten für den Verzeichniseintrag an, damit der Sektor dort hinein geschrieben werden kann---------- 00192 uint8_t empty_entry[512] = {0}; 00193 uint8_t entry[32]; 00194 void* start_long; 00195 00196 for(uint16_t j = 0; j < 32; j++) entry[j] = 0x0; //------------Array mit 0en belegen, da Datenmüll nicht zu verantworten wäre bei einem Eintrag---------- 00197 00198 if(kstrlen(name) < 9) { 00199 low_to_up(name); 00200 for(uint16_t j = 0; j < 8; j++) { if(name[j] == 0x0 || name[j] < 0x20 || name[j] == 0x22 || name[j] == 0x2A || name[j] == 0x2B || name[j] == 0x2C || name[j] == 0x2E || name[j] == 0x2F || name[j] == 0x3A || name[j] == 0x3B || name[j] == 0x3C || name[j] == 0x3D || name[j] == 0x3E || name[j] == 0x3F || name[j] == 0x5B || name[j] == 0x5C || name[j] == 0x5D || name[j] == 0x7C) name[j] = 0x20; } 00201 for(uint16_t j = 0; j < 8; j++) entry[j] = name[j]; //------------Wenn der Ordnername weniger als 8 Buchstaben hat, braucht man nur ein Eintrag---------- 00202 } else { 00203 for(uint16_t j = 0; j < 8; j++) entry[j] = name[j]; //------------Wenn mehr, dann muss eine LongNameEintragsliste angelegt werden---------- 00204 start_long = fat_long_name(name); 00205 } 00206 00207 entry[0x0B] = 0x10; //------------Der Typ ist 0x10, da 0x10 für ein Ordner steht---------- 00208 for(uint8_t j = 0; j < 3; j++) entry[0x08+j] = 0x20; //------------Dateiendung mit 0x20en belegen, denn ein Directory hat keine Endung---------- 00209 uint16_t cluster = fat_get_cluster(); //------------Einen freien Cluster für die Datei bekommen, der dann im Eintrag steht---------- 00210 if(cluster == 0xFFFFFFFF) { kprintf("Diskette voll!"); return;} 00211 entry[0x1A] = cluster & 0xFF; 00212 entry[0x1B] = (cluster << 8) & 0xFF; 00213 00214 uint16_t toread_sectors = dir_size / 16; 00215 if(toread_sectors == 0) toread_sectors = 1; 00216 00217 uint8_t search_done = 0; 00218 uint16_t sec_temp = sec_actdir; 00219 for(uint16_t k = 0; k < toread_sectors; k++) { //----------Führe das ganze für jeden belegten Sektor des Ordners aus---------- 00220 if(search_done) break; 00221 fat_copy_act_sector((void*)dir_entry,sec_temp,false); 00222 for(uint16_t i = 0; i < 16; i++) { //----------Füre dies für 16 Einträge aus---------- 00223 if(dir_entry[(i*32)+0x0] == 0x0 || dir_entry[(i*32)+0x0] == 0x0E) { 00224 00225 for(uint16_t j = 0; j < 32; j++) dir_entry[((i)*32)+j] = entry[j]; 00226 search_done = 1; 00227 fat_copy_act_sector((void*)dir_entry,sec_temp,true); //------------Nun wieder alles zurück auf die Diskette, damit der Ordner auch vorhanden sein kann---------- 00228 break; 00229 } //------------Schreibe den Eintrag in einen freien Verzeichniseintragsbereich---------- 00230 } 00231 sec_temp++; 00232 } 00233 00234 empty_entry[0] = 0x2E; 00235 for(uint8_t i = 1; i < 12;i++) empty_entry[i] = 0x20; 00236 empty_entry[11] = 0x10; 00237 empty_entry[0x1A] = cluster & 0xFF; 00238 empty_entry[0x1B] = (cluster << 8) & 0xFF; 00239 00240 uint16_t temp_cluster = cluster; 00241 00242 cluster = sec_actdir - first_data + 2; 00243 empty_entry[0+32] = 0x2E; 00244 empty_entry[1+32] = 0x2E; 00245 for(uint8_t i = 2; i < 12;i++) empty_entry[i+32] = 0x20; 00246 empty_entry[11+32] = 0x10; 00247 empty_entry[0x1A+32] = cluster & 0xFF; 00248 empty_entry[0x1B+32] = (cluster << 8) & 0xFF; 00249 00250 fat_copy_act_sector((void*)empty_entry,(temp_cluster-2)+first_data,true); 00251 00252 kprintf("\nDer Ordner %s wurde erstellt!",name); 00253 return; 00254 } 00255 00257 00267 void fat_del(char* name) { 00268 uint8_t dir_entry[512]; 00269 00270 uint16_t toread_sectors = dir_size / 16; 00271 if(toread_sectors == 0) toread_sectors = 1; 00272 00273 uint8_t search_done = 0; 00274 char dir_name[9]; 00275 uint16_t sec_temp = sec_actdir; 00276 for(uint16_t k = 0; k < toread_sectors; k++) { //----------Führe das ganze für jeden belegten Sektor des Ordners aus---------- 00277 if(search_done) break; 00278 fat_copy_act_sector((void*)dir_entry,sec_temp,false); 00279 for(uint16_t i = 0; i < 16; i++) { //----------Führe dies für 16 Einträge aus---------- 00280 for(uint16_t j = 0; j < 8; j++) dir_name[j] = dir_entry[(i*32)+j]; 00281 if(!kstrcmp(dir_name,name)) { 00282 dir_entry[((i-1)*32)] = 0xE5; 00283 uint16_t cluster; 00284 cluster = dir_entry[(i*32)+0x1B]; 00285 cluster = cluster << 8; 00286 cluster += dir_entry[(i*32)+0x1A]; 00287 search_done = 1; 00288 fat_copy_act_sector((void*)dir_entry,sec_temp,true); //------------Nun wieder alles zurück auf die Diskette, damit der Ordner auch vorhanden sein kann---------- 00289 fat_change_cluster(cluster,0x0); 00290 break; 00291 } //------------Schreibe den Eintrag in einen freien Verzeichniseintragsbereich---------- 00292 } 00293 sec_temp++; 00294 } 00295 kprintf("\n%s wurde erfolgreich gelöscht!",name); 00296 } 00297 00299 00309 void fat_change_cluster(uint16_t para_cluster, uint16_t val) { 00310 00311 uint32_t offset = 0; 00312 uint8_t fat_table[9 * 512]; 00313 00314 for(uint8_t i = 0; i < table->sectors_of_fat; i++) fat_copy_act_sector((fat_table + (i*512)),i+1,false); 00315 00316 for(uint32_t cluster = 2; cluster < ((table->sectors_of_fat * 512) / 3)+2; cluster++) { 00317 uint16_t entry = *(uint16_t*)&fat_table[offset/8]; 00318 offset += 12; 00319 00320 if(cluster == para_cluster) { 00321 00322 if(cluster % 2) { 00323 entry = entry >> 4; 00324 } 00325 else { 00326 entry = entry & 0x0FFF; 00327 } 00328 00329 if(cluster % 2) { 00330 entry = val; 00331 *(uint16_t*)&fat_table[(offset/8)-1] = entry & 0xFFF; 00332 } 00333 else { 00334 entry = val; 00335 *(uint16_t*)&fat_table[(offset/8)-1] = entry & 0x0FFF; 00336 } 00337 00338 for(uint8_t i = 0; i < table->sectors_of_fat; i++) fat_copy_act_sector((fat_table + (i*512)),i+1,true); 00339 for(uint8_t i = 9; i < table->sectors_of_fat+9; i++) fat_copy_act_sector((fat_table + ((i-9)*512)),i+1,true); 00340 break; 00341 } 00342 } 00343 return; 00344 } 00345 00347 00357 void fat_copy_act_sector(void* buffer, uint16_t act_sector, bool write) { 00358 uint8_t head = (act_sector % (2 * 18)) / 18; //----------Berechne den Head aus der Gesamt-Sektor-Nummer (LBA-Formel), für den Copy-Sector-Befehl---------- 00359 uint8_t cylinder = act_sector / (2 * 18); //----------Berechne den Cylinder aus der Gesamt-Sektor-Nummer (LBA-Formel), für den Copy-Sector-Befehl---------- 00360 uint8_t sector = ((act_sector %(2 * 18)) % 18) + 1; //----------Berechne den eigentlichen Sektor aus der Gesamt-Sektor-Nummer (LBA-Formel), für den Copy-Sector-Befehl---------- 00361 copy_sector(act_drive, head, cylinder, sector, buffer, write); //----------Lies den Sektor aus, um einen freien Verzeichniseintrag zu finden--------- 00362 } 00363 00365 00374 void* fat_long_name(char* name) { 00375 return 0; 00376 } 00377 00379 00387 uint32_t fat_get_cluster() { 00388 uint32_t address = 0; 00389 uint32_t offset = 0; 00390 uint8_t fat_table[9 * 512]; 00391 00392 for(uint8_t i = 0; i < table->sectors_of_fat; i++) fat_copy_act_sector((fat_table + (i*512)),i+1,false); 00393 for(uint32_t cluster = 2; cluster < ((table->sectors_of_fat * 512) / 3)+2; cluster++) { 00394 00395 uint16_t entry = *(uint16_t*)&fat_table[offset/8]; 00396 offset += 12; 00397 00398 if(cluster % 2) { 00399 entry = entry >> 4; 00400 } 00401 else { 00402 entry = entry & 0x0FFF; 00403 } 00404 if(entry == 0x0) { 00405 address = cluster; 00406 if(cluster % 2) { 00407 entry = 0xFFF; 00408 *(uint16_t*)&fat_table[(offset/8)-1] = entry & 0xFFF; 00409 } 00410 else { 00411 entry = 0x0FFF; 00412 *(uint16_t*)&fat_table[(offset/8)-1] = entry & 0x0FFF; 00413 } 00414 00415 for(uint8_t i = 0; i < table->sectors_of_fat; i++) fat_copy_act_sector((fat_table + (i*512)),i+1,true); 00416 for(uint8_t i = 9; i < table->sectors_of_fat+9; i++) fat_copy_act_sector((fat_table + ((i-9)*512)),i+1,true); 00417 return address - 2; 00418 } 00419 } 00420 return 0xFFFFFFFF; 00421 } 00422 00424 00433 void fat_get_boot(boot_fat_table_t* fat_table) { 00434 uint8_t bootsector[512]; //----------Lege ein Array für den Bootsektor an---------- 00435 __asm("sti"); //----------Aktiviere Interrupts, da beim auslesen der IRQ6 gesendet werden muss---------- 00436 copy_sector(0,0,0,1,bootsector,false); __asm("cli"); //----------Kopiere den Bootsektor---------- 00437 fat_table->cluster_size = bootsector[0x0D]; //----------Lies aus, wie viele Sektoren einen Cluster bilden, bei Floppy meist 1(512Byte), bei Platte meist 8(4096Byte)---------- 00438 00439 fat_table->reserved_sectors = bootsector[0x0F]; //----------Lies die Anzahl der reservierten Sektoren vor dem ersten Datensektor aus---------- 00440 fat_table->reserved_sectors = fat_table->reserved_sectors << 8; 00441 fat_table->reserved_sectors += bootsector[0x0E]; 00442 00443 fat_table->num_of_fats = bootsector[0x10]; //----------Lies die Anzahl der FATs aus, meist 2---------- 00444 00445 fat_table->max_entry_workdirectory = bootsector[0x12]; //----------Lies die Anzahl der maximalen Verzeichniseinträge im Wurzelverzeichnis aus, meist 244---------- 00446 fat_table->max_entry_workdirectory = fat_table->max_entry_workdirectory << 8; 00447 fat_table->max_entry_workdirectory += bootsector[0x11]; 00448 00449 fat_table->sectors_of_fat = bootsector[0x17]; //----------Lies die Sektoren einer FAT-Größe aus(meistens 9 Sektoren)---------- 00450 fat_table->sectors_of_fat = fat_table->sectors_of_fat << 8; 00451 fat_table->sectors_of_fat += bootsector[0x16]; 00452 }