Базовый функционал определения железа
This commit is contained in:
parent
b3b3c496ae
commit
8591760539
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,3 +6,5 @@ mseos.iso
|
||||
bin/
|
||||
limine/
|
||||
ovmf/
|
||||
modules/helloworld/helloworld.elf
|
||||
modules/com/com.elf
|
||||
|
37
build.py
37
build.py
@ -7,7 +7,7 @@ from multiprocessing import Pool
|
||||
|
||||
CC = "g++"
|
||||
ARCH_FLAGS = "-m64 -march=x86-64 -mabi=sysv -mno-80387 -mno-red-zone -mcmodel=kernel -MMD -MP"
|
||||
WARN_FLAGS = "-Wall -Wextra"
|
||||
WARN_FLAGS = "-w -Wall -Wextra"
|
||||
STANDART_FLAGS = "-std=gnu11"
|
||||
PROTECT_FLAGS = "-O0 -pipe -ffreestanding -fno-stack-protector -fno-lto -fno-stack-check -fno-PIC -fno-PIE"
|
||||
CHARSET_FLAGS = "-finput-charset=UTF-8 -fexec-charset=cp1251"
|
||||
@ -71,7 +71,23 @@ def check_tools():
|
||||
subprocess.run(["sudo", "apt", "install"] + missing_tools)
|
||||
|
||||
|
||||
def create_hdd(IMAGE_NAME):
|
||||
subprocess.run(["rm", "-f", IMAGE_NAME+".hdd"])
|
||||
subprocess.run(["dd", "if=/dev/zero", "bs=1M", "count=0", "seek=64", "of="+IMAGE_NAME+".hdd"])
|
||||
subprocess.run(["sgdisk", IMAGE_NAME+".hdd", "-n", "1:2048", "-t", "1:ef00"])
|
||||
subprocess.run(["./limine/limine", "bios-install", IMAGE_NAME+".hdd"])
|
||||
subprocess.run(["mformat", "-i", IMAGE_NAME+".hdd@@1M"])
|
||||
subprocess.run(["mmd", "-i", IMAGE_NAME+".hdd@@1M", "::/mod", "::/EFI", "::/EFI/BOOT"])
|
||||
subprocess.run(["mcopy", "-i", IMAGE_NAME+".hdd@@1M",
|
||||
"kernel.elf", "configs/limine.cfg", "limine/limine-bios.sys", "::/"])
|
||||
subprocess.run(["mcopy", "-i", IMAGE_NAME+".hdd@@1M",
|
||||
"modules/com/com.elf", "modules/helloworld/helloworld.elf", "::/mod"])
|
||||
subprocess.run(["mcopy", "-i", IMAGE_NAME+".hdd@@1M",
|
||||
"limine/BOOTX64.EFI", "limine/BOOTIA32.EFI", "::/EFI/BOOT"])
|
||||
|
||||
|
||||
def create_iso(IMAGE_NAME):
|
||||
subprocess.run(["rm", "-f", IMAGE_NAME+".iso"])
|
||||
subprocess.run(["rm", "-rf", "iso_root"])
|
||||
subprocess.run(["mkdir", "-p", "iso_root"])
|
||||
subprocess.run(["cp", "-v", "iso_root/"])
|
||||
@ -80,6 +96,9 @@ def create_iso(IMAGE_NAME):
|
||||
"limine/limine-bios-cd.bin", "limine/limine-uefi-cd.bin",
|
||||
"iso_root/"])
|
||||
subprocess.run(["mkdir", "-p", "iso_root/EFI/BOOT"])
|
||||
subprocess.run(["mkdir", "-p", "iso_root/mod/"])
|
||||
subprocess.run(["cp", "-v", "modules/helloworld/helloworld.elf", "iso_root/mod/"])
|
||||
subprocess.run(["cp", "-v", "modules/com/com.elf", "iso_root/mod/"])
|
||||
subprocess.run(["cp", "-v", "limine/BOOTX64.EFI", "iso_root/EFI/BOOT/"])
|
||||
subprocess.run(["cp", "-v", "limine/BOOTIA32.EFI", "iso_root/EFI/BOOT/"])
|
||||
subprocess.run(["xorriso", "-as", "mkisofs", "-b", "limine-bios-cd.bin",
|
||||
@ -90,20 +109,8 @@ def create_iso(IMAGE_NAME):
|
||||
subprocess.run(["./limine/limine", "bios-install", IMAGE_NAME+".iso"])
|
||||
subprocess.run(["rm", "-rf", "iso_root"])
|
||||
|
||||
def create_hdd(IMAGE_NAME):
|
||||
subprocess.run(["rm", "-f", IMAGE_NAME+".hdd"])
|
||||
subprocess.run(["dd", "if=/dev/zero", "bs=1M", "count=0", "seek=64", "of="+IMAGE_NAME+".hdd"])
|
||||
subprocess.run(["sgdisk", IMAGE_NAME+".hdd", "-n", "1:2048", "-t", "1:ef00"])
|
||||
subprocess.run(["./limine/limine", "bios-install", IMAGE_NAME+".hdd"])
|
||||
subprocess.run(["mformat", "-i", IMAGE_NAME+".hdd@@1M"])
|
||||
subprocess.run(["mmd", "-i", IMAGE_NAME+".hdd@@1M", "::/EFI", "::/EFI/BOOT"])
|
||||
subprocess.run(["mcopy", "-i", IMAGE_NAME+".hdd@@1M",
|
||||
"kernel.elf", "configs/limine.cfg", "limine/limine-bios.sys", "::/"])
|
||||
subprocess.run(["mcopy", "-i", IMAGE_NAME+".hdd@@1M",
|
||||
"limine/BOOTX64.EFI", "limine/BOOTIA32.EFI", "::/EFI/BOOT"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.system("""find . \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) -print0 | xargs -0 clang-format -i -style=file""")
|
||||
subprocess.run(["rm", "-rf", "bin"])
|
||||
subprocess.run(["mkdir", "-p", "bin"])
|
||||
|
||||
@ -116,7 +123,7 @@ if __name__ == "__main__":
|
||||
check_limine()
|
||||
check_tools()
|
||||
compile_all()
|
||||
create_hdd("mseos")
|
||||
create_iso("mseos")
|
||||
create_hdd("mseos")
|
||||
|
||||
print("qemu-system-x86_64 -M q35 -m 8G -smp 8 -bios ovmf/OVMF.fd -hda mseos.hdd")
|
@ -10,3 +10,11 @@ INTERFACE_BRANDING=By Aren Elchinyan
|
||||
KASLR=no
|
||||
KERNEL_PATH=boot:///kernel.elf
|
||||
|
||||
MODULE_PATH=boot:///kernel.elf
|
||||
MODULE_CMDLINE=boot:///kernel.elf
|
||||
|
||||
MODULE_PATH=boot:///mod/helloworld.elf
|
||||
MODULE_CMDLINE=helloworld
|
||||
|
||||
MODULE_PATH=boot:///mod/com.elf
|
||||
MODULE_CMDLINE=com
|
@ -1,3 +1,3 @@
|
||||
namespace arch {
|
||||
void init();
|
||||
void init( );
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
namespace cpu {
|
||||
void init();
|
||||
void init( );
|
||||
}
|
13
include/fb.h
13
include/fb.h
@ -1,3 +1,12 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace fb {
|
||||
void init();
|
||||
}
|
||||
|
||||
void init( );
|
||||
|
||||
void printf(char *str, ...);
|
||||
|
||||
void printf_at(size_t x, size_t y, char *str, ...);
|
||||
} // namespace fb
|
15
include/lock.h
Normal file
15
include/lock.h
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
int lock;
|
||||
const char* file;
|
||||
} lock_t;
|
||||
|
||||
#define LOCK_INIT \
|
||||
(lock_t) { 0, __FILE__ }
|
||||
|
||||
namespace lock {
|
||||
int swap(lock_t* lock);
|
||||
void acquire(lock_t* lock);
|
||||
void release(lock_t* lock);
|
||||
} // namespace lock
|
5
include/mem.h
Normal file
5
include/mem.h
Normal file
@ -0,0 +1,5 @@
|
||||
namespace mem {
|
||||
void init( );
|
||||
void *alloc_block( );
|
||||
void free_block(void *block);
|
||||
} // namespace mem
|
3
include/mod.h
Normal file
3
include/mod.h
Normal file
@ -0,0 +1,3 @@
|
||||
namespace mod {
|
||||
void init( );
|
||||
}
|
@ -1,6 +1,25 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#define assert(check) \
|
||||
({ \
|
||||
if (!(check)) { \
|
||||
fb::printf("\nassert() failed in %s() (%s:%d)\n", __func__, \
|
||||
__FILE__, __LINE__); \
|
||||
for (;;) asm volatile("hlt"); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ALIGN_UP(NUM, ALIGN) (((NUM) + ALIGN - 1) & ~(ALIGN - 1))
|
||||
#define ALIGN_DOWN(NUM, ALIGN) ((NUM) & ~(ALIGN - 1))
|
||||
#define CONTAINER_OF(PTR, TYPE, MEMBER) \
|
||||
((TYPE *)((void *)PTR - OFFSET_OF(TYPE, MEMBER)))
|
||||
|
||||
#define BIT_SET(BIT) (bitmap[(BIT) / 8] |= (1 << ((BIT) % 8)))
|
||||
#define BIT_CLEAR(BIT) (bitmap[(BIT) / 8] &= ~(1 << ((BIT) % 8)))
|
||||
#define BIT_GET(BIT) ((bitmap[(BIT) / 8] >> ((BIT) % 8)) & 1)
|
||||
|
||||
namespace tool {
|
||||
void format(void (*putc)(char c), const char *format_string, va_list args);
|
||||
}
|
||||
void memcpy(void *dest, void *src, uint64_t n);
|
||||
void *memset(void *ptr, uint8_t n, uint64_t size);
|
||||
void format(void (*putc)(char c), const char *format_string, va_list args);
|
||||
} // namespace tool
|
@ -1,17 +1,15 @@
|
||||
#include <limine.h>
|
||||
|
||||
|
||||
|
||||
namespace arch {
|
||||
static volatile struct limine_kernel_address_request kernel_address_request = {
|
||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_kernel_address_response *)0
|
||||
};
|
||||
|
||||
struct limine_kernel_address_response *kernel_address_response;
|
||||
static volatile struct limine_kernel_address_request kernel_address_request = {
|
||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_kernel_address_response *)0
|
||||
};
|
||||
|
||||
void init() {
|
||||
kernel_address_response = kernel_address_request.response;
|
||||
}
|
||||
}
|
||||
struct limine_kernel_address_response *kernel_address_response;
|
||||
|
||||
void init( ) {
|
||||
kernel_address_response = kernel_address_request.response;
|
||||
}
|
||||
} // namespace arch
|
173
kernel/cpu.cpp
173
kernel/cpu.cpp
@ -1,15 +1,168 @@
|
||||
#include <stdint.h>
|
||||
#include <fb.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
namespace cpu {
|
||||
static bool x87_support = false;
|
||||
static bool sse_support = false;
|
||||
static bool avx_support = false;
|
||||
static bool acpi_msrs_support = false;
|
||||
static bool mmx_support = false;
|
||||
static bool sse2_support = false;
|
||||
static bool avx_support = false;
|
||||
static bool rdrnd_support = false;
|
||||
|
||||
void init() {
|
||||
x87_support = false;
|
||||
sse_support = false;
|
||||
avx_support = false;
|
||||
}
|
||||
void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
|
||||
uint32_t *edx) {
|
||||
asm volatile("cpuid"
|
||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||
: "a"(leaf));
|
||||
}
|
||||
|
||||
void msr_get(uint32_t msr, uint32_t *lo, uint32_t *hi) {
|
||||
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
|
||||
}
|
||||
|
||||
void msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
|
||||
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
|
||||
}
|
||||
|
||||
uint64_t get_cpu_temperature( ) {
|
||||
uint32_t lo, hi;
|
||||
|
||||
// Чтение температуры из MSR
|
||||
cpu::msr_get(0x19C, &lo, &hi);
|
||||
|
||||
uint64_t temp = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
|
||||
// Преобразование значения температуры
|
||||
uint64_t temperature = (temp >> 16) / 256;
|
||||
|
||||
return temperature;
|
||||
}
|
||||
|
||||
void l2_cache( ) {
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
unsigned int lsize, assoc, cache;
|
||||
|
||||
cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
|
||||
lsize = ecx & 0xFF;
|
||||
fb::printf("Кэш L1: %d KB\n", lsize);
|
||||
|
||||
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
|
||||
lsize = ecx & 0xFF;
|
||||
assoc = (ecx >> 12) & 0x0F;
|
||||
cache = (ecx >> 16) & 0xFF;
|
||||
|
||||
fb::printf("Кэш L2: %d KB\n", lsize);
|
||||
}
|
||||
|
||||
void do_amd( ) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
uint32_t eggs[4];
|
||||
uint32_t cpu_model;
|
||||
uint32_t cpu_family;
|
||||
char eggs_string[13];
|
||||
|
||||
cpuid(0x8FFFFFFF, &eggs[0], &eggs[1], &eggs[2], &eggs[3]);
|
||||
tool::memcpy(eggs_string, eggs, 12);
|
||||
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
cpu_model = (eax >> 4) & 0x0F;
|
||||
cpu_family = (eax >> 8) & 0x0F;
|
||||
|
||||
fb::printf("Используется процессор AMD, 8FFFFFFF = [%s]\n", eggs_string);
|
||||
fb::printf("cpu_model = [%u]\n", cpu_model);
|
||||
fb::printf("cpu_family = [%u]\n", cpu_family);
|
||||
}
|
||||
|
||||
void brandname( ) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
char brand_string[49];
|
||||
uint32_t brand[12];
|
||||
uint32_t manufacturer[4];
|
||||
char manufacturer_string[13];
|
||||
|
||||
cpuid(0, &manufacturer[3], &manufacturer[0], &manufacturer[2],
|
||||
&manufacturer[1]);
|
||||
tool::memcpy(manufacturer_string, manufacturer, 12);
|
||||
|
||||
brand_string[48] = 0;
|
||||
manufacturer_string[12] = 0;
|
||||
|
||||
fb::printf("[CPUID] manufacturer [%s]\n", manufacturer_string);
|
||||
|
||||
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
||||
if (eax >= 0x80000004) {
|
||||
cpuid(0x80000002, &brand[0], &brand[1], &brand[2], &brand[3]);
|
||||
cpuid(0x80000003, &brand[4], &brand[5], &brand[6], &brand[7]);
|
||||
cpuid(0x80000004, &brand[8], &brand[9], &brand[10], &brand[11]);
|
||||
tool::memcpy(brand_string, brand, 48);
|
||||
fb::printf("[CPUID] 0x80000002:0x80000004 [%s]\n", brand_string);
|
||||
}
|
||||
|
||||
if (manufacturer[0] == 0x68747541) { do_amd( ); }
|
||||
}
|
||||
|
||||
void sse_init( ) {
|
||||
asm volatile("clts\n"
|
||||
"mov %%cr0, %%rax\n"
|
||||
"and $0xFFFD, %%ax\n"
|
||||
"or $0x10, %%ax\n"
|
||||
"mov %%rax, %%cr0\n"
|
||||
"fninit\n"
|
||||
"mov %%cr0, %%rax\n"
|
||||
"and $0xfffb, %%ax\n"
|
||||
"or $0x0002, %%ax\n"
|
||||
"mov %%rax, %%cr0\n"
|
||||
"mov %%cr4, %%rax\n"
|
||||
"or $0x600, %%rax\n"
|
||||
"mov %%rax, %%cr4\n"
|
||||
"push $0x1F80\n"
|
||||
"ldmxcsr (%%rsp)\n"
|
||||
"addq $8, %%rsp\n"
|
||||
:
|
||||
:
|
||||
: "rax");
|
||||
}
|
||||
|
||||
void init( ) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if ((edx >> 0) & 1) { fb::printf("FPU(x87) подерживается!\n"); }
|
||||
|
||||
if ((edx >> 22) & 1) {
|
||||
acpi_msrs_support = true;
|
||||
fb::printf("Встроенный терморегулятор MSRS для ACPI\n");
|
||||
fb::printf("Температура: %u\n", get_cpu_temperature( ));
|
||||
}
|
||||
|
||||
if ((edx >> 23) & 1) {
|
||||
mmx_support = true;
|
||||
fb::printf("MMX подерживается!\n");
|
||||
}
|
||||
|
||||
if ((edx >> 25) & 1) {
|
||||
sse2_support = true;
|
||||
fb::printf("SSE2 подерживается!\n");
|
||||
sse_init( );
|
||||
}
|
||||
|
||||
if ((edx >> 29) & 1) {
|
||||
fb::printf("Термоконтроллер автоматически ограничивает температуру\n");
|
||||
}
|
||||
|
||||
if ((ecx >> 28) & 1) {
|
||||
avx_support = true;
|
||||
fb::printf("AVX подерживается!\n");
|
||||
}
|
||||
|
||||
cpuid(0x7, &eax, &ebx, &ecx, &edx);
|
||||
if ((ebx >> 30) & 1) {
|
||||
rdrnd_support = true;
|
||||
fb::printf("RDRND подерживается!\n");
|
||||
}
|
||||
|
||||
brandname( );
|
||||
l2_cache( );
|
||||
}
|
||||
} // namespace cpu
|
157
kernel/fb.cpp
157
kernel/fb.cpp
@ -1,32 +1,137 @@
|
||||
#include <6x8_slim_font.h>
|
||||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
|
||||
enum colors {
|
||||
WHITE = 0xFFFFFF,
|
||||
BLACK = 0x000000,
|
||||
RED = 0xFF0000,
|
||||
GREEN = 0x00FF00,
|
||||
BLUE = 0x0000FF,
|
||||
DARK_GREEN = 0x013220,
|
||||
};
|
||||
|
||||
namespace fb {
|
||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_framebuffer_response *)0
|
||||
};
|
||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_framebuffer_response *)0
|
||||
};
|
||||
|
||||
struct limine_framebuffer_response *framebuffer_response;
|
||||
struct limine_framebuffer *boot_framebuffer;
|
||||
uint32_t *fb_addr;
|
||||
uint64_t width;
|
||||
uint64_t height;
|
||||
uint64_t pitch;
|
||||
uint16_t bpp;
|
||||
|
||||
void init() {
|
||||
framebuffer_response = framebuffer_request.response;
|
||||
boot_framebuffer = framebuffer_response->framebuffers[0];
|
||||
fb_addr = (uint32_t*)boot_framebuffer->address;
|
||||
width = boot_framebuffer->width;
|
||||
height = boot_framebuffer->height;
|
||||
bpp = boot_framebuffer->bpp;
|
||||
struct limine_framebuffer_response *framebuffer_response;
|
||||
struct limine_framebuffer *boot_framebuffer;
|
||||
uint32_t *fb_addr;
|
||||
uint32_t text_color = GREEN;
|
||||
uint32_t background = DARK_GREEN;
|
||||
uint64_t width;
|
||||
uint64_t height;
|
||||
uint64_t pitch;
|
||||
uint16_t bpp;
|
||||
|
||||
for (uint64_t i = 0; i < width * height; i++) {
|
||||
fb_addr[i] = 0x0000FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t pos_x = 4;
|
||||
size_t pos_y = 4;
|
||||
|
||||
#define SCREEN_WIDTH width
|
||||
#define SCREEN_HEIGHT height
|
||||
#define SCREEN_BUFFER fb_addr
|
||||
|
||||
void init( ) {
|
||||
framebuffer_response = framebuffer_request.response;
|
||||
boot_framebuffer = framebuffer_response->framebuffers[0];
|
||||
fb_addr = (uint32_t *)boot_framebuffer->address;
|
||||
width = boot_framebuffer->width;
|
||||
height = boot_framebuffer->height;
|
||||
bpp = boot_framebuffer->bpp;
|
||||
|
||||
for (uint64_t i = 0; i < width * height; i++) { fb_addr[i] = background; }
|
||||
}
|
||||
|
||||
static inline void print_bits(size_t x, size_t y, uint8_t num) {
|
||||
for (size_t i = 0; i <= 7; i++) {
|
||||
if ((num >> i) & 1) {
|
||||
SCREEN_BUFFER[x + i + y * SCREEN_WIDTH] = text_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t analyze(char glyth) {
|
||||
return ((uint8_t)glyth - 32) * 8;
|
||||
}
|
||||
|
||||
static void print_char(int x, int y, char glyth) {
|
||||
for (size_t i = 0; i < FONT_6X8_SLIM_CHAR_HEIGHT; i++) {
|
||||
print_bits(x, y + i, font_6x8_slim[analyze(glyth) + i]);
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_fb( ) {
|
||||
size_t last_line_index =
|
||||
(SCREEN_HEIGHT - (FONT_6X8_SLIM_CHAR_HEIGHT)) * SCREEN_WIDTH;
|
||||
|
||||
for (size_t y = 0; y < SCREEN_HEIGHT - (FONT_6X8_SLIM_CHAR_HEIGHT); y++) {
|
||||
for (size_t x = 0; x < SCREEN_WIDTH; x++) {
|
||||
SCREEN_BUFFER[x + y * SCREEN_WIDTH] =
|
||||
SCREEN_BUFFER[x +
|
||||
(y + (FONT_6X8_SLIM_CHAR_HEIGHT)) * SCREEN_WIDTH];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = last_line_index; i < SCREEN_HEIGHT * SCREEN_WIDTH; i++) {
|
||||
SCREEN_BUFFER[i] = background;
|
||||
}
|
||||
}
|
||||
|
||||
static void fb_putchar(char c) {
|
||||
if (c == '\t') {
|
||||
pos_x += FONT_6X8_SLIM_CHAR_WIDTH * 4;
|
||||
} else if (c == '\n') {
|
||||
// Новая строка
|
||||
pos_x = 4;
|
||||
pos_y += FONT_6X8_SLIM_CHAR_HEIGHT + 1;
|
||||
} else {
|
||||
if (pos_x >= SCREEN_WIDTH) {
|
||||
pos_x = 4;
|
||||
pos_y += FONT_6X8_SLIM_CHAR_HEIGHT + 1;
|
||||
}
|
||||
if (pos_y >= SCREEN_HEIGHT - FONT_6X8_SLIM_CHAR_HEIGHT) {
|
||||
scroll_fb( );
|
||||
pos_y -= FONT_6X8_SLIM_CHAR_HEIGHT;
|
||||
}
|
||||
print_char(pos_x, pos_y, c);
|
||||
pos_x += FONT_6X8_SLIM_CHAR_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
void printf(char *str, ...) {
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
tool::format(&fb_putchar, str, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void printf_at(size_t x, size_t y, char *str, ...) {
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
|
||||
// Сохраняем текущие значения pos_x и pos_y
|
||||
size_t prev_pos_x = pos_x;
|
||||
size_t prev_pos_y = pos_y;
|
||||
|
||||
// Устанавливаем новые значения координат вывода
|
||||
pos_x = x;
|
||||
pos_y = y;
|
||||
|
||||
// Выводим строку
|
||||
tool::format(&fb_putchar, str, args);
|
||||
|
||||
// Восстанавливаем предыдущие значения pos_x и pos_y
|
||||
pos_x = prev_pos_x;
|
||||
pos_y = prev_pos_y;
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
} // namespace fb
|
29
kernel/lock.cpp
Normal file
29
kernel/lock.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include <fb.h>
|
||||
#include <lock.h>
|
||||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
namespace lock {
|
||||
int swap(lock_t *lock) {
|
||||
return __sync_bool_compare_and_swap(&lock->lock, 0, 1);
|
||||
}
|
||||
|
||||
void acquire(lock_t *lock) {
|
||||
uint64_t count = 0;
|
||||
|
||||
for (;;) {
|
||||
if (swap(lock)) { break; }
|
||||
count++;
|
||||
if (count > 1000000) {
|
||||
fb::printf("%s deadlock", lock->file);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
asm volatile("pause");
|
||||
}
|
||||
}
|
||||
|
||||
void release(lock_t *lock) {
|
||||
__sync_bool_compare_and_swap(&lock->lock, 1, 0);
|
||||
}
|
||||
} // namespace lock
|
@ -0,0 +1,53 @@
|
||||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <lock.h>
|
||||
#include <tool.h>
|
||||
|
||||
#define BLOCK_SIZE 4096
|
||||
static volatile struct limine_memmap_request memmap_request = {
|
||||
.id = LIMINE_MEMMAP_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_memmap_response *)0
|
||||
};
|
||||
static volatile struct limine_hhdm_request hhdm_request = {
|
||||
.id = LIMINE_HHDM_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_hhdm_response *)0
|
||||
};
|
||||
|
||||
namespace mem {
|
||||
|
||||
#define HHDM_OFFSET (hhdm_request.response->offset)
|
||||
|
||||
struct limine_memmap_response *memmap_response;
|
||||
struct limine_memmap_entry *memmap_entry;
|
||||
uint8_t *bitmap;
|
||||
uint64_t limit;
|
||||
uint64_t usable = 0;
|
||||
uint64_t available = 0;
|
||||
uint64_t highest = 0;
|
||||
uint64_t mmmap_count = 0;
|
||||
|
||||
lock_t lock = LOCK_INIT;
|
||||
|
||||
void init( ) {
|
||||
memmap_response = memmap_request.response;
|
||||
mmmap_count = memmap_response->entry_count;
|
||||
|
||||
fb::printf("В карте памяти: %u записей.\n", memmap_response->entry_count);
|
||||
}
|
||||
|
||||
void free(void *ptr, uint64_t frames) {}
|
||||
|
||||
void *malloc(uint64_t count) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *calloc(uint64_t frames) {
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
void *alloc(uint64_t size) {
|
||||
return (void *)0;
|
||||
}
|
||||
} // namespace mem
|
32
kernel/mod.cpp
Normal file
32
kernel/mod.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <mod.h>
|
||||
|
||||
namespace mod {
|
||||
static volatile struct limine_module_request module_request = {
|
||||
.id = LIMINE_MODULE_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_module_response *)0
|
||||
};
|
||||
|
||||
struct limine_module_response *module_response;
|
||||
static uint64_t module_count = 0;
|
||||
|
||||
void init( ) {
|
||||
module_response = module_request.response;
|
||||
module_count = module_response->module_count;
|
||||
struct limine_file *module_ptr = (struct limine_file *)0;
|
||||
|
||||
for (uint64_t i = 0; i < module_count; i++) {
|
||||
module_ptr = module_response->modules[i];
|
||||
fb::printf("[%d] %s [%s] 0x%x\n", i, module_ptr->path,
|
||||
module_ptr->cmdline, module_ptr->address);
|
||||
fb::printf("->Size: %u, media_type: %u, partition_index: %u\n",
|
||||
module_ptr->size, module_ptr->media_type,
|
||||
module_ptr->partition_index);
|
||||
fb::printf("->mbr_disk_id: %u, tftp_ip: %u, tftp_port: %u\n\n",
|
||||
module_ptr->mbr_disk_id, module_ptr->tftp_ip,
|
||||
module_ptr->tftp_port);
|
||||
}
|
||||
}
|
||||
} // namespace mod
|
@ -1,20 +1,19 @@
|
||||
#include <limine.h>
|
||||
#include <arch.h>
|
||||
#include <cpu.h>
|
||||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <mem.h>
|
||||
#include <mod.h>
|
||||
#include <tool.h>
|
||||
|
||||
|
||||
|
||||
// Точка входа
|
||||
extern "C" void _start() {
|
||||
asm volatile("cli");
|
||||
extern "C" void _start( ) {
|
||||
asm volatile("cli");
|
||||
|
||||
arch::init();
|
||||
cpu::init();
|
||||
fb::init();
|
||||
fb::init( );
|
||||
fb::printf("Привет, мир!!\n");
|
||||
cpu::init( );
|
||||
mem::init( );
|
||||
|
||||
for (;;) {
|
||||
asm volatile("hlt");
|
||||
}
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
192
kernel/tool.cpp
192
kernel/tool.cpp
@ -3,54 +3,150 @@
|
||||
#include <stdint.h>
|
||||
|
||||
namespace tool {
|
||||
// Функция для форматированного вывода
|
||||
void format(void (*putc)(char c), const char *format_string, va_list args) {
|
||||
while (*format_string != '\0') {
|
||||
if (*format_string == '%') {
|
||||
format_string++;
|
||||
if (*format_string == '\0') {
|
||||
break; // Неожиданный конец строки формата
|
||||
}
|
||||
if (*format_string == '%') {
|
||||
putc('%'); // Вывод одного символа '%'
|
||||
} else if (*format_string == 'd') {
|
||||
int arg = va_arg(args, int);
|
||||
// Преобразование целочисленного аргумента в строку и вывод каждого символа
|
||||
if (arg < 0) {
|
||||
putc('-');
|
||||
arg = -arg;
|
||||
}
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[10]; // Предполагаем, что максимальное число из 10 цифр
|
||||
int i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 10);
|
||||
arg /= 10;
|
||||
}
|
||||
void memcpy(void *dest, void *src, uint64_t n) {
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
while (i > 0) {
|
||||
putc(buffer[--i]);
|
||||
}
|
||||
}
|
||||
} else if (*format_string == 's') {
|
||||
const char* arg = va_arg(args, const char*);
|
||||
// Вывод каждого символа строки
|
||||
while (*arg != '\0') {
|
||||
putc(*arg);
|
||||
arg++;
|
||||
}
|
||||
} else {
|
||||
// Неподдерживаемый спецификатор формата
|
||||
putc('?');
|
||||
}
|
||||
} else {
|
||||
putc(*format_string);
|
||||
}
|
||||
for (uint64_t i = 0; i < n; i++) { d[i] = s[i]; }
|
||||
}
|
||||
|
||||
format_string++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void *memset(void *ptr, uint8_t n, uint64_t size) {
|
||||
uint8_t *p = (uint8_t *)ptr;
|
||||
for (uint64_t i = 0; i < size; i++) { p[i] = n; }
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Функция для форматированного вывода
|
||||
void format(void (*putc)(char c), const char *format_string, va_list args) {
|
||||
while (*format_string != '\0') {
|
||||
if (*format_string == '%') {
|
||||
format_string++;
|
||||
if (*format_string == '\0') {
|
||||
break; // Неожиданный конец строки формата
|
||||
}
|
||||
if (*format_string == '%') {
|
||||
putc('%'); // Вывод одного символа '%'
|
||||
} else if (*format_string == 'd') {
|
||||
int arg = va_arg(args, int);
|
||||
// Преобразование целочисленного аргумента в строку и вывод
|
||||
// каждого символа
|
||||
if (arg < 0) {
|
||||
putc('-');
|
||||
arg = -arg;
|
||||
}
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[10]; // Предполагаем, что максимальное число из
|
||||
// 10 цифр
|
||||
int i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 10);
|
||||
arg /= 10;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else if (*format_string == 's') {
|
||||
const char *arg = va_arg(args, const char *);
|
||||
// Вывод каждого символа строки
|
||||
while (*arg != '\0') {
|
||||
putc(*arg);
|
||||
arg++;
|
||||
}
|
||||
} else if (*format_string == 'u') {
|
||||
unsigned int arg = va_arg(args, unsigned int);
|
||||
// Преобразование беззнакового целочисленного аргумента в строку
|
||||
// и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[10]; // Предполагаем, что максимальное число из
|
||||
// 10 цифр
|
||||
int i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 10);
|
||||
arg /= 10;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else if (*format_string == 'x') {
|
||||
unsigned int arg = va_arg(args, unsigned int);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// шестнадцатеричную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[9]; // Предполагаем, что максимальное число из 8
|
||||
// символов
|
||||
int i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
int rem = arg % 16;
|
||||
if (rem < 10) {
|
||||
buffer[i++] = '0' + rem;
|
||||
} else {
|
||||
buffer[i++] = 'a' + (rem - 10);
|
||||
}
|
||||
arg /= 16;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else if (*format_string == 'c') {
|
||||
char arg = va_arg(args, int);
|
||||
// Вывод символа
|
||||
putc(arg);
|
||||
} else if (*format_string == 'o') {
|
||||
unsigned int arg = va_arg(args, unsigned int);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// восьмеричную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[12]; // Предполагаем, что максимальное число из
|
||||
// 11 символов
|
||||
int i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 8);
|
||||
arg /= 8;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else if (*format_string == 'b') {
|
||||
unsigned int arg = va_arg(args, unsigned int);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// двоичную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[33]; // Предполагаем, что максимальное число из
|
||||
// 32 символа
|
||||
int i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 2);
|
||||
arg /= 2;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else {
|
||||
// Неподдерживаемый спецификатор формата
|
||||
putc('?');
|
||||
}
|
||||
} else {
|
||||
putc(*format_string);
|
||||
}
|
||||
|
||||
format_string++;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tool
|
0
modules/com/main.cpp
Normal file
0
modules/com/main.cpp
Normal file
0
modules/helloworld/main.cpp
Normal file
0
modules/helloworld/main.cpp
Normal file
Loading…
Reference in New Issue
Block a user