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 - Svenska

Seiten: 1 2 3 [4] 5 6 ... 90
61
Softwareentwicklung / Re: GNU ld
« am: 09. September 2016, 23:19 »
Hier ein Beispiel, was mein Makefile aufruft (ist allerdings für einen ARM-Controller, was anderes hab ich gerade nicht da):

CFLAGS = -mcpu=cortex-m3 -mthumb -mfloat-abi=soft \
    -ffunction-sections -fdata-sections -fno-common -g -std=gnu99 -Wall -Wextra -Os -I.
LFLAGS = -static -nostartfiles -lc -lgcc -specs=nano.specs -Wl,--gc-sections

# kompilieren
arm-none-eabi-gcc $(CFLAGS) -c -o startup.o startup.c
arm-none-eabi-gcc $(CFLAGS) -c -o syscalls.o syscalls.c
arm-none-eabi-gcc $(CFLAGS) -c -o main.o main.c
arm-none-eabi-gcc $(CFLAGS) -c -o uart.o uart.c
arm-none-eabi-gcc $(CFLAGS) -c -o display.o display.c

# linken
arm-none-eabi-gcc -Tlm3s811.ld $(CFLAGS) $(LFLAGS) -o main.elf startup.o syscalls.o main.o uart.o display.o

Ich benutze gcc also sowohl für das Kompilieren der einzelnen C-Dateien (übrigens auch für das Assemblieren der S-Dateien), als auch für das Linken der Objekte zum Endergebnis.

Da ich kein Windows benutze, kann ich dir leider nicht sagen, was die beste Toolchain (oder welche Version) dafür ist. Aber es kann gut sein, dass das ein Fehler (oder eine Eigenheit) von DJGPP ist. Am Anfang spielt die Toolchain keine große Rolle, später solltest du sowieso auf einen Crosscompiler umsteigen. Ich benutze Linux und würde dir eine virtuelle Maschine empfehlen, aber MinGW oder Cygwin sollten's auch tun.

Gruß,
Svenska
62
Softwareentwicklung / Re: GNU ld
« am: 03. September 2016, 21:35 »
Du solltest zum Linken nicht ld direkt aufrufen, sondern besser gcc benutzen. Tritt das Problem dann auch noch auf?

Die GNU-Tools unter Windows sind immer so eine Sache. Benutzt du cygwin, MinGW oder etwas anderes?
63
Lowlevel-Coding / Re: Festplatten Sektoren direkt einlesen
« am: 29. August 2016, 23:05 »
hmm, ist es dann so, dass das Bios von neuen Rechnern auch die maximale Geschwindigkeit erreicht. Was macht den Zugriff über das Bios eigentlich langsamer?
Die BIOS-Treiber sind langsam, weil sie nicht schnell sein müssen. Die Aufgabe des BIOS ist es, Bootloader und Betriebssystem zu laden, also vielleicht ein paar MB pro Systemstart. Das darf auch gern 200ms länger dauern - beim deutlich langsameren POST (Power-On Self-Test) fällt das nicht weiter auf.

Dafür sind zwei andere Dinge wesentlich wichtiger: Größe und Kompatiblität. Das BIOS liegt in einem Flash-Baustein, und der ist wesentlich teurer pro MB als die Festplatte, daher sollte der Treiber eher klein sein. Außerdem muss dieser Treiber mit jeder Festplatte(*) klarkommen, denn er kann nur mit extrem viel Aufwand (BIOS-Update) aktualisiert werden. Also gilt es, Fehlerquellen zu vermeiden.

(*) Auch Festplattenfirmware kann fehlerhaft sein. Es gab z.B. ein paar SSDs, die TRIM und NCQ beworben haben, aber wenn man beides gleichzeitig gemacht hat, hatte man Datenverlust. Oder ältere IDE-Festplatten, die elektrisch nicht so gut waren - bei höheren Geschwindigkeiten gab es dann Bitfehler. Oder oder oder.

