Add time stuff
This commit is contained in:
parent
6ad7df109b
commit
8db7cdcbd1
35
STIVALE.md
35
STIVALE.md
@ -2,15 +2,18 @@
|
||||
|
||||
The stivale boot protocol aims to be a *simple* to implement protocol which
|
||||
provides the kernel with most of the features one may need in a *modern*
|
||||
x86_64 context.
|
||||
x86_64 context (although 32-bit x86 is also supported).
|
||||
|
||||
## General information
|
||||
|
||||
In order to have a stivale compliant kernel, one must have a kernel executable
|
||||
in the `elf64` format and have a `.stivalehdr` section (described below).
|
||||
in the `elf64` or `elf32` format and have a `.stivalehdr` section (described below).
|
||||
Other executable formats are not supported.
|
||||
|
||||
stivale natively supports and encourages higher half kernels.
|
||||
stivale will recognise whether the ELF file is 32-bit or 64-bit and load the kernel
|
||||
into the appropriate CPU mode.
|
||||
|
||||
stivale natively supports (only for 64-bit kernels) and encourages higher half kernels.
|
||||
The kernel can load itself at `0xffffffff80100000` (as defined in the linker script)
|
||||
and the bootloader will take care of everything, no AT linker script directives needed.
|
||||
|
||||
@ -27,6 +30,8 @@ The kernel MUST NOT request to load itself at an address lower than `0x100000`
|
||||
|
||||
## Kernel entry machine state
|
||||
|
||||
### 64-bit kernel
|
||||
|
||||
`rip` will be the entry point as defined in the ELF file.
|
||||
|
||||
At entry, the bootloader will have setup paging such that there is a 4GiB identity
|
||||
@ -58,6 +63,29 @@ The A20 gate is enabled.
|
||||
|
||||
`rdi` will point to the stivale structure (described below).
|
||||
|
||||
### 32-bit kernel
|
||||
|
||||
`eip` will be the entry point as defined in the ELF file.
|
||||
|
||||
At entry all segment registers are loaded as 32 bit code/data segments.
|
||||
All segment bases are `0x00000000` and all limits are `0xffffffff`.
|
||||
|
||||
DO NOT reload segment registers or rely on the provided GDT. The kernel MUST load
|
||||
its own GDT as soon as possible and not rely on the bootloader's.
|
||||
|
||||
The IDT is in an undefined state. Kernel must load its own.
|
||||
|
||||
IF flag, VM flag, and direction flag are cleared on entry. Other flags undefined.
|
||||
|
||||
PE is enabled (`cr0`).
|
||||
|
||||
The A20 gate is enabled.
|
||||
|
||||
`esp` is set to the requested stack as per stivale header.
|
||||
|
||||
A pointer to the stivale structure (described below) is pushed onto this stack
|
||||
before the entry point is called.
|
||||
|
||||
## stivale header (.stivalehdr)
|
||||
|
||||
The kernel executable shall have a section `.stivalehdr` which will contain
|
||||
@ -96,6 +124,7 @@ struct stivale_struct {
|
||||
uint64_t rsdp; // Pointer to the ACPI RSDP structure
|
||||
uint64_t module_count; // Count of modules that stivale loaded according to config
|
||||
uint64_t modules; // Pointer to the first entry in the linked list of modules (described below)
|
||||
uint64_t epoch; // UNIX epoch at boot, read from system RTC
|
||||
} __attribute__((packed));
|
||||
```
|
||||
|
||||
|
BIN
qloader2.bin
BIN
qloader2.bin
Binary file not shown.
@ -8,6 +8,10 @@
|
||||
#include <lib/real.h>
|
||||
#include <lib/cio.h>
|
||||
|
||||
uint8_t bcd_to_int(uint8_t val) {
|
||||
return (val & 0x0f) + ((val & 0xf0) >> 4) * 10;
|
||||
}
|
||||
|
||||
int cpuid(uint32_t leaf, uint32_t subleaf,
|
||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
|
||||
uint32_t cpuid_max;
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t bcd_to_int(uint8_t val);
|
||||
|
||||
int cpuid(uint32_t leaf, uint32_t subleaf,
|
||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
|
||||
|
||||
|
44
src/lib/time.c
Normal file
44
src/lib/time.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <lib/time.h>
|
||||
#include <lib/real.h>
|
||||
#include <lib/blib.h>
|
||||
|
||||
// Julian date calculation from https://en.wikipedia.org/wiki/Julian_day
|
||||
static uint64_t get_jdn(uint8_t days, uint8_t months, uint16_t years) {
|
||||
return (1461 * (years + 4800 + (months - 14)/12))/4 + (367 *
|
||||
(months - 2 - 12 * ((months - 14)/12)))/12 -
|
||||
(3 * ((years + 4900 + (months - 14)/12)/100))/4
|
||||
+ days - 32075;
|
||||
}
|
||||
|
||||
static uint64_t get_unix_epoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
|
||||
uint8_t days, uint8_t months, uint16_t years) {
|
||||
uint64_t jdn_current = get_jdn(days, months, years);
|
||||
uint64_t jdn_1970 = get_jdn(1, 1, 1970);
|
||||
|
||||
uint64_t jdn_diff = jdn_current - jdn_1970;
|
||||
|
||||
return (jdn_diff * (60 * 60 * 24)) + hours * 3600 + minutes * 60 + seconds;
|
||||
}
|
||||
|
||||
uint64_t time(void) {
|
||||
struct rm_regs r = {0};
|
||||
|
||||
r.eax = 0x0400;
|
||||
rm_int(0x1a, &r, &r);
|
||||
|
||||
uint8_t day = bcd_to_int( r.edx & 0x00ff);
|
||||
uint8_t month = bcd_to_int((r.edx & 0xff00) >> 8);
|
||||
uint16_t year = bcd_to_int( r.ecx & 0x00ff) +
|
||||
/* century */ bcd_to_int((r.ecx & 0xff00) >> 8) * 100;
|
||||
|
||||
r.eax = 0x0200;
|
||||
rm_int(0x1a, &r, &r);
|
||||
|
||||
uint8_t second = bcd_to_int((r.edx & 0xff00) >> 8);
|
||||
uint8_t minute = bcd_to_int( r.ecx & 0x00ff);
|
||||
uint8_t hour = bcd_to_int((r.ecx & 0xff00) >> 8);
|
||||
|
||||
return get_unix_epoch(second, minute, hour, day, month, year);
|
||||
}
|
8
src/lib/time.h
Normal file
8
src/lib/time.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __LIB__TIME_H__
|
||||
#define __LIB__TIME_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint64_t time(void);
|
||||
|
||||
#endif
|
@ -6,6 +6,7 @@
|
||||
#include <lib/acpi.h>
|
||||
#include <lib/e820.h>
|
||||
#include <lib/config.h>
|
||||
#include <lib/time.h>
|
||||
#include <drivers/vbe.h>
|
||||
#include <drivers/vga_textmode.h>
|
||||
#include <fs/file.h>
|
||||
@ -39,6 +40,7 @@ struct stivale_struct {
|
||||
uint64_t rsdp;
|
||||
uint64_t module_count;
|
||||
uint64_t modules;
|
||||
uint64_t epoch;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct stivale_struct stivale_struct = {0};
|
||||
@ -146,6 +148,8 @@ void stivale_load(struct file_handle *fd, char *cmdline) {
|
||||
|
||||
stivale_struct.cmdline = (uint64_t)(size_t)cmdline;
|
||||
|
||||
stivale_struct.epoch = time();
|
||||
|
||||
stivale_struct.framebuffer_width = stivale_hdr.framebuffer_width;
|
||||
stivale_struct.framebuffer_height = stivale_hdr.framebuffer_height;
|
||||
stivale_struct.framebuffer_bpp = stivale_hdr.framebuffer_bpp;
|
||||
|
Loading…
x
Reference in New Issue
Block a user