Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - AcidIO

Seiten: [1]
1
Lowlevel-Coding / Re: Registerübergabe von ASM an C
« am: 15. November 2009, 01:09 »
Zitat
Die CPU_Register sind ja alle unterschiedlich groß. (Es gibt 32bit, 16bit, ...)
Warum werden in allen Tuts die Register in jeweils einen int gepackt? Wenn sie doch unterschiedlich groß sind, müsste man doch auch unterschiedliche Datentypen nehmen.

Das liegt daran, dass die Register auf dem Stack(welchen du als Pointer an die Funktion übergibts) alle 32-Bit groß sind.

Zitat
Aber es funktioniert nicht. Der ISR-handler wird zwar aufgerufen, aber als Description kommen nur 3 kryptische Zeichen.

Hast du daran gedacht, dass dein C-Fault-Handler als Parameter einen Pointer auf SISRParam haben muss, da du ja nur den Stackpointer als Parameter übergibst? Könntest du deinen C-Fault-Handler vlt. mal posten?
2
Also ich glaub ich werte verückt.....

Bei einem pop wird doch normalerweise der wert [esp] geholt und esp um vier erhöht.
Jetzt wird in meiner make_rpc funtion, der stack erniedrigt und dabei werte gesetzt(so wie beim erstellen eines Tasks) und dann die momentane addresse des (erniedrigten) stacks nach callee->stack gespeichert(ebanfalls genau so wie beim erstellen eines Tasks).
Danach liegt der Stack bei 0xBADF0F00. Am Ende meines syscall-handlers (um genau zu sein beim laden der segmentregister vom Stack), steht ESP(wenn der GPF kommt) komischerweise auf 0xBADF0EFC(also noch niedriger, weil ESP müsste ja dann > 0xBADF0F00 sein).

Entweder hab ich irgendwo einen großen Denkfehler oder das ist richtig so(ich tendiere zum Denkfehler).

Ich hoffe mal irgendwer weiß woran das liegt weil ich weiß echt nicht mehr weiter.
3
Wenn ich meine Konstanten so setzte:

#define BASE_STACK_SIZE     0x8000
#define VIRT_STACK_ADDR     0xBADF0000

tritt der GPF bei 0x1050F0 auf, also also am Ende meiner Syscall-Behandlungsroutine. Meine Behandlungsroutine sieht momentan so aus:

%macro save_regs 0
  ; alle register sichern
pushad
;segmente sichern
push ds
push es
push fs
push gs
; den kernel daten deskriptor laden
cld
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; das kernel-pd laden
mov eax, [kernel_pd]
mov cr3, eax
; den stack des momentaten prozesses nach current_process
mov eax, [current_task]
mov [eax], esp
; alten stack nach ecx sichern
mov eax, esp
; jetzt den kernel_stack laden
; jetzt in den kernel_stack wechseln(wenn task nicht ring3, da der schon im kernel stack liegt)
mov ebx, [current_task]
    mov ecx, [ebx + 12]
    sub ecx, 3
    jz %%l1
    mov esp, [ebx + 4]
%%l1:
push eax
%endmacro

%macro rest_regs 0
pop eax
; in den stack des momentanen(evtl. auch nächsten) prozesses wechseln

mov eax, [current_task]
mov esp, [eax]
; das pd setzten
mov ebx, [current_task]
mov eax, [ebx + 8];
mov cr3, eax
;cli
;hlt
    ;  register zurückholen
pop gs
pop fs
pop es ; <--------- HIER KOMMT DER GPF(es wird mit 0x01 beladen)
pop ds

popad
%endmacro

; syscall(push ebenfalls int_no und error_code(0), damit man auch in ihm einen prozess wechseln kann kann)
global sc
sc:
        ; dummy werte auf den stack
push byte 0
push byte 0x77
save_regs
; jetzt den syscall hander aufrufen
mov eax, Syscall_handler
call eax
rest_regs
; die dummy paramter vom stack nehmen
add esp, 8
iret

; wird als rücksprungaddresse für einen rpc-call benutzt, damit der stack kontant bleibt, und beendet diesen
global rpc_end_stub
rpc_end_stub:
    mov eax, 0x02
    pop ebx
    int 0x77


Je nachdem wo ich den Stack platziere 0xE0000000 oder 0xBADF0000 kommt der GPF irgendwo beim pop'en der segment register, aber nur wenn der RPC_Handler eines Prozesses aufgerufen wird und nicht der des Kernels.

Achja der Platzt des Stacks ist reserviert, d.h keine funktion wie malloc o.ä alloziert die virtuellen speicher zwischen VIRT_STACK_ADDR und VIRT_STACK_ADDR + BASE_STACK_SIZE.

