10
« am: 14. April 2009, 20:46 »
also ein taskswitch kanns nicht sein da ich "noch" kein multitasking habe, relocatet & geladen werden die treiber auch richtig, da die andren treiber(floppy, hdd, dma, usw.) fehlerfrei funktionieren( und die haben auch fast alle globale variablen).
#include "G:\KOV1\libc\system.h"
#define ATTR_READ_ONLY 0x01
#define ATTR_HIDDEN 0x02
#define ATTR_SYSTEM 0x04
#define ATTR_VOLUME_ID 0x08
#define ATTR_DIRECTORY 0x10
#define ATTR_ARCHIVE 0x20
#define DT_FAT12 1
#define DT_FAT16 2
#define DT_FAT32 3
struct BiosParameterBlock
{
unsigned char jmp[3]; // jmp befehl(für bootloader)
unsigned char name[8]; // Der Name (k.p. wofür)
unsigned short bytes_per_sector; // bytes pro sektor
unsigned char sectors_per_cluster; // sektoren pro cluster(kleinste ansprechbare einheit)
unsigned short sectors_reserved; // reservierte sektoren
unsigned char fat_cnt; // anzahl der fats
unsigned short root_entry_cnt; // anzahl der root entrys
unsigned short sectors_cnt_16; // 16-bit angabe der anzahl an sektoren
unsigned char media_type; // typ des mediums
unsigned short fat_size_16; // 16-bit größe der fat
unsigned short sectors_per_track; // wieviele sektoren auf einem track
unsigned char heads_cnt; // anzahl der köpfe
unsigned long hidden_sectors_cnt; // anzahl der versteckten sektoren
unsigned long sectors_cnt_32; // 32-bit anzahl der sektoren
unsigned char drvnum; // welches laufwerk(diskette == 0) is aber eig. egal
unsigned char reserved_for_nt; // für windows nt reserviert
unsigned char boot_signature; // gibt an ob die nächsten 3 felder vorhanden sind(sollte 0x29 sein);
unsigned long volume_id; // identifizierungsnummer meist eine zusammenfassung aus datum und zeit
//unsigned char reserved; // reserviert für kp was
unsigned char volume_label[11]; // die bezeichnung des mediums( der name der unter windoof annezeigt wird)
unsigned char file_sys_name; // name des Dateisystems !! ACHTUNG !! ----> SAGT NICHT WELCHES DATEISYSTEM DA IST!!!
} __attribute__((packed));
struct Fat12_struct
{
char drive_num; // was für ein laufwerk
char reserved1; // reserviert
long volume_id; // identifizierungsnummer des laufwerks
char fs_type[8]; // name des Dateisystems(sollte immer "FAT12 " sein, muss aber nicht)
}__attribute__((packed));
struct Fat12_Entry
{
unsigned char name[11]; // der datei name 8 zeichen name + 3 zeichen endung !!!Punkt ist nicht dabei!!!
unsigned char attr; // das attribute (siehe oben (#define ATTR_*))
unsigned char reserved; // unwichittig
unsigned char crt_time_ms; // erstellungszeit millisekunden, muss noch * 10 gerechnet werden
unsigned short foo; // unwichtig
unsigned short crt_time; // erstellungszeit
unsigned short foo2; // unwichtig
unsigned short wrt_time; // änderungszeit
unsigned short wrt_date; // änderungsdatum
unsigned short foo3; // unwichtig
unsigned short start_sector; // nummer des anfangsclusters
unsigned long size; // die dateigröße
}__attribute__((packed));
struct Fat12_fat
{
unsigned int size; // die größe der Fat
unsigned char *entrys; // die addresse
};
struct Fat32_struct
{
long fat_size; // 32-bit angabe der fat-länge
short flags; // flags
short version; // version
long root_cluster; // das erste cluster
short fs_info; // unwichtig glaub ich
short boot_sector; // bootsektor (sollte 6 sein)
char reserved[12]; // reserviert
char drive_num; // was für ein laufwerk
char reserved1; // reserviert
char boot_signatur; // bootsignatur
long volume_id; // identifizierungsnummer des laufwerks
char volume_label[11]; // name des laufwerks
char fs_type[8]; // name des Dateisystems(immer "FAT32 ")
} __attribute__((packed));
struct Drive
{
char *name; // der name(z.b fd0 für erste floppy oder hd0 für erste festplatte
long start_sec; // der sektor an dem die Partition beginnt
char fstype; // der FS-Type 0 = FAT12; 1 = FAT16; 2 = FAT32
struct BiosParameterBlock *bpb; // der Bios-Parameter-Block
int fat_cnt; // anzahl der FAT's
void *fats; // der zeiger zur fat(zeiger weil noch unbaekant ist waqs für ein dateisystemtyp das ist)
int root_entrys_cnt; // anzahl der einträge im root directory
void *root_entrys; // zeiger auf root dir
unsigned int data_sec; // erster datensektor
};
volatile struct Drive drives[5];
struct FileHandle // speicher die momentan geöffneten dateien
{
unsigned int start_cluster; // das anfangscluster
unsigned int cur_cluster; // der cluster der gelesen werden muss
};
struct FileHandle files[100];
int last_file;
struct BiosParameterBlock bpb;
void scan_drive(int id) // liest ein laufwerk ein id = nummer des laufwerks in drives und readfunc = funktion zum lesen
{
// der Buffer für die daten eines sektors
char buf[512];
// Meldung an benutzer
writestringf("Analysiere Laufwerk \"");
writestring(((struct Drive*)drives)[id].name);
writestring("\".\n");
// den ersten sektor einlesen
SendMessage("hdd", CTLCODE_IO_READSEKTOR, 0, ((struct Drive*)drives)[id].start_sec, buf);
// speicher für biosparamterblockanlegen
((struct Drive*)drives)[id].bpb = mem_alloc((int)sizeof(struct BiosParameterBlock));
// den biosparameterblock nach struct drive kopieren
mem_copy(((struct Drive*)drives)[id].bpb, buf, (int)sizeof(struct BiosParameterBlock)); //readBPB(((struct Drive*)drives)[id].bpb, buf);
// testen ob bpb in ordung ist
/*if(((struct Drive*)drives)[id].bpb->jmp[0] != 0xEB)
{
writestringf("Fehler im Bootsektor!\nDas Laufwerk ist entweder defekt oder unformatiert! %x %x %x %x\n", ((struct Drive*)drives)[id].bpb->jmp[0], ((struct Drive*)drives)[id].bpb->jmp[1], ((struct Drive*)drives)[id].bpb->jmp[2], ((struct Drive*)drives)[id].bpb->jmp[3]);
int t;
char *b = (char *)((struct Drive*)drives)[id].bpb;
for(t = 0; t < 512; t++)
{
writestringf("%x", b[t]);
}
b = buf;
for(t = 0; t < 512; t++)
{
writestringf("%x", b[t]);
}
return;
}*/
// ausgeben des datenträgernamens
writestring("Datenträgerbezeichnung ist ");
int dni;
for(dni = 0; dni < 11; dni++)
{
writechar(((struct Drive*)drives)[id].bpb->volume_label[dni]);
}
writestring("\n");
// die anzahl der cluster( zur bestimmung welches dateisystem)
long clus_cnt;
// üerprüfen ob 32 oder 16 bit wert genommen werden muss
if(((struct Drive*)drives)[id].bpb->sectors_cnt_32 == 0)
{
clus_cnt = ((struct Drive*)drives)[id].bpb->sectors_cnt_16;
}
else
{
clus_cnt = ((struct Drive*)drives)[id].bpb->sectors_cnt_32;
}
// die reservierten sektoren abziehen
clus_cnt -= ((struct Drive*)drives)[id].bpb->sectors_reserved;
// die größe der fat abziehen
clus_cnt -= (((struct Drive*)drives)[id].bpb->fat_cnt * ((struct Drive*)drives)[id].bpb->fat_size_16);
// die größe vom root-dir abziehen
clus_cnt -= (((struct Drive*)drives)[id].bpb->root_entry_cnt * 32) / 512;
// meldung das teil eins fertig ist
writestring("Dateisystem ist ");
// anhand von anzahl der cluster den dateisystemtyp bestimmen
if(clus_cnt > 65525)
{
// FAT32
((struct Drive*)drives)[id].fstype = DT_FAT32;
// meldung
writestring("Fat32\n");
}
else if((clus_cnt < 65525) && (clus_cnt > 4085))
{
// FAT 16
((struct Drive*)drives)[id].fstype = DT_FAT16;
// meldung
writestring("Fat16\n");
// zur fat 12 auslesung gehn
}
else if(clus_cnt < 4085)
{
// FAT 12
((struct Drive*)drives)[id].fstype = DT_FAT12;
// meldung
writestring("Fat12\n");
}
if((((struct Drive*)drives)[id].fstype == DT_FAT12) || (((struct Drive*)drives)[id].fstype == DT_FAT16))
{
// anzahl der fats eintragen
((struct Drive*)drives)[id].fat_cnt = ((struct Drive*)drives)[id].bpb->fat_cnt;
// temporärer verweis auf die fat( weil in drive struktur ein void pointer is und ich zu faul bin jedesmal ((struct Fat12_fat *)((struct Drive*)drives)[id].fat) zu schreiben)
struct Fat12_fat *fat_tmp;
// speicher für FAT's reservieren
fat_tmp = mem_alloc(sizeof(struct Fat12_fat) * ((struct Drive*)drives)[id].fat_cnt);
// begin der ersten fat suchen
int fat_begin = ((struct Drive*)drives)[id].bpb->sectors_reserved;
// index zum durchgehen der fats
int i = 0;
// meldung
writestringf("Lese FAT");
// fats durchgehen und laden
for(i = 0; i < ((struct Drive*)drives)[id].fat_cnt; i++)
{
// die größe festlegen (in 512 byte blöcken)
fat_tmp[i].size = ((struct Drive*)drives)[id].bpb->fat_size_16;
// speicher für die einträge reservieren
fat_tmp[i].entrys = mem_alloc((fat_tmp[i].size * 512));
// einträge nullen
mem_set(fat_tmp[i].entrys, 0, (fat_tmp[i].size * 512) );
// der buffer für das einlesen der fat
unsigned char *fatbuf = mem_alloc((fat_tmp[i].size * 512));
// den buffer leeren
mem_set(fatbuf, 0, (fat_tmp[i].size * 512));
// der index des aktuellen sektors
int j;
// die schleife zum einlesen
for(j = 0; j < (fat_tmp[i].size); j++)
{
// einlesen in den buffer
SendMessage("hdd", CTLCODE_IO_READSEKTOR, 0, ((struct Drive*)drives)[id].start_sec + fat_begin + j + (fat_tmp[i].size * i) , fatbuf+(j*512));
writestring(".");
}
if(fatbuf[0] != 0xF0)
{
writestring("Ungültige fat\n");
return;
}
if(fatbuf[1] != 0xFF)
{
writestring("Ungültige fat\n");
return;
}
if(fatbuf[2] != 0xFF)
{
writestring("Ungültige fat\n");
return;
}
mem_copy(fat_tmp[i].entrys, fatbuf, (fat_tmp[i].size+1) * 512);
/*
// momentaner fat eintrag
int pos = 0;
// index initialisieren
j = 0;
// temporärer wert
unsigned short tmp;
// die 12 bit werte in 16 bit werte konvertieren
for(j = 0, pos = 0; j < (fat_tmp[i].size * 512); j++, pos++)
{
tmp = *((unsigned short *) &fatbuf[j]);
// *((unsigned short *) ((fatbuf + j)));
if((j & 0x0001))
{
tmp = tmp >> 4; // bei ungeraden wert
}
else
{
tmp = (tmp & 0x0FFF); // bei geraden wert
}
//writestringf(" %i", tmp);
fat_tmp[i].entrys[pos] = tmp;
//writestringf(" = %i", fat_tmp[i].entrys[pos]);
/*fat_tmp[i].entrys[pos++] = (((int)fatbuf[j]) << 4) | ((int)((fatbuf[j+1]) & 0xF0));
j++;
fat_tmp[i].entrys[pos++] = (((int)((fatbuf[j]) & 0x0F)) << 8) | ((int)((fatbuf[ + 1])));
j++;
*/
//fat_tmp[i].entrys[pos++] = (*ft) & 0xFFF0;
/*
fat_tmp[i].entrys[pos++] = ((((unsigned short)fatbuf[j+0])) << 4) + (fatbuf[j+1] & 0xF0);
fat_tmp[i].entrys[pos++] = (((((unsigned short)fatbuf[j+1]) & 0x0F)) << 8) + (fatbuf[j+2]);
*/
//writestringf("%i ", (unsigned long)tmp);
// eintragen in fat
//fat_tmp[i].entrys[pos++] = c2;
}
/*if(fat_tmp[i].entrys[0] != 0xF0F)
{
writestringf("\nFehlerhafte FAT!!!\nEintrg 0 ist %i", fat_tmp[i].entrys[0]);
}
if(fat_tmp[i].entrys[1] != 0xFFF)
{
writestringf("\nFehlerhafte FAT!!!\nEintrg 1 ist %i", fat_tmp[i].entrys[1]);
}*/
//}
// meldung
writestring("OK.\n");
// in die drive struktur eintragen
((struct Drive*)drives)[id].fats = fat_tmp;
// fat1 mit fat 2 abgleichen um fehler zu finden
for(i = 0; i < fat_tmp[0].size; i++)
{
if(((struct Fat12_fat*)((struct Drive*)drives)[0].fats)[0].entrys[i] != ((struct Fat12_fat*)((struct Drive*)drives)[0].fats)[1].entrys[i])
{
writestring("Fehler in FAT!( Eintrag ");
writestringf("%i", i);
writestring(")\n");
break;
}
}
// anzahl der RootDir einträge in die Drive struktur packen
((struct Drive*)drives)[id].root_entrys_cnt = ((struct Drive*)drives)[id].bpb->root_entry_cnt;
// speicher für root-dir anlegen
struct Fat12_entry *rootdirs = mem_alloc(((struct Drive*)drives)[id].root_entrys_cnt * 32);
// anzahl der belegten sektoren
int root_dir_secs = (((struct Drive*)drives)[id].root_entrys_cnt * 32) / 512;
// tempörärer buffer
char *rdbuf = mem_alloc(root_dir_secs * 512);
// startsektor
int rd_begin = ((struct Drive*)drives)[id].bpb->sectors_reserved + ( ((struct Drive*)drives)[id].fat_cnt * ((struct Drive*)drives)[id].bpb->fat_size_16);
// meldung
writestring("Lese RootDir");
// schleife zum einlesen
for(i = 0; i < root_dir_secs; i++)
{
// meldung
writestring(".");
// einlesen in den buffer
SendMessage("hdd", CTLCODE_IO_READSEKTOR, 0, ((struct Drive*)drives)[id].start_sec + rd_begin + i, rdbuf+(i*512));
}
// buffer nach rootdirs casten
rootdirs = (struct Fat12_entry*) rdbuf;
// in struct drive übertragen
((struct Drive*)drives)[id].root_entrys = rootdirs;
// beginn des datensektors eintragen
((struct Drive*)drives)[id].data_sec = (((struct Drive*)drives)[id].bpb->fat_cnt * ((struct Drive*)drives)[id].bpb->fat_size_16) + 13;
// meldung
writestring("OK.\n");
}
}
char *name;
char *getName()
{
name = "fs";
return name;
}
int getType()
{
return 1;
}
int getClusterValueFAT12(int id, int cn)
{
unsigned short cv = 0;
unsigned char *ba = ((unsigned short*)((struct Fat12_fat*)((struct Drive*)drives)[id].fats)[0].entrys);
int of = (cn * 3) / 2;
cv = *((unsigned short *)(ba + of));
/*writestringf("GCV: %i", cn);
writestringf(" %i", of);
*/
if((cn % 2) != 0)
{
cv = cv >> 4;
}
else
{
cv = cv & 0x0FFF;
}
return cv;
}
int getClusterValueFAT16(int id, int cn)
{
unsigned short *ba = ((struct Fat12_fat*)((struct Drive*)drives)[id].fats)[0].entrys;
ba += cn;
return *(ba);
}
int fread(int id, char *buf)
{
writestringf("DA: %X", drives);
int did = 0;
if(((struct Drive*)drives)[did].fstype == DT_FAT12)
{
if(files[id].cur_cluster == 0x0FFF)
{
//writestring("OK(Letzter)\n");
return 0;
}
if(files[id].cur_cluster == 0)
{
writestring("Fehler: Datei belegt ein als Frei markiertes Cluster!!!\n");
return -1;
}
if(files[id].cur_cluster == 0x0FF7)
{
writestring("Fehler: Datei belegt ein als Defekt markiertes Cluster!!!\n");
return -1;
}
if(files[id].cur_cluster > 2880)
{
writestring("Fehler: Datei belegt ein Cluster, welches zu groß ist!!!\n");
return -1;
}
}
if(((struct Drive*)drives)[did].fstype == DT_FAT16)
{
if(files[id].cur_cluster == 0xFFFF)
{
writestring("OK(Letzter)\n");
return 0;
}
if(files[id].cur_cluster == 0)
{
writestring("Fehler: Datei belegt ein als Frei markiertes Cluster!!!\n");
return -1;
}
if(files[id].cur_cluster == 0xFFF7)
{
writestring("Fehler: Datei belegt ein als Defekt markiertes Cluster!!!\n");
return -1;
}
if(files[id].cur_cluster > 2880)
{
writestring("Fehler: Datei belegt ein Cluster, welches zu groß ist!!!\n");
return -1;
}
}
if((((struct Drive*)drives)[did].fstype != DT_FAT12) && (((struct Drive*)drives)[did].fstype != DT_FAT16) )
{
writestringf("Ungueltiges Dateisystem(lw: %i fstype: %i)\n", did, ((struct Drive*)drives)[did].fstype);
return -1;
}
//writestringf("Lese Block %i\n", (unsigned int)files[id].cur_cluster);
SendMessage("hdd", CTLCODE_IO_READSEKTOR, 0, ((struct Drive*)drives)[did].start_sec + ((struct Drive*)drives)[did].data_sec + files[id].cur_cluster, buf);
switch(((struct Drive*)drives)[did].fstype)
{
case DT_FAT12:
writestringf("%i", files[id].cur_cluster);
writestringf("-->%i ", getClusterValueFAT12(0, files[id].cur_cluster));
files[id].cur_cluster = getClusterValueFAT12(0, files[id].cur_cluster);
break;
case DT_FAT16:
writestringf("%i", files[id].cur_cluster);
writestringf("-->%i ", getClusterValueFAT16(0, files[id].cur_cluster));
files[id].cur_cluster = getClusterValueFAT16(0, files[id].cur_cluster);
break;
}
return 1;
}
int fopen(char *path, unsigned long *size)
{
writestringf("DA: %X ", drives);
char *path83 = convert_to83(path);
int did = 0;
((struct Drive*)drives)[did].fstype = DT_FAT16;
if((((struct Drive*)drives)[did].fstype != DT_FAT12) && (((struct Drive*)drives)[did].fstype != DT_FAT16) )
{
writestringf("Konnte Datei \"%s\" nicht finden. Ungueltiges Dateisystem(lw:%i fstype: %i)\n", path, did, ((struct Drive*)drives)[did].fstype);
return -1;
}
//writestring("Suche Datei");
int i;
for(i = 0; i < ((struct Drive*)drives)[did].root_entrys_cnt; i++)
{
if(((struct Fat12_Entry*)((struct Drive*)drives)[did].root_entrys)[i].name[0] == 0x0E)
{
continue;
}
if(((struct Fat12_Entry*)((struct Drive*)drives)[did].root_entrys)[i].name[0] == 0xE5)
{
continue;
}
if(cmp_filename(path83, ((struct Fat12_Entry*)((struct Drive*)drives)[did].root_entrys)[i].name) == 0)
{
//writestring("found");
struct Fat12_Entry ent = ((struct Fat12_Entry*)((struct Drive*)drives)[did].root_entrys)[i];
*size = ent.size;
long ss = ent.start_sector;
last_file = 1;
/* writestringf("Datei beginnt in cluster %i", ss);
writestring("\n");*/
files[last_file].start_cluster = ss;
files[last_file].cur_cluster = ss;
last_file++;
return last_file-1;
}
}
return -1;
}
// finden den anfang einer partition, durch lesen des MBR
long GetPartitionStart(int did, int pid)
{
// buffer für mbr
char *mbrbuf = mem_alloc(512);
// lesen
SendMessage("hdd", CTLCODE_IO_READSEKTOR, 0, 0, mbrbuf);
// anfang berechnen
long s = *((long *)(((mbrbuf + 0x01BE) + ( pid * 16)) + 0x8 ));
return s;
}
int init()
{
//writestring("Dateisystem Treiber 0.1 - geschrieben von Florian Reinhard\n");
name = "fs";
//drives = mem_alloc(sizeof(struct Drive) * 5);
writestringf("DA: %X ", drives);
writestringf("DA: %X ", drives);
((struct Drive*)drives)[0].name = "hd0";
((struct Drive*)drives)[0].start_sec = GetPartitionStart(0, 0);
scan_drive(0);
last_file = 0;
writestringf("DA: %X ", drives);
writestringf("DA: %X ", drives);
//writestring("\nInit fertig!!!\n");
return 0;
}
die funktioien init, getName, GetType, fopen und fread werden vom Kernel aufgerufen. ein paar funktionen hab ich rausgelassen, weil der text snst zu lang geworden wäre, diese haben aber nur dateinamen nach 8.3 konvertiert etc.