mirror of https://github.com/0Nera/BMOSP.git
Перевод кодовой базы на язык C
This commit is contained in:
parent
94dca214ca
commit
1ca922bb15
|
@ -6,6 +6,8 @@
|
|||
"string_view": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"complex": "cpp",
|
||||
"string": "cpp"
|
||||
"string": "cpp",
|
||||
"limine.h": "c",
|
||||
"tool.h": "c"
|
||||
}
|
||||
}
|
4
API.md
4
API.md
|
@ -1,6 +1,6 @@
|
|||
# Системные вызовы
|
||||
|
||||
## mem::alloc(size_t size)
|
||||
## mem_alloc(size_t size)
|
||||
|
||||
Выделение блока памяти размером `size`.
|
||||
Вовзращает адрес на блок памяти или 0 в случае ошибки.
|
||||
|
@ -10,7 +10,7 @@
|
|||
- `-1 не хватает ОЗУ`;
|
||||
- `-2 неправильный размер блока`.
|
||||
|
||||
## mem::free(uintptr_t mem)
|
||||
## mem_free(uintptr_t mem)
|
||||
|
||||
Освобождение блока памяти `mem`.
|
||||
Вовзращает 0 в случае успеха или -1 в случае ошибки.
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
БМПОС - Базовая Модульная Платформа Операционных Систем для платформы x86_64 (BIOS/UEFI). Это отечественное программное обеспечение, созданное при поддержке Синапс ОС на языке программирования C++.
|
||||
|
||||
![Скриншот вывода ядра в эмуляторе Qemu](https://0nera.github.io/BMOSP/assets/0_0.1.231.png
|
||||
|
||||
## Реализовано
|
||||
|
||||
Ядро:
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
namespace arch {
|
||||
void init( );
|
||||
}
|
||||
/**
|
||||
* arch.h
|
||||
* Заголовок для инициализации архитектурно-зависимых функций
|
||||
*
|
||||
* Данный заголовочный файл содержит определения которые используются для
|
||||
* инициализации архитектуры
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ARCH_H
|
||||
#define ARCH_H
|
||||
|
||||
void arch_init( );
|
||||
void cpu_init( );
|
||||
void gdt_init( );
|
||||
void idt_init( );
|
||||
|
||||
#endif // arch.h
|
|
@ -1,3 +0,0 @@
|
|||
namespace cpu {
|
||||
void init( );
|
||||
}
|
24
include/fb.h
24
include/fb.h
|
@ -1,12 +1,22 @@
|
|||
/**
|
||||
* fb.h
|
||||
* Заголовок с функциями фреймбуффера
|
||||
*
|
||||
* Данный заголовочный файл содержит определения которые используются для работы
|
||||
* с экранным буффером(фреймбуффером)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FB_H
|
||||
#define FB_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace fb {
|
||||
void fb_init( );
|
||||
void fb_print_buf(size_t x, size_t y, size_t h, size_t w, uint32_t *buf);
|
||||
void fb_printf(char *str, ...);
|
||||
void fb_printf_at(size_t x, size_t y, char *str, ...);
|
||||
|
||||
void init( );
|
||||
void print_buf(size_t x, size_t y, size_t h, size_t w, uint32_t *buf);
|
||||
void printf(char *str, ...);
|
||||
|
||||
void printf_at(size_t x, size_t y, char *str, ...);
|
||||
} // namespace fb
|
||||
#endif // fb.h
|
|
@ -1,3 +1,15 @@
|
|||
/**
|
||||
* lock.h
|
||||
* Заголовок с функциями блокировок
|
||||
*
|
||||
* Данный заголовочный файл содержит определения которые используются для работы
|
||||
* с блокировками ресурсов
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOCK_H
|
||||
#define LOCK_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
|
@ -10,8 +22,8 @@ typedef struct {
|
|||
0, __FILE__ \
|
||||
}
|
||||
|
||||
namespace lock {
|
||||
int swap(lock_t* lock);
|
||||
void acquire(lock_t* lock);
|
||||
void release(lock_t* lock);
|
||||
} // namespace lock
|
||||
int lock_swap(lock_t* lock);
|
||||
void lock_acquire(lock_t* lock);
|
||||
void lock_release(lock_t* lock);
|
||||
|
||||
#endif // lock.h
|
||||
|
|
|
@ -1,10 +1,28 @@
|
|||
namespace mem {
|
||||
void dump_memory( );
|
||||
void init( );
|
||||
void *alloc(size_t size);
|
||||
void free(void *addr);
|
||||
void *realloc(void *addr, size_t size);
|
||||
void *frame_alloc(uint64_t wanted_frames);
|
||||
void frame_free(void *ptr, uint64_t frames);
|
||||
void *frame_calloc(uint64_t frames);
|
||||
} // namespace mem
|
||||
/**
|
||||
* mem.h
|
||||
* Заголовочный файл с функциями менеджера памяти
|
||||
*
|
||||
* Данный заголовочный файл содержит определения, которые используются для
|
||||
* работы с памятью
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MEM_H
|
||||
#define MEM_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define BLOCK_SIZE 4096
|
||||
#define HHDM_OFFSET (hhdm_request.response->offset)
|
||||
|
||||
void mem_dump_memory( );
|
||||
void mem_init( );
|
||||
void *mem_alloc(size_t size);
|
||||
void mem_free(void *addr);
|
||||
void *mem_realloc(void *addr, size_t size);
|
||||
void *mem_frame_alloc(uint64_t wanted_frames);
|
||||
void mem_frame_free(void *ptr, uint64_t frames);
|
||||
void *mem_frame_calloc(uint64_t frames);
|
||||
|
||||
#endif // mem.h
|
|
@ -1,3 +1,15 @@
|
|||
namespace mod {
|
||||
void init( );
|
||||
}
|
||||
/**
|
||||
* mod.h
|
||||
* Заголовочный файл с функциями работы с памятью
|
||||
*
|
||||
* Данный заголовочный файл содержит определения, которые используются для
|
||||
* работы с памятью
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MOD_H
|
||||
#define MOD_H
|
||||
|
||||
void mod_init( );
|
||||
|
||||
#endif // mod.h
|
|
@ -1,6 +1,17 @@
|
|||
/**
|
||||
* sys.h
|
||||
* Заголовок содержащий определения для работы системного API
|
||||
*
|
||||
* Данный заголовочный файл содержит определения которые используются для
|
||||
* объявления структур и системных функций
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SYS_H
|
||||
#define SYS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" {
|
||||
typedef struct {
|
||||
void (*fb_printf)(char *str, ...);
|
||||
} env_t;
|
||||
|
@ -42,4 +53,5 @@ typedef struct {
|
|||
uint8_t day;
|
||||
uint8_t second;
|
||||
} time_t;
|
||||
}
|
||||
|
||||
#endif // sys.h
|
|
@ -1,20 +1,33 @@
|
|||
/**
|
||||
* tool.h
|
||||
* Заголовок содержащий определения вспомогательных функций
|
||||
*
|
||||
* Данный заголовочный файл содержит определения которые используются для
|
||||
* упрощения написания кода
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOL_H
|
||||
#define TOOL_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
#define assert(check) \
|
||||
({ \
|
||||
do { \
|
||||
if (!(check)) { \
|
||||
fb::printf("\nassert() failed in %s() (%s:%d)\n", __func__, \
|
||||
__FILE__, __LINE__); \
|
||||
fb_printf("\nassert() failed in %s() (%s:%d)\n", __func__, \
|
||||
__FILE__, __LINE__); \
|
||||
for (;;) asm volatile("hlt"); \
|
||||
} \
|
||||
})
|
||||
} while (0)
|
||||
|
||||
#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)))
|
||||
((TYPE *)((void *)PTR - offsetof(TYPE, MEMBER)))
|
||||
|
||||
#define BIT_SET(BIT) (bitmap[(BIT) / 8] |= (1 << ((BIT) % 8)))
|
||||
#define BIT_CLEAR(BIT) (bitmap[(BIT) / 8] &= ~(1 << ((BIT) % 8)))
|
||||
|
@ -28,10 +41,10 @@ static inline void pause( ) {
|
|||
}
|
||||
}
|
||||
|
||||
namespace tool {
|
||||
void memcpy(void *dest, void *src, uint64_t n);
|
||||
void *memset(void *ptr, uint8_t n, uint64_t size);
|
||||
uint64_t strlen(const char *str);
|
||||
uint64_t starts_with(const char *str, const char *prefix);
|
||||
void format(void (*putc)(char c), const char *format_string, va_list args);
|
||||
} // namespace tool
|
||||
void tool_memcpy(void *dest, void *src, uint64_t n);
|
||||
void *tool_memset(void *ptr, uint8_t n, uint64_t size);
|
||||
uint64_t tool_strlen(const char *str);
|
||||
uint64_t tool_starts_with(const char *str, const char *prefix);
|
||||
void tool_format(void (*putc)(char c), const char *format_string, va_list args);
|
||||
|
||||
#endif // tool.h
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 1
|
||||
#define VERSION_BUILD 231
|
||||
#define VERSION_BUILD 244
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
#include <arch.h>
|
||||
#include <limine.h>
|
||||
|
||||
extern "C" {
|
||||
void gdt_init( );
|
||||
|
||||
void idt_init( );
|
||||
}
|
||||
|
||||
namespace arch {
|
||||
static volatile struct limine_kernel_address_request kernel_address_request = {
|
||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||
.revision = 0,
|
||||
|
@ -15,9 +9,8 @@ static volatile struct limine_kernel_address_request kernel_address_request = {
|
|||
|
||||
struct limine_kernel_address_response *kernel_address_response;
|
||||
|
||||
void init( ) {
|
||||
void arch_init( ) {
|
||||
kernel_address_response = kernel_address_request.response;
|
||||
gdt_init( );
|
||||
idt_init( );
|
||||
}
|
||||
} // namespace arch
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
#include <fb.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
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;
|
||||
|
||||
static void sse_init( ) {
|
||||
uint64_t _cr0 = 0;
|
||||
asm volatile("mov %0, %%cr0" : "=r"(_cr0) : : "memory");
|
||||
_cr0 &= ~(1 << 2);
|
||||
_cr0 |= (1 << 1);
|
||||
asm volatile("mov %%cr0, %0" : : "r"(_cr0) : "memory");
|
||||
|
||||
uint64_t _cr4 = 0;
|
||||
asm volatile("mov %0, %%cr4" : "=r"(_cr4) : : "memory");
|
||||
_cr4 |= (3 << 9);
|
||||
asm volatile("mov %%cr4, %0" : : "r"(_cr4) : "memory");
|
||||
}
|
||||
|
||||
static 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));
|
||||
}
|
||||
|
||||
static void msr_get(uint32_t msr, uint32_t *lo, uint32_t *hi) {
|
||||
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
|
||||
}
|
||||
|
||||
static void msr_set(uint32_t msr, uint32_t lo, uint32_t hi) {
|
||||
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
|
||||
}
|
||||
|
||||
static uint64_t get_cpu_temperature( ) {
|
||||
uint32_t lo, hi;
|
||||
|
||||
// Чтение температуры из MSR
|
||||
msr_get(0x19C, &lo, &hi);
|
||||
|
||||
uint64_t temp = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
|
||||
// Преобразование значения температуры
|
||||
uint64_t temperature = (temp >> 16) / 256;
|
||||
|
||||
return temperature;
|
||||
}
|
||||
|
||||
static void l2_cache( ) {
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
unsigned int lsize, assoc, cache;
|
||||
|
||||
cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
|
||||
lsize = ecx & 0xFF;
|
||||
assoc = (ecx >> 12) & 0x07;
|
||||
cache = (ecx >> 16) & 0xFFFF;
|
||||
|
||||
fb_printf("Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
|
||||
lsize, assoc, cache);
|
||||
}
|
||||
|
||||
static 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, 0x8FFFFFFF = [%s]\n", eggs_string);
|
||||
fb_printf("cpu_model = [%u]\n", cpu_model);
|
||||
fb_printf("cpu_family = [%u]\n", cpu_family);
|
||||
}
|
||||
|
||||
static 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 cpu_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( );
|
||||
}
|
||||
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
if ((edx >> 29) & 1) {
|
||||
fb_printf("Термоконтроллер автоматически ограничивает температуру\n");
|
||||
}
|
||||
|
||||
if ((ecx >> 28) & 1) {
|
||||
avx_support = true;
|
||||
fb_printf("AVX подерживается!\n");
|
||||
}
|
||||
|
||||
if ((ecx >> 26) & 1) { fb_printf("XSAVE подерживается!\n"); }
|
||||
|
||||
if ((ecx >> 30) & 1) {
|
||||
rdrnd_support = true;
|
||||
fb_printf("RDRND подерживается!\n");
|
||||
}
|
||||
|
||||
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
||||
fb_printf("0x80000000 [EAX] = 0x%x (%u)\n", eax, eax);
|
||||
|
||||
cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if ((edx >> 5) & 1) { fb_printf("Регистры MSR подерживаются!\n"); }
|
||||
|
||||
if ((edx >> 6) & 1) {
|
||||
fb_printf("Расширение физического адреса подерживается!\n");
|
||||
}
|
||||
|
||||
if ((edx >> 7) & 1) {
|
||||
fb_printf("Исключение проверки компьютера (MCE) подерживается!\n");
|
||||
}
|
||||
|
||||
if ((edx >> 9) & 1) {
|
||||
fb_printf("Усовершенствованный программируемый контроллер прерываний "
|
||||
"подерживаются!\n");
|
||||
}
|
||||
|
||||
if ((edx >> 10) & 1) {
|
||||
fb_printf(
|
||||
"SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n");
|
||||
}
|
||||
if ((edx >> 11) & 1) { fb_printf("SYSCALL/SYSRET подерживаются!\n"); }
|
||||
|
||||
if ((edx >> 26) & 1) { fb_printf("Гигабайтные страницы подерживаются!\n"); }
|
||||
|
||||
if ((edx >> 29) & 1) { fb_printf("AMD64 подерживается!\n"); }
|
||||
if ((edx >> 30) & 1) { fb_printf("\"3DNow!\" подерживается!\n"); }
|
||||
if ((edx >> 31) & 1) { fb_printf("\"Extended 3DNow!\" подерживается!\n"); }
|
||||
if ((ecx >> 6) & 1) { fb_printf("SSE4a подерживается!\n"); }
|
||||
if ((ecx >> 7) & 1) { fb_printf("Смещенный режим SSE подерживается!\n"); }
|
||||
|
||||
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
|
||||
if ((ebx >> 0) & 1) {
|
||||
fb_printf("Восстановление после переполнения MCA подерживается!\n");
|
||||
}
|
||||
if ((ebx >> 1) & 1) {
|
||||
fb_printf("Возможность локализации и восстановления неисправимых "
|
||||
"программных ошибок подерживается!\n");
|
||||
}
|
||||
if ((edx >> 0) & 1) { fb_printf("Датчик температуры подерживается!\n"); }
|
||||
if ((edx >> 3) & 1) { fb_printf("Терморегулятор подерживается!\n"); }
|
||||
if ((edx >> 4) & 1) {
|
||||
fb_printf("Аппаратный терморегулятор (HTC) подерживается!\n");
|
||||
}
|
||||
if ((edx >> 5) & 1) {
|
||||
fb_printf("Программный терморегулятор (STC) подерживается!\n");
|
||||
}
|
||||
if ((edx >> 6) & 1) {
|
||||
fb_printf("Управление множителем 100 МГц подерживается!\n");
|
||||
}
|
||||
|
||||
fb_printf("0x80000007[ECX] = 0x%x (%u)\n", ecx, ecx);
|
||||
|
||||
cpuid(0xC0000000, &eax, &ebx, &ecx, &edx);
|
||||
if (eax > 0xC0000000) {
|
||||
fb_printf("0xC0000000 [EAX] = 0x%x (%u)\n", eax, eax);
|
||||
}
|
||||
|
||||
brandname( );
|
||||
l2_cache( );
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
#include <fb.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
extern "C" {
|
||||
void sse_init( ) {
|
||||
uint64_t _cr0 = 0;
|
||||
asm volatile("mov %0, %%cr0" : "=r"(_cr0) : : "memory");
|
||||
_cr0 &= ~(1 << 2);
|
||||
_cr0 |= (1 << 1);
|
||||
asm volatile("mov %%cr0, %0" : : "r"(_cr0) : "memory");
|
||||
|
||||
uint64_t _cr4 = 0;
|
||||
asm volatile("mov %0, %%cr4" : "=r"(_cr4) : : "memory");
|
||||
_cr4 |= (3 << 9);
|
||||
asm volatile("mov %%cr4, %0" : : "r"(_cr4) : "memory");
|
||||
}
|
||||
}
|
||||
|
||||
namespace cpu {
|
||||
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 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(0x80000006, &eax, &ebx, &ecx, &edx);
|
||||
lsize = ecx & 0xFF;
|
||||
assoc = (ecx >> 12) & 0x07;
|
||||
cache = (ecx >> 16) & 0xFFFF;
|
||||
|
||||
fb::printf("Размер строки: %u B, Тип ассоциации: %u, Размер кэша: %u КБ\n",
|
||||
lsize, assoc, cache);
|
||||
}
|
||||
|
||||
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, 0x8FFFFFFF = [%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 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( );
|
||||
}
|
||||
|
||||
cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
if ((edx >> 29) & 1) {
|
||||
fb::printf("Термоконтроллер автоматически ограничивает температуру\n");
|
||||
}
|
||||
|
||||
if ((ecx >> 28) & 1) {
|
||||
avx_support = true;
|
||||
fb::printf("AVX подерживается!\n");
|
||||
}
|
||||
|
||||
if ((ecx >> 26) & 1) { fb::printf("XSAVE подерживается!\n"); }
|
||||
|
||||
if ((ecx >> 30) & 1) {
|
||||
rdrnd_support = true;
|
||||
fb::printf("RDRND подерживается!\n");
|
||||
}
|
||||
|
||||
cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
|
||||
fb::printf("0x80000000 [EAX] = 0x%x (%u)\n", eax, eax);
|
||||
|
||||
cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if ((edx >> 5) & 1) { fb::printf("Регистры MSR подерживаются!\n"); }
|
||||
|
||||
if ((edx >> 6) & 1) {
|
||||
fb::printf("Расширение физического адреса подерживается!\n");
|
||||
}
|
||||
|
||||
if ((edx >> 7) & 1) {
|
||||
fb::printf("Исключение проверки компьютера (MCE) подерживается!\n");
|
||||
}
|
||||
|
||||
if ((edx >> 9) & 1) {
|
||||
fb::printf("Усовершенствованный программируемый контроллер прерываний "
|
||||
"подерживаются!\n");
|
||||
}
|
||||
|
||||
if ((edx >> 10) & 1) {
|
||||
fb::printf(
|
||||
"SYSCALL/SYSRET(для AMD семейства 5 линейки 7) подерживаются!\n");
|
||||
}
|
||||
if ((edx >> 11) & 1) { fb::printf("SYSCALL/SYSRET подерживаются!\n"); }
|
||||
|
||||
if ((edx >> 26) & 1) {
|
||||
fb::printf("Гигабайтные страницы подерживаются!\n");
|
||||
}
|
||||
|
||||
if ((edx >> 29) & 1) { fb::printf("AMD64 подерживается!\n"); }
|
||||
if ((edx >> 30) & 1) { fb::printf("\"3DNow!\" подерживается!\n"); }
|
||||
if ((edx >> 31) & 1) { fb::printf("\"Extended 3DNow!\" подерживается!\n"); }
|
||||
if ((ecx >> 6) & 1) { fb::printf("SSE4a подерживается!\n"); }
|
||||
if ((ecx >> 7) & 1) { fb::printf("Смещенный режим SSE подерживается!\n"); }
|
||||
|
||||
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
|
||||
if ((ebx >> 0) & 1) {
|
||||
fb::printf("Восстановление после переполнения MCA подерживается!\n");
|
||||
}
|
||||
if ((ebx >> 1) & 1) {
|
||||
fb::printf("Возможность локализации и восстановления неисправимых "
|
||||
"программных ошибок подерживается!\n");
|
||||
}
|
||||
if ((edx >> 0) & 1) { fb::printf("Датчик температуры подерживается!\n"); }
|
||||
if ((edx >> 3) & 1) { fb::printf("Терморегулятор подерживается!\n"); }
|
||||
if ((edx >> 4) & 1) {
|
||||
fb::printf("Аппаратный терморегулятор (HTC) подерживается!\n");
|
||||
}
|
||||
if ((edx >> 5) & 1) {
|
||||
fb::printf("Программный терморегулятор (STC) подерживается!\n");
|
||||
}
|
||||
if ((edx >> 6) & 1) {
|
||||
fb::printf("Управление множителем 100 МГц подерживается!\n");
|
||||
}
|
||||
|
||||
fb::printf("0x80000007[ECX] = 0x%x (%u)\n", ecx, ecx);
|
||||
|
||||
cpuid(0xC0000000, &eax, &ebx, &ecx, &edx);
|
||||
if (eax > 0xC0000000) {
|
||||
fb::printf("0xC0000000 [EAX] = 0x%x (%u)\n", eax, eax);
|
||||
}
|
||||
|
||||
brandname( );
|
||||
l2_cache( );
|
||||
}
|
||||
} // namespace cpu
|
|
@ -4,8 +4,6 @@
|
|||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t limit;
|
||||
uint16_t base_16;
|
||||
|
@ -56,6 +54,5 @@ void gdt_init( ) {
|
|||
set_gdt_entry(&gdt[10], 0, 0, 0, 0);
|
||||
|
||||
gdt_load( );
|
||||
fb::printf("GDT инициализирован\n");
|
||||
}
|
||||
}
|
||||
fb_printf("GDT инициализирован\n");
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
extern "C" {
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
|
@ -101,24 +100,23 @@ static void encode_idt_entry(uint8_t vector, void *handler, uint8_t flags) {
|
|||
}
|
||||
|
||||
static void exception_handler(struct frame state) {
|
||||
fb::printf("\nПОЛУЧЕНО ИСКЛЮЧЕНИЕ: %s\n",
|
||||
exception_names[state.int_number]);
|
||||
fb_printf("\nПОЛУЧЕНО ИСКЛЮЧЕНИЕ: %s\n", exception_names[state.int_number]);
|
||||
|
||||
fb::printf(" RAX=%x RBX=%x\n"
|
||||
" RCX=%x RDX=%x\n"
|
||||
" RSI=%x RDI=%x\n"
|
||||
" RBP=%x RSP=%x\n"
|
||||
" R08=%x R09=%x\n"
|
||||
" R10=%x R11=%x\n"
|
||||
" R12=%x R13=%x\n"
|
||||
" R14=%x R15=%x\n"
|
||||
" RIP=%x RFLAGS=%x\n"
|
||||
" CS=%x SS=%x\n"
|
||||
" ERR=%x INT=%u",
|
||||
state.rax, state.rbx, state.rcx, state.rdx, state.rsi, state.rdi,
|
||||
state.rbp, state.rsp, state.r8, state.r9, state.r10, state.r11,
|
||||
state.r12, state.r13, state.r14, state.r15, state.rip,
|
||||
state.rflags, state.cs, state.ss, state.err, state.int_number);
|
||||
fb_printf(" RAX=%x RBX=%x\n"
|
||||
" RCX=%x RDX=%x\n"
|
||||
" RSI=%x RDI=%x\n"
|
||||
" RBP=%x RSP=%x\n"
|
||||
" R08=%x R09=%x\n"
|
||||
" R10=%x R11=%x\n"
|
||||
" R12=%x R13=%x\n"
|
||||
" R14=%x R15=%x\n"
|
||||
" RIP=%x RFLAGS=%x\n"
|
||||
" CS=%x SS=%x\n"
|
||||
" ERR=%x INT=%u",
|
||||
state.rax, state.rbx, state.rcx, state.rdx, state.rsi, state.rdi,
|
||||
state.rbp, state.rsp, state.r8, state.r9, state.r10, state.r11,
|
||||
state.r12, state.r13, state.r14, state.r15, state.rip,
|
||||
state.rflags, state.cs, state.ss, state.err, state.int_number);
|
||||
|
||||
asm volatile("cli; hlt");
|
||||
}
|
||||
|
@ -127,7 +125,7 @@ void isr_generic(struct frame state) {
|
|||
if (state.int_number < 32) {
|
||||
exception_handler(state);
|
||||
} else {
|
||||
fb::printf("\nПрерывание! %u необработано :(\n", state.int_number);
|
||||
fb_printf("\nПрерывание! %u необработано :(\n", state.int_number);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,10 +143,9 @@ void idt_init( ) {
|
|||
}
|
||||
|
||||
idt_load( );
|
||||
fb::printf("IDT инициализирован\n");
|
||||
fb_printf("IDT инициализирован\n");
|
||||
}
|
||||
|
||||
void idt_set_ist(uint8_t vector, uint8_t ist) {
|
||||
idt[vector].ist = ist;
|
||||
}
|
||||
}
|
|
@ -1,150 +1,148 @@
|
|||
#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
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
pitch = boot_framebuffer->pitch;
|
||||
|
||||
for (uint64_t i = 0; i < width * height; i++) { fb_addr[i] = background; }
|
||||
|
||||
fb::printf("0x%x %ux%u\n", fb_addr, width, height);
|
||||
}
|
||||
|
||||
void print_buf(size_t x, size_t y, size_t h, size_t w, uint32_t *buf) {
|
||||
for (size_t j = 0; j < h; j++) {
|
||||
for (size_t i = 0; i < w; i++) {
|
||||
uint64_t where = (i + x) + (j + y) * width;
|
||||
SCREEN_BUFFER[where] = buf[i + j * w];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
#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,
|
||||
};
|
||||
|
||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_framebuffer_response *)0
|
||||
};
|
||||
|
||||
static struct limine_framebuffer_response *framebuffer_response;
|
||||
static 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;
|
||||
|
||||
size_t pos_x = 4;
|
||||
size_t pos_y = 4;
|
||||
|
||||
#define SCREEN_WIDTH width
|
||||
#define SCREEN_HEIGHT height
|
||||
#define SCREEN_BUFFER fb_addr
|
||||
|
||||
void fb_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;
|
||||
pitch = boot_framebuffer->pitch;
|
||||
|
||||
for (uint64_t i = 0; i < width * height; i++) { fb_addr[i] = background; }
|
||||
|
||||
fb_printf("0x%x %ux%u\n", fb_addr, width, height);
|
||||
}
|
||||
|
||||
void fb_print_buf(size_t x, size_t y, size_t h, size_t w, uint32_t *buf) {
|
||||
for (size_t j = 0; j < h; j++) {
|
||||
for (size_t i = 0; i < w; i++) {
|
||||
uint64_t where = (i + x) + (j + y) * width;
|
||||
SCREEN_BUFFER[where] = buf[i + j * w];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 fb_printf(char *str, ...) {
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
tool_format(&fb_putchar, str, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void fb_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);
|
||||
}
|
|
@ -3,19 +3,18 @@
|
|||
#include <stdint.h>
|
||||
#include <tool.h>
|
||||
|
||||
namespace lock {
|
||||
int swap(lock_t *lock) {
|
||||
int lock_swap(lock_t *lock) {
|
||||
return __sync_bool_compare_and_swap(&lock->lock, 0, 1);
|
||||
}
|
||||
|
||||
void acquire(lock_t *lock) {
|
||||
void lock_acquire(lock_t *lock) {
|
||||
uint64_t count = 0;
|
||||
|
||||
for (;;) {
|
||||
if (swap(lock)) { break; }
|
||||
if (lock_swap(lock)) { break; }
|
||||
count++;
|
||||
if (count > 1000000) {
|
||||
fb::printf("%s deadlock", lock->file);
|
||||
fb_printf("%s блокировка зависла", lock->file);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
@ -23,7 +22,6 @@ void acquire(lock_t *lock) {
|
|||
}
|
||||
}
|
||||
|
||||
void release(lock_t *lock) {
|
||||
void lock_release(lock_t *lock) {
|
||||
__sync_bool_compare_and_swap(&lock->lock, 1, 0);
|
||||
}
|
||||
} // namespace lock
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
#include <tool.h>
|
||||
extern void *bootpng_ptr;
|
||||
extern uint64_t bootpng_size;
|
||||
extern "C" {
|
||||
|
||||
typedef struct {
|
||||
unsigned char magic1; // must be zero
|
||||
|
@ -28,10 +27,10 @@ unsigned int *tga_parse(unsigned char *ptr, int size) {
|
|||
|
||||
if (w < 1 || h < 1) return NULL;
|
||||
|
||||
data = (unsigned int *)mem::alloc((w * h + 2) * sizeof(unsigned int));
|
||||
data = (unsigned int *)mem_alloc((w * h + 2) * sizeof(unsigned int));
|
||||
if (!data) {
|
||||
fb::printf("Err %u, %x, %u kb\n", __LINE__, data,
|
||||
((w * h + 2) * sizeof(unsigned int)) / 1024);
|
||||
fb_printf("Err %u, %x, %u kb\n", __LINE__, data,
|
||||
((w * h + 2) * sizeof(unsigned int)) / 1024);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -39,8 +38,8 @@ unsigned int *tga_parse(unsigned char *ptr, int size) {
|
|||
case 1:
|
||||
if (ptr[6] != 0 || ptr[4] != 0 || ptr[3] != 0 ||
|
||||
(ptr[7] != 24 && ptr[7] != 32)) {
|
||||
fb::printf("Err %u\n", __LINE__);
|
||||
mem::free(data);
|
||||
fb_printf("Err %u\n", __LINE__);
|
||||
mem_free(data);
|
||||
return NULL;
|
||||
}
|
||||
for (y = i = 0; y < h; y++) {
|
||||
|
@ -56,8 +55,8 @@ unsigned int *tga_parse(unsigned char *ptr, int size) {
|
|||
case 2:
|
||||
if (ptr[5] != 0 || ptr[6] != 0 || ptr[1] != 0 ||
|
||||
(ptr[16] != 24 && ptr[16] != 32)) {
|
||||
fb::printf("Err %u\n", __LINE__);
|
||||
mem::free(data);
|
||||
fb_printf("Err %u\n", __LINE__);
|
||||
mem_free(data);
|
||||
return NULL;
|
||||
}
|
||||
for (y = i = 0; y < h; y++) {
|
||||
|
@ -73,8 +72,8 @@ unsigned int *tga_parse(unsigned char *ptr, int size) {
|
|||
case 9:
|
||||
if (ptr[6] != 0 || ptr[4] != 0 || ptr[3] != 0 ||
|
||||
(ptr[7] != 24 && ptr[7] != 32)) {
|
||||
fb::printf("Err %u\n", __LINE__);
|
||||
mem::free(data);
|
||||
fb_printf("Err %u\n", __LINE__);
|
||||
mem_free(data);
|
||||
return NULL;
|
||||
}
|
||||
y = i = 0;
|
||||
|
@ -112,8 +111,8 @@ unsigned int *tga_parse(unsigned char *ptr, int size) {
|
|||
case 10:
|
||||
if (ptr[5] != 0 || ptr[6] != 0 || ptr[1] != 0 ||
|
||||
(ptr[16] != 24 && ptr[16] != 32)) {
|
||||
fb::printf("Err %u\n", __LINE__);
|
||||
mem::free(data);
|
||||
fb_printf("Err %u\n", __LINE__);
|
||||
mem_free(data);
|
||||
return NULL;
|
||||
}
|
||||
y = i = 0;
|
||||
|
@ -149,8 +148,8 @@ unsigned int *tga_parse(unsigned char *ptr, int size) {
|
|||
}
|
||||
break;
|
||||
default: {
|
||||
fb::printf("Err %u\n", __LINE__);
|
||||
mem::free(data);
|
||||
fb_printf("Err %u\n", __LINE__);
|
||||
mem_free(data);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -160,18 +159,17 @@ unsigned int *tga_parse(unsigned char *ptr, int size) {
|
|||
}
|
||||
void main( ) {
|
||||
for (uint64_t i = 512; i > 1; i--) { pause( ); }
|
||||
fb::printf("Загрузка завершена! 1\n");
|
||||
fb_printf("Загрузка завершена! 1\n");
|
||||
unsigned int *res = tga_parse((uint8_t *)bootpng_ptr, bootpng_size);
|
||||
fb::printf("Загрузка завершена! 2 %x\n", res);
|
||||
fb_printf("Загрузка завершена! 2 %x\n", res);
|
||||
|
||||
tga_header_t *head = (tga_header_t *)bootpng_ptr;
|
||||
|
||||
if (res != NULL) {
|
||||
fb::printf("Размер экрана загрузки: %ux%u \n", res[0], res[1]);
|
||||
fb_printf("Размер экрана загрузки: %ux%u \n", res[0], res[1]);
|
||||
}
|
||||
fb::printf("Размер экрана загрузки: %ux%u \n", head->h, head->w);
|
||||
mem::dump_memory( );
|
||||
fb_printf("Размер экрана загрузки: %ux%u \n", head->h, head->w);
|
||||
mem_dump_memory( );
|
||||
|
||||
fb::print_buf(0, 0, head->w, head->h, (uint32_t *)(res + 2));
|
||||
}
|
||||
fb_print_buf(0, 0, head->w, head->h, (uint32_t *)(res + 2));
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <lock.h>
|
||||
#include <mem.h>
|
||||
#include <stdbool.h>
|
||||
#include <tool.h>
|
||||
|
||||
#define BLOCK_SIZE 4096
|
||||
#define HHDM_OFFSET (hhdm_request.response->offset)
|
||||
|
||||
static volatile struct limine_memmap_request memmap_request = {
|
||||
.id = LIMINE_MEMMAP_REQUEST,
|
||||
.revision = 0,
|
||||
|
@ -23,49 +22,48 @@ struct mem_entry {
|
|||
size_t size;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
typedef struct mem_entry mem_entry_t;
|
||||
|
||||
// Битовая карта для отслеживания занятых и свободных фреймов памяти
|
||||
uint8_t *bitmap;
|
||||
static uint8_t *bitmap;
|
||||
// Объем доступных блоков
|
||||
uint64_t bitmap_available = 0;
|
||||
static uint64_t bitmap_available = 0;
|
||||
// Объем блоков
|
||||
uint64_t bitmap_limit = 0;
|
||||
static uint64_t bitmap_limit = 0;
|
||||
// Верхняя граница доступной памяти
|
||||
uint64_t limit;
|
||||
static uint64_t limit;
|
||||
// Объем всего доступного физического адресного пространства
|
||||
uint64_t usable = 0;
|
||||
static uint64_t usable = 0;
|
||||
// Объем доступной виртуальной памяти
|
||||
uint64_t available = 0;
|
||||
static uint64_t available = 0;
|
||||
// Наивысший адрес в available space
|
||||
uint64_t highest = 0;
|
||||
static uint64_t highest = 0;
|
||||
// Количество записей в карте памяти
|
||||
uint64_t mmmap_count = 0;
|
||||
static uint64_t mmmap_count = 0;
|
||||
|
||||
const char memory_types[8][82] = {
|
||||
static const char memory_types[8][82] = {
|
||||
"Доступно", "Зарезервировано", "ACPI, можно освободить",
|
||||
"ACPI NVS", "Плохая память", "Загрузчик, можно освободить",
|
||||
"Ядро и модули", "Буфер кадра"
|
||||
};
|
||||
|
||||
struct limine_memmap_response *memmap_response;
|
||||
static struct limine_memmap_response *memmap_response;
|
||||
|
||||
static mem_entry_t *first_node;
|
||||
|
||||
namespace mem {
|
||||
|
||||
void dump_memory( ) {
|
||||
void mem_dump_memory( ) {
|
||||
mem_entry_t *curr = first_node;
|
||||
|
||||
while (curr) {
|
||||
fb::printf("->0x%x | %u.%u kb | %u | 0x%x\n", &curr->data,
|
||||
(curr->size) / 1024, (curr->size) % 1024, curr->free,
|
||||
curr->next);
|
||||
fb_printf("->0x%x | %u.%u kb | %u | 0x%x\n", &curr->data,
|
||||
(curr->size) / 1024, (curr->size) % 1024, curr->free,
|
||||
curr->next);
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
void frame_free(void *addr, uint64_t frames) {
|
||||
void mem_frame_free(void *addr, uint64_t frames) {
|
||||
// Проход по фреймам памяти и очистка битов в битовой карте
|
||||
uint64_t frame = (uint64_t)addr / BLOCK_SIZE;
|
||||
for (uint64_t i = frame; i < frames + frame; i++) { BIT_CLEAR(i); }
|
||||
|
@ -73,7 +71,7 @@ void frame_free(void *addr, uint64_t frames) {
|
|||
}
|
||||
|
||||
// Функция выделения памяти
|
||||
void *frame_alloc(uint64_t wanted_frames) {
|
||||
void *mem_frame_alloc(uint64_t wanted_frames) {
|
||||
void *addr;
|
||||
|
||||
uint64_t available_frames = 0;
|
||||
|
@ -97,13 +95,13 @@ void *frame_alloc(uint64_t wanted_frames) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void *frame_calloc(uint64_t frames) {
|
||||
void *addr = frame_alloc(frames);
|
||||
tool::memset(addr + HHDM_OFFSET, 0, frames * BLOCK_SIZE);
|
||||
void *mem_frame_calloc(uint64_t frames) {
|
||||
void *addr = mem_frame_alloc(frames);
|
||||
tool_memset(addr + HHDM_OFFSET, 0, frames * BLOCK_SIZE);
|
||||
return addr;
|
||||
}
|
||||
|
||||
void merge_blocks(mem_entry_t *start) {
|
||||
static void merge_blocks(mem_entry_t *start) {
|
||||
if (!start->free) return;
|
||||
mem_entry_t *block = start;
|
||||
while (block->next && block->next->free) {
|
||||
|
@ -112,7 +110,7 @@ void merge_blocks(mem_entry_t *start) {
|
|||
}
|
||||
}
|
||||
|
||||
void merge_all_blocks( ) {
|
||||
void mem_merge_all_blocks( ) {
|
||||
mem_entry_t *curr = first_node;
|
||||
|
||||
while (curr) {
|
||||
|
@ -121,7 +119,7 @@ void merge_all_blocks( ) {
|
|||
}
|
||||
}
|
||||
|
||||
void add_block(void *addr, size_t size) {
|
||||
static void add_block(void *addr, size_t size) {
|
||||
mem_entry_t *new_entry = (mem_entry_t *)addr;
|
||||
|
||||
new_entry->size = size - sizeof(mem_entry_t);
|
||||
|
@ -139,7 +137,7 @@ void add_block(void *addr, size_t size) {
|
|||
}
|
||||
}
|
||||
|
||||
void alloc_init(void *address, size_t length) {
|
||||
static void alloc_init(void *address, size_t length) {
|
||||
first_node = (mem_entry_t *)address;
|
||||
|
||||
first_node->size = length - sizeof(mem_entry_t);
|
||||
|
@ -147,7 +145,7 @@ void alloc_init(void *address, size_t length) {
|
|||
first_node->next = NULL;
|
||||
}
|
||||
|
||||
void *alloc_align(size_t size, size_t alignment) {
|
||||
static void *alloc_align(size_t size, size_t alignment) {
|
||||
mem_entry_t *curr = first_node;
|
||||
|
||||
while (curr) {
|
||||
|
@ -181,11 +179,11 @@ void *alloc_align(size_t size, size_t alignment) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void *alloc(size_t size) {
|
||||
void *mem_alloc(size_t size) {
|
||||
return alloc_align(size, 1);
|
||||
}
|
||||
|
||||
void free(void *addr) {
|
||||
void mem_free(void *addr) {
|
||||
mem_entry_t *curr = first_node, *prev = NULL;
|
||||
while (curr != NULL) {
|
||||
if (curr->data == addr) {
|
||||
|
@ -198,44 +196,44 @@ void free(void *addr) {
|
|||
}
|
||||
}
|
||||
|
||||
void *realloc(void *addr, size_t size) {
|
||||
void *mem_realloc(void *addr, size_t size) {
|
||||
if (size == 0) {
|
||||
free(addr);
|
||||
mem_free(addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (addr == NULL) { return alloc(size); }
|
||||
if (addr == NULL) { return mem_alloc(size); }
|
||||
|
||||
void *new_addr = alloc(size);
|
||||
void *new_addr = mem_alloc(size);
|
||||
|
||||
if (new_addr == NULL) { return NULL; }
|
||||
|
||||
tool::memcpy(new_addr, addr, size);
|
||||
free(addr);
|
||||
tool_memcpy(new_addr, addr, size);
|
||||
mem_free(addr);
|
||||
|
||||
return new_addr;
|
||||
}
|
||||
|
||||
// Инициализация менеджера памяти
|
||||
void init( ) {
|
||||
void mem_init( ) {
|
||||
// Получение информации о доступной памяти из Limine bootloader
|
||||
memmap_response = memmap_request.response;
|
||||
mmmap_count = memmap_response->entry_count;
|
||||
struct limine_memmap_entry **mmaps = memmap_response->entries;
|
||||
|
||||
fb::printf("Записей в карте памяти: %u\n", memmap_response->entry_count);
|
||||
fb_printf("Записей в карте памяти: %u\n", memmap_response->entry_count);
|
||||
|
||||
// Обработка каждой записи в карте памяти
|
||||
for (int i = 0; i < mmmap_count; i++) {
|
||||
available += mmaps[i]->length;
|
||||
|
||||
// fb::printf("\t%d: 0x%x\tдлина: 0x%x\tтип: %s\n", i + 1,
|
||||
// fb_printf("\t%d: 0x%x\tдлина: 0x%x\tтип: %s\n", i + 1,
|
||||
// mmaps[i]->base, mmaps[i]->length, memory_types[mmaps[i]->type]);
|
||||
if (mmaps[i]->type == LIMINE_MEMMAP_FRAMEBUFFER) {
|
||||
fb::printf("На видеопамять BIOS/UEFI выделено: %u мегабайт + %u "
|
||||
"килобайт\n",
|
||||
mmaps[i]->length / 1024 / 1024,
|
||||
(mmaps[i]->length / 1024) % 1024);
|
||||
fb_printf("На видеопамять BIOS/UEFI выделено: %u мегабайт + %u "
|
||||
"килобайт\n",
|
||||
mmaps[i]->length / 1024 / 1024,
|
||||
(mmaps[i]->length / 1024) % 1024);
|
||||
}
|
||||
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
|
||||
|
||||
|
@ -253,7 +251,7 @@ void init( ) {
|
|||
|
||||
if (mmaps[i]->length >= bitmap_size) {
|
||||
bitmap = (uint8_t *)mmaps[i]->base;
|
||||
tool::memset(bitmap, 0xFF, bitmap_size);
|
||||
tool_memset(bitmap, 0xFF, bitmap_size);
|
||||
mmaps[i]->length -= bitmap_size;
|
||||
mmaps[i]->base += bitmap_size;
|
||||
available -= bitmap_size;
|
||||
|
@ -270,26 +268,24 @@ void init( ) {
|
|||
if (!(mmaps[i]->type == LIMINE_MEMMAP_USABLE)) { continue; }
|
||||
|
||||
for (uint64_t t = 0; t < mmaps[i]->length; t += BLOCK_SIZE) {
|
||||
frame_free((void *)mmaps[i]->base + t, 1);
|
||||
mem_frame_free((void *)mmaps[i]->base + t, 1);
|
||||
}
|
||||
}
|
||||
|
||||
fb::printf("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
||||
fb::printf("Размер битовой карты: %u\n", bitmap_size);
|
||||
alloc_init(frame_alloc(1), BLOCK_SIZE);
|
||||
fb_printf("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
||||
fb_printf("Размер битовой карты: %u\n", bitmap_size);
|
||||
alloc_init(mem_frame_alloc(1), BLOCK_SIZE);
|
||||
for (uint64_t i = 256 * 1024; i > 0; i -= BLOCK_SIZE) {
|
||||
add_block(frame_alloc(1024), 1024 * BLOCK_SIZE);
|
||||
add_block(mem_frame_alloc(1024), 1024 * BLOCK_SIZE);
|
||||
}
|
||||
merge_all_blocks( );
|
||||
mem::dump_memory( );
|
||||
fb::printf("%u мегабайт выделено в динамичную память\n",
|
||||
(256 * 1024 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
|
||||
fb::printf("%u МБ объем доступной памяти, %u МБ объем виртуальной памяти\n",
|
||||
(bitmap_available * BLOCK_SIZE) / 1024 / 1024,
|
||||
available / 1024 / 1024);
|
||||
mem_merge_all_blocks( );
|
||||
mem_dump_memory( );
|
||||
fb_printf("%u мегабайт выделено в динамичную память\n",
|
||||
(256 * 1024 * BLOCK_SIZE + BLOCK_SIZE) / 1024 / 1024);
|
||||
fb_printf("%u МБ объем доступной памяти, %u МБ объем виртуальной памяти\n",
|
||||
(bitmap_available * BLOCK_SIZE) / 1024 / 1024,
|
||||
available / 1024 / 1024);
|
||||
|
||||
fb::printf("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
||||
fb::printf("Проверка менеджера памяти\n");
|
||||
}
|
||||
|
||||
} // namespace mem
|
||||
fb_printf("%u / %u блоков доступно\n", bitmap_available, bitmap_limit);
|
||||
fb_printf("Проверка менеджера памяти\n");
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <mod.h>
|
||||
#include <sys.h>
|
||||
#include <tool.h>
|
||||
|
||||
// Структуры соответствующие ELF заголовкам
|
||||
typedef struct {
|
||||
unsigned char e_ident[16];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
uint64_t e_entry;
|
||||
uint64_t e_phoff;
|
||||
uint64_t e_shoff;
|
||||
uint32_t e_flags;
|
||||
uint16_t e_ehsize;
|
||||
uint16_t e_phentsize;
|
||||
uint16_t e_phnum;
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shstrndx;
|
||||
} elf64_header_t;
|
||||
|
||||
static env_t main_env;
|
||||
|
||||
void *bootpng_ptr;
|
||||
uint64_t bootpng_size;
|
||||
void main( );
|
||||
|
||||
static void *elf_entry(void *module_bin, uint64_t size) {
|
||||
// Приводим заголовок ELF файла к типу elf64_header_t
|
||||
elf64_header_t *elf_header = (elf64_header_t *)module_bin;
|
||||
|
||||
fb_printf(" Класс: ELF64\n");
|
||||
fb_printf(" Версия: %u\n", elf_header->e_ident[6]);
|
||||
fb_printf(" ОС/ABI: %u\n", elf_header->e_ident[7]);
|
||||
fb_printf(" Тип: %u\n", elf_header->e_type);
|
||||
fb_printf(" Машина: %u\n", elf_header->e_machine);
|
||||
fb_printf(" Версия: %u\n", elf_header->e_version);
|
||||
fb_printf(" Точка входа: 0x%x\n", elf_header->e_entry);
|
||||
|
||||
// Возвращаем указатель на точку входа
|
||||
return (void *)((uint64_t)elf_header->e_entry + (uint64_t)module_bin);
|
||||
}
|
||||
|
||||
static volatile struct limine_module_request module_request = {
|
||||
.id = LIMINE_MODULE_REQUEST,
|
||||
.revision = 0,
|
||||
.response = (struct limine_module_response *)0
|
||||
};
|
||||
|
||||
static struct limine_module_response *module_response;
|
||||
static uint64_t modules_count = 0;
|
||||
|
||||
void mod_init( ) {
|
||||
main_env.fb_printf = &fb_printf;
|
||||
module_response = module_request.response;
|
||||
uint64_t 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("->Размер: %u, тип носителя: %u, индекс раздела: %u\n",
|
||||
module_ptr->size, module_ptr->media_type,
|
||||
module_ptr->partition_index);
|
||||
fb_printf("->Идентификатор диска MBR: %u, TFTP IP: %u, TFTP порт: %u\n",
|
||||
module_ptr->mbr_disk_id, module_ptr->tftp_ip,
|
||||
module_ptr->tftp_port);
|
||||
|
||||
if (tool_starts_with(module_ptr->cmdline, "[BOOTIMG]")) {
|
||||
fb_printf("\t\t[BOOTIMG]\n");
|
||||
bootpng_ptr = module_ptr->address;
|
||||
bootpng_size = module_ptr->size;
|
||||
continue;
|
||||
}
|
||||
if (!tool_starts_with(module_ptr->cmdline, "[MOD]")) { continue; }
|
||||
modules_count++;
|
||||
module_info_t *(*module_init)(env_t * env) =
|
||||
(module_info_t * (*)(env_t * env))
|
||||
elf_entry(module_ptr->address, module_ptr->size);
|
||||
|
||||
fb_printf("\t->Точка входа: 0x%x\n", module_init);
|
||||
|
||||
// module_info_t *ret = module_init(&main_env);
|
||||
|
||||
// fb_printf("Инициализированно с кодом: %u\n", ret->err_code);
|
||||
// fb_printf("Сообщение из модуля: %s\n\n", ret->message);
|
||||
}
|
||||
fb_printf("Модулей обработано: %u\n", modules_count);
|
||||
}
|
114
kernel/mod.cpp
114
kernel/mod.cpp
|
@ -1,114 +0,0 @@
|
|||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <mod.h>
|
||||
#include <sys.h>
|
||||
#include <tool.h>
|
||||
|
||||
// Структуры соответствующие ELF заголовкам
|
||||
typedef struct {
|
||||
unsigned char e_ident[16];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
uint64_t e_entry;
|
||||
uint64_t e_phoff;
|
||||
uint64_t e_shoff;
|
||||
uint32_t e_flags;
|
||||
uint16_t e_ehsize;
|
||||
uint16_t e_phentsize;
|
||||
uint16_t e_phnum;
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shstrndx;
|
||||
} elf64_header_t;
|
||||
|
||||
env_t main_env;
|
||||
|
||||
extern "C" {
|
||||
void *bootpng_ptr;
|
||||
uint64_t bootpng_size;
|
||||
void main( );
|
||||
}
|
||||
|
||||
void *elf_entry(void *module_bin, uint64_t size) {
|
||||
// Приводим заголовок ELF файла к типу elf64_header_t
|
||||
elf64_header_t *elf_header = (elf64_header_t *)module_bin;
|
||||
|
||||
fb::printf(" Класс: ELF64\n");
|
||||
fb::printf(" Версия: %u\n", elf_header->e_ident[6]);
|
||||
fb::printf(" ОС/ABI: %u\n", elf_header->e_ident[7]);
|
||||
fb::printf(" Тип: %u\n", elf_header->e_type);
|
||||
fb::printf(" Машина: %u\n", elf_header->e_machine);
|
||||
fb::printf(" Версия: %u\n", elf_header->e_version);
|
||||
fb::printf(" Точка входа: 0x%x\n", elf_header->e_entry);
|
||||
#if 0
|
||||
fb::printf(" Смещение таблицы программ: %u\n", elf_header->e_phoff);
|
||||
fb::printf(" Смещение таблицы секций: %u\n", elf_header->e_shoff);
|
||||
fb::printf(" Флаги: %u\n", elf_header->e_flags);
|
||||
fb::printf(" Размер заголовка ELF файла: %u (байт)\n",
|
||||
elf_header->e_ehsize);
|
||||
fb::printf(" Размер записи таблицы программ: %u (байт)\n",
|
||||
elf_header->e_phentsize);
|
||||
fb::printf(" Количество записей таблицы программ: %u\n",
|
||||
elf_header->e_phnum);
|
||||
fb::printf(" Размер записи таблицы секций: %u (байт)\n",
|
||||
elf_header->e_shentsize);
|
||||
fb::printf(" Количество записей таблицы секций: %u\n",
|
||||
elf_header->e_shnum);
|
||||
fb::printf(" Индекс строки таблицы секций: %u\n", elf_header->e_shstrndx);
|
||||
#endif
|
||||
|
||||
// Возвращаем указатель на точку входа
|
||||
return (void *)((uint64_t)elf_header->e_entry + (uint64_t)module_bin);
|
||||
}
|
||||
|
||||
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 modules_count = 0;
|
||||
|
||||
void init( ) {
|
||||
main_env.fb_printf = &fb::printf;
|
||||
module_response = module_request.response;
|
||||
uint64_t 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("->Размер: %u, тип носителя: %u, индекс раздела: %u\n",
|
||||
module_ptr->size, module_ptr->media_type,
|
||||
module_ptr->partition_index);
|
||||
fb::printf(
|
||||
"->Идентификатор диска MBR: %u, TFTP IP: %u, TFTP порт: %u\n",
|
||||
module_ptr->mbr_disk_id, module_ptr->tftp_ip,
|
||||
module_ptr->tftp_port);
|
||||
|
||||
if (tool::starts_with(module_ptr->cmdline, "[BOOTIMG]")) {
|
||||
fb::printf("\t\t[BOOTIMG]\n");
|
||||
bootpng_ptr = module_ptr->address;
|
||||
bootpng_size = module_ptr->size;
|
||||
continue;
|
||||
}
|
||||
if (!tool::starts_with(module_ptr->cmdline, "[MOD]")) { continue; }
|
||||
modules_count++;
|
||||
module_info_t *(*module_init)(env_t * env) =
|
||||
(module_info_t * (*)(env_t * env))
|
||||
elf_entry(module_ptr->address, module_ptr->size);
|
||||
|
||||
fb::printf("\t->Точка входа: 0x%x\n", module_init);
|
||||
|
||||
// module_info_t *ret = module_init(&main_env);
|
||||
|
||||
// fb::printf("Инициализированно с кодом: %u\n", ret->err_code);
|
||||
// fb::printf("Сообщение из модуля: %s\n\n", ret->message);
|
||||
}
|
||||
fb::printf("Модулей обработано: %u\n", modules_count);
|
||||
}
|
||||
} // namespace mod
|
|
@ -0,0 +1,24 @@
|
|||
#include <arch.h>
|
||||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <mem.h>
|
||||
#include <mod.h>
|
||||
#include <tool.h>
|
||||
#include <version.h>
|
||||
|
||||
// Точка входа
|
||||
void _start( ) {
|
||||
asm volatile("cli");
|
||||
|
||||
fb_init( );
|
||||
arch_init( );
|
||||
cpu_init( );
|
||||
mem_init( );
|
||||
mod_init( );
|
||||
fb_printf("\t\t\t\t *** Базовая Модульная Платформа Операционных Систем "
|
||||
"версии %u.%u.%u ***\n",
|
||||
VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
|
||||
fb_printf("\t\t\t\t *** Дата сборки: %s %s ***\n", __DATE__, __TIME__);
|
||||
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#include <arch.h>
|
||||
#include <cpu.h>
|
||||
#include <fb.h>
|
||||
#include <limine.h>
|
||||
#include <mem.h>
|
||||
#include <mod.h>
|
||||
#include <tool.h>
|
||||
#include <version.h>
|
||||
|
||||
// Точка входа
|
||||
extern "C" void _start( ) {
|
||||
asm volatile("cli");
|
||||
|
||||
fb::init( );
|
||||
arch::init( );
|
||||
cpu::init( );
|
||||
mem::init( );
|
||||
mod::init( );
|
||||
fb::printf("\t\t\t\t *** Базовая Модульная Платформа Операционных Систем "
|
||||
"версии %u.%u.%u ***\n",
|
||||
VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
|
||||
fb::printf("\t\t\t\t *** Дата сборки: %s %s ***\n", __DATE__, __TIME__);
|
||||
|
||||
for (;;) { asm volatile("hlt"); }
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#include <stdint.h>
|
||||
#include <sys.h>
|
||||
|
||||
void sys_init( ) {}
|
||||
|
||||
framebuffer_t *sys_alloc_framebuffer( ) {
|
||||
return (framebuffer_t *)0;
|
||||
}
|
||||
|
||||
void sys_free_framebuffer(framebuffer_t *frame) {}
|
||||
|
||||
void sys_exit(int code) {}
|
||||
|
||||
int sys_get_error( ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sys_info_t *sys_get_info( ) {}
|
||||
|
||||
module_info_t *sys_get_module(uid_t module_id) {}
|
||||
|
||||
uid_t sys_new_thread(func_t func) {}
|
||||
|
||||
int sys_delete_thread(uid_t thread_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t sys_get_time( ) {}
|
||||
|
||||
void sys_set_alarm(time_t time, func_t func) {}
|
|
@ -1,40 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#include <sys.h>
|
||||
|
||||
namespace sys {
|
||||
void init( ) {}
|
||||
|
||||
framebuffer_t *alloc_framebuffer( ) {
|
||||
return (framebuffer_t *)0;
|
||||
}
|
||||
|
||||
void free_framebuffer(framebuffer_t *frame) {}
|
||||
|
||||
void exit(int code) {}
|
||||
|
||||
int get_error( ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sys_info_t *get_info( ) {
|
||||
return (sys_info_t *)0;
|
||||
}
|
||||
|
||||
module_info_t *get_module(uid_t module_id) {
|
||||
return (module_info_t *)0;
|
||||
}
|
||||
|
||||
uid_t new_thread(func_t func) {
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
|
||||
int delete_thread(uid_t thread_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t get_time( ) {
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
|
||||
void set_alarm(time_t time, func_t func) {}
|
||||
} // namespace sys
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
|
||||
void task_new_thread( ) {
|
||||
return;
|
||||
}
|
||||
|
||||
void task_delete_thread( ) {
|
||||
return;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
|
||||
void new_thread( ) {
|
||||
return;
|
||||
}
|
||||
|
||||
void delete_thread( ) {
|
||||
return;
|
||||
}
|
|
@ -1,174 +1,171 @@
|
|||
#include <limine.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace tool {
|
||||
|
||||
void memcpy(void *dest, void *src, uint64_t n) {
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
for (uint64_t i = 0; i < n; i++) { d[i] = s[i]; }
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
uint64_t strlen(const char *str) {
|
||||
uint64_t length = 0;
|
||||
while (*str) {
|
||||
length++;
|
||||
str++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
uint64_t starts_with(const char *str, const char *prefix) {
|
||||
uint64_t str_len = strlen(str);
|
||||
uint64_t prefix_len = strlen(prefix);
|
||||
|
||||
if (prefix_len > str_len) { return 0; }
|
||||
|
||||
for (uint64_t i = 0; i < prefix_len; i++) {
|
||||
if (str[i] != prefix[i]) { return 0; }
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Функция для форматированного вывода
|
||||
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') {
|
||||
int64_t arg = va_arg(args, int64_t);
|
||||
// Преобразование целочисленного аргумента в строку и вывод
|
||||
// каждого символа
|
||||
if (arg < 0) {
|
||||
putc('-');
|
||||
arg = -arg;
|
||||
}
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[10]; // Предполагаем, что максимальное число из
|
||||
// 10 цифр
|
||||
int64_t 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') {
|
||||
uint64_t arg = va_arg(args, uint64_t);
|
||||
// Преобразование беззнакового целочисленного аргумента в строку
|
||||
// и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[32]; // Предполагаем, что максимальное число из
|
||||
// 10 цифр
|
||||
int64_t i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 10);
|
||||
arg /= 10;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else if (*format_string == 'x') {
|
||||
uint64_t arg = va_arg(args, uint64_t);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// шестнадцатеричную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[32]; // Предполагаем, что максимальное число из
|
||||
// 8 символов
|
||||
int64_t i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
int64_t 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') {
|
||||
uint64_t arg = va_arg(args, uint64_t);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// восьмеричную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[12]; // Предполагаем, что максимальное число из
|
||||
// 11 символов
|
||||
int64_t i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 8);
|
||||
arg /= 8;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else if (*format_string == 'b') {
|
||||
uint64_t arg = va_arg(args, uint64_t);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// двоичную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[33]; // Предполагаем, что максимальное число из
|
||||
// 32 символа
|
||||
int64_t 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
|
||||
#include <limine.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void tool_memcpy(void *dest, void *src, uint64_t n) {
|
||||
char *d = (char *)dest;
|
||||
const char *s = (const char *)src;
|
||||
|
||||
for (uint64_t i = 0; i < n; i++) { d[i] = s[i]; }
|
||||
}
|
||||
|
||||
void *tool_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;
|
||||
}
|
||||
|
||||
uint64_t tool_strlen(const char *str) {
|
||||
uint64_t length = 0;
|
||||
while (*str) {
|
||||
length++;
|
||||
str++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
uint64_t tool_starts_with(const char *str, const char *prefix) {
|
||||
uint64_t str_len = tool_strlen(str);
|
||||
uint64_t prefix_len = tool_strlen(prefix);
|
||||
|
||||
if (prefix_len > str_len) { return 0; }
|
||||
|
||||
for (uint64_t i = 0; i < prefix_len; i++) {
|
||||
if (str[i] != prefix[i]) { return 0; }
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Функция для форматированного вывода
|
||||
void tool_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') {
|
||||
int64_t arg = va_arg(args, int64_t);
|
||||
// Преобразование целочисленного аргумента в строку и вывод
|
||||
// каждого символа
|
||||
if (arg < 0) {
|
||||
putc('-');
|
||||
arg = -arg;
|
||||
}
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[10]; // Предполагаем, что максимальное число из
|
||||
// 10 цифр
|
||||
int64_t 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') {
|
||||
uint64_t arg = va_arg(args, uint64_t);
|
||||
// Преобразование беззнакового целочисленного аргумента в строку
|
||||
// и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[32]; // Предполагаем, что максимальное число из
|
||||
// 10 цифр
|
||||
int64_t i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 10);
|
||||
arg /= 10;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else if (*format_string == 'x') {
|
||||
uint64_t arg = va_arg(args, uint64_t);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// шестнадцатеричную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[32]; // Предполагаем, что максимальное число из
|
||||
// 8 символов
|
||||
int64_t i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
int64_t 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') {
|
||||
uint64_t arg = va_arg(args, uint64_t);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// восьмеричную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[12]; // Предполагаем, что максимальное число из
|
||||
// 11 символов
|
||||
int64_t i = 0;
|
||||
|
||||
while (arg > 0) {
|
||||
buffer[i++] = '0' + (arg % 8);
|
||||
arg /= 8;
|
||||
}
|
||||
|
||||
while (i > 0) { putc(buffer[--i]); }
|
||||
}
|
||||
} else if (*format_string == 'b') {
|
||||
uint64_t arg = va_arg(args, uint64_t);
|
||||
// Преобразование беззнакового целочисленного аргумента в
|
||||
// двоичную строку и вывод каждого символа
|
||||
if (arg == 0) {
|
||||
putc('0');
|
||||
} else {
|
||||
char buffer[33]; // Предполагаем, что максимальное число из
|
||||
// 32 символа
|
||||
int64_t 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++;
|
||||
}
|
||||
}
|
|
@ -56,7 +56,7 @@ def find_files(directory, extensions):
|
|||
|
||||
|
||||
def compile(file: str):
|
||||
CC = "g++" if file.endswith('cpp') else "gcc"
|
||||
CC = "gcc"
|
||||
output_file = file.replace('/', '_')
|
||||
obj_file = f"bin/{output_file}.o"
|
||||
cmd = f"{CC} {WARN_FLAGS} {PROTECT_FLAGS} {ARCH_FLAGS} {CHARSET_FLAGS} {LIBS_FLAGS} -c {file} -o {obj_file}"
|
||||
|
@ -107,7 +107,7 @@ def check_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(["dd", "if=/dev/zero", "bs=1M", "count=0", "seek=4", "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"])
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* <название файла>.c
|
||||
* Краткое описание
|
||||
*
|
||||
* Полное описание
|
||||
*
|
||||
*/
|
||||
|
||||
// Описание функции
|
||||
void функция( ) {
|
||||
Тело функции
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* <название файла>.h
|
||||
* Краткое описание
|
||||
*
|
||||
* Полное описание
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ИМЯ_ФАЙЛА_H
|
||||
#define ИМЯ_ФАЙЛА_H
|
||||
|
||||
void функция( );
|
||||
|
||||
#endif // <название файла>.h
|
Loading…
Reference in New Issue