Ich hab mir auch in qemu mittels "info tlb" mal die zuordnung zwischen virtuellem und physischem Speicher angesehen, es zeigt auch keine andere virtuelle addresse auf den physischen platzt des Stacks, von da an kann ich mir diesen Fehler absolut nicht erklären. Wenn ich VIRT_STACK ADDR auf 0xF0000000 setzte kommt der GPF nur auf einer Realen Maschiene nicht in qemu/bochs.
4
Lowlevel-Coding / Re: RPC geht unter bochs, aber nicht unter qemu
« am: 30. September 2009, 20:36 »
Also die funktion multitasking_taskswitch ist mein scheduler und wählt den task aus, der am ende des RPC syscalls laufen soll.

Der GPF kommt beim pop'en der segmentregister wo (in bei diesem beispiel) gs komischer mit 0x01 beladen wird.

Allerdings erklärt das alles nicht wieso es mit bochs ohne probleme läuft.

Was du mit signals meinst weiß ich leider nicht.
5
Lowlevel-Coding / RPC geht unter bochs, aber nicht unter qemu
« am: 30. September 2009, 19:38 »
Also ich hab ein Problem(mal wieder).....

Wenn ein Task einen RPC zum Kernel ausführt, funktioniert das ganze ohne probleme, wenn ein Task aber einen RPC zu einem anderen Task macht bekomm ich eine GPF in Qemu und auf einem echten PC, debuggen kann ich das leider schlecht da es unter bochs ohne probleme funktioniert.
Komischerweise tritt dieses Problem nur dann auf wenn die Stackaddresse des callee(so heißt doch der aufgerufene RPC Handler dann, oder?) != 0xF0000000 ist oder BASE_STACK SIZE >= 0x4000, ansonsten funktioniert es ganz normal(jedenfalls im Emulator auf einem echtem Computer bekomm ich auch ne GPF).

Hier mal meine make_rpc Funktion:

// führt einen rpc-aus(zu einem RING0-Task)
void make_rpc(UINT32 callee_pid, rpc_data *data)
{
    //den task suchen, dessen rpc-handler afgerufen werden soll
    Task *callee = get_task_from_pid(callee_pid);
    if(callee == 0)
    {
        Console_putf("make_rpc: callee %i existiert nicht.\n");
        return;
    }
    // wenn kein rpc-handler vorhanden ---> ende
    if(callee->rpc_handler == 0)
    {
        Console_putf("make_rpc: callee %i hat keinen rpc-handler.\n");
        return;
    }
    UINT32 callee_stack;
    if(callee->pid != 0)
    {
        int i;
        for (i = 0; i <= BASE_STACK_SIZE; i+=0x1000)
        {
            UINT32 va = (VIRT_STACK_ADDR + i);
            UINT32 pa = mem_get_phys_addr(VIRT_STACK_ADDR + i, (page*)callee->page_dir);
            mem_map(kernel_pd, va, pa);
            if (mem_get_phys_addr(va, kernel_pd) != pa)
            {
                Console_putf("Fehler beim mappen des callee_stacks(i = %x)", i);
            }
        }
        callee_stack = callee->stack;
    }
    else
    {
        // ok, den kernel stack brauchen wir icht mappen, da das kernel_pd schon geladen ist
        callee_stack = callee->stack;
    }
    // jetzt dort einen weiteren irq-stack hinzufügen
    UINT32 *stack = (UINT32 *) callee_stack;
    data->caller_pid = current_task->pid;
    // vor den daten wird noch der alte stackpointer gespeichert
    data->callee_old_esp = (UINT32) callee_stack;
    // jetzt die daten auf den stack
    *(--stack) = (UINT32)data;
    // die rücksprungaddresse des rpc-hadnler, welche diesen beendet
    *(--stack) = (UINT32)rpc_end_stub;
    *(--stack) = 0x0202;
// das codesegment(kernel-task = 0x08)
*(--stack) = 0x08;
// der einstiegspunkt(eip)
*(--stack) = callee->rpc_handler;
// WICHTIG: die IRQ-nummer und error-code(weil der timer-interrupt zuständig ist für multitasking)
*(--stack) = 0x00;
*(--stack) = 0x00;
// Allzweckregister
*(--stack) = 0x00;
*(--stack) = 0x00;
*(--stack) = 0x00;
*(--stack) = 0x00;
*(--stack) = 0x00;
*(--stack) = 0x00;
*(--stack) = 0x00;
*(--stack) = 0x00;
// jetzt die datensegment(kernel-task = 0x10)
*(--stack) = 0x10;
*(--stack) = 0x10;
*(--stack) = 0x10;
*(--stack) = 0x10;


    // jetzt den stack verschieben
    callee->stack = (UINT32)stack;
    callee->makes_rpc = 1;
    // ok jetzt den caller blocken und zum callee wechseln
    current_task->blocked = 1;
    callee->last_rpc_data = data;
    // ok wenn der callee, schläft, ihn jetzt aufwecken
    callee->sleeping = 0;
    //while(current_task != callee)
    while(current_task->blocked == 1)
    {
     multitasking_taskswitch();
    }
}

Hier die verwendeten Konstanten:

#define BASE_STACK_SIZE     0x2000
#define VIRT_STACK_ADDR     0xF0000000

