Squash commits for public release
This commit is contained in:
29
boot/libboot/abi/drivers.h
Normal file
29
boot/libboot/abi/drivers.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef _BOOT_LIBBOOT_ABI_DRIVERS_H
|
||||
#define _BOOT_LIBBOOT_ABI_DRIVERS_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define MASKDEFINE(N, P, S) \
|
||||
N##_POS = (P), \
|
||||
N##_SIZE = (S), \
|
||||
N##_MASK = ((~(~0 << (S))) << (P))
|
||||
|
||||
#define TOKEN_PASTE_IMPL(x, y) x##y
|
||||
#define TOKEN_PASTE(x, y) TOKEN_PASTE_IMPL(x, y)
|
||||
#define SKIP(x, y) char TOKEN_PASTE(prefix, __LINE__)[y - x - 8]
|
||||
|
||||
struct drive_desc {
|
||||
void* init;
|
||||
void* read;
|
||||
void* write;
|
||||
};
|
||||
typedef struct drive_desc drive_desc_t;
|
||||
|
||||
struct fs_desc {
|
||||
int (*get_inode)(drive_desc_t* drive_desc, const char* path, void* file_inode);
|
||||
int (*read)(drive_desc_t* drive_desc, const char* path, uint8_t* buf, uint32_t from, uint32_t len);
|
||||
int (*read_from_inode)(drive_desc_t* drive_desc, void* file_inode, uint8_t* buf, uint32_t from, uint32_t len);
|
||||
};
|
||||
typedef struct fs_desc fs_desc_t;
|
||||
|
||||
#endif // _BOOT_LIBBOOT_ABI_DRIVERS_H
|
||||
11
boot/libboot/abi/kernel.h
Normal file
11
boot/libboot/abi/kernel.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef _BOOT_LIBBOOT_ABI_KERNEL_H
|
||||
#define _BOOT_LIBBOOT_ABI_KERNEL_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
// Bootloaders and Kernel are tight together and share ABI in order
|
||||
// to run kernel, see docs/boot.md for more information.
|
||||
|
||||
static size_t shadow_area_size() { return 4 << 20; }
|
||||
|
||||
#endif // _BOOT_LIBBOOT_ABI_KERNEL_H
|
||||
45
boot/libboot/abi/memory.h
Normal file
45
boot/libboot/abi/memory.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef _BOOT_LIBBOOT_ABI_MEMORY_H
|
||||
#define _BOOT_LIBBOOT_ABI_MEMORY_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
enum MEMORY_LAYOUT_FLAGS {
|
||||
MEMORY_LAYOUT_FLAG_TERMINATE = (1 << 0),
|
||||
};
|
||||
|
||||
struct memory_layout {
|
||||
uint64_t base;
|
||||
uint64_t size;
|
||||
uint32_t flags;
|
||||
};
|
||||
typedef struct memory_layout memory_layout_t;
|
||||
|
||||
struct memory_boot_desc {
|
||||
uint64_t ram_base;
|
||||
uint64_t ram_size;
|
||||
memory_layout_t* reserved_areas;
|
||||
};
|
||||
typedef struct memory_boot_desc memory_boot_desc_t;
|
||||
|
||||
struct fb_boot_desc {
|
||||
uintptr_t vaddr;
|
||||
uintptr_t paddr;
|
||||
size_t width;
|
||||
size_t height;
|
||||
size_t pixels_per_row;
|
||||
};
|
||||
typedef struct fb_boot_desc fb_boot_desc_t;
|
||||
|
||||
struct boot_args {
|
||||
size_t paddr;
|
||||
size_t vaddr;
|
||||
size_t kernel_data_size;
|
||||
memory_boot_desc_t mem_boot_desc;
|
||||
fb_boot_desc_t fb_boot_desc;
|
||||
void* devtree;
|
||||
char cmd_args[32];
|
||||
char init_process[32];
|
||||
};
|
||||
typedef struct boot_args boot_args_t;
|
||||
|
||||
#endif // _BOOT_LIBBOOT_ABI_MEMORY_H
|
||||
110
boot/libboot/abi/multiboot.h
Normal file
110
boot/libboot/abi/multiboot.h
Normal file
@@ -0,0 +1,110 @@
|
||||
#ifndef _BOOT_LIBBOOT_ABI_MULTIBOOT_H
|
||||
#define _BOOT_LIBBOOT_ABI_MULTIBOOT_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define MULTIBOOT_INFO_MEMORY (0x1)
|
||||
#define MULTIBOOT_INFO_BOOTDEV (0x2)
|
||||
#define MULTIBOOT_INFO_CMDLINE (0x4)
|
||||
#define MULTIBOOT_INFO_MODS (0x8)
|
||||
#define MULTIBOOT_INFO_AOUT_SYMS (0x10)
|
||||
#define MULTIBOOT_INFO_ELF_SHDR (0x20)
|
||||
#define MULTIBOOT_INFO_MEM_MAP (0x40)
|
||||
#define MULTIBOOT_INFO_DRIVE_INFO (0x80)
|
||||
#define MULTIBOOT_INFO_CONFIG_TABLE (0x100)
|
||||
#define MULTIBOOT_INFO_BOOT_LOADER_NAME (0x200)
|
||||
#define MULTIBOOT_INFO_APM_TABLE (0x400)
|
||||
#define MULTIBOOT_INFO_VBE_INFO (0x800)
|
||||
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO (0x1000)
|
||||
|
||||
struct multiboot_module_entry {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
uint32_t string_addr;
|
||||
uint32_t reserved;
|
||||
};
|
||||
typedef struct multiboot_module_entry multiboot_module_entry_t;
|
||||
|
||||
struct multiboot_aout_symbol_table {
|
||||
uint32_t tabsize;
|
||||
uint32_t strsize;
|
||||
uint32_t addr;
|
||||
uint32_t reserved;
|
||||
};
|
||||
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
|
||||
|
||||
struct multiboot_elf_section_header_table {
|
||||
uint32_t num;
|
||||
uint32_t size;
|
||||
uint32_t addr;
|
||||
uint32_t shndx;
|
||||
};
|
||||
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
|
||||
|
||||
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||
#define MULTIBOOT_MEMORY_NVS 4
|
||||
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||
struct PACKED multiboot_mmap_entry {
|
||||
uint32_t size;
|
||||
uint64_t addr;
|
||||
uint64_t len;
|
||||
uint32_t type;
|
||||
};
|
||||
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||
struct multiboot_info {
|
||||
uint32_t flags;
|
||||
uint32_t mem_lower;
|
||||
uint32_t mem_upper;
|
||||
uint32_t boot_device;
|
||||
uint32_t cmdline;
|
||||
uint32_t mods_count;
|
||||
uint32_t mods_addr;
|
||||
union {
|
||||
multiboot_aout_symbol_table_t aout_sym;
|
||||
multiboot_elf_section_header_table_t elf_sec;
|
||||
} syms;
|
||||
uint32_t mmap_length;
|
||||
uint32_t mmap_addr;
|
||||
uint32_t drives_length;
|
||||
uint32_t drives_addr;
|
||||
uint32_t config_table;
|
||||
uint32_t boot_loader_name;
|
||||
uint32_t apm_table;
|
||||
uint32_t vbe_control_info;
|
||||
uint32_t vbe_mode_info;
|
||||
uint16_t vbe_mode;
|
||||
uint16_t vbe_interface_seg;
|
||||
uint16_t vbe_interface_off;
|
||||
uint16_t vbe_interface_len;
|
||||
uint64_t framebuffer_addr;
|
||||
uint32_t framebuffer_pitch;
|
||||
uint32_t framebuffer_width;
|
||||
uint32_t framebuffer_height;
|
||||
uint8_t framebuffer_bpp;
|
||||
uint8_t framebuffer_type;
|
||||
union {
|
||||
struct
|
||||
{
|
||||
uint32_t framebuffer_palette_addr;
|
||||
uint16_t framebuffer_palette_num_colors;
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint8_t framebuffer_red_field_position;
|
||||
uint8_t framebuffer_red_mask_size;
|
||||
uint8_t framebuffer_green_field_position;
|
||||
uint8_t framebuffer_green_mask_size;
|
||||
uint8_t framebuffer_blue_field_position;
|
||||
uint8_t framebuffer_blue_mask_size;
|
||||
};
|
||||
};
|
||||
};
|
||||
typedef struct multiboot_info multiboot_info_t;
|
||||
|
||||
#endif // _BOOT_LIBBOOT_ABI_MULTIBOOT_H
|
||||
18
boot/libboot/abi/rawimage.h
Normal file
18
boot/libboot/abi/rawimage.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _BOOT_LIBBOOT_ABI_RAWIMAGE_H
|
||||
#define _BOOT_LIBBOOT_ABI_RAWIMAGE_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
struct rawimage_header {
|
||||
uint64_t kern_off;
|
||||
uint64_t kern_size;
|
||||
uint64_t devtree_off;
|
||||
uint64_t devtree_size;
|
||||
uint64_t ramdisk_off;
|
||||
uint64_t ramdisk_size;
|
||||
uint64_t rawimage_size;
|
||||
uint64_t padding;
|
||||
};
|
||||
typedef struct rawimage_header rawimage_header_t;
|
||||
|
||||
#endif // _BOOT_LIBBOOT_ABI_RAWIMAGE_H
|
||||
149
boot/libboot/crypto/sha256.c
Normal file
149
boot/libboot/crypto/sha256.c
Normal file
@@ -0,0 +1,149 @@
|
||||
#include "sha256.h"
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
|
||||
const static sha256_word_t sha256_consts[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
const static sha256_word_t sha256_state_init[8] = {
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
};
|
||||
|
||||
#define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
#define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
|
||||
|
||||
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
#define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22))
|
||||
#define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25))
|
||||
#define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3))
|
||||
#define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10))
|
||||
|
||||
static void sha256_transform(sha256_ctx_t* ctx, const void* vdata)
|
||||
{
|
||||
sha256_byte_t* data = (sha256_byte_t*)vdata;
|
||||
sha256_word_t m[64];
|
||||
|
||||
size_t i = 0;
|
||||
for (sha256_word_t j = 0; i < 16; i++, j += 4) {
|
||||
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
|
||||
}
|
||||
|
||||
for (; i < 64; i++) {
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
}
|
||||
|
||||
sha256_word_t a = ctx->state[0];
|
||||
sha256_word_t b = ctx->state[1];
|
||||
sha256_word_t c = ctx->state[2];
|
||||
sha256_word_t d = ctx->state[3];
|
||||
sha256_word_t e = ctx->state[4];
|
||||
sha256_word_t f = ctx->state[5];
|
||||
sha256_word_t g = ctx->state[6];
|
||||
sha256_word_t h = ctx->state[7];
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
sha256_word_t t1 = h + EP1(e) + CH(e, f, g) + sha256_consts[i] + m[i];
|
||||
sha256_word_t t2 = EP0(a) + MAJ(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
|
||||
ctx->state[0] += a;
|
||||
ctx->state[1] += b;
|
||||
ctx->state[2] += c;
|
||||
ctx->state[3] += d;
|
||||
ctx->state[4] += e;
|
||||
ctx->state[5] += f;
|
||||
ctx->state[6] += g;
|
||||
ctx->state[7] += h;
|
||||
}
|
||||
|
||||
void sha256_init(sha256_ctx_t* ctx)
|
||||
{
|
||||
ctx->bufnxt = 0;
|
||||
ctx->bits_count = 0;
|
||||
memcpy(ctx->state, sha256_state_init, sizeof(sha256_state_init));
|
||||
}
|
||||
|
||||
void sha256_update(sha256_ctx_t* ctx, const void* vdata, size_t len)
|
||||
{
|
||||
sha256_byte_t* data = (sha256_byte_t*)vdata;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ctx->buf[ctx->bufnxt] = data[i];
|
||||
ctx->bufnxt++;
|
||||
if (ctx->bufnxt == 64) {
|
||||
sha256_transform(ctx, ctx->buf);
|
||||
ctx->bits_count += 512;
|
||||
ctx->bufnxt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_hash(sha256_ctx_t* ctx, char* hash)
|
||||
{
|
||||
size_t i = ctx->bufnxt;
|
||||
|
||||
if (ctx->bufnxt < 56) {
|
||||
ctx->buf[i++] = 0x80;
|
||||
} else {
|
||||
ctx->buf[i++] = 0x80;
|
||||
while (i < 64) {
|
||||
ctx->buf[i++] = 0x00;
|
||||
}
|
||||
sha256_transform(ctx, ctx->buf);
|
||||
i = 0;
|
||||
}
|
||||
|
||||
while (i < 56) {
|
||||
ctx->buf[i++] = 0x00;
|
||||
}
|
||||
|
||||
ctx->bits_count += ctx->bufnxt * 8;
|
||||
ctx->buf[56] = ctx->bits_count >> 56;
|
||||
ctx->buf[57] = ctx->bits_count >> 48;
|
||||
ctx->buf[58] = ctx->bits_count >> 40;
|
||||
ctx->buf[59] = ctx->bits_count >> 32;
|
||||
ctx->buf[60] = ctx->bits_count >> 24;
|
||||
ctx->buf[61] = ctx->bits_count >> 16;
|
||||
ctx->buf[62] = ctx->bits_count >> 8;
|
||||
ctx->buf[63] = ctx->bits_count >> 0;
|
||||
|
||||
sha256_transform(ctx, ctx->buf);
|
||||
|
||||
// Making hash big endian.
|
||||
for (i = 0; i < 4; i++) {
|
||||
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
|
||||
}
|
||||
}
|
||||
22
boot/libboot/crypto/sha256.h
Normal file
22
boot/libboot/crypto/sha256.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef _BOOT_LIBBOOT_CRYPTO_SHA256_H
|
||||
#define _BOOT_LIBBOOT_CRYPTO_SHA256_H
|
||||
|
||||
#include <libboot/mem/mem.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
typedef uint8_t sha256_byte_t;
|
||||
typedef uint32_t sha256_word_t;
|
||||
|
||||
struct sha256_ctx {
|
||||
uint64_t bits_count;
|
||||
sha256_word_t state[8];
|
||||
sha256_word_t bufnxt;
|
||||
sha256_byte_t buf[64];
|
||||
};
|
||||
typedef struct sha256_ctx sha256_ctx_t;
|
||||
|
||||
void sha256_init(sha256_ctx_t* ctx);
|
||||
void sha256_update(sha256_ctx_t* ctx, const void* data, size_t len);
|
||||
void sha256_hash(sha256_ctx_t* ctx, char* hash);
|
||||
|
||||
#endif // #define _BOOT_LIBBOOT_CRYPTO_SHA256_H
|
||||
136
boot/libboot/crypto/signature.c
Normal file
136
boot/libboot/crypto/signature.c
Normal file
@@ -0,0 +1,136 @@
|
||||
const char pub_xos_key_e[] = {
|
||||
(char)0x1,
|
||||
(char)0x0,
|
||||
(char)0x1,
|
||||
};
|
||||
|
||||
const char pub_xos_key_n[] = {
|
||||
(char)0x1d,
|
||||
(char)0x7e,
|
||||
(char)0x51,
|
||||
(char)0xed,
|
||||
(char)0xdc,
|
||||
(char)0x86,
|
||||
(char)0x89,
|
||||
(char)0x86,
|
||||
(char)0xb1,
|
||||
(char)0xa4,
|
||||
(char)0x84,
|
||||
(char)0x87,
|
||||
(char)0xc9,
|
||||
(char)0x35,
|
||||
(char)0xe7,
|
||||
(char)0x7f,
|
||||
(char)0x8a,
|
||||
(char)0xea,
|
||||
(char)0xcb,
|
||||
(char)0xda,
|
||||
(char)0xdf,
|
||||
(char)0xec,
|
||||
(char)0x7a,
|
||||
(char)0xa5,
|
||||
(char)0x2a,
|
||||
(char)0x60,
|
||||
(char)0x15,
|
||||
(char)0x91,
|
||||
(char)0x14,
|
||||
(char)0xd5,
|
||||
(char)0x2c,
|
||||
(char)0xbb,
|
||||
(char)0x8f,
|
||||
(char)0x8f,
|
||||
(char)0xad,
|
||||
(char)0x17,
|
||||
(char)0x5b,
|
||||
(char)0xd7,
|
||||
(char)0xda,
|
||||
(char)0x4d,
|
||||
(char)0x4b,
|
||||
(char)0xe3,
|
||||
(char)0x3e,
|
||||
(char)0x83,
|
||||
(char)0xb5,
|
||||
(char)0xb4,
|
||||
(char)0x38,
|
||||
(char)0x60,
|
||||
(char)0x59,
|
||||
(char)0x94,
|
||||
(char)0xef,
|
||||
(char)0xad,
|
||||
(char)0x39,
|
||||
(char)0x72,
|
||||
(char)0x9d,
|
||||
(char)0x7d,
|
||||
(char)0xc6,
|
||||
(char)0x1b,
|
||||
(char)0xcf,
|
||||
(char)0x4e,
|
||||
(char)0x6f,
|
||||
(char)0xee,
|
||||
(char)0xf7,
|
||||
(char)0xd3,
|
||||
(char)0xbc,
|
||||
(char)0xcf,
|
||||
(char)0xe9,
|
||||
(char)0xb9,
|
||||
(char)0xf1,
|
||||
(char)0x21,
|
||||
(char)0xef,
|
||||
(char)0x9a,
|
||||
(char)0x6,
|
||||
(char)0x75,
|
||||
(char)0xc8,
|
||||
(char)0xc2,
|
||||
(char)0x6e,
|
||||
(char)0x99,
|
||||
(char)0x28,
|
||||
(char)0xa6,
|
||||
(char)0x3,
|
||||
(char)0xe6,
|
||||
(char)0xc6,
|
||||
(char)0x4d,
|
||||
(char)0x2,
|
||||
(char)0x83,
|
||||
(char)0xe4,
|
||||
(char)0xe0,
|
||||
(char)0x21,
|
||||
(char)0xd9,
|
||||
(char)0x19,
|
||||
(char)0x11,
|
||||
(char)0x29,
|
||||
(char)0xe8,
|
||||
(char)0xff,
|
||||
(char)0x11,
|
||||
(char)0x7,
|
||||
(char)0x23,
|
||||
(char)0x44,
|
||||
(char)0x7f,
|
||||
(char)0xfb,
|
||||
(char)0x76,
|
||||
(char)0xb1,
|
||||
(char)0x7,
|
||||
(char)0xe7,
|
||||
(char)0xab,
|
||||
(char)0x83,
|
||||
(char)0x7e,
|
||||
(char)0xa6,
|
||||
(char)0xd9,
|
||||
(char)0x7a,
|
||||
(char)0x50,
|
||||
(char)0x36,
|
||||
(char)0xf,
|
||||
(char)0xb3,
|
||||
(char)0xc0,
|
||||
(char)0xb7,
|
||||
(char)0x4f,
|
||||
(char)0x17,
|
||||
(char)0xc7,
|
||||
(char)0xb5,
|
||||
(char)0x50,
|
||||
(char)0xe8,
|
||||
(char)0xe6,
|
||||
(char)0xc1,
|
||||
(char)0x3f,
|
||||
(char)0x5f,
|
||||
(char)0xa6,
|
||||
};
|
||||
10
boot/libboot/crypto/signature.h
Normal file
10
boot/libboot/crypto/signature.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _BOOT_LIBBOOT_CRYPTO_SIGNATURE_H
|
||||
#define _BOOT_LIBBOOT_CRYPTO_SIGNATURE_H
|
||||
|
||||
#define pub_xos_key_e_len (3)
|
||||
extern const char pub_xos_key_e[];
|
||||
|
||||
#define pub_xos_key_n_len (128)
|
||||
extern const char pub_xos_key_n[];
|
||||
|
||||
#endif // _BOOT_LIBBOOT_CRYPTO_SIGNATURE_H
|
||||
299
boot/libboot/crypto/uint2048.c
Normal file
299
boot/libboot/crypto/uint2048.c
Normal file
@@ -0,0 +1,299 @@
|
||||
#include "uint2048.h"
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
|
||||
#define EOVERFLOW 75
|
||||
|
||||
int uint2048_init(uint2048_t* d, uint32_t n)
|
||||
{
|
||||
int i = 0;
|
||||
d->bucket[i++] = n;
|
||||
while (i < N_UINT2048) {
|
||||
d->bucket[i++] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uint2048_init_bytes(uint2048_t* d, const char* f, size_t n)
|
||||
{
|
||||
if (n > sizeof(uint2048_t)) {
|
||||
return -1;
|
||||
}
|
||||
memset(d->bucket, 0, sizeof(uint2048_t));
|
||||
memcpy(d->bucket, f, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t char_to_u32_safe_convert(char x)
|
||||
{
|
||||
return x >= 0 ? x : 256 + x;
|
||||
}
|
||||
|
||||
int uint2048_init_bytes_be(uint2048_t* d, const char* f, size_t n)
|
||||
{
|
||||
if (n > sizeof(uint2048_t)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
uint32_t bytes4 = 0;
|
||||
size_t dd = (n / 4) * 4;
|
||||
size_t dr = n - dd;
|
||||
for (int fi = n - 4; fi >= 0; fi -= 4) {
|
||||
bytes4 = 0;
|
||||
bytes4 |= char_to_u32_safe_convert(f[fi]) << 24;
|
||||
bytes4 |= char_to_u32_safe_convert(f[fi + 1]) << 16;
|
||||
bytes4 |= char_to_u32_safe_convert(f[fi + 2]) << 8;
|
||||
bytes4 |= char_to_u32_safe_convert(f[fi + 3]) << 0;
|
||||
d->bucket[i++] = bytes4;
|
||||
}
|
||||
|
||||
bytes4 = 0;
|
||||
for (int remi = dr - 1; remi >= 0; remi--) {
|
||||
bytes4 |= char_to_u32_safe_convert(f[dd + remi]) << (remi * 8);
|
||||
}
|
||||
d->bucket[i++] = bytes4;
|
||||
|
||||
while (i < N_UINT2048) {
|
||||
d->bucket[i++] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uint2048_copy(uint2048_t* dest, uint2048_t* src)
|
||||
{
|
||||
memcpy(dest, src, sizeof(uint2048_bucket_t) * N_UINT2048);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uint2048_add(uint2048_t* a, uint2048_t* b, uint2048_t* c)
|
||||
{
|
||||
uint64_t carry = 0;
|
||||
uint64_t sum = 0;
|
||||
for (int i = 0; i < N_UINT2048; i++) {
|
||||
uint64_t ab = a->bucket[i];
|
||||
uint64_t bb = b->bucket[i];
|
||||
sum = ab + bb + carry;
|
||||
if (sum >= BASE_UINT2048U) {
|
||||
carry = 1;
|
||||
sum -= BASE_UINT2048U;
|
||||
} else {
|
||||
carry = 0;
|
||||
}
|
||||
c->bucket[i] = (uint2048_bucket_t)sum;
|
||||
}
|
||||
|
||||
return carry ? -EOVERFLOW : 0;
|
||||
}
|
||||
|
||||
int uint2048_sub(uint2048_t* a, uint2048_t* b, uint2048_t* c)
|
||||
{
|
||||
uint32_t carry = 0;
|
||||
uint64_t sum = 0;
|
||||
for (int i = 0; i < N_UINT2048; i++) {
|
||||
uint64_t ab = a->bucket[i];
|
||||
uint64_t bb = b->bucket[i];
|
||||
sum = carry + bb;
|
||||
if (ab >= sum) {
|
||||
ab = ab - (sum);
|
||||
carry = 0;
|
||||
} else {
|
||||
ab = ab + BASE_UINT2048U - (sum);
|
||||
carry = 1;
|
||||
}
|
||||
c->bucket[i] = (uint2048_bucket_t)ab;
|
||||
}
|
||||
|
||||
if (carry) {
|
||||
uint2048_init(c, 0);
|
||||
}
|
||||
return carry ? -EOVERFLOW : 0;
|
||||
}
|
||||
|
||||
int uint2048_shl(uint2048_t* a, int n)
|
||||
{
|
||||
int i;
|
||||
for (i = N_UINT2048 - 1; i >= n; i--) {
|
||||
a->bucket[i] = a->bucket[i - n];
|
||||
}
|
||||
|
||||
while (i >= 0) {
|
||||
a->bucket[i--] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uint2048_shr(uint2048_t* a, int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < N_UINT2048 - n; i++) {
|
||||
a->bucket[i] = a->bucket[i + n];
|
||||
}
|
||||
while (i < N_UINT2048) {
|
||||
a->bucket[i++] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uint2048_mult_by_digit(uint2048_t* a, uint2048_t* b, uint2048_bucket_t un)
|
||||
{
|
||||
uint64_t carry = 0;
|
||||
uint64_t tmp;
|
||||
uint64_t n = (uint64_t)un;
|
||||
for (int i = 0; i < N_UINT2048; i++) {
|
||||
uint64_t ab = a->bucket[i];
|
||||
tmp = n * ab + carry;
|
||||
if (tmp >= BASE_UINT2048U) {
|
||||
carry = tmp / BASE_UINT2048U;
|
||||
tmp %= BASE_UINT2048U;
|
||||
} else {
|
||||
carry = 0;
|
||||
}
|
||||
|
||||
b->bucket[i] = (uint2048_bucket_t)tmp;
|
||||
}
|
||||
|
||||
return carry ? -EOVERFLOW : 0;
|
||||
}
|
||||
|
||||
int uint2048_mult(uint2048_t* a, uint2048_t* b, uint2048_t* c)
|
||||
{
|
||||
uint2048_t p;
|
||||
|
||||
uint2048_init(c, 0);
|
||||
for (int i = 0; i < N_UINT2048; i++) {
|
||||
if (!a->bucket[i]) {
|
||||
continue;
|
||||
}
|
||||
uint2048_mult_by_digit(b, &p, a->bucket[i]);
|
||||
uint2048_shl(&p, i);
|
||||
uint2048_add(c, &p, c);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uint2048_div(uint2048_t* a, uint2048_t* b, uint2048_t* dividend, uint2048_t* reminder)
|
||||
{
|
||||
uint2048_t tmp;
|
||||
|
||||
if (dividend) {
|
||||
uint2048_init(dividend, 0);
|
||||
}
|
||||
uint2048_init(reminder, 0);
|
||||
for (int i = N_UINT2048 - 1; i >= 0; i--) {
|
||||
uint2048_shl(reminder, 1);
|
||||
reminder->bucket[0] = a->bucket[i];
|
||||
uint64_t l = 0, r = BASE_UINT2048U;
|
||||
while (r - l > 1) {
|
||||
uint64_t m = (l + r) / 2;
|
||||
uint2048_mult_by_digit(b, &tmp, (uint2048_bucket_t)m);
|
||||
if (uint2048_less_equal(&tmp, reminder)) {
|
||||
l = m;
|
||||
} else {
|
||||
r = m;
|
||||
}
|
||||
}
|
||||
|
||||
if (dividend) {
|
||||
dividend->bucket[i] = (uint2048_bucket_t)l;
|
||||
}
|
||||
uint2048_mult_by_digit(b, &tmp, (uint2048_bucket_t)l);
|
||||
uint2048_sub(reminder, &tmp, reminder);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uint2048_pow(uint2048_t* ua, uint2048_t* up, uint2048_t* mod, uint2048_t* ans)
|
||||
{
|
||||
uint2048_t tmp1;
|
||||
uint2048_t tmp2;
|
||||
uint2048_t const2;
|
||||
uint2048_t a;
|
||||
uint2048_t p;
|
||||
|
||||
uint2048_copy(&a, ua);
|
||||
uint2048_copy(&p, up);
|
||||
|
||||
uint2048_init(ans, 1);
|
||||
uint2048_init(&const2, 2);
|
||||
while (uint2048_is_not_zero(&p)) {
|
||||
if (uint2048_is_odd(&p)) {
|
||||
uint2048_mult(ans, &a, &tmp1);
|
||||
uint2048_div(&tmp1, mod, NULL, &tmp2);
|
||||
uint2048_copy(ans, &tmp2);
|
||||
}
|
||||
uint2048_mult(&a, &a, &tmp1);
|
||||
uint2048_div(&tmp1, mod, NULL, &tmp2);
|
||||
uint2048_copy(&a, &tmp2);
|
||||
|
||||
uint2048_div(&p, &const2, &tmp1, &tmp2);
|
||||
uint2048_copy(&p, &tmp1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool uint2048_less(uint2048_t* a, uint2048_t* b)
|
||||
{
|
||||
for (int i = N_UINT2048 - 1; i >= 0; i--) {
|
||||
if (a->bucket[i] < b->bucket[i]) {
|
||||
return true;
|
||||
}
|
||||
if (a->bucket[i] > b->bucket[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool uint2048_less_equal(uint2048_t* a, uint2048_t* b)
|
||||
{
|
||||
for (int i = N_UINT2048 - 1; i >= 0; i--) {
|
||||
if (a->bucket[i] < b->bucket[i]) {
|
||||
return true;
|
||||
}
|
||||
if (a->bucket[i] > b->bucket[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uint2048_equal(uint2048_t* a, uint2048_t* b)
|
||||
{
|
||||
for (int i = 0; i < N_UINT2048; i++) {
|
||||
if (a->bucket[i] != b->bucket[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uint2048_is_not_zero(uint2048_t* a)
|
||||
{
|
||||
for (int i = 0; i < N_UINT2048; i++) {
|
||||
if (a->bucket[i] != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool uint2048_is_odd(uint2048_t* a)
|
||||
{
|
||||
return (a->bucket[0] % 2) == 1;
|
||||
}
|
||||
|
||||
int uint2048_dump(uint2048_t* a)
|
||||
{
|
||||
log("dumping");
|
||||
for (int i = N_UINT2048 - 1; i >= 0; i--) {
|
||||
log(" %x", a->bucket[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
43
boot/libboot/crypto/uint2048.h
Normal file
43
boot/libboot/crypto/uint2048.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef _BOOT_LIBBOOT_CRYPTO_UINT2048_H
|
||||
#define _BOOT_LIBBOOT_CRYPTO_UINT2048_H
|
||||
|
||||
#include <libboot/mem/mem.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define N_UINT2048 (64)
|
||||
#define BITS_IN_BASE_UINT2048 (32)
|
||||
#define BASE_UINT2048 ((uint64_t)((uint64_t)1 << BITS_IN_BASE_UINT2048))
|
||||
#define BASE_UINT2048U ((uint64_t)((uint64_t)1 << (uint64_t)BITS_IN_BASE_UINT2048))
|
||||
typedef uint32_t uint2048_bucket_t;
|
||||
struct uint2048 {
|
||||
uint2048_bucket_t bucket[N_UINT2048];
|
||||
};
|
||||
typedef struct uint2048 uint2048_t;
|
||||
|
||||
int uint2048_init(uint2048_t* d, uint32_t n);
|
||||
int uint2048_init_bytes(uint2048_t* d, const char* f, size_t n);
|
||||
int uint2048_init_bytes_be(uint2048_t* d, const char* f, size_t n);
|
||||
int uint2048_copy(uint2048_t* dest, uint2048_t* src);
|
||||
|
||||
int uint2048_add(uint2048_t* a, uint2048_t* b, uint2048_t* c);
|
||||
int uint2048_sub(uint2048_t* a, uint2048_t* b, uint2048_t* c);
|
||||
|
||||
int uint2048_shl(uint2048_t* a, int n);
|
||||
int uint2048_shr(uint2048_t* a, int n);
|
||||
|
||||
int uint2048_mult_by_digit(uint2048_t* a, uint2048_t* b, uint2048_bucket_t un);
|
||||
int uint2048_mult(uint2048_t* a, uint2048_t* b, uint2048_t* c);
|
||||
|
||||
int uint2048_div(uint2048_t* a, uint2048_t* b, uint2048_t* ans, uint2048_t* rem);
|
||||
int uint2048_pow(uint2048_t* ua, uint2048_t* up, uint2048_t* mod, uint2048_t* ans);
|
||||
|
||||
bool uint2048_equal(uint2048_t* a, uint2048_t* b);
|
||||
bool uint2048_less(uint2048_t* a, uint2048_t* b);
|
||||
bool uint2048_less_equal(uint2048_t* a, uint2048_t* b);
|
||||
|
||||
bool uint2048_is_not_zero(uint2048_t* a);
|
||||
bool uint2048_is_odd(uint2048_t* a);
|
||||
|
||||
int uint2048_dump(uint2048_t* a);
|
||||
|
||||
#endif // _BOOT_LIBBOOT_CRYPTO_UINT2048_H
|
||||
103
boot/libboot/crypto/validate.c
Normal file
103
boot/libboot/crypto/validate.c
Normal file
@@ -0,0 +1,103 @@
|
||||
#include <libboot/crypto/sha256.h>
|
||||
#include <libboot/crypto/signature.h>
|
||||
#include <libboot/crypto/uint2048.h>
|
||||
#include <libboot/crypto/validate.h>
|
||||
#include <libboot/elf/elf_lite.h>
|
||||
#include <libboot/fs/ext2_lite.h>
|
||||
#include <libboot/log/log.h>
|
||||
|
||||
#define tmp_buf_size (4096)
|
||||
char tmp_buf[tmp_buf_size];
|
||||
|
||||
static int get_elf_signature(elfctx_t* elfctx, void* signature_buffer)
|
||||
{
|
||||
elf_section_header_32_t shstrtab_section_header;
|
||||
elf_read_section_header(elfctx, elfctx->header.e_shstrndx, &shstrtab_section_header);
|
||||
uintptr_t shstrtab_offset = shstrtab_section_header.sh_offset;
|
||||
|
||||
for (uint32_t i = 0; i < elfctx->header.e_shnum; i++) {
|
||||
elf_section_header_32_t section_header;
|
||||
elf_read_section_header(elfctx, i, §ion_header);
|
||||
|
||||
char tmp_name_buffer[32];
|
||||
uintptr_t name_offset_abs = shstrtab_offset + section_header.sh_name;
|
||||
elfctx->fs_desc->read_from_inode(elfctx->drive_desc, &elfctx->file_inode, (void*)tmp_name_buffer, name_offset_abs, 32);
|
||||
size_t len = strnlen(tmp_name_buffer, 32);
|
||||
if (len != sizeof("._signature") - 1) {
|
||||
continue;
|
||||
}
|
||||
if (memcmp(tmp_name_buffer, "._signature", len)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
elfctx->fs_desc->read_from_inode(elfctx->drive_desc, &elfctx->file_inode, signature_buffer, section_header.sh_offset, 128);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int calc_elf_hash(elfctx_t* elfctx, char* hash)
|
||||
{
|
||||
sha256_ctx_t shactx;
|
||||
sha256_init(&shactx);
|
||||
|
||||
for (uint32_t i = 0; i < elfctx->header.e_phnum; i++) {
|
||||
elf_program_header_32_t program_header;
|
||||
elf_read_program_header(elfctx, i, &program_header);
|
||||
|
||||
if (program_header.p_type != PT_LOAD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t from = program_header.p_offset;
|
||||
size_t rem_to_read = program_header.p_filesz;
|
||||
|
||||
while (rem_to_read) {
|
||||
size_t will_read = min(tmp_buf_size, rem_to_read);
|
||||
int rd = elfctx->fs_desc->read_from_inode(elfctx->drive_desc, &elfctx->file_inode, (void*)tmp_buf, from, will_read);
|
||||
from += will_read;
|
||||
sha256_update(&shactx, tmp_buf, will_read);
|
||||
|
||||
rem_to_read -= will_read;
|
||||
}
|
||||
}
|
||||
|
||||
sha256_hash(&shactx, hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool validate_elf(const char* path, drive_desc_t* drive_desc, fs_desc_t* fs_desc)
|
||||
{
|
||||
elfctx_t elfctx;
|
||||
char hash[32];
|
||||
|
||||
int err = elf_init_ctx(drive_desc, fs_desc, path, &elfctx);
|
||||
if (err) {
|
||||
return false;
|
||||
}
|
||||
|
||||
err = get_elf_signature(&elfctx, tmp_buf);
|
||||
if (err) {
|
||||
return false;
|
||||
}
|
||||
uint2048_t signature;
|
||||
uint2048_init_bytes(&signature, tmp_buf, 128);
|
||||
|
||||
err = calc_elf_hash(&elfctx, hash);
|
||||
if (err) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint2048_t ihash;
|
||||
uint2048_init_bytes_be(&ihash, hash, 32);
|
||||
|
||||
uint2048_t public_e;
|
||||
uint2048_init_bytes(&public_e, pub_xos_key_e, pub_xos_key_e_len);
|
||||
uint2048_t public_n;
|
||||
uint2048_init_bytes(&public_n, pub_xos_key_n, pub_xos_key_n_len);
|
||||
uint2048_t signed_ihash;
|
||||
uint2048_pow(&signature, &public_e, &public_n, &signed_ihash);
|
||||
|
||||
return uint2048_equal(&signed_ihash, &ihash);
|
||||
}
|
||||
11
boot/libboot/crypto/validate.h
Normal file
11
boot/libboot/crypto/validate.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef STAGE2_SECURITY_VALIDATE_H
|
||||
#define STAGE2_SECURITY_VALIDATE_H
|
||||
|
||||
#include <libboot/abi/drivers.h>
|
||||
#include <libboot/abi/memory.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
bool validate_file(const char* path, const char* signature_path, drive_desc_t* drive_desc, fs_desc_t* fs_desc);
|
||||
bool validate_elf(const char* path, drive_desc_t* drive_desc, fs_desc_t* fs_desc);
|
||||
|
||||
#endif // STAGE2_SECURITY_VALIDATE_H
|
||||
52
boot/libboot/devtree/devtree.c
Normal file
52
boot/libboot/devtree/devtree.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "devtree.h"
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
|
||||
static size_t _devtree_size = 0;
|
||||
static devtree_header_t* _devtree_header = NULL;
|
||||
static devtree_entry_t* _devtree_body = NULL;
|
||||
static char* _devtree_name_section = NULL;
|
||||
|
||||
void* devtree_start()
|
||||
{
|
||||
return (void*)_devtree_header;
|
||||
}
|
||||
|
||||
size_t devtree_size()
|
||||
{
|
||||
return _devtree_size;
|
||||
}
|
||||
|
||||
int devtree_init(void* devtree, size_t size)
|
||||
{
|
||||
if (!devtree) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
devtree_header_t* dth = (devtree_header_t*)devtree;
|
||||
_devtree_header = dth;
|
||||
_devtree_body = (devtree_entry_t*)&dth[1];
|
||||
_devtree_name_section = ((char*)dth + dth->name_list_offset);
|
||||
_devtree_size = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* devtree_name_of_entry(devtree_entry_t* en)
|
||||
{
|
||||
return &_devtree_name_section[en->rel_name_offset];
|
||||
}
|
||||
|
||||
devtree_entry_t* devtree_find_device(const char* name)
|
||||
{
|
||||
if (!_devtree_body) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _devtree_header->entries_count; i++) {
|
||||
const char* curdev_name = devtree_name_of_entry(&_devtree_body[i]);
|
||||
if (strcmp(curdev_name, name) == 0) {
|
||||
return &_devtree_body[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
50
boot/libboot/devtree/devtree.h
Normal file
50
boot/libboot/devtree/devtree.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef _BOOT_LIBBOOT_DEVTREE_DEVTREE_H
|
||||
#define _BOOT_LIBBOOT_DEVTREE_DEVTREE_H
|
||||
|
||||
#include <libboot/mem/mem.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define DEVTREE_HEADER_SIGNATURE ("odtr3")
|
||||
#define DEVTREE_HEADER_SIGNATURE_LEN (sizeof(DEVTREE_HEADER_SIGNATURE) - 1)
|
||||
|
||||
struct PACKED devtree_header {
|
||||
char signature[8];
|
||||
uint32_t revision;
|
||||
uint32_t flags;
|
||||
uint32_t entries_count;
|
||||
uint32_t name_list_offset;
|
||||
};
|
||||
typedef struct devtree_header devtree_header_t;
|
||||
|
||||
#define DEVTREE_ENTRY_FLAGS_MMIO = (1 << 0)
|
||||
#define DEVTREE_ENTRY_TYPE_IO (0)
|
||||
#define DEVTREE_ENTRY_TYPE_FB (1)
|
||||
#define DEVTREE_ENTRY_TYPE_UART (2)
|
||||
#define DEVTREE_ENTRY_TYPE_RAM (3)
|
||||
#define DEVTREE_ENTRY_TYPE_STORAGE (4)
|
||||
#define DEVTREE_ENTRY_TYPE_BUS_CONTROLLER (5)
|
||||
#define DEVTREE_ENTRY_TYPE_RTC (6)
|
||||
|
||||
struct PACKED devtree_entry {
|
||||
uint32_t type;
|
||||
uint32_t flags;
|
||||
uint64_t region_base;
|
||||
uint64_t region_size;
|
||||
uint32_t irq_lane;
|
||||
uint32_t irq_flags;
|
||||
uint32_t irq_priority;
|
||||
uint32_t rel_name_offset;
|
||||
uint64_t aux1;
|
||||
uint64_t aux2;
|
||||
uint64_t aux3;
|
||||
uint64_t aux4;
|
||||
};
|
||||
typedef struct devtree_entry devtree_entry_t;
|
||||
|
||||
int devtree_init(void* devtree, size_t size);
|
||||
const char* devtree_name_of_entry(devtree_entry_t* en);
|
||||
devtree_entry_t* devtree_find_device(const char* name);
|
||||
void* devtree_start();
|
||||
size_t devtree_size();
|
||||
|
||||
#endif // _BOOT_LIBBOOT_DEVTREE_DEVTREE_H
|
||||
144
boot/libboot/elf/elf_lite.c
Normal file
144
boot/libboot/elf/elf_lite.c
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "elf_lite.h"
|
||||
#include <libboot/crypto/sha256.h>
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/alloc.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
|
||||
// #define DEBUG_ELF
|
||||
|
||||
int elf_init_ctx(drive_desc_t* drive_desc, fs_desc_t* fs_desc, const char* path, elfctx_t* elfctx)
|
||||
{
|
||||
elfctx->drive_desc = drive_desc;
|
||||
elfctx->fs_desc = fs_desc;
|
||||
fs_desc->get_inode(drive_desc, path, &elfctx->file_inode);
|
||||
fs_desc->read_from_inode(drive_desc, &elfctx->file_inode, (void*)&elfctx->header, 0, sizeof(elfctx->header));
|
||||
|
||||
if (elfctx->header.e_ident[EI_MAG0] != 0x7F || elfctx->header.e_ident[EI_MAG1] != 0x45 || elfctx->header.e_ident[EI_MAG2] != 0x4c || elfctx->header.e_ident[EI_MAG3] != 0x46) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elf_read_program_header(elfctx_t* elfctx, size_t id, elf_program_header_32_t* program_header)
|
||||
{
|
||||
uintptr_t offset = elfctx->header.e_phoff + id * elfctx->header.e_phentsize;
|
||||
return elfctx->fs_desc->read_from_inode(elfctx->drive_desc, &elfctx->file_inode, (void*)program_header, offset, sizeof(*program_header));
|
||||
}
|
||||
|
||||
int elf_read_section_header(elfctx_t* elfctx, uint32_t id, elf_section_header_32_t* section_header)
|
||||
{
|
||||
uintptr_t offset = elfctx->header.e_shoff + id * elfctx->header.e_shentsize;
|
||||
return elfctx->fs_desc->read_from_inode(elfctx->drive_desc, &elfctx->file_inode, (void*)section_header, offset, sizeof(*section_header));
|
||||
}
|
||||
|
||||
#ifdef BITS32
|
||||
int elf_load_kernel(drive_desc_t* drive_desc, fs_desc_t* fs_desc, const char* path, size_t* kernel_vaddr, size_t* kernel_paddr, size_t* kernel_size)
|
||||
{
|
||||
elfctx_t elfctx;
|
||||
int err = elf_init_ctx(drive_desc, fs_desc, path, &elfctx);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
size_t vaddr = -1;
|
||||
size_t paddr = -1;
|
||||
size_t vaddr_end = 0;
|
||||
|
||||
for (uint32_t i = 0; i < elfctx.header.e_phnum; i++) {
|
||||
elf_program_header_32_t program_header;
|
||||
elf_read_program_header(&elfctx, i, &program_header);
|
||||
|
||||
if (program_header.p_type == PT_LOAD) {
|
||||
paddr = min(paddr, program_header.p_paddr);
|
||||
vaddr = min(vaddr, program_header.p_vaddr);
|
||||
fs_desc->read(drive_desc, path, (void*)program_header.p_paddr, program_header.p_offset, program_header.p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < elfctx.header.e_shnum; i++) {
|
||||
elf_section_header_32_t section_header;
|
||||
elf_read_section_header(&elfctx, i, §ion_header);
|
||||
|
||||
if ((section_header.sh_flags & SHF_ALLOC) == SHF_ALLOC) {
|
||||
vaddr_end = max(vaddr_end, section_header.sh_addr + section_header.sh_size);
|
||||
}
|
||||
}
|
||||
|
||||
*kernel_vaddr = vaddr;
|
||||
*kernel_paddr = paddr;
|
||||
*kernel_size = vaddr_end - vaddr;
|
||||
return 0;
|
||||
}
|
||||
// #endif
|
||||
#else
|
||||
size_t elf_get_kernel_size(void* elffile)
|
||||
{
|
||||
elf_header_64_t* header = (elf_header_64_t*)elffile;
|
||||
if (header->e_ident[EI_MAG0] != 0x7F || header->e_ident[EI_MAG1] != 0x45 || header->e_ident[EI_MAG2] != 0x4c || header->e_ident[EI_MAG3] != 0x46) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t vaddr = 0xffffffffffffffff;
|
||||
size_t vaddr_end = 0;
|
||||
|
||||
for (size_t i = 0; i < header->e_phnum; i++) {
|
||||
uintptr_t offset = header->e_phoff + i * header->e_phentsize;
|
||||
elf_program_header_64_t* program_header = (elf_program_header_64_t*)((uintptr_t)elffile + offset);
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
vaddr = min(vaddr, program_header->p_vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < header->e_shnum; i++) {
|
||||
uintptr_t offset = header->e_shoff + i * header->e_shentsize;
|
||||
elf_section_header_64_t* section_header = (elf_section_header_64_t*)((uintptr_t)elffile + offset);
|
||||
|
||||
if ((section_header->sh_flags & SHF_ALLOC) == SHF_ALLOC) {
|
||||
vaddr_end = max(vaddr_end, section_header->sh_addr + section_header->sh_size);
|
||||
}
|
||||
}
|
||||
|
||||
return vaddr_end - vaddr;
|
||||
}
|
||||
|
||||
int elf_load_kernel(void* elffile, size_t size, uintptr_t* kernel_vaddr, uintptr_t* kernel_paddr)
|
||||
{
|
||||
elf_header_64_t* header = (elf_header_64_t*)elffile;
|
||||
if (header->e_ident[EI_MAG0] != 0x7F || header->e_ident[EI_MAG1] != 0x45 || header->e_ident[EI_MAG2] != 0x4c || header->e_ident[EI_MAG3] != 0x46) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t vaddr = 0xffffffffffffffff;
|
||||
for (size_t i = 0; i < header->e_phnum; i++) {
|
||||
uintptr_t offset = header->e_phoff + i * header->e_phentsize;
|
||||
elf_program_header_64_t* program_header = (elf_program_header_64_t*)((uintptr_t)elffile + offset);
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
vaddr = min(vaddr, program_header->p_vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t paddr = (uintptr_t)palloc(size);
|
||||
if (!paddr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < header->e_phnum; i++) {
|
||||
uintptr_t offset = header->e_phoff + i * header->e_phentsize;
|
||||
elf_program_header_64_t* program_header = (elf_program_header_64_t*)((uintptr_t)elffile + offset);
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
uintptr_t data_paddr = (program_header->p_vaddr - vaddr) + paddr;
|
||||
uintptr_t data_offset = (uintptr_t)elffile + program_header->p_offset;
|
||||
|
||||
#ifdef DEBUG_ELF
|
||||
log("copying elf %lx %lx %lx", data_paddr, data_offset, program_header->p_filesz);
|
||||
#endif
|
||||
memcpy((void*)data_paddr, (void*)data_offset, program_header->p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
*kernel_vaddr = vaddr;
|
||||
*kernel_paddr = paddr;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
196
boot/libboot/elf/elf_lite.h
Normal file
196
boot/libboot/elf/elf_lite.h
Normal file
@@ -0,0 +1,196 @@
|
||||
#ifndef _BOOT_LIBBOOT_ELF_ELF_LITE
|
||||
#define _BOOT_LIBBOOT_ELF_ELF_LITE
|
||||
|
||||
#include <libboot/abi/drivers.h>
|
||||
#include <libboot/fs/ext2_lite.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
enum E_IDENT_FIELDS {
|
||||
EI_MAG0,
|
||||
EI_MAG1,
|
||||
EI_MAG2,
|
||||
EI_MAG3,
|
||||
EI_CLASS,
|
||||
EI_DATA,
|
||||
EI_VERSION,
|
||||
EI_OSABI,
|
||||
EI_ABIVERSION,
|
||||
};
|
||||
|
||||
enum E_TYPE_FIELDS {
|
||||
ET_NONE,
|
||||
ET_REL,
|
||||
ET_EXEC,
|
||||
ET_DYN,
|
||||
ET_CORE,
|
||||
};
|
||||
|
||||
enum E_MACHINE_FIELDS {
|
||||
EM_NONE,
|
||||
EM_386 = 3,
|
||||
EM_PPC = 20,
|
||||
EM_PPC64 = 21,
|
||||
EM_X86_64 = 62,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t e_ident[16];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
uint32_t e_entry;
|
||||
uint32_t e_phoff;
|
||||
uint32_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;
|
||||
} elf_header_32_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t 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;
|
||||
} elf_header_64_t;
|
||||
|
||||
enum P_TYPE_FIELDS {
|
||||
PT_NULL,
|
||||
PT_LOAD,
|
||||
PT_DYNAMIC,
|
||||
PT_INTERP,
|
||||
PT_NOTE,
|
||||
PT_SHLIB,
|
||||
PT_PHDR,
|
||||
PT_TLS,
|
||||
PT_LOOS = 0x60000000,
|
||||
PT_HIOS = 0x6FFFFFFF,
|
||||
PT_LOPROC = 0x70000000,
|
||||
PT_HIPROC = 0x7FFFFFFF,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t p_type;
|
||||
uint32_t p_offset;
|
||||
uint32_t p_vaddr;
|
||||
uint32_t p_paddr;
|
||||
uint32_t p_filesz;
|
||||
uint16_t p_memsz;
|
||||
uint16_t p_flags;
|
||||
uint16_t p_align;
|
||||
} elf_program_header_32_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t p_type;
|
||||
uint32_t p_flags;
|
||||
uint64_t p_offset;
|
||||
uint64_t p_vaddr;
|
||||
uint64_t p_paddr;
|
||||
uint64_t p_filesz;
|
||||
uint64_t p_memsz;
|
||||
uint64_t p_align;
|
||||
} elf_program_header_64_t;
|
||||
|
||||
enum SH_TYPE_FIELDS {
|
||||
SHT_NULL,
|
||||
SHT_PROGBITS,
|
||||
SHT_SYMTAB,
|
||||
SHT_STRTAB,
|
||||
SHT_RELA,
|
||||
SHT_HASH,
|
||||
SHT_DYNAMIC,
|
||||
SHT_NOTE,
|
||||
SHT_NOBITS,
|
||||
SHT_REL,
|
||||
SHT_SHLIB,
|
||||
SHT_DYNSYM,
|
||||
SHT_INIT_ARRAY,
|
||||
SHT_FINI_ARRAY,
|
||||
SHT_PREINIT_ARRAY,
|
||||
SHT_GROUP,
|
||||
SHT_SYMTAB_SHNDX,
|
||||
|
||||
SHT_LOOS = 1610612736,
|
||||
SHT_HIOS = 1879048191,
|
||||
SHT_LOPROC = 1879048192,
|
||||
SHT_HIPROC = 2147483647,
|
||||
SHT_LOUSER = 2147483648,
|
||||
SHT_HIUSER = 4294967295,
|
||||
};
|
||||
|
||||
enum SH_FLAGS_FIELDS {
|
||||
SHF_WRITE = 0x1,
|
||||
SHF_ALLOC = 0x2,
|
||||
SHF_EXECINSTR = 0x4,
|
||||
SHF_MERGE = 0x10,
|
||||
SHF_STRINGS = 0x20,
|
||||
|
||||
SHF_INFO_LINK = 0x40,
|
||||
SHF_LINK_ORDER = 0x80,
|
||||
SHF_OS_NONCONFORMING = 0x100,
|
||||
SHF_GROUP = 0x200,
|
||||
SHF_TLS = 0x400,
|
||||
SHF_COMPRESSED = 0x800,
|
||||
SHF_MASKOS = 0x0ff00000,
|
||||
SHF_MASKPROC = 0xf0000000
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t sh_name;
|
||||
uint32_t sh_type;
|
||||
uint32_t sh_flags;
|
||||
uint32_t sh_addr;
|
||||
uint32_t sh_offset;
|
||||
uint32_t sh_size;
|
||||
uint32_t sh_link;
|
||||
uint32_t sh_info;
|
||||
uint32_t sh_addralign;
|
||||
uint32_t sh_entsize;
|
||||
} elf_section_header_32_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sh_name;
|
||||
uint32_t sh_type;
|
||||
uint64_t sh_flags;
|
||||
uint64_t sh_addr;
|
||||
uint64_t sh_offset;
|
||||
uint64_t sh_size;
|
||||
uint32_t sh_link;
|
||||
uint32_t sh_info;
|
||||
uint64_t sh_addralign;
|
||||
uint64_t sh_entsize;
|
||||
} elf_section_header_64_t;
|
||||
|
||||
struct elfctx {
|
||||
drive_desc_t* drive_desc;
|
||||
fs_desc_t* fs_desc;
|
||||
inode_t file_inode;
|
||||
elf_header_32_t header;
|
||||
};
|
||||
typedef struct elfctx elfctx_t;
|
||||
|
||||
int elf_init_ctx(drive_desc_t* drive_desc, fs_desc_t* fs_desc, const char* path, elfctx_t* elfctx);
|
||||
int elf_read_program_header(elfctx_t* elfctx, size_t id, elf_program_header_32_t* program_header);
|
||||
int elf_read_section_header(elfctx_t* elfctx, uint32_t id, elf_section_header_32_t* section_header);
|
||||
|
||||
#ifdef BITS32
|
||||
int elf_load_kernel(drive_desc_t* drive_desc, fs_desc_t* fs_desc, const char* path, size_t* kernel_vaddr, size_t* kernel_paddr, size_t* kernel_size);
|
||||
#else
|
||||
size_t elf_get_kernel_size(void* elffile);
|
||||
int elf_load_kernel(void* elffile, size_t size, uintptr_t* kernel_vaddr, uintptr_t* kernel_paddr);
|
||||
#endif
|
||||
|
||||
#endif // _BOOT_LIBBOOT_ELF_ELF_LITE
|
||||
233
boot/libboot/fs/ext2_lite.c
Normal file
233
boot/libboot/fs/ext2_lite.c
Normal file
@@ -0,0 +1,233 @@
|
||||
#include <libboot/fs/ext2_lite.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
superblock_t superblock;
|
||||
drive_desc_t* active_drive_desc;
|
||||
|
||||
uint32_t _ext2_lite_get_block_len()
|
||||
{
|
||||
return (1 << (superblock.log_block_size + 10));
|
||||
}
|
||||
|
||||
uint32_t _ext2_lite_get_offset_of_block(uint32_t block_index)
|
||||
{
|
||||
return SUPERBLOCK_START + (block_index - 1) * _ext2_lite_get_block_len();
|
||||
}
|
||||
|
||||
static uint8_t tmp_read_buf[8192];
|
||||
void _ext2_lite_read(uint8_t* buf, uint32_t start, uint32_t len)
|
||||
{
|
||||
void (*read)(uint32_t sector, uint8_t* read_to) = active_drive_desc->read;
|
||||
int already_read = 0;
|
||||
while (len != 0) {
|
||||
uint32_t sector = start / 512;
|
||||
uint32_t start_offset = start % 512;
|
||||
read(sector, tmp_read_buf);
|
||||
for (int i = 0; i < min(512 - start_offset, len); i++) {
|
||||
buf[already_read++] = tmp_read_buf[start_offset + i];
|
||||
}
|
||||
len -= min(512 - start_offset, len);
|
||||
start += min(512 - start_offset, len);
|
||||
}
|
||||
}
|
||||
|
||||
void _ext2_lite_read_group(uint32_t group_id, group_desc_t* group)
|
||||
{
|
||||
uint32_t group_start = SUPERBLOCK_START + _ext2_lite_get_block_len() + (group_id * GROUP_LEN);
|
||||
_ext2_lite_read((uint8_t*)group, group_start, GROUP_LEN);
|
||||
}
|
||||
|
||||
void _ext2_lite_read_inode(uint32_t inode_id, inode_t* inode)
|
||||
{
|
||||
uint32_t inodes_per_group = superblock.inodes_per_group;
|
||||
uint32_t holder_group = (inode_id - 1) / inodes_per_group;
|
||||
uint32_t pos_inside_group = (inode_id - 1) % inodes_per_group;
|
||||
|
||||
group_desc_t gr;
|
||||
_ext2_lite_read_group(holder_group, &gr);
|
||||
|
||||
uint32_t inode_start = SUPERBLOCK_START + ((gr.inode_table - 1) * _ext2_lite_get_block_len()) + (pos_inside_group * INODE_LEN);
|
||||
_ext2_lite_read((uint8_t*)inode, inode_start, INODE_LEN);
|
||||
}
|
||||
|
||||
int ext2_lite_init(drive_desc_t* drive_desc, fs_desc_t* fs_desc)
|
||||
{
|
||||
active_drive_desc = drive_desc;
|
||||
void (*read)(uint32_t sector, uint8_t* read_to) = drive_desc->read;
|
||||
_ext2_lite_read((uint8_t*)&superblock, SUPERBLOCK_START, SUPERBLOCK_LEN);
|
||||
|
||||
if (superblock.magic != 0xEF53) {
|
||||
return -1;
|
||||
}
|
||||
if (superblock.rev_level != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO currently support up to 8192 bytes a block.
|
||||
if (superblock.log_block_size > 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fs_desc->get_inode = (void*)ext2_lite_get_inode;
|
||||
fs_desc->read = ext2_lite_read;
|
||||
fs_desc->read_from_inode = (void*)ext2_lite_read_inode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t tmp_dir_buf[8192];
|
||||
int ext2_lite_has_in_dir(uint32_t block_index, const char* path, uint32_t* found_inode_index)
|
||||
{
|
||||
if (block_index == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (_ext2_lite_get_block_len() != 1024) {
|
||||
while (1) { }
|
||||
return -1;
|
||||
}
|
||||
|
||||
_ext2_lite_read(tmp_dir_buf, _ext2_lite_get_offset_of_block(block_index), _ext2_lite_get_block_len());
|
||||
dir_entry_t* start_of_entry = (dir_entry_t*)tmp_dir_buf;
|
||||
for (;;) {
|
||||
if (start_of_entry->inode == 0) {
|
||||
return -1;
|
||||
}
|
||||
// checking name of this entry
|
||||
bool is_name_correct = true;
|
||||
for (int i = 0; i < start_of_entry->name_len; i++) {
|
||||
is_name_correct &= (path[i] == *((char*)start_of_entry + 8 + i));
|
||||
}
|
||||
is_name_correct &= (path[start_of_entry->name_len] == '\0' || path[start_of_entry->name_len] == '/');
|
||||
|
||||
if (is_name_correct) {
|
||||
*found_inode_index = start_of_entry->inode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
start_of_entry = (dir_entry_t*)((uint32_t)start_of_entry + start_of_entry->rec_len);
|
||||
if ((uint32_t)start_of_entry >= (uint32_t)tmp_dir_buf + _ext2_lite_get_block_len()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int ext2_lite_scan_dir(inode_t inode, const char* path, inode_t* res_inode)
|
||||
{
|
||||
uint32_t nxt_inode_index;
|
||||
uint32_t path_offset = 0;
|
||||
new_inode:
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (inode.block[i] != 0) {
|
||||
if (ext2_lite_has_in_dir(inode.block[i], &path[path_offset], &nxt_inode_index) == 0) {
|
||||
while (path[path_offset] != '\0' && path[path_offset] != '/')
|
||||
path_offset++;
|
||||
for (; path[path_offset] != '/'; path_offset++) {
|
||||
if (path[path_offset] == '\0') {
|
||||
_ext2_lite_read_inode(nxt_inode_index, res_inode);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
path_offset++;
|
||||
_ext2_lite_read_inode(nxt_inode_index, &inode);
|
||||
goto new_inode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ext2_lite_get_inode(drive_desc_t* drive_desc, const char* path, inode_t* file_inode)
|
||||
{
|
||||
active_drive_desc = drive_desc;
|
||||
inode_t root_inode;
|
||||
_ext2_lite_read_inode(2, &root_inode);
|
||||
|
||||
int res = -1;
|
||||
if (path[0] == '/') {
|
||||
res = ext2_lite_scan_dir(root_inode, &path[1], file_inode);
|
||||
} else {
|
||||
res = ext2_lite_scan_dir(root_inode, path, file_inode);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static uint8_t tmp_block_buf[8192];
|
||||
uint32_t _ext2_lite_get_block_of_file_lev0(uint32_t cur_block, uint32_t file_block_index)
|
||||
{
|
||||
_ext2_lite_read(tmp_block_buf, _ext2_lite_get_offset_of_block(cur_block), _ext2_lite_get_block_len());
|
||||
uint32_t* buf = (uint32_t*)tmp_block_buf;
|
||||
return buf[file_block_index];
|
||||
}
|
||||
|
||||
uint32_t _ext2_lite_get_block_of_file_lev1(uint32_t cur_block, uint32_t file_block_index)
|
||||
{
|
||||
_ext2_lite_read(tmp_block_buf, _ext2_lite_get_offset_of_block(cur_block), _ext2_lite_get_block_len());
|
||||
uint32_t* buf = (uint32_t*)tmp_block_buf;
|
||||
|
||||
uint32_t lev_contain = _ext2_lite_get_block_len() / 4;
|
||||
uint32_t offset = file_block_index / lev_contain;
|
||||
uint32_t offset_inner = file_block_index % lev_contain;
|
||||
|
||||
return _ext2_lite_get_block_of_file_lev0(buf[offset], offset_inner);
|
||||
}
|
||||
|
||||
uint32_t _ext2_lite_get_block_of_file_lev2(uint32_t cur_block, uint32_t file_block_index)
|
||||
{
|
||||
_ext2_lite_read(tmp_block_buf, _ext2_lite_get_offset_of_block(cur_block), _ext2_lite_get_block_len());
|
||||
uint32_t* buf = (uint32_t*)tmp_block_buf;
|
||||
|
||||
uint32_t block_len = _ext2_lite_get_block_len() / 4;
|
||||
uint32_t lev_contain = block_len * block_len;
|
||||
uint32_t offset = file_block_index / lev_contain;
|
||||
uint32_t offset_inner = file_block_index % lev_contain;
|
||||
|
||||
return _ext2_lite_get_block_of_file_lev1(buf[offset], offset_inner);
|
||||
}
|
||||
|
||||
// TODO think of more effecient version
|
||||
uint32_t _ext2_lite_get_block_of_file(inode_t* inode, uint32_t file_block_index)
|
||||
{
|
||||
uint32_t block_len = _ext2_lite_get_block_len() / 4;
|
||||
if (file_block_index < 12) {
|
||||
return inode->block[file_block_index];
|
||||
} else if (file_block_index < 12 + block_len) { // single indirect
|
||||
return _ext2_lite_get_block_of_file_lev0(inode->block[12], file_block_index - 12);
|
||||
} else if (file_block_index < 12 + block_len + block_len * block_len) { // double indirect
|
||||
return _ext2_lite_get_block_of_file_lev1(inode->block[13], file_block_index - 12 - block_len);
|
||||
} else { // triple indirect
|
||||
return _ext2_lite_get_block_of_file_lev2(inode->block[14], file_block_index - (12 + block_len + block_len * block_len));
|
||||
}
|
||||
}
|
||||
|
||||
// Note to save mem: the func reuses tmp_block_buf.
|
||||
int ext2_lite_read_inode(drive_desc_t* drive_desc, inode_t* inode, uint8_t* buf, uint32_t from, uint32_t len)
|
||||
{
|
||||
active_drive_desc = drive_desc;
|
||||
|
||||
const uint32_t block_len = _ext2_lite_get_block_len();
|
||||
uint32_t start_block_index = from / block_len;
|
||||
uint32_t end_block_index = (from + len - 1) / block_len;
|
||||
uint32_t read_offset = from % block_len;
|
||||
uint32_t write_offset = 0;
|
||||
|
||||
for (uint32_t block_index = start_block_index; block_index <= end_block_index; block_index++) {
|
||||
uint32_t data_block_index = _ext2_lite_get_block_of_file(inode, block_index);
|
||||
_ext2_lite_read(tmp_block_buf, _ext2_lite_get_offset_of_block(data_block_index), _ext2_lite_get_block_len());
|
||||
for (int i = 0; i < min(len, block_len - read_offset); i++) {
|
||||
buf[write_offset++] = tmp_block_buf[read_offset + i];
|
||||
}
|
||||
len -= min(len, block_len - read_offset);
|
||||
read_offset = 0;
|
||||
}
|
||||
return write_offset;
|
||||
}
|
||||
|
||||
int ext2_lite_read(drive_desc_t* drive_desc, const char* path, uint8_t* buf, uint32_t from, uint32_t len)
|
||||
{
|
||||
active_drive_desc = drive_desc;
|
||||
inode_t inode;
|
||||
ext2_lite_get_inode(drive_desc, path, &inode);
|
||||
return ext2_lite_read_inode(drive_desc, &inode, buf, from, len);
|
||||
}
|
||||
124
boot/libboot/fs/ext2_lite.h
Normal file
124
boot/libboot/fs/ext2_lite.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#ifndef _BOOT_LIBBOOT_FS_EXT2_LITE
|
||||
#define _BOOT_LIBBOOT_FS_EXT2_LITE
|
||||
|
||||
#include <libboot/abi/drivers.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define SUPERBLOCK_START 1024
|
||||
#define SUPERBLOCK_LEN (sizeof(superblock_t))
|
||||
typedef struct {
|
||||
uint32_t inodes_count;
|
||||
uint32_t blocks_count;
|
||||
uint32_t r_blocks_count;
|
||||
uint32_t free_blocks_count;
|
||||
uint32_t free_inodes_count;
|
||||
uint32_t first_data_block;
|
||||
uint32_t log_block_size;
|
||||
uint32_t log_frag_size;
|
||||
uint32_t blocks_per_group;
|
||||
uint32_t frags_per_group;
|
||||
uint32_t inodes_per_group;
|
||||
uint32_t mtime;
|
||||
uint32_t wtime;
|
||||
uint16_t mnt_count;
|
||||
uint16_t max_mnt_count;
|
||||
uint16_t magic;
|
||||
uint16_t state;
|
||||
uint16_t errors;
|
||||
uint16_t minor_rev_level;
|
||||
uint32_t lastcheck;
|
||||
uint32_t checkinterval;
|
||||
uint32_t creator_os;
|
||||
uint32_t rev_level;
|
||||
uint16_t def_resuid;
|
||||
uint16_t def_resgid;
|
||||
|
||||
uint32_t first_ino;
|
||||
uint16_t inode_size;
|
||||
uint16_t block_group_nr;
|
||||
uint32_t feature_compat;
|
||||
uint32_t feature_incompat;
|
||||
uint32_t feature_ro_compat;
|
||||
uint8_t uuid[16];
|
||||
uint8_t volume_name[16];
|
||||
uint8_t last_mounted[64];
|
||||
uint32_t algo_bitmap;
|
||||
|
||||
uint8_t prealloc_blocks;
|
||||
uint8_t prealloc_dir_blocks;
|
||||
|
||||
// current jurnalling is unsupported
|
||||
uint8_t unused[1024 - 206];
|
||||
} superblock_t;
|
||||
|
||||
#define GROUP_LEN (sizeof(group_desc_t))
|
||||
typedef struct {
|
||||
uint32_t block_bitmap;
|
||||
uint32_t inode_bitmap;
|
||||
uint32_t inode_table;
|
||||
uint16_t free_blocks_count;
|
||||
uint16_t free_inodes_count;
|
||||
uint16_t used_dirs_count;
|
||||
uint16_t pad;
|
||||
uint8_t reserved[12];
|
||||
} group_desc_t;
|
||||
|
||||
#define S_IFSOCK 0xC000
|
||||
#define S_IFLNK 0xA000
|
||||
#define S_IFREG 0x8000
|
||||
#define S_IFBLK 0x6000
|
||||
#define S_IFDIR 0x4000
|
||||
#define S_IFCHR 0x2000
|
||||
#define S_IFIFO 0x1000
|
||||
|
||||
#define S_ISUID 0x0800
|
||||
#define S_ISGID 0x0400
|
||||
#define S_ISVTX 0x0200
|
||||
|
||||
#define S_IRUSR 0x0100
|
||||
#define S_IWUSR 0x0080
|
||||
#define S_IXUSR 0x0040
|
||||
#define S_IRGRP 0x0020
|
||||
#define S_IWGRP 0x0010
|
||||
#define S_IXGRP 0x0008
|
||||
#define S_IROTH 0x0004
|
||||
#define S_IWOTH 0x0002
|
||||
#define S_IXOTH 0x0001
|
||||
|
||||
#define INODE_LEN (sizeof(inode_t))
|
||||
#define INODES_RESERVED 11
|
||||
typedef struct {
|
||||
uint16_t mode;
|
||||
uint16_t uid;
|
||||
uint32_t size;
|
||||
uint32_t atime;
|
||||
uint32_t ctime;
|
||||
uint32_t mtime;
|
||||
uint32_t dtime;
|
||||
uint16_t gid;
|
||||
uint16_t links_count;
|
||||
uint32_t blocks;
|
||||
uint32_t flags;
|
||||
uint32_t osd1;
|
||||
uint32_t block[15];
|
||||
uint32_t generation;
|
||||
uint32_t file_acl;
|
||||
uint32_t dir_acl;
|
||||
uint32_t faddr;
|
||||
uint32_t osd2[3];
|
||||
} inode_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t inode;
|
||||
uint16_t rec_len;
|
||||
uint8_t name_len;
|
||||
uint8_t file_type;
|
||||
char* name; // may be a problematic for 64bit versions
|
||||
} dir_entry_t;
|
||||
|
||||
int ext2_lite_init(drive_desc_t* drive_desc, fs_desc_t* fs_desc);
|
||||
int ext2_lite_get_inode(drive_desc_t* drive_desc, const char* path, inode_t* file_inode);
|
||||
int ext2_lite_read(drive_desc_t* drive_desc, const char* path, uint8_t* buf, uint32_t from, uint32_t len);
|
||||
int ext2_lite_read_inode(drive_desc_t* drive_desc, inode_t* inode, uint8_t* buf, uint32_t from, uint32_t len);
|
||||
|
||||
#endif // _BOOT_LIBBOOT_FS_EXT2_LITE
|
||||
377
boot/libboot/log/log.c
Normal file
377
boot/libboot/log/log.c
Normal file
@@ -0,0 +1,377 @@
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
|
||||
typedef int (*_putch_callback)(char ch, char* buf_base, size_t* written, void* callback_params);
|
||||
|
||||
static uart_put_char_t uart_handler = NULL;
|
||||
static const char HEX_alphabet[] = "0123456789ABCDEF";
|
||||
static const char hex_alphabet[] = "0123456789abcdef";
|
||||
|
||||
static int putch_callback_stream(char c, char* buf_base, size_t* written, void* callback_params)
|
||||
{
|
||||
if (uart_handler) {
|
||||
return uart_handler(c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_hex32_impl(unsigned int value, const char* alph, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
int nxt = 0;
|
||||
char tmp_buf[16];
|
||||
|
||||
while (value > 0) {
|
||||
tmp_buf[nxt++] = alph[(value % 16)];
|
||||
value /= 16;
|
||||
}
|
||||
|
||||
callback('0', base_buf, written, callback_params);
|
||||
callback('x', base_buf, written, callback_params);
|
||||
if (nxt == 0) {
|
||||
callback('0', base_buf, written, callback_params);
|
||||
}
|
||||
|
||||
while (nxt) {
|
||||
callback(tmp_buf[--nxt], base_buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_hex64_impl(unsigned long value, const char* alph, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
int nxt = 0;
|
||||
char tmp_buf[32];
|
||||
|
||||
while (value > 0) {
|
||||
tmp_buf[nxt++] = alph[(value % 16)];
|
||||
value /= 16;
|
||||
}
|
||||
|
||||
callback('0', base_buf, written, callback_params);
|
||||
callback('x', base_buf, written, callback_params);
|
||||
if (nxt == 0) {
|
||||
callback('0', base_buf, written, callback_params);
|
||||
}
|
||||
|
||||
while (nxt) {
|
||||
callback(tmp_buf[--nxt], base_buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_hex32(unsigned int value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
return _printf_hex32_impl(value, hex_alphabet, base_buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_HEX32(unsigned int value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
return _printf_hex32_impl(value, HEX_alphabet, base_buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_hex64(unsigned long value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
return _printf_hex64_impl(value, hex_alphabet, base_buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_HEX64(unsigned long value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
return _printf_hex64_impl(value, HEX_alphabet, base_buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_u32(unsigned int value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
int nxt = 0;
|
||||
char tmp_buf[16];
|
||||
|
||||
while (value > 0) {
|
||||
tmp_buf[nxt++] = (value % 10) + '0';
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
if (nxt == 0) {
|
||||
callback('0', base_buf, written, callback_params);
|
||||
}
|
||||
|
||||
while (nxt) {
|
||||
callback(tmp_buf[--nxt], base_buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_u64(unsigned long value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
int nxt = 0;
|
||||
char tmp_buf[32];
|
||||
|
||||
while (value > 0) {
|
||||
tmp_buf[nxt++] = (value % 10) + '0';
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
if (nxt == 0) {
|
||||
callback('0', base_buf, written, callback_params);
|
||||
}
|
||||
|
||||
while (nxt) {
|
||||
callback(tmp_buf[--nxt], base_buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_i32(int value, char* buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
if (value < 0) {
|
||||
callback('-', buf, written, callback_params);
|
||||
value = -value;
|
||||
}
|
||||
return _printf_u32(value, buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_i64(long value, char* buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
if (value < 0) {
|
||||
callback('-', buf, written, callback_params);
|
||||
value = -value;
|
||||
}
|
||||
return _printf_u64(value, buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_string(const char* value, char* buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len = strlen(value);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
callback(value[i], buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t _printf_internal(char* buf, const char* format, _putch_callback callback, void* callback_params, va_list arg)
|
||||
{
|
||||
const char* p = format;
|
||||
size_t written = 0;
|
||||
while (*p) {
|
||||
int l_arg = 0;
|
||||
int h_arg = 0;
|
||||
if (*p == '%' && *(p + 1)) {
|
||||
// Reading arguments
|
||||
parse_args:
|
||||
p++;
|
||||
switch (*p) {
|
||||
case 'l':
|
||||
l_arg++;
|
||||
if (*(p + 1)) {
|
||||
goto parse_args;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
h_arg++;
|
||||
if (*(p + 1)) {
|
||||
goto parse_args;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Reading conversion specifiers
|
||||
switch (*p) {
|
||||
case 'i':
|
||||
case 'd':
|
||||
if (l_arg) {
|
||||
long value = va_arg(arg, long);
|
||||
_printf_i64(value, buf, &written, callback, callback_params);
|
||||
} else {
|
||||
int value = va_arg(arg, int);
|
||||
_printf_i32(value, buf, &written, callback, callback_params);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (l_arg) {
|
||||
uint64_t value = va_arg(arg, uint64_t);
|
||||
_printf_u64(value, buf, &written, callback, callback_params);
|
||||
} else {
|
||||
uint32_t value = va_arg(arg, uint32_t);
|
||||
_printf_u32(value, buf, &written, callback, callback_params);
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
if (l_arg) {
|
||||
uint64_t value = va_arg(arg, uint64_t);
|
||||
_printf_hex64(value, buf, &written, callback, callback_params);
|
||||
} else {
|
||||
uint32_t value = va_arg(arg, uint32_t);
|
||||
_printf_hex32(value, buf, &written, callback, callback_params);
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
if (l_arg) {
|
||||
uint64_t value = va_arg(arg, uint64_t);
|
||||
_printf_HEX64(value, buf, &written, callback, callback_params);
|
||||
} else {
|
||||
uint32_t value = va_arg(arg, uint32_t);
|
||||
_printf_HEX32(value, buf, &written, callback, callback_params);
|
||||
}
|
||||
break;
|
||||
case 'c': {
|
||||
char value = (char)va_arg(arg, int);
|
||||
callback(value, buf, &written, callback_params);
|
||||
} break;
|
||||
case '%': {
|
||||
callback('%', buf, &written, callback_params);
|
||||
} break;
|
||||
case 's': {
|
||||
const char* value = va_arg(arg, const char*);
|
||||
_printf_string(value, buf, &written, callback, callback_params);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
callback(*p, buf, &written, callback_params);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
static int putch_callback_sized_buf(char ch, char* buf_base, size_t* written, void* callback_params)
|
||||
{
|
||||
if (!callback_params) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!written) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t n = *(size_t*)callback_params;
|
||||
size_t vw = *written;
|
||||
if (vw >= n) {
|
||||
return -1;
|
||||
}
|
||||
buf_base[vw++] = ch;
|
||||
*written = vw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vsnprintf(char* s, size_t n, const char* format, va_list arg)
|
||||
{
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t wr = _printf_internal(s, format, putch_callback_sized_buf, &n, arg);
|
||||
if (wr == n) {
|
||||
s[n - 1] = '\0';
|
||||
} else {
|
||||
s[wr] = '\0';
|
||||
}
|
||||
return (int)wr;
|
||||
}
|
||||
|
||||
int snprintf(char* s, size_t n, const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int res = vsnprintf(s, n, format, arg);
|
||||
va_end(arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int putch_callback_buf(char ch, char* buf_base, size_t* written, void* callback_params)
|
||||
{
|
||||
if (!written) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t vw = *written;
|
||||
buf_base[vw++] = ch;
|
||||
*written = vw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vsprintf(char* s, const char* format, va_list arg)
|
||||
{
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
ssize_t wr = _printf_internal(s, format, putch_callback_buf, NULL, arg);
|
||||
s[wr] = '\0';
|
||||
return (int)wr;
|
||||
}
|
||||
|
||||
int sprintf(char* s, const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int res = vsprintf(s, format, arg);
|
||||
va_end(arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int vlog_unfmt(const char* format, va_list arg)
|
||||
{
|
||||
return _printf_internal(NULL, format, putch_callback_stream, NULL, arg);
|
||||
}
|
||||
|
||||
static int vlog_fmt(const char* init_msg, const char* format, va_list arg)
|
||||
{
|
||||
vlog_unfmt(init_msg, arg);
|
||||
vlog_unfmt(format, arg);
|
||||
|
||||
size_t formatlen = strlen(format);
|
||||
if (format[formatlen - 1] != '\n') {
|
||||
vlog_unfmt("\n", arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log(const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int ret = vlog_fmt("\033[1;37m[BOOT LOG]\033[0m ", format, arg);
|
||||
va_end(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_warn(const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int ret = vlog_fmt("\033[1;33m[BOOT WARN]\033[0m ", format, arg);
|
||||
va_end(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_error(const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int ret = vlog_fmt("\033[1;31m[BOOT ERR]\033[0m ", format, arg);
|
||||
va_end(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_not_formatted(const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int ret = vlog_unfmt(format, arg);
|
||||
va_end(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void log_init(uart_put_char_t ur)
|
||||
{
|
||||
uart_handler = ur;
|
||||
}
|
||||
20
boot/libboot/log/log.h
Normal file
20
boot/libboot/log/log.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _BOOT_LIBBOOT_LOG_LOG_H
|
||||
#define _BOOT_LIBBOOT_LOG_LOG_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
typedef int (*uart_put_char_t)(uint8_t ch);
|
||||
|
||||
void log_init(uart_put_char_t ur);
|
||||
|
||||
int vsnprintf(char* s, size_t n, const char* format, va_list arg);
|
||||
int vsprintf(char* s, const char* format, va_list arg);
|
||||
int snprintf(char* s, size_t n, const char* format, ...);
|
||||
int sprintf(char* s, const char* format, ...);
|
||||
|
||||
int log(const char* format, ...);
|
||||
int log_warn(const char* format, ...);
|
||||
int log_error(const char* format, ...);
|
||||
int log_not_formatted(const char* format, ...);
|
||||
|
||||
#endif // _BOOT_LIBBOOT_LOG_LOG_H
|
||||
96
boot/libboot/mem/alloc.c
Normal file
96
boot/libboot/mem/alloc.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/alloc.h>
|
||||
|
||||
void* _malloc_next_addr = NULL;
|
||||
void* _malloc_end_addr = NULL;
|
||||
|
||||
void* _palloc_start_addr = NULL;
|
||||
void* _palloc_next_addr = NULL;
|
||||
void* _palloc_end_addr = NULL;
|
||||
|
||||
int malloc_init(void* addr, size_t size)
|
||||
{
|
||||
_malloc_next_addr = addr;
|
||||
_malloc_end_addr = _malloc_next_addr + size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Current implementation is a simple linear allocator.
|
||||
void* malloc(size_t size)
|
||||
{
|
||||
if (!_malloc_next_addr) {
|
||||
return NULL;
|
||||
}
|
||||
if (_malloc_next_addr >= _malloc_end_addr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* res = _malloc_next_addr;
|
||||
|
||||
size = ROUND_CEIL(size, 0x10);
|
||||
_malloc_next_addr += size;
|
||||
return res;
|
||||
}
|
||||
|
||||
// Current implementation is a simple linear allocator.
|
||||
void* malloc_aligned(size_t size, size_t alignment)
|
||||
{
|
||||
if ((size_t)_malloc_next_addr % alignment) {
|
||||
malloc(alignment - ((size_t)_malloc_next_addr % alignment));
|
||||
}
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void free(void* ptr)
|
||||
{
|
||||
UNUSED(ptr);
|
||||
}
|
||||
|
||||
// Preserve alloc
|
||||
|
||||
int palloc_init(size_t size, size_t alignment)
|
||||
{
|
||||
_palloc_start_addr = _palloc_next_addr = malloc_aligned(size, alignment);
|
||||
if (!_palloc_next_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
_palloc_end_addr = (void*)((uintptr_t)_palloc_next_addr + size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* palloc(size_t size)
|
||||
{
|
||||
if (!_palloc_next_addr) {
|
||||
log("palloc not init");
|
||||
while (1) { };
|
||||
}
|
||||
if (_palloc_next_addr >= _palloc_end_addr) {
|
||||
log("palloc out of mem");
|
||||
while (1) { };
|
||||
}
|
||||
|
||||
void* res = _palloc_next_addr;
|
||||
|
||||
size = ROUND_CEIL(size, 0x10);
|
||||
_palloc_next_addr += size;
|
||||
return res;
|
||||
}
|
||||
|
||||
void* palloc_aligned(size_t size, size_t alignment)
|
||||
{
|
||||
if ((size_t)_palloc_next_addr % alignment) {
|
||||
palloc(alignment - ((size_t)_palloc_next_addr % alignment));
|
||||
}
|
||||
return palloc(size);
|
||||
}
|
||||
|
||||
size_t palloc_total_size()
|
||||
{
|
||||
return (size_t)_palloc_end_addr - (size_t)_palloc_start_addr;
|
||||
}
|
||||
|
||||
size_t palloc_used_size()
|
||||
{
|
||||
return (size_t)_palloc_next_addr - (size_t)_palloc_start_addr;
|
||||
}
|
||||
17
boot/libboot/mem/alloc.h
Normal file
17
boot/libboot/mem/alloc.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _BOOT_LIBBOOT_MEM_MALLOC_H
|
||||
#define _BOOT_LIBBOOT_MEM_MALLOC_H
|
||||
|
||||
#include <libboot/mem/mem.h>
|
||||
|
||||
int malloc_init(void* addr, size_t size);
|
||||
void* malloc(size_t size);
|
||||
void* malloc_aligned(size_t size, size_t alignment);
|
||||
void free(void* ptr);
|
||||
|
||||
int palloc_init(size_t size, size_t alignment);
|
||||
void* palloc(size_t size);
|
||||
void* palloc_aligned(size_t size, size_t alignment);
|
||||
size_t palloc_used_size();
|
||||
size_t palloc_total_size();
|
||||
|
||||
#endif // _BOOT_LIBBOOT_MEM_MALLOC_H
|
||||
110
boot/libboot/mem/mem.c
Normal file
110
boot/libboot/mem/mem.c
Normal file
@@ -0,0 +1,110 @@
|
||||
#include <libboot/mem/mem.h>
|
||||
|
||||
int strcmp(const char* a, const char* b)
|
||||
{
|
||||
while (*a == *b && *a != 0 && *b != 0) {
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
if (*a < *b) {
|
||||
return -1;
|
||||
}
|
||||
if (*a > *b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strncmp(const char* a, const char* b, uint32_t num)
|
||||
{
|
||||
while (*a == *b && *a != 0 && *b != 0 && num) {
|
||||
a++;
|
||||
b++;
|
||||
num--;
|
||||
}
|
||||
|
||||
if (!num) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*a < *b) {
|
||||
return -1;
|
||||
}
|
||||
if (*a > *b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t strlen(const char* s)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (s[i] != '\0')
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t strnlen(const char* s, size_t maxlen)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (s[i] != '\0' && maxlen) {
|
||||
i++;
|
||||
maxlen--;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void* memset(void* dest, uint8_t fll, uint32_t nbytes)
|
||||
{
|
||||
for (int i = 0; i < nbytes; ++i) {
|
||||
*((uint8_t*)dest + i) = fll;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void* memcpy(void* dest, const void* src, uint32_t nbytes)
|
||||
{
|
||||
for (int i = 0; i < nbytes; ++i) {
|
||||
*(char*)(dest + i) = *(char*)(src + i);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void* memmove(void* dest, const void* src, uint32_t nbytes)
|
||||
{
|
||||
if (src > dest) {
|
||||
for (int i = 0; i < nbytes; ++i) {
|
||||
*((uint8_t*)dest + i) = *((uint8_t*)src + i);
|
||||
}
|
||||
} else {
|
||||
for (int i = nbytes - 1; i >= 0; --i) {
|
||||
*((uint8_t*)dest + i) = *((uint8_t*)src + i);
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void* memccpy(void* dest, const void* src, uint8_t stop, uint32_t nbytes)
|
||||
{
|
||||
for (int i = 0; i < nbytes; ++i) {
|
||||
*((uint8_t*)dest + i) = *((uint8_t*)src + i);
|
||||
if (*((uint8_t*)src + i) == stop) {
|
||||
return ((uint8_t*)dest + i + 1);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int memcmp(const void* src1, const void* src2, uint32_t nbytes)
|
||||
{
|
||||
for (int i = 0; i < nbytes; ++i) {
|
||||
if (*(uint8_t*)(src1 + i) < *((uint8_t*)src2 + i)) {
|
||||
return -1;
|
||||
}
|
||||
if (*(uint8_t*)(src1 + i) > *(uint8_t*)(src2 + i)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
37
boot/libboot/mem/mem.h
Normal file
37
boot/libboot/mem/mem.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef _BOOT_LIBBOOT_MEM_MEM_H
|
||||
#define _BOOT_LIBBOOT_MEM_MEM_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
int strcmp(const char* a, const char* b);
|
||||
int strncmp(const char* a, const char* b, uint32_t num);
|
||||
size_t strlen(const char* s);
|
||||
size_t strnlen(const char* s, size_t maxlen);
|
||||
void* memset(void* dest, uint8_t fll, uint32_t nbytes);
|
||||
void* memcpy(void* dest, const void* src, uint32_t nbytes);
|
||||
void* memccpy(void* dest, const void* src, uint8_t stop, uint32_t nbytes);
|
||||
void* memmove(void* dest, const void* src, uint32_t nbytes);
|
||||
int memcmp(const void* src1, const void* src2, uint32_t nbytes);
|
||||
|
||||
static size_t align_size(size_t size, size_t align)
|
||||
{
|
||||
if (size % align) {
|
||||
size += align - (size % align);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline void* copy_after_kernel(size_t kbase, void* from, size_t size, size_t* kernel_size, size_t align)
|
||||
{
|
||||
void* pp = (void*)(kbase + *kernel_size);
|
||||
memcpy(pp, from, size);
|
||||
*kernel_size += align_size(size, align);
|
||||
return pp;
|
||||
}
|
||||
|
||||
static inline void* paddr_to_vaddr(void* ptr, size_t pbase, size_t vbase)
|
||||
{
|
||||
return (void*)((size_t)ptr - pbase + vbase);
|
||||
}
|
||||
|
||||
#endif // _BOOT_LIBBOOT_MEM_MEM_H
|
||||
89
boot/libboot/types.h
Normal file
89
boot/libboot/types.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef _BOOT_LIBBOOT_TYPES_H
|
||||
#define _BOOT_LIBBOOT_TYPES_H
|
||||
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#ifdef __i386__
|
||||
typedef int32_t intptr_t;
|
||||
typedef uint32_t uintptr_t;
|
||||
#if defined(__clang__)
|
||||
typedef unsigned int size_t;
|
||||
typedef int ssize_t;
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
typedef unsigned long size_t;
|
||||
typedef long ssize_t;
|
||||
#endif
|
||||
#define BITS32
|
||||
#elif __x86_64__
|
||||
typedef uint64_t size_t;
|
||||
typedef int64_t ssize_t;
|
||||
typedef int64_t intptr_t;
|
||||
typedef uint64_t uintptr_t;
|
||||
#define BITS64
|
||||
#elif __arm__
|
||||
typedef unsigned int size_t;
|
||||
typedef int ssize_t;
|
||||
typedef int32_t intptr_t;
|
||||
typedef uint32_t uintptr_t;
|
||||
#define BITS32
|
||||
#elif __aarch64__
|
||||
typedef uint64_t size_t;
|
||||
typedef int64_t ssize_t;
|
||||
typedef int64_t intptr_t;
|
||||
typedef uint64_t uintptr_t;
|
||||
#define BITS64
|
||||
#elif defined(__riscv) && (__riscv_xlen == 64)
|
||||
typedef uint64_t size_t;
|
||||
typedef int64_t ssize_t;
|
||||
typedef int64_t intptr_t;
|
||||
typedef uint64_t uintptr_t;
|
||||
#define BITS64
|
||||
#endif
|
||||
|
||||
typedef _Bool bool;
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
#define va_start(v, l) __builtin_va_start(v, l)
|
||||
#define va_end(v) __builtin_va_end(v)
|
||||
#define va_arg(v, l) __builtin_va_arg(v, l)
|
||||
|
||||
#define true (1)
|
||||
#define false (0)
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
#define ALIGNED(x) __attribute__((aligned(x)))
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
#endif /* max */
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
#endif /* min */
|
||||
|
||||
#define ROUND_CEIL(a, b) (((a) + ((b)-1)) & ~((b)-1))
|
||||
#define ROUND_FLOOR(a, b) ((a) & ~((b)-1))
|
||||
|
||||
#define TEST_FLAG(val, flag) (((val) & (flag)) == (flag))
|
||||
#define TEST_BIT(val, bitnum) (((val) & (1 << bitnum)) == (1 << bitnum))
|
||||
|
||||
#endif // _BOOT_LIBBOOT_TYPES_H
|
||||
Reference in New Issue
Block a user