Mathieu Serandour 10 months ago
parent
commit
7e7148a0bb
  1. 2
      Makefile
  2. BIN
      core
  3. 5
      kernel/Makefile
  4. 4
      kernel/acpi/acpi.c
  5. 204
      kernel/drivers/pcie.c
  6. 24
      kernel/drivers/pcie.h
  7. 23
      kernel/drivers/pcie_driver_interface.h
  8. 16
      kernel/entry.c
  9. 3
      kernel/extern_files.s
  10. 6
      kernel/linker.ld
  11. 8
      kernel/video/terminal.c
  12. 4
      kernel/video/video.c

2
Makefile

@ -21,7 +21,7 @@ QEMU_ARGS := -monitor stdio \
-D qemu.log \
-drive format=raw,file=
QEMU_DEBUG_ARGS:= -no-shutdown -d int $(QEMU_ARGS)
QEMU_DEBUG_ARGS:= -no-shutdown -d int -s -S $(QEMU_ARGS)
run: all

BIN
core

Binary file not shown.

5
kernel/Makefile

@ -28,7 +28,8 @@ INTERNALCFLAGS := -mgeneral-regs-only \
CFILES := $(shell find ./ -type f -name '*.c')
SFILES := $(shell find ./ -type f -name '*.s')
OBJ := $(SFILES:.s=.s.o) $(CFILES:.c=.c.o)
OBJ := $(SFILES:.s=.s.o) $(CFILES:.c=.c.o)
LDSCRIPT := linker.ld
#charmap.bmp.o
.PHONY: all clean
@ -36,7 +37,7 @@ all: $(KERNEL)
$(KERNEL): $(OBJ)
$(KERNEL): $(OBJ) $(LDSCRIPT)
$(CC) $(INTERNALLDFLAGS) $(OBJ) -o $@
#%.bmp.o: ../resources/bmp/%.bmp

4
kernel/acpi/acpi.c