Hoffe ihr könnt mir helfen...
6
Lowlevel-Coding / Re: Compiler entfernt linefeeds
« am: 05. August 2009, 15:47 »
Ahh...

Danke für den Hinweis, mein puts war nicht Standartkonform(es hat kein '\n' am Ende mitausgegeben).

Jetzt geht alles, thx.
7
Lowlevel-Coding / Compiler entfernt linefeeds
« am: 05. August 2009, 15:34 »
Wenn ich in meinem Code meine printf Funktion aufrufe entfernt gcc bei mir alle '\n' am Ende eines Strings.
Wenn ich statt printf meine puts Funktion aufrufe, oder das '\n' mitten inner halb eines Wortes schreibe(zum Beispiel: printf("Erf\nolgreich(Code %x)",0);) funktioniert alles problemlos.
Das Problem habe ich sowohl unter Windows als auch unter Linux.

Hier mal ein bisschen Code als Beispiel(Auszug aus meinem Tastaturtreiber, in dem das Problem auftritt):

void TestController()
{
printf("Teste Tastatur-Anschluss...");
// den befehl zum testen senden
writeCmd(0xAB);
// den rückgabewert holen
UINT8 err_code = readData();
// rückgabe überprüfen
switch(err_code)
{
case 0x00:
printf("Erfolgreich.\n");
break;
case 0x01:
printf("Fehler(Clock low).\n");
break;
case 0x02:
printf("Fehler(Clock high).\n");
break;
case 0x03:
printf("Fehler(Data low).\n");
break;
case 0x04:
printf("Fehler(Data high).\n");
break;
case 0xFF:
printf("Fehler(Komplettausfall).\n");
break;
default:
printf("Unbekannter Status(%x).\n", err_code);
break;
}
}

Wenn ich mir jetzt mit objdump oder einem Hexeditor das objectfile anschaue, kommt das Folgende:

Contents of section .rodata:
 0000 54657374 65205461 73746174 75722d41  Teste Tastatur-A
 0010 6e736368 6c757373 2e002e20 00457266  nschluss... .Erf
 0020 6f6c6772 65696368 2e004665 686c6572  olgreich..Fehler
 0030 28436c6f 636b206c 6f77292e 00466568  (Clock low)..Feh
 0040 6c657228 436c6f63 6b206869 6768292e  ler(Clock high).
 0050 00466568 6c657228 44617461 206c6f77  .Fehler(Data low
 0060 292e0046 65686c65 72284461 74612068  )..Fehler(Data h
 0070 69676829 2e004665 686c6572 284b6f6d  igh)..Fehler(Kom
 0080 706c6574 74617573 66616c6c 292e0055  plettausfall)..U
 0090 6e62656b 616e6e74 65722053 74617475  nbekannter Statu
 00a0 73282578 292e0a00 54657374 65205461  s(%x)...Teste Ta
 00b0 73746174 75722e2e 2e20004f 4b2e0046  statur... .OK..F
 00c0 65686c65 72282578 292e0a00 4b6f6e66  ehler(%x)...Konf
 00d0 69677572 69657265 20546173 74617475  iguriere Tastatu
 00e0 722e2e2e 2000

Ich habe auch schon alle moglichen Compileroptionen durchprobiert, die damit was zu tun haben könnten(Optimierungen, etc..) doch das hat auch nichts gebracht.

Vlt. weiß ja einer von euch woran das liegen könnte...
8
Wie meinst du die Frage?
Soweit ich weiß wird doch bei einem IRQ oder einem Interrupt die in der IDT gespeicherte Methode genommen.
9
Also ich Benutzer Dev-Cpp unter Windows Vista(ist zwar ein bisschen Buggy aber unter XP läuft perfekt scheint wohl an Vista zu liegen) und hab dort einfach die Compilerpath auf die des Corsscompilers aus dem Wiki gestellt.
Und den NASM hab ich einfach in den Bin-Ordner des Comilers gepackt so das er den auch findet.
10
Lowlevel-Coding / Re: problem mit globaler variable
« 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.
11
Lowlevel-Coding / problem mit globaler variable
« am: 14. April 2009, 00:18 »
Hey Leute, erstmal möchte ich euch sagen das das hier ein sehr gutes forum ist.

So jetzt aber zu meinem problem:

in meinem datesystemtreiber habe ich die folgende stuktur:

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
};

diese möchte ich als globale variable definieren, da viele funktionen diese daten benötigen.
allerdings habe ich dabei das problem das sich nach einigen funktionen die addressen ändern.

wenn ich die variable so

struct Drive drives[5];
oder so

struct Drive *drives;
definiere ändert bleibt die adresse beim initialisieren des treiber, und beim einlesen der laufwerksinfo's und fat's glecih(z.b 0x0074B06B).
wenn jetzt allerdings eine andrere methode vom kernel aus aufgerufen wird ist die addresse der varaible auf einmal zu hoch(0x6D64B06B).
wenn ich die variable als static definiere ändert sich die addresse sogar sagor nachdem ich die addresse ausgegeben habe.
Seiten: [1]

Einloggen