COBE 0.1 ALPHA

D:/COBE-Packet/cobe/system/fat.c

gehe zur Dokumentation dieser Datei
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; //----------&Uuml;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 }
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Makrodefinitionen