Wie läuft eigentlich das Schreiben auf neue Festplatten? Werden da nicht die ankommenden Daten einfach in einen Puffer gespeichert und danach von der Festplatten-Firmware physikalisch auf die Platte gespeichert?
Neue und alte (mechanische) Festplatten unterscheiden sich nicht... um zu wissen, ob ein Sektor leer ist, müsste die Festplatte ihn zuerst lesen, das kostet Zeit, also lässt man es. Die Daten werden selbstverständlich in der Festplatte gepuffert, aber der Puffer kann nicht zu groß sein, sonst werden die Verluste bei Stromausfall zu groß (außerdem wird er von modernen Dateisystemen an bestimmten Punkten geflusht, damit das Dateisystem dann auch konsistent bleibt).

Hätte man kaum Wartezeit.
Ich glaube, du machst es dir da zu einfach. Caches sind keine Wundermittel.

Lesen ist eine synchrone Aktion, du kannst also nicht weitermachen, bis du die Daten hast(**), und das dauert im Mittel eine halbe Umdrehung (bei 7200 U/Min also etwa 4,1 ms). Und beim Schreiben musst du auch entscheiden, ob du warten möchtest, bis die Daten sicher geschrieben sind oder ob du bei Stromausfall auch drauf verzichten kannst. Wenn du verschiedene Stellen der Festplatte gleichzeitig lesen möchtest, geht außerdem der Kopf hin und her, das kostet zusätzlich Zeit.

SSDs funktionieren wieder völlig anders.

(**) Du kannst zwar in der Zwischenzeit etwas anderes machen, aber das hilft dem lesenden Thread auch nicht weiter.
64
Lowlevel-Coding / Re: Festplatten Sektoren direkt einlesen
« am: 25. August 2016, 14:10 »
Das BIOS nutzt vermutlich den langsamsten PIO-Modus, um die Festplatte anzusprechen. Es gibt auch schnellere PIO-Modi, sowie DMA-Modi (wo die Datenübertragung im Hintergrund stattfinden kann), aber nicht alle (antiken) Controller und Festplatten können das.
65
Softwareentwicklung / Re: GRUB4DOS funktioniert nicht
« am: 18. August 2016, 13:50 »
Alle COM-Dateien, und damit auch bootlace.com, sind 16-Bit DOS-Programme (die gehen auf CP/M und die 70er zurück). Ein 64-bittiges Windows unterstützt diese nicht mehr.
66
Lowlevel-Coding / Re: Festplatten Sektoren direkt einlesen
« am: 18. August 2016, 13:46 »
1) Gibt es einen Möglichkeit die HDD ganz ohne Bios zu lesen?
Ja, mit einem eigenen Festplattentreiber (IDE oder SATA). Der kann auch deutlich schneller als das BIOS sein, wenn du es richtig machst.

2) Gibt es eine Möglichkeit die Daten direkt in den hohen Speicherbereich zu lesen?
Im Real Mode gibt es keinen hohen Speicher, der Unreal Mode ist ein funktionierender Hack. Mit dem BIOS wirst du keinen zuverlässigen Weg finden, dadrauf zuzugreifen.

Sinnvollerweise lässt du solche Tricks einfach sein und steigst auf den Protected Mode um. Im Wiki gibt es die Reihe OS-Dev für Einsteiger, wie du dazu vorgehen kannst. Der Nachteil daran ist, dass du dort ohne relativ viel Aufwand keine BIOS-Treiber mehr benutzen kannst.
67
Softwareentwicklung / Re: .img datei laufen lassen
« am: 18. August 2016, 13:38 »
Man kann keine Dateien emulieren.
68
Lowlevel-Coding / Re: kprintf char ausgeben
« am: 12. May 2016, 02:31 »
Array mit keycodes -> Array mit UTF-8 Eingaben -> Array mit CP437 (wobei der Pfeil fürs mappen stehen soll)
Das ist eine eher schlechte Idee, denn dann kannst du auch direkt Keycodes -> CP437 mappen und auf UTF-8 verzichten.

Wenn du UTF-8 Unterstützung einbauen willst, dann baue sie am besten so ein, dass alles intern mit UTF-8 arbeitet. Das heißt, dass dein Tastaturtreiber "Keycode -> UTF-8" wandelt und deine Konsole "UTF-8 -> CP437". Das heißt auch, dass alle API-Funktionen, die irgendwas mit Strings zu tun haben, UTF-8 nehmen - auch kprintf(). Du musst aber keinen vollständigen Unicode-Support anbieten.