@ -97,9 +97,9 @@ void map_acpi_mmios(void) {
// mmios to map: HPET, PCIE
// cache disable
map_pages((uint64_t)apic_config_base, APIC_VIRTUAL_ADDRESS, 1,
PRESENT_ENTRY | PCD);
PRESENT_ENTRY | PCD | PL_XD);
map_pages((uint64_t)hpet_config_space, HPET_VIRTUAL_ADDRESS, 1,
PRESENT_ENTRY | PCD);
PRESENT_ENTRY | PCD | PL_XD);
}
static void parse_hpet(const struct HPET* table) {

204
kernel/drivers/pcie.c

@ -1,17 +1,205 @@
#include "pcie.h"
#include "../debug/logging.h"
#include "../debug/dump.h"
#include "../debug/assert.h"
#include "../memory/kalloc.h"
#include "../memory/paging.h"
#include "../klib/string.h"
struct PCIE_configuration_space {
volatile uint16_t vendorID;
volatile uint16_t deviceID;
uint16_t unused0;
uint16_t unused1;
volatile uint32_t class_code_revID;
volatile uint32_t infos;
volatile uint64_t bar[3];
volatile uint32_t cardbud_cis_ptr;
volatile uint16_t subsystemID;
volatile uint16_t subsystem_vendorID;
volatile uint32_t expansion_base;
volatile uint8_t capabilities;
uint8_t reserved0[3];
uint32_t reserved1;
volatile uint8_t interrupt_line;
volatile uint8_t interrupt_pin;
uint16_t reserved2[2];
};
// higher bus number: could be 0xff
// if there is only one bus group
static size_t max_bus = 0;
struct PCIE_Descriptor pcie_descriptor = {0};
// 0 | group | bus | 0 | slot | 0 | func |
// | 2 | 8 | 1 | 3 | 1 | 3 |
// 16 8
static struct PCIE_segment_group_descriptor* get_segment_group(unsigned bus) {
struct PCIE_segment_group_descriptor* group = &pcie_descriptor.array[0];
unsigned group_number = 0;
unsigned start_bus, end_bus;
// go through all segment groups
// if the bus is not in the range,
// it is not the right segment
while((start_bus = group->start_bus) > bus
|| (end_bus = group->end_bus) < bus) {
assert(group_number != pcie_descriptor.size);
group_number++;
group++;
}
return group;
}
static struct PCIE_configuration_space* __attribute__((pure)) get_config_space_base(
unsigned bus,
unsigned device,
unsigned func
) {
struct PCIE_segment_group_descriptor* group_desc = get_segment_group(bus);
return group_desc->address + (
(bus - group_desc->start_bus) << 20
| device << 15
| func << 12);
}
static int __attribute__((pure)) check_function(unsigned bus, unsigned device, unsigned func) {
struct PCIE_configuration_space* config_space = get_config_space_base(bus,device,func);
return config_space->vendorID != 0xffff;
}
struct pcie_device_descriptor {
uint16_t bus, device, function;
struct PCIE_configuration_space* config_space;
};
// array of all installed devices' functions
static struct pcie_device_descriptor* installed_devices = NULL;
static size_t n_installed_devices = 0;
/**
* constructs the installed_devices array
*/
static void scan_devices(void) {
// first create a linked list
// as we dont know how many devices are present
struct device_desc_node {
struct pcie_device_descriptor e;
struct device_desc_node* next;
};
// head of the list
struct device_desc_node ghost_node = {.next = NULL};
struct device_desc_node* current = &ghost_node;
// count the number of devices
void insert(
unsigned bus,
unsigned device,
unsigned func,
struct PCIE_configuration_space* config_space
) {
current->next = kmalloc(
sizeof(struct device_desc_node)
);
current = current->next;
current->next = NULL;
// fill the new node
current->e.bus = bus;
current->e.device = device;
current->e.function = func;
current->e.config_space = config_space;
n_installed_devices++;
}
for(unsigned bus = 0; bus < max_bus; bus++) {
for(unsigned device = 0; device < 32; device++) {
// if the first function doesn't exist, so does
// the device
if(!check_function(bus,device, 0))
continue;
insert(bus, device, 0, get_config_space_base(bus,device,0));
for(unsigned func = 0; func < 8; func++)
if(check_function(bus,device, func))
insert(bus, device, func, get_config_space_base(bus,device,func));
}
}
// now create the final array
installed_devices = kmalloc(
n_installed_devices
* sizeof(struct pcie_device_descriptor));
// now fill it and free the devices structure
struct pcie_device_descriptor* ptr = installed_devices;
for(struct device_desc_node* device = ghost_node.next;
device != NULL;
) {
memcpy(ptr++, &device->e, sizeof(struct pcie_device_descriptor));
struct device_desc_node* next = device->next;
kfree(device);
device = next;
}
}
/**
* during the init,
* we identity map the pcie configuration spaces
*
*/
void pcie_init(void) {
klog_debug("init pcie...");
klog_debug("%d", pcie_descriptor.size);
dump(
pcie_descriptor.array,
pcie_descriptor.size * sizeof(struct PCIE_segment_group_descriptor),
sizeof(struct PCIE_segment_group_descriptor),
DUMP_HEX8
);
// calculate the highest bus number
for(unsigned i = 0; i < pcie_descriptor.size; i++) {
// map the corresponding pages
if(pcie_descriptor.array[i].end_bus > max_bus)
max_bus = pcie_descriptor.array[i].end_bus;
klog_debug("map %lx", pcie_descriptor.array[i].address);
// identity map the corresponding pages
map_pages(
pcie_descriptor.array[i].address, // phys
pcie_descriptor.array[i].address, // virt
256 * // busses
32 * // devices
8 , // functions
PRESENT_ENTRY | PCD | PL_XD
// no cache, execute disable
);
}
asm("hlt");
scan_devices();
klog_info("found %u PCI Express devices", n_installed_devices);
}

24
kernel/drivers/pcie.h

@ -28,5 +28,29 @@ extern struct PCIE_Descriptor pcie_descriptor;
void pcie_init(void);
void pcie_scan(void);
typedef void (*driver_init_fun)(void* config_space);
typedef void (*driver_callback)(void);
struct driver_descriptor {
driver_init_fun install;
driver_callback remove;
};
/**
* PCIE drivers interfaces:
*
* provide void init(void* config_space_base)
*
* functions to call:
* register_irq(unsigned)
* unregister_irq(unsigned)
*
* int register_timer(void callback(void), unsigned period)
* void unregister_timer(int timer_id)
*
*/

23
kernel/drivers/pcie_driver_interface.h

@ -0,0 +1,23 @@
/**
* PCIE drivers interfaces:
*
* provide void init(void* config_space_base)
*
* functions to call:
* register_irq(unsigned)
* unregister_irq(unsigned)
*
* int register_timer(void callback(void), unsigned period)
* void unregister_timer(int timer_id)
*
*/
void
/**
* return 0 if the irq was successfully installed
*/
int register_irq(uint8_t irq_number, );

16
kernel/entry.c

@ -9,7 +9,7 @@
#include "klib/string.h"
#include "acpi/acpi.h"
#include "common.h"
#include "regs.h"
#include "registers.h"
#include "int/apic.h"
#include "drivers/hpet.h"
#include "drivers/pcie.h"
@ -18,13 +18,14 @@
#include "memory/physical_allocator.h"
#include "memory/paging.h"
#include "memory/vmap.h"
#include "memory/kalloc.h"
#include "debug/logging.h"
#define KERNEL_STACK_SIZE 8192
// 8K stack
static uint8_t stack_base[KERNEL_STACK_SIZE] __align(16);
static uint8_t stack_base[KERNEL_STACK_SIZE] __attribute__((section(".stack"))) __align(16);
#define INITIAL_STACK_PTR ((uintptr_t)(stack_base + KERNEL_STACK_SIZE))
@ -123,8 +124,11 @@ static void init_memory(const struct stivale2_struct_tag_memmap* memmap_tag,
PRESENT_ENTRY
);
// map lapic registers
// map lapic & hpet registers
map_acpi_mmios();
// init kernel heap
kheap_init();
}
@ -138,9 +142,10 @@ void _start(struct stivale2_struct *stivale2_struct) {
const struct stivale2_struct_tag_memmap* memmap_tag;
const struct stivale2_struct_tag_framebuffer* fbtag;
const struct stivale2_struct_tag_rsdp* rsdp_tag_ptr;
term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID);
memmap_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_MEMMAP_ID);
fbtag = stivale2_get_tag(stivale2_struct, 0x506461d2950408fa);
fbtag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID);
rsdp_tag_ptr = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_RSDP_ID);
@ -174,10 +179,9 @@ void _start(struct stivale2_struct *stivale2_struct) {
setup_terminal();
append_paging_initialization();
terminal_set_colors(0xfff0a0, 0x212121);
terminal_clear();
kputs(&_binary_bootmessage_txt);

3
kernel/extern_files.s

@ -16,6 +16,5 @@ _binary_bootmessage_txt:
[section .bss]
alignb 4
__image_pix:
TIMES 0x2000 resb 0
__image_pix: resb 2048

6
kernel/linker.ld

@ -22,8 +22,8 @@ SECTIONS
/* Since we are going to use PIE, this is just the base load address, but the */
/* bootloader will be able to relocate us as it sees fit. */
. = 0xffffffff80200000;
_kernel_base_address = .;
.text ALIGN(0x1000): {
*(.text*)
@ -57,6 +57,10 @@ SECTIONS
*(.bss*)
} :data
.stack : {
*(.stack)
} :data
/* Dynamic section needed for PIE */
.dynamic : {

8
kernel/video/terminal.c

@ -14,7 +14,7 @@ struct Char {
uint32_t fg_color: 24;
char c;
uint32_t bg_color;
} __packed;
} __attribute__((packed));
static_assert_equals(sizeof(struct Char), 8);
@ -64,10 +64,10 @@ void setup_terminal(void) {
assert(charmap == NULL);
assert(char_buffer == NULL);
charmap = loadBMP_24b_1b(&_binary_charmap_bmp);
assert(charmap != NULL);
assert(charmap->bpp == 1);
assert(charmap->pitch == 1);
@ -103,8 +103,6 @@ void setup_terminal(void) {
#endif
set_terminal_handler(write_string);
}

4
kernel/video/video.c

@ -4,6 +4,7 @@
#include <stivale2.h>
#include "../klib/string.h"
#include "../debug/logging.h"
//#include "../memory/kalloc.h"
#include "../common.h"
#include "../debug/assert.h"
@ -69,8 +70,6 @@ void imageLower_blitBinaryMask(
size_t dst_skip = screen.pitch - copy_size;
size_t src_skip = img -> pitch - copy_size;
// assert that everything are 2-aligned
// so that we can process faster
assert((size_t)dst_ptr % 8 == 0);
@ -597,6 +596,7 @@ Image* loadBMP_24b_1b(const void* rawFile) {
}
}
pix[y] = byte;
}
return &loadBMP_24b_1b_ret;

Loading…
Cancel
Save