Espresso 0.0.1c
This commit is contained in:
6
Makefile
6
Makefile
@ -11,7 +11,8 @@ NASMFLAGS := -f elf32
|
||||
WNOFLAGS := -Wno-discarded-qualifiers
|
||||
CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse $(WNOFLAGS)
|
||||
LDFLAGS := -T linker.ld -ffreestanding -O2 -nostdlib
|
||||
QEMUFLAGS := -boot d -cdrom $(ISO) -drive file=espresso.img,format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse4.1 -singlestep
|
||||
QEMUFLAGS := -boot d -cdrom $(ISO) -drive file=espresso.img,format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse4.1
|
||||
QEMUFLGS_EXT := -net none -netdev user,id=n0 -device rtl8139,netdev=n0 #-singlestep
|
||||
SRC_DIRS := kernel drivers lib
|
||||
INCLUDE_DIRS := include
|
||||
INCLUDES := $(addprefix -I, $(INCLUDE_DIRS))
|
||||
@ -68,7 +69,8 @@ run: iso
|
||||
$(QEMU_MKE_IMG)
|
||||
echo "\n"
|
||||
$(MKFS_VFAT) $(MKFS_FLAGS) espresso.img
|
||||
qemu-system-i386 $(QEMUFLAGS)
|
||||
qemu-system-i386 $(QEMUFLAGS) $(QEMUFLGS_EXT)
|
||||
|
||||
|
||||
# === Clean all build artifacts ===
|
||||
clean:
|
||||
|
@ -1 +1,6 @@
|
||||
|
||||
|
||||
#include <drivers/ahci.h>
|
||||
|
||||
|
||||
|
||||
|
@ -1,248 +0,0 @@
|
||||
#include <drivers/ide.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <fs/fat16.h>
|
||||
|
||||
static fat16_t fat;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint8_t jmp[3];
|
||||
char oem[8];
|
||||
uint16_t bytes_per_sector;
|
||||
uint8_t sectors_per_cluster;
|
||||
uint16_t reserved_sectors;
|
||||
uint8_t fat_count;
|
||||
uint16_t root_entries;
|
||||
uint16_t total_sectors_short;
|
||||
uint8_t media_desc;
|
||||
uint16_t fat_size_sectors;
|
||||
uint16_t sectors_per_track;
|
||||
uint16_t heads;
|
||||
uint32_t hidden_sectors;
|
||||
uint32_t total_sectors_long;
|
||||
// Extended Boot Record...
|
||||
} fat16_bpb_t;
|
||||
|
||||
typedef struct {
|
||||
char name[8];
|
||||
char ext[3];
|
||||
uint8_t attr;
|
||||
uint8_t reserved;
|
||||
uint8_t create_time_tenth;
|
||||
uint16_t create_time;
|
||||
uint16_t create_date;
|
||||
uint16_t access_date;
|
||||
uint16_t first_cluster_hi;
|
||||
uint16_t write_time;
|
||||
uint16_t write_date;
|
||||
uint16_t first_cluster_lo;
|
||||
uint32_t size;
|
||||
} fat16_direntry_raw_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
static uint8_t sector_buffer[512];
|
||||
|
||||
uint32_t cluster_to_lba(uint16_t cluster)
|
||||
{
|
||||
return fat.data_start + ((cluster - 2) * fat.sectors_per_cluster);
|
||||
}
|
||||
|
||||
|
||||
int32_t fat16_init(uint8_t drive)
|
||||
{
|
||||
if (ide_read48(drive, 0, 1, sector_buffer) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
fat16_bpb_t* bpb = (fat16_bpb_t*)sector_buffer;
|
||||
|
||||
fat.drive = drive;
|
||||
fat.bytes_per_sector = bpb->bytes_per_sector;
|
||||
fat.sectors_per_cluster = bpb->sectors_per_cluster;
|
||||
fat.root_entry_count = bpb->root_entries;
|
||||
|
||||
fat.fat_start = bpb->reserved_sectors;
|
||||
fat.root_dir_start = fat.fat_start + bpb->fat_count * bpb->fat_size_sectors;
|
||||
fat.data_start = fat.root_dir_start + ((bpb->root_entries * 32 + fat.bytes_per_sector - 1) / fat.bytes_per_sector);
|
||||
fat.current_dir_cluster = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t fat16_get_fat_entry(uint16_t cluster)
|
||||
{
|
||||
uint32_t fat_offset = cluster * 2;
|
||||
uint32_t fat_sector = fat.fat_start + (fat_offset / fat.bytes_per_sector);
|
||||
uint32_t ent_offset = fat_offset % fat.bytes_per_sector;
|
||||
|
||||
if (ide_read48(fat.drive, fat_sector, 1, sector_buffer) < 0)
|
||||
{
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
return *(uint16_t*)§or_buffer[ent_offset];
|
||||
}
|
||||
|
||||
uint16_t fat16_alloc_cluster(void)
|
||||
{
|
||||
for (uint16_t cluster = 2; cluster < 0xFFF0; ++cluster) {
|
||||
uint16_t entry = fat16_get_fat_entry(cluster);
|
||||
if (entry == 0x0000) {
|
||||
// Mark as end of chain
|
||||
uint32_t fat_offset = cluster * 2;
|
||||
uint32_t fat_sector = fat.fat_start + (fat_offset / fat.bytes_per_sector);
|
||||
uint32_t ent_offset = fat_offset % fat.bytes_per_sector;
|
||||
|
||||
if (ide_read48(fat.drive, fat_sector, 1, sector_buffer) < 0) return 0;
|
||||
*(uint16_t*)§or_buffer[ent_offset] = 0xFFFF;
|
||||
if (ide_write48(fat.drive, fat_sector, 1, sector_buffer) < 0) return 0;
|
||||
|
||||
return cluster;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32_t fat16_list_dir(fat16_dir_entry_t* entries, size_t max_entries)
|
||||
{
|
||||
size_t count = 0;
|
||||
if (fat.current_dir_cluster == 0)
|
||||
{
|
||||
uint16_t root_sectors = ((fat.root_entry_count * 32) + (fat.bytes_per_sector - 1)) / fat.bytes_per_sector;
|
||||
for (uint32_t i = 0; i < root_sectors && count < max_entries; ++i)
|
||||
{
|
||||
if (ide_read48(fat.drive, fat.root_dir_start + i, 1, sector_buffer) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
fat16_direntry_raw_t* de = (fat16_direntry_raw_t*)sector_buffer;
|
||||
for (int32_t j = 0; j < 512 / 32 && count < max_entries; ++j, ++de)
|
||||
{
|
||||
if (de->name[0] == 0x00 || de->name[0] == 0xE5)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(entries[count].name, de->name, 8);
|
||||
entries[count].name[8] = '\0';
|
||||
entries[count].attr = de->attr;
|
||||
entries[count].cluster = de->first_cluster_lo;
|
||||
entries[count].size = de->size;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* TODO: Add support for listing subdirectories if current_dir_cluster != 0 */
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t fat16_read_file(const char* filename, void* buffer, size_t max_size) {
|
||||
fat16_dir_entry_t entries[64];
|
||||
int32_t n = fat16_list_dir(entries, 64);
|
||||
for (int32_t i = 0; i < n; ++i) {
|
||||
if (!(entries[i].attr & FAT16_ATTR_DIRECTORY) &&
|
||||
strncmp(entries[i].name, filename, FAT16_MAX_FILENAME) == 0) {
|
||||
|
||||
uint16_t cluster = entries[i].cluster;
|
||||
uint8_t* out = (uint8_t*)buffer;
|
||||
size_t remaining = entries[i].size < max_size ? entries[i].size : max_size;
|
||||
|
||||
while (cluster >= 0x0002 && cluster < 0xFFF8 && remaining > 0) {
|
||||
uint32_t lba = cluster_to_lba(cluster);
|
||||
size_t to_read = fat.bytes_per_sector * fat.sectors_per_cluster;
|
||||
|
||||
if (ide_read48(fat.drive, lba, fat.sectors_per_cluster, sector_buffer) < 0)
|
||||
return -1;
|
||||
|
||||
size_t copy_size = (remaining < to_read) ? remaining : to_read;
|
||||
memcpy(out, sector_buffer, copy_size);
|
||||
out += copy_size;
|
||||
remaining -= copy_size;
|
||||
|
||||
cluster = fat16_get_fat_entry(cluster);
|
||||
}
|
||||
|
||||
return (int32_t)(out - (uint8_t*)buffer);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int32_t fat16_write_file(const char* filename, const void* data, size_t size) {
|
||||
fat16_dir_entry_t entries[64];
|
||||
int32_t n = fat16_list_dir(entries, 64);
|
||||
for (int32_t i = 0; i < n; ++i) {
|
||||
if (strncmp(entries[i].name, filename, FAT16_MAX_FILENAME) == 0) {
|
||||
uint16_t cluster = entries[i].cluster;
|
||||
const uint8_t* src = (const uint8_t*)data;
|
||||
size_t remaining = size;
|
||||
|
||||
while (remaining > 0) {
|
||||
uint32_t lba = cluster_to_lba(cluster);
|
||||
size_t cluster_bytes = fat.sectors_per_cluster * fat.bytes_per_sector;
|
||||
size_t to_write = remaining < cluster_bytes ? remaining : cluster_bytes;
|
||||
|
||||
memset(sector_buffer, 0, cluster_bytes); // Clear old data
|
||||
memcpy(sector_buffer, src, to_write);
|
||||
if (ide_write48(fat.drive, lba, fat.sectors_per_cluster, sector_buffer) < 0)
|
||||
return -1;
|
||||
|
||||
src += to_write;
|
||||
remaining -= to_write;
|
||||
|
||||
// Last chunk?
|
||||
if (remaining == 0)
|
||||
break;
|
||||
|
||||
// Check next cluster
|
||||
uint16_t next = fat16_get_fat_entry(cluster);
|
||||
if (next >= 0xFFF8 || next == 0x0000) {
|
||||
// Need to allocate a new cluster
|
||||
uint16_t new_cluster = fat16_alloc_cluster();
|
||||
if (new_cluster == 0) return -1;
|
||||
|
||||
// Update FAT to point to new cluster
|
||||
uint32_t fat_offset = cluster * 2;
|
||||
uint32_t fat_sector = fat.fat_start + (fat_offset / fat.bytes_per_sector);
|
||||
uint32_t ent_offset = fat_offset % fat.bytes_per_sector;
|
||||
|
||||
if (ide_read48(fat.drive, fat_sector, 1, sector_buffer) < 0) return -1;
|
||||
*(uint16_t*)§or_buffer[ent_offset] = new_cluster;
|
||||
if (ide_write48(fat.drive, fat_sector, 1, sector_buffer) < 0) return -1;
|
||||
|
||||
next = new_cluster;
|
||||
}
|
||||
|
||||
cluster = next;
|
||||
}
|
||||
|
||||
return (int32_t)size;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t fat16_change_dir(const char* dirname)
|
||||
{
|
||||
fat16_dir_entry_t entries[64];
|
||||
int32_t n = fat16_list_dir(entries, 64);
|
||||
for (int32_t i = 0; i < n; ++i)
|
||||
{
|
||||
if ((entries[i].attr & FAT16_ATTR_DIRECTORY) && strncmp(entries[i].name, dirname, FAT16_MAX_FILENAME) == 0)
|
||||
{
|
||||
fat.current_dir_cluster = entries[i].cluster;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
94
drivers/fs/sfs.c
Normal file
94
drivers/fs/sfs.c
Normal file
@ -0,0 +1,94 @@
|
||||
#include <drivers/ide.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fs/sfs.h>
|
||||
|
||||
|
||||
#define SFS_BEGINNING_LBA 8
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct sfs_file_header {
|
||||
uint16_t magic; /* 0xBEEF */
|
||||
/*
|
||||
32 chars for the filename itself,
|
||||
4 chars for the file's extension,
|
||||
and 1 char for the null zero.
|
||||
*/
|
||||
char filename[37];
|
||||
|
||||
uint64_t data_beginning; /* Actually a 48 bit LBA mind you */
|
||||
uint32_t num_sectors; /* Number of sectors after data_beginning that are this file's data */
|
||||
|
||||
uint8_t padding[13]; /* Padding to 64 bytes total */
|
||||
} sfs_file_header_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
static sfs_file_header_t* base;
|
||||
|
||||
|
||||
|
||||
|
||||
int32_t sfs_init(bool format)
|
||||
{
|
||||
uint8_t buffer[512] = { 0 };
|
||||
|
||||
int32_t kl = read_sector(SFS_BEGINNING_LBA, buffer);
|
||||
|
||||
if (kl != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
volatile sfs_file_header_t null_file;
|
||||
memcpy(&null_file, buffer, sizeof(sfs_file_header_t));
|
||||
|
||||
if ((&null_file)->magic != 0xBEEF)
|
||||
{
|
||||
if (!format)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
//sfs_format();
|
||||
return -2;
|
||||
}
|
||||
|
||||
memcpy(base, &null_file, sizeof(sfs_file_header_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool sfs_get_formatted_name(const char* raw_name, char output[37])
|
||||
{
|
||||
size_t len = strlen(raw_name);
|
||||
|
||||
if (len > 36 || strchr(raw_name, '/') || strchr(raw_name, '*') || strchr(raw_name, '\\')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(output, ' ', 36);
|
||||
output[36] = '\0';
|
||||
|
||||
memcpy(output, raw_name, len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Note: if a negative value is passed for num, then read the whole file
|
||||
*/
|
||||
int32_t sfs_read_file(char* _name, void* buffer, uint32_t num)
|
||||
{
|
||||
char name[37] = { '\0' };
|
||||
|
||||
if (sfs_get_formatted_name(_name, name))
|
||||
{
|
||||
return -128;
|
||||
}
|
||||
|
||||
printf("%s", name);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,30 +1,32 @@
|
||||
/*#include <fs/fat16.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fs/vfs.h>*/
|
||||
#include <fs/vfs.h>
|
||||
|
||||
|
||||
typedef struct vfs_file_header {
|
||||
char* filename; /* The filename, not the path. */
|
||||
|
||||
int32_t fd;
|
||||
|
||||
uint8_t type_info; /* Bits 0 - 3 -> File type, Bits 4 - 7 FS type */
|
||||
|
||||
uint16_t* fs_header;
|
||||
|
||||
struct vfs_file_header* next; /* Linked list */
|
||||
} vfs_file_header_t;
|
||||
|
||||
|
||||
vfs_file_header_t* root;
|
||||
|
||||
|
||||
/*
|
||||
Note: the special FILE value -128 means the current directory.
|
||||
-32 means stdin
|
||||
-33 means stdout (which can be read)
|
||||
*/
|
||||
|
||||
/*bool vfs_initialized = false;
|
||||
ramfs_file_header_t* vfs_current_dir = NULL;
|
||||
|
||||
void vfs_init(void)
|
||||
{
|
||||
if (!vfs_initialized)
|
||||
{
|
||||
ramfs_init();
|
||||
|
||||
ramfs_make_root();
|
||||
|
||||
vfs_initialized = true;
|
||||
vfs_current_dir = ramfs_get_root();
|
||||
}
|
||||
}
|
||||
|
||||
This is being written as a test.
|
||||
This has no affect on aaand my CPU is at 87 degrees Celsius and /usr/bin/gnome-shell is at 115% CPU utilization.
|
||||
Just by writing that.
|
||||
wow.
|
||||
and now my CPU fan is going nuts.
|
||||
|
||||
--update: now it works. I had to go back to nouveau instead of the proprietary nVidia drivers..
|
||||
*/
|
||||
|
@ -16,11 +16,21 @@ extern void gdt_flush(uint32_t);
|
||||
|
||||
void gdt_install(bool prnt_gdt)
|
||||
{
|
||||
create_descriptor(0, 0, 0, 0, prnt_gdt); // Null
|
||||
create_descriptor(1, 0, 0x000FFFFF, GDT_CODE_PL0, prnt_gdt); // Kernel code
|
||||
create_descriptor(2, 0, 0x000FFFFF, GDT_DATA_PL0, prnt_gdt); // Kernel data
|
||||
create_descriptor(3, 0, 0x000FFFFF, GDT_CODE_PL3, prnt_gdt); // User code
|
||||
create_descriptor(4, 0, 0x000FFFFF, GDT_DATA_PL3, prnt_gdt); // User data
|
||||
if (prnt_gdt)
|
||||
{
|
||||
printf("<===== GDT =====>\n");
|
||||
}
|
||||
|
||||
create_descriptor(0, 0, 0, 0, prnt_gdt); /* Null */
|
||||
create_descriptor(1, 0, 0x000FFFFF, GDT_CODE_PL0, prnt_gdt); /* Kernel code */
|
||||
create_descriptor(2, 0, 0x000FFFFF, GDT_DATA_PL0, prnt_gdt); /* Kernel data */
|
||||
create_descriptor(3, 0, 0x000FFFFF, GDT_CODE_PL3, prnt_gdt); /* User code */
|
||||
create_descriptor(4, 0, 0x000FFFFF, GDT_DATA_PL3, prnt_gdt); /* User data */
|
||||
|
||||
if (prnt_gdt)
|
||||
{
|
||||
printf("<===== GDT =====>\n");
|
||||
}
|
||||
|
||||
gp.limit = sizeof(gdt) - 1;
|
||||
gp.base = (uint32_t)&gdt;
|
||||
@ -32,15 +42,15 @@ void create_descriptor(int index, uint32_t base, uint32_t limit, uint16_t flag,
|
||||
{
|
||||
uint64_t descriptor;
|
||||
|
||||
descriptor = limit & 0x000F0000; // limit bits 19:16
|
||||
descriptor |= (flag << 8) & 0x00F0FF00; // flags and access
|
||||
descriptor |= (base >> 16) & 0x000000FF; // base bits 23:16
|
||||
descriptor |= base & 0xFF000000; // base bits 31:24
|
||||
descriptor = limit & 0x000F0000; /* limit bits 19:16 */
|
||||
descriptor |= (flag << 8) & 0x00F0FF00; /* flags and access */
|
||||
descriptor |= (base >> 16) & 0x000000FF; /* base bits 23:16 */
|
||||
descriptor |= base & 0xFF000000; /* base bits 31:24 */
|
||||
|
||||
descriptor <<= 32;
|
||||
|
||||
descriptor |= ((uint64_t)base << 16); // base bits 15:0
|
||||
descriptor |= (limit & 0x0000FFFF); // limit bits 15:0
|
||||
descriptor |= ((uint64_t)base << 16); /* base bits 15:0 */
|
||||
descriptor |= (limit & 0x0000FFFF); /* limit bits 15:0 */
|
||||
|
||||
gdt[index] = descriptor;
|
||||
|
||||
|
@ -199,3 +199,13 @@ int32_t ide_write48(uint8_t drive, uint64_t lba, uint8_t sector_count, const voi
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t read_sector(uint64_t lba, void* buffer)
|
||||
{
|
||||
return ide_read48(0, lba, 1, buffer);
|
||||
}
|
||||
|
||||
int32_t write_sector(uint64_t lba, const void* buffer)
|
||||
{
|
||||
return ide_write48(0, lba, 1, buffer);
|
||||
}
|
||||
|
@ -16,16 +16,16 @@
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
|
||||
uint8_t reserved; // Set to zero
|
||||
uint8_t attributes; // Type and attributes; see the IDT page
|
||||
uint16_t isr_high; // The higher 16 bits of the ISR's address
|
||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
|
||||
uint8_t reserved; // Set to zero
|
||||
uint8_t attributes; // Type and attributes; see the IDT page
|
||||
uint16_t isr_high; // The higher 16 bits of the ISR's address
|
||||
} __attribute__((packed)) idt_entry_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} __attribute__((packed)) idtr_t;
|
||||
|
||||
__attribute__((aligned(0x10)))
|
||||
@ -81,7 +81,8 @@ void exception_dispatcher(uint32_t int_no, uint32_t err_code)
|
||||
|
||||
|
||||
|
||||
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags) {
|
||||
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags)
|
||||
{
|
||||
idt_entry_t* descriptor = &idt[vector];
|
||||
|
||||
descriptor->isr_low = (uint32_t)isr & 0xFFFF;
|
||||
|
@ -4,19 +4,26 @@
|
||||
|
||||
#include <drivers/irq.h>
|
||||
|
||||
irq_func_t func_list[64];
|
||||
|
||||
void irq_init(void)
|
||||
{
|
||||
set_irq_handler(0, (irq_func_t*)pit_handler);
|
||||
set_irq_handler(1, (irq_func_t*)keyboard_handler);
|
||||
}
|
||||
|
||||
void irq_handler(uint8_t irq_number)
|
||||
{
|
||||
switch (irq_number)
|
||||
if (irq_number < 64 && func_list[irq_number])
|
||||
{
|
||||
case 0:
|
||||
pit_handler();
|
||||
break;
|
||||
case 1:
|
||||
keyboard_handler();
|
||||
break;
|
||||
default:
|
||||
printf("Unhandled IRQ %u\n", irq_number);
|
||||
break;
|
||||
func_list[irq_number]();
|
||||
}
|
||||
}
|
||||
|
||||
void set_irq_handler(uint32_t num, irq_func_t* handler)
|
||||
{
|
||||
if (num < 64)
|
||||
{
|
||||
func_list[num] = (irq_func_t)handler;
|
||||
}
|
||||
}
|
||||
|
118
drivers/pci.c
118
drivers/pci.c
@ -1,59 +1,97 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <drivers/pci.h>
|
||||
#include <drivers/ahci.h>
|
||||
#include <port_io.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <drivers/pci.h>
|
||||
|
||||
#define PCI_CONFIG_ADDRESS 0xCF8
|
||||
#define PCI_CONFIG_DATA 0xCFC
|
||||
|
||||
/*
|
||||
Register Offset Bits 31-24 Bits 23-16 Bits 15-8 Bits 7-0
|
||||
0x0 0x0 Device ID Vendor ID
|
||||
0x1 0x4 Status Command
|
||||
0x2 0x8 Class code Subclass Prog IF Revision ID
|
||||
0x3 0xC BIST Header type Latency Timer Cache Line Size
|
||||
*/
|
||||
|
||||
uint32_t pci_config_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset)
|
||||
{
|
||||
uint32_t address = 0;
|
||||
address |= (bus << 16); // Bus number (bits 23-16)
|
||||
address |= (device << 11); // Device number (bits 15-11)
|
||||
address |= (function << 8); // Function number (bits 10-8)
|
||||
address |= (offset & 0xFC); // Register offset (bits 7-0)
|
||||
address |= (1 << 31); // Enable configuration access
|
||||
uint32_t address = 0;
|
||||
address |= (bus << 16); /* Bus number (bits 23-16) */
|
||||
address |= (device << 11); /* Device number (bits 15-11) */
|
||||
address |= (function << 8); /* Function number (bits 10-8) */
|
||||
address |= (offset & 0xFC); /* Register offset (bits 7-0) */
|
||||
address |= (1 << 31); /* Enable configuration access */
|
||||
|
||||
outl(PCI_CONFIG_ADDRESS, address); // Write address to PCI config space
|
||||
return inl(PCI_CONFIG_DATA); // Read data from PCI config space
|
||||
outl(PCI_CONFIG_ADDRESS, address); /* Write address to PCI config space */
|
||||
return inl(PCI_CONFIG_DATA); /* Read data from PCI config space */
|
||||
}
|
||||
|
||||
void pci_config_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value)
|
||||
{
|
||||
uint32_t address = 0x80000000 | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC);
|
||||
outl(PCI_CONFIG_ADDRESS, address); // Send the address to PCI config space
|
||||
outl(PCI_CONFIG_DATA, value); // Write data to PCI config space
|
||||
uint32_t address = 0x80000000 | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC);
|
||||
outl(PCI_CONFIG_ADDRESS, address); /* Send the address to PCI config space */
|
||||
outl(PCI_CONFIG_DATA, value); /* Write data to PCI config space */
|
||||
}
|
||||
|
||||
void pci_enumerate()
|
||||
void pci_config_read_block(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, void* buffer, size_t size)
|
||||
{
|
||||
for (uint16_t bus = 0; bus < 256; bus++) // Maximum 256 buses
|
||||
uint8_t* buf = (uint8_t*)buffer;
|
||||
|
||||
for (size_t i = 0; i < size; i += 4)
|
||||
{
|
||||
uint32_t value = pci_config_read(bus, device, function, offset + i);
|
||||
|
||||
size_t remaining = size - i;
|
||||
if (remaining >= 4)
|
||||
{
|
||||
for (uint8_t device = 0; device < 32; device++) // Maximum 32 devices per bus
|
||||
{
|
||||
for (uint8_t function = 0; function < 8; function++) // Maximum 8 functions per device
|
||||
{
|
||||
uint32_t vendor_id = pci_config_read(bus, device, function, 0x00);
|
||||
if (vendor_id == 0xFFFFFFFF) continue; // No device present
|
||||
|
||||
uint32_t device_id = pci_config_read(bus, device, function, 0x02);
|
||||
uint32_t class_code = pci_config_read(bus, device, function, 0x08);
|
||||
printf("Found PCI device: Vendor ID: 0x%X Device ID: 0x%X Class: 0x%X\n", vendor_id, device_id, class_code);
|
||||
|
||||
printf("0x%X", class_code);
|
||||
printf(" --- ");
|
||||
printf("0x%X\n", (class_code >> 8));
|
||||
|
||||
|
||||
if ((class_code >> 8) == 0x0C) {
|
||||
printf("Found USB controller (Class: 0x%02X)\n", class_code);
|
||||
// Now, you can initialize and configure the USB controller.
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*(uint32_t*)(buf + i) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t j = 0; j < remaining; ++j)
|
||||
{
|
||||
buf[i + j] = (value >> (8 * j)) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pci_enumerate(void)
|
||||
{
|
||||
for (uint16_t bus = 0; bus < 256; bus++) /* Maximum 256 buses */
|
||||
{
|
||||
for (uint8_t device = 0; device < 32; device++) /* Maximum 32 devices per bus */
|
||||
{
|
||||
for (uint8_t function = 0; function < 8; function++) /* Maximum 8 functions per device */
|
||||
{
|
||||
struct pci_header pre_header;
|
||||
pci_config_read_block(bus, device, function, 0x00, &pre_header, sizeof(pre_header));
|
||||
|
||||
if (pre_header.vendor_id == 0xFFFF)
|
||||
{
|
||||
continue; /* No device present */
|
||||
}
|
||||
|
||||
if (pre_header.class_code == 0xB)
|
||||
{
|
||||
printf("Processor found on PCI bus, what?!?!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pre_header.header_type == 0x00)
|
||||
{
|
||||
struct pci_header_type_0 hdr;
|
||||
pci_config_read_block(bus, device, function, 0x00, &hdr, sizeof(hdr));
|
||||
|
||||
if (hdr.class_code == 0x1 && hdr.subclass == 0x6 && hdr.prog_if == 0x1)
|
||||
{
|
||||
/*configure_ahci_controller(hdr);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef _AHCI_H
|
||||
#define _AHCI_H
|
||||
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#endif
|
||||
|
6
include/drivers/ahci_types.h
Normal file
6
include/drivers/ahci_types.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _AHCI_TYPES_H
|
||||
#define _AHCI_TYPES_H
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -33,8 +33,12 @@
|
||||
#define ATA_SR_ERR 0x01
|
||||
|
||||
void ide_initialize(void);
|
||||
|
||||
int32_t ide_identify(uint8_t drive, uint16_t* buffer);
|
||||
|
||||
int32_t ide_read48(uint8_t drive, uint64_t lba, uint8_t sector_count, void* buffer);
|
||||
int32_t ide_write48(uint8_t drive, uint64_t lba, uint8_t sector_count, const void* buffer);
|
||||
int32_t read_sector(uint64_t lba, void* buffer);
|
||||
int32_t write_sector(uint64_t lba, const void* buffer);
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,10 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef void (*irq_func_t)(void);
|
||||
|
||||
void irq_init(void);
|
||||
void irq_handler(uint8_t irq_number);
|
||||
void set_irq_handler(uint32_t num, irq_func_t* handler);
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,66 @@
|
||||
#ifndef _PCI_H
|
||||
#define _PCI_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <types.h>
|
||||
|
||||
struct pci_header {
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
|
||||
uint16_t command;
|
||||
uint16_t status;
|
||||
|
||||
uint8_t revision_id;
|
||||
uint8_t prog_if;
|
||||
uint8_t subclass;
|
||||
uint8_t class_code;
|
||||
|
||||
uint8_t cache_line_size;
|
||||
uint8_t latency_timer;
|
||||
uint8_t header_type;
|
||||
uint8_t bist;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct pci_header_type_0 {
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
|
||||
uint16_t command;
|
||||
uint16_t status;
|
||||
|
||||
uint8_t revision_id;
|
||||
uint8_t prog_if;
|
||||
uint8_t subclass;
|
||||
uint8_t class_code;
|
||||
|
||||
uint8_t cache_line_size;
|
||||
uint8_t latency_timer;
|
||||
uint8_t header_type;
|
||||
uint8_t bist;
|
||||
|
||||
uint32_t bar0;
|
||||
uint32_t bar1;
|
||||
uint32_t bar2;
|
||||
uint32_t bar3;
|
||||
uint32_t bar4;
|
||||
uint32_t bar5;
|
||||
|
||||
uint32_t cardbus_cis_ptr;
|
||||
uint16_t subsystem_vendor_id;
|
||||
uint16_t subsystem_id;
|
||||
|
||||
uint32_t expansion_rom_base;
|
||||
|
||||
uint8_t capabilities_ptr;
|
||||
uint8_t reserved1[3];
|
||||
|
||||
uint32_t reserved2;
|
||||
|
||||
uint8_t interrupt_line;
|
||||
uint8_t interrupt_pin;
|
||||
uint8_t min_grant;
|
||||
uint8_t max_latency;
|
||||
} __attribute__((packed));
|
||||
|
||||
uint32_t pci_config_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset);
|
||||
void pci_config_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value);
|
||||
|
@ -1,38 +0,0 @@
|
||||
#ifndef _FAT16_H
|
||||
#define _FAT16_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define FAT16_MAX_FILENAME 256
|
||||
#define FAT16_ATTR_DIRECTORY 0x10
|
||||
|
||||
typedef struct {
|
||||
uint8_t drive;
|
||||
uint32_t fat_start;
|
||||
uint32_t root_dir_start;
|
||||
uint32_t data_start;
|
||||
uint16_t bytes_per_sector;
|
||||
uint8_t sectors_per_cluster;
|
||||
uint16_t root_entry_count;
|
||||
uint32_t current_dir_cluster;
|
||||
} fat16_t;
|
||||
|
||||
typedef struct {
|
||||
char name[FAT16_MAX_FILENAME];
|
||||
uint8_t attr;
|
||||
uint32_t cluster;
|
||||
uint32_t size;
|
||||
} fat16_dir_entry_t;
|
||||
|
||||
int32_t fat16_init(uint8_t drive);
|
||||
|
||||
uint32_t cluster_to_lba(uint16_t cluster);
|
||||
uint16_t fat16_get_fat_entry(uint16_t cluster);
|
||||
uint16_t fat16_alloc_cluster(void);
|
||||
|
||||
int32_t fat16_list_dir(fat16_dir_entry_t* entries, size_t max_entries);
|
||||
int32_t fat16_change_dir(const char* dirname);
|
||||
int32_t fat16_read_file(const char* filename, void* buffer, size_t max_size);
|
||||
int32_t fat16_write_file(const char* filename, const void* data, size_t size);
|
||||
|
||||
#endif
|
12
include/fs/sfs.h
Normal file
12
include/fs/sfs.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _SFS_H
|
||||
#define _SFS_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
int32_t sfs_init(bool format);
|
||||
|
||||
bool sfs_get_formatted_name(const char* raw_name, char output[37]);
|
||||
|
||||
int32_t sfs_read_file(char* name, void* buffer, uint32_t num);
|
||||
|
||||
#endif
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef int32_t FILE;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#define SSE_XMM_SIZE 128
|
||||
|
||||
void enable_sse(void);
|
||||
/*void enable_sse(void);*/ /* We use _enable_sse_asm (in boot.s) instead */
|
||||
|
||||
int32_t test_sse(void);
|
||||
|
@ -8,9 +8,7 @@
|
||||
#error "This kernel needs to be compiled with a ix86-elf compiler"
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -19,6 +17,7 @@
|
||||
|
||||
#include <gdt.h>
|
||||
#include <drivers/idt.h>
|
||||
#include <drivers/irq.h>
|
||||
|
||||
#include <multiboot.h>
|
||||
|
||||
@ -32,15 +31,14 @@
|
||||
#include <fs/fat32.h>
|
||||
#include <fs/duckfs.h>
|
||||
#include <fs/vfs.h>
|
||||
#include <fs/sfs.h>
|
||||
|
||||
#include <vector_extentions/sse.h>
|
||||
#include <vector_extensions/sse.h>
|
||||
|
||||
#include <kernel/intro.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
/*extern HBA_MEM *abar;
|
||||
extern HBA_PORT *ahci_port;*/
|
||||
|
||||
extern void _hang_asm(void);
|
||||
extern void _sti_asm(void);
|
||||
@ -80,6 +78,8 @@ void kernel_main(multiboot_info_t* mbd, unsigned int magic)
|
||||
idt_init();
|
||||
_sti_asm();
|
||||
|
||||
irq_init(); /* MUST be done after pci_remap() and idt_init() */
|
||||
|
||||
terminal_setcolor(VGA_COLOR_GREEN);
|
||||
|
||||
printd("Initializing physical memory manager...\n");
|
||||
@ -102,7 +102,7 @@ void kernel_main(multiboot_info_t* mbd, unsigned int magic)
|
||||
}
|
||||
else
|
||||
{
|
||||
printd("SSE test succeeded\n");
|
||||
printd("SSE test passed\n");
|
||||
}
|
||||
|
||||
printd("Initializing the PIT...\n");
|
||||
@ -123,17 +123,13 @@ void kernel_main(multiboot_info_t* mbd, unsigned int magic)
|
||||
ide_initialize();
|
||||
printd("IDE initialized\n");
|
||||
|
||||
/*printd("Initializing fat16...\n");
|
||||
fat16_init(0);
|
||||
printd("fat16 initialized.\n");*/
|
||||
|
||||
/*printd("Initializing DuckFS...\n");
|
||||
duckfs_init();
|
||||
printd("DuckFS initialized\n");*/
|
||||
|
||||
/*printd("Initializing FAT32...\n");
|
||||
fat32_init(0);
|
||||
printd("FAT32 initialized\n");*/
|
||||
printd("Initializing PCI...\n");
|
||||
pci_enumerate();
|
||||
printd("PCI initialized\n");
|
||||
|
||||
|
||||
|
||||
@ -147,6 +143,11 @@ void kernel_main(multiboot_info_t* mbd, unsigned int magic)
|
||||
|
||||
printf("Guten tag and welcome to Espresso\n");
|
||||
|
||||
/*printf("here\n");
|
||||
|
||||
printf("%i\n", sfs_init(false));
|
||||
|
||||
printf("here\n");*/
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
20
lib/stdio.c
20
lib/stdio.c
@ -25,7 +25,7 @@ char* getstring(void)
|
||||
return "HELLO\0";
|
||||
}
|
||||
|
||||
char* fgets(char* buf, int n, FILE file)
|
||||
/*char* fgets(char* buf, int n, FILE file)
|
||||
{
|
||||
if (!buf || n <= 1 || file < 1)
|
||||
{
|
||||
@ -37,26 +37,26 @@ char* fgets(char* buf, int n, FILE file)
|
||||
|
||||
while (total_read < n - 1)
|
||||
{
|
||||
int bytes = 0/*read_file(file, &c, 1)*/;
|
||||
int bytes = 0*//*read_file(file, &c, 1)*/;
|
||||
|
||||
if (bytes <= 0)
|
||||
/*if (bytes <= 0)
|
||||
{
|
||||
break; /* EOF or error */
|
||||
}
|
||||
break; *//* EOF or error */
|
||||
/*}
|
||||
|
||||
buf[total_read++] = c;
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
break; /* Stop at newline */
|
||||
}
|
||||
break; *//* Stop at newline */
|
||||
/*}
|
||||
}
|
||||
|
||||
if (total_read == 0)
|
||||
{
|
||||
return NULL; /* Nothing read (e.g. EOF) */
|
||||
}
|
||||
return NULL; *//* Nothing read (e.g. EOF) */
|
||||
/*}
|
||||
|
||||
buf[total_read] = '\0';
|
||||
return buf;
|
||||
}
|
||||
}*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <vector_extentions/sse.h>
|
||||
#include <vector_extensions/sse.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -184,7 +184,6 @@ char* strchr(const char* s, int c)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* memset(void *dst, char c, uint32_t n)
|
||||
{
|
||||
char *temp = dst;
|
||||
|
@ -1,10 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vector_extentions/sse.h>
|
||||
#include <vector_extensions/sse.h>
|
||||
|
||||
|
||||
void enable_sse(void)
|
||||
@ -12,17 +9,17 @@ void enable_sse(void)
|
||||
uint32_t cr0, cr4;
|
||||
|
||||
__asm__ volatile ("mov %%cr0, %0" : "=r"(cr0));
|
||||
cr0 &= ~(1 << 2); // EM = 0
|
||||
cr0 |= (1 << 1); // MP = 1
|
||||
cr0 &= ~(1 << 2);
|
||||
cr0 |= (1 << 1);
|
||||
__asm__ volatile ("mov %0, %%cr0" :: "r"(cr0));
|
||||
|
||||
__asm__ volatile ("mov %%cr4, %0" : "=r"(cr4));
|
||||
cr4 |= (1 << 9); // OSFXSR = 1
|
||||
cr4 |= (1 << 10); // OSXMMEXCPT = 1
|
||||
cr4 |= (1 << 9);
|
||||
cr4 |= (1 << 10);
|
||||
__asm__ volatile ("mov %0, %%cr4" :: "r"(cr4));
|
||||
}
|
||||
|
||||
// Basic SSE test: add two arrays of 4 floats using xmm registers
|
||||
/* Basic SSE test: add two arrays of 4 floats using xmm registers */
|
||||
__attribute__((force_align_arg_pointer))
|
||||
int32_t test_sse(void)
|
||||
{
|
Reference in New Issue
Block a user