Dann habe ich noch eine Frage zu den Funktionstasten. Enter, Tab und Return (\n, \t, \r) umzusetzen habe ich hinbekommen. Wie mache ich das jetzt bei Tasten die nicht so eine Escapesequenz haben?
Da gibt es mehrere Möglichkeiten:
(a) Du kannst die Tasten ignorieren und eine zusätzliche API anbieten, die mit Keycodes arbeitet. Das ist die beste Methode, wenn du an z.B. Multimedia-Tastaturen oder andere Eingabegeräte mit irgendwelchen Sondertasten denkst. Dafür hast du dann zwei Programmierschnittstellen.

(b) Alle diese Tasten haben ein Logo aufgedruckt, und dieses Logo gibt es auch als Unicode-Zeichen, z.B. U+2190 ist "Pfeil nach links". In UTF-8 wäre das dann die Bytesequenz 0xE2 0x86 0x90. Die kannst du nehmen.

(c) Unicode reserviert in der Basic Multilingual Plane (BMP) den Bereich U+E000 bis U+F8FF für "private Nutzung", d.h. dort wird nie ein Zeichen standardisiert werden. Du kannst allen Sondertasten ein Zeichen aus diesem Bereich zuweisen.

(d) Du kannst ein anderes Codeschema nutzen. Die Konsole unter Linux bildet grob ein ANSI-Terminal nach (bzw. ein Subset von VT102/VT220). Solche Terminals (Bildschirm, Tastatur und serielle Schnittstelle) wirst du allerdings kaum noch finden. Daher kommen die ANSI-Codes, die kevin beschrieben hat. Der Nachteil an ANSI-Codes ist, dass sie alle mit einem ESC-Zeichen beginnen und damit von einem Druck auf die ESC-Taste nicht ordentlich zu unterscheiden sind.

Bedenke, dass UTF-8 mehrere Bytes für ein Zeichen benutzen kann, was so Dinge wie "ein Zeichen rückwärts gehen" wesentlich komplizierter macht als ein z.B. single-byte Zeichensatz. Aus diesem Grund nutzt Windows intern durchgängig UTF-16, womit allerdings nur die BMP abgedeckt werden kann (das war Anfang der 90er noch kein Problem). Mit UTF-32 hast du damit keine Probleme, dafür brauchen normale ASCII-Texte viermal so viel Speicher.

Gruß,
Svenska
69
Also bei meinem Kernel deaktivieren alle Interrupts Interrupts ausser der Interrupt, der für Syscalls verwendet wird.
Das heißt, dass alle deine Interrupthandler mit CLI anfangen? Das sollte nicht nötig sein, wenn ich mich recht entsinne.
70
Innerhalb von Interrupthandlern sind Interrupts normalerweise gesperrt, das sollte auch für Software-Interrupts gelten. Das macht einen Kernel sehr viel einfacher. Systeme, die für verschachtelte Interrupts gebaut sind, können so konfiguriert werden, dass sie automatisch "niedriger priorisierte" Interrupts zu sperren, während ein Interrupt-Handler läuft. Der PIC kann das nicht, darum musst du verschachtelte Interrupts selbst implementieren bzw. deine Interrupt-Handler unterbrechbar machen.

Dazu muss der Handler seine eigene Interruptquelle abschalten (sonst führt ein zu schnell feuernder Interrupt zu einem Stack-Overflow) und kann dann Interrupts im Handler wieder einschalten (sti). Außerdem müssen dann alle Funktionen, die von mehreren Interrupts aus aufgerufen werden können, reentrant sein.

Zum Syscall-Befehl kann ich nichts sagen. Statt die Zeit über einen Tick-Timer zu messen, würde ich allerdings zu RDTSC o.ä. raten, das ist für sowas gemacht. Oder du lässt einen hochauflösenden Zähler frei laufen.
71
Mein Ziel ist es nicht ein Betriebssystem oder einen vollwertigen Bootloader zu schreiben, sondern mein grundsätzliches Verständnis für das Zusammenspiel von Software und Hardware auszubauen.
Ich persönlich finde dafür Mikrocontroller eine wesentlich bessere Ausgangsbasis. Also zum Beispiel ein Arduino (ohne die Arduino-Tools, also klassisch mit make und gcc), ein STM32-Discovery, ein LPC-Launchpad oder sowas in der Art. Wenn du die paar Euros übrig hast, kriegst du das günstig im Internet. Da musst du dich zwar auch einarbeiten, aber du bekommst eine relativ einfache Architektur und vor allem eine Plattform, die aus einem Guss und an einer einzigen Stelle vollständig dokumentiert ist. Und du brauchst dich nicht mit beschränkten Kompatiblitätsmodi (Real Mode, A20) rumschlagen, sondern kannst den Kram ausreizen.

Im Gegensatz zum PC kann man solche Boards auch für Echtzeitanwendungen benutzen, dafür hast du weniger schicke Hardware (wenig Flash, wenig RAM, kein VGA-Display, etc). Aber für das Verständnis sind die Dinger prima.
72
ob ich outportb oder outportw benutzte macht auch kein unterschied....
Das kann reale Hardware deutlich anders sehen als ein Emulator.
73
Lowlevel-Coding / Re: VESA EDID Infos
« am: 19. February 2016, 22:39 »
Das VGA-BIOS von Qemu unterstützt diesen Aufruf nicht. Laut diesem Code werden nur die VBE-Funktionen 0x00 bis 0x08, 0x0a und 0x10 unterstützt. Ich würde nicht erwarten, dass reale (moderne) Hardware besser viel ist.

Moderne Features und ein VESA-Standardtreiber vertragen sich nicht besonders gut. Windows setzt standardmäßig 1024x768 (seit Vista auch im Bootloader) und lässt dann den Nutzer entscheiden. Das ist ausreichend und so ziemlich das beste, was du ohne speziellen Treiber erreichen kannst.
74
OS-Design / Re: Linux-Kernel kompilieren mit make-kpkg
« am: 13. February 2016, 17:00 »
Ich habe make-kpkg bisher nur benutzt, um Debian-Pakete zu erstellen. Zum Testen benutze ich immer direkt "make bzImage" aus einem Vanilla-Tree, da funktioniert das. Allerdings sind solche Kernel bei mir auch immer ohne initramfs lebensfähig.
75
Lowlevel-Coding / Re: [QEMU] AC97 driver - Kein Sound
« am: 08. February 2016, 03:00 »
PS: Ist das normal dass der Interrupt nach dem abspielen des Sounds durchgehend gespammed wird? o.o
(Achtung: Post komplett ohne Ahnung vom Thema!)
Ich kann mir gut vorstellen, dass der Interrupt ein "Puffer ist leer, bitte Daten einfüllen"-Zeichen ist und so lange aktiv bleibt, bis du entweder neue Daten einfüllst oder ihn abschaltest. Pegelgesteuerte (level-triggered) Interrupts lassen sich in Hardware relativ einfach implementieren. Ob das in deinem Fall auch so ist, sagt das Datenblatt... mit AC97 habe ich mich noch nicht befasst.

PS: Willkommen im Forum! Hab ich ganz vergessen. ;-)
76
Das Wiki / Re: Das Wiki und https
« am: 23. January 2016, 01:55 »
Am 21.01.2016 ist das SSL-Zertifikat abgelaufen. Seitdem schiebt mein eisiger Feuerfuchs Panik, wenn ich auf das Forum oder das Wiki mit HTTPS zugreifen möchte.
77
Lowlevel-Coding / Re: anfängerfrage: problem mit tutorial
« am: 22. January 2016, 13:44 »
Bitfelder sind nie eine gute Idee, wenn du eine bestimmte Anordnung brauchst, weil die Anordnung schlicht undefiniert ist.
Hm. Ich weiß, dass Bitfelder für Registerbeschreibungen eingesetzt werden, weil es den Code lesbar halten kann und einem das manuelle Ausmaskieren (und damit Fehler) erspart. Ist natürlich alles implementation-defined, aber das wäre hier ja eher egal. In C++ kann man Bitfelder auch portabel als Klasse nachbilden und bekommt dann typsichere Registerbeschreibungen.

Im von dir verlinkten Tutorial finde ich aber nur dass die Funktionen set_entry und load_gdt aufgerufen werden, aber die sind nirgendwo definiert, oder zu mindest habe ich die nicht gefunden.
Den Code dazu findest du im Artikel zur GDT.

Von welchem Bitfeld redest du? Die gdt_entry struct? Und wenn ja, was bringen mir da unions? Ich weiss eigentlich schon wie unions funktionieren, ich seh nur den Anwendungszweck in dem Zusammenhang gerade nicht.
Das ist ein sehr breiter Weg ins Land von implementation-defined und daher nur vorsichtig zu genießen (ungetestet):

union gdt_entry {
  struct {
    unsigned limit_low : 16;
    unsigned base_low : 24;
    unsigned type : 4;
    unsigned segment : 1;
    unsigned dpl : 1;
    unsigned present : 1;
    unsigned limit_high : 4;
    unsigned available : 1;
    unsigned longmode : 1;
    unsigned size : 1;
    unsigned granularity : 1;
    unsigned base_high : 8;
  } PACKED;
  char raw[8];
};

Damit kannst du jedes Teilfeld des Registers einzeln setzen und lesen, wobei der Compiler das Maskieren und Shiften für dich erledigt; das gesamte Register findest du dann, wenn du "raw" ausliest. Achtung: Bitfelder sind pfui. In ein Element einer Union was reinschreiben und aus einem anderen Element etwas rauslesen ist auch pfui. Da musst du aufpassen, was dein Compiler draus macht.

Gruß,
Svenska
78
Lowlevel-Coding / Re: anfängerfrage: problem mit tutorial
« am: 21. January 2016, 02:46 »
Nur Kleinkram, und vermutlich auch nicht die Lösung:
  • Gibt es einen Grund, dass du die GDT in Assembler lädst?
    Im hauseigenen Tutorial gibt es dafür wunderbar funktionierenden C-Code. ;-)
  • Für Strukturen fixer Größe solltest du immer(!) auch Datentypen fixer Größe nehmen.
    Also in struct gdt_entry sollten uint16_t, uint8_t und so auftauchen.
  • Bitfelder sind zwar nicht portabel, aber für solche (ohnehin nicht portablen) Datenstrukturen auch eine gute Idee.
    Also eine Union aus dem Bitfeld und einem uint64_t (oder char[8]).
  • In deiner struct gdt_ptr ist der offset ein unsigned int, die Adresse wird aber als int da reingecastet.
  • Solltest du der Funktion lgdt() nicht eher die Adresse von ptr mitteilen? Stimmt die ABI für den Aufruf?
  • Nachtrag: Deine io.s sollte io.S heißen, sonst kannst du Probleme mit dem Präprozessor bekommen (Windows ist nicht case-sensitive, aber immerhin case-preserving; falls du den Code jemals auf ein Linux kopierst oder so.)

Im Qemu-Monitor kannst du dir GDTR, IDTR und die Segmentregister anzeigen lassen (info registers) und prüfen, ob die Werte auch stimmen. Außerdem kann Qemu noch ein Log schreiben (qemu-system-i386 -d int). Außerdem kannst du GDB zum Debuggen benutzen, aber das habe ich nur für Breakpoints zwischen Instruktionen genutzt (zwischen "lade CR3" und "lade die nächste Instruktion"; im Monitor konnte man sich dann die kaputten Paging-Strukturen anschauen, bevor es knallte). Ist auch schon länger her.

Ansonsten schaffe ich mir grundsätzlich möglichst früh eine Debugausgabe, also ein rudimentäres printf(), welches direkt auf Bildschirm oder UART schreibt. Das geht auch schon, bevor die GDT steht. ;-)
79
Ist die Bridges zu konfigurieren nicht normalerweise die Aufgabe des BIOS?
Meines Wissens ist die Aufgabe des BIOS nur, alle bootfähigen Geräte zu konfigurieren. Das schließt nicht zwingend Geräte hinter einer Bridge ein (die sind dann halt nicht bootfähig). Ob das für ein EFI auch zutrifft, weiß ich nicht und bezweifle es mal.
80
Konfigurierst du die PCI-PCI-Bridges korrekt? Vielleicht ist dein Gerät dahinter versteckt.

Die PCI-ISA-Bridge dürfte den Chipsatz mit dem LPC-Bus verbinden. Da sind die ganzen klassischen ISA-Geräte dran, die das System unbedingt braucht, z.B. der SuperIO-Chip für PS/2, COM, LPT und SMBUS. Vielleicht ist dein "zusätzliches Gerät" einfach nur ein Alias für die Legacy-IDE-Ports.
Seiten: 1 2 3 [4] 5 6 ... 90

Einloggen