mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
Initial ramdisk support
- Create initrd library to support definitions and loading - Allow tools compiled for the host machine to be built by wscript - Create makerd tool to build initrd from manifest - Move screenfont to initrd, so don't load framebuffer initially
This commit is contained in:
1
assets/initrd.manifest
Normal file
1
assets/initrd.manifest
Normal file
@@ -0,0 +1 @@
|
|||||||
|
assets/fonts/tamsyn8x16r.psf screenfont.psf
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
#define PAGE_SIZE 0x1000
|
#define PAGE_SIZE 0x1000
|
||||||
|
|
||||||
static CHAR16 kernel_name[] = KERNEL_FILENAME;
|
static CHAR16 kernel_name[] = KERNEL_FILENAME;
|
||||||
static CHAR16 font_name[] = KERNEL_FONT;
|
static CHAR16 initrd_name[] = INITRD_FILENAME;
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
loader_alloc_pages(
|
loader_alloc_pages(
|
||||||
@@ -38,7 +38,7 @@ loader_alloc_pages(
|
|||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
loader_load_font(
|
loader_load_initrd(
|
||||||
EFI_BOOT_SERVICES *bootsvc,
|
EFI_BOOT_SERVICES *bootsvc,
|
||||||
EFI_FILE_PROTOCOL *root,
|
EFI_FILE_PROTOCOL *root,
|
||||||
struct loader_data *data)
|
struct loader_data *data)
|
||||||
@@ -46,13 +46,13 @@ loader_load_font(
|
|||||||
EFI_STATUS status;
|
EFI_STATUS status;
|
||||||
|
|
||||||
EFI_FILE_PROTOCOL *file = NULL;
|
EFI_FILE_PROTOCOL *file = NULL;
|
||||||
status = root->Open(root, &file, (CHAR16 *)font_name, EFI_FILE_MODE_READ,
|
status = root->Open(root, &file, (CHAR16 *)initrd_name, EFI_FILE_MODE_READ,
|
||||||
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
|
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
|
||||||
|
|
||||||
if (status == EFI_NOT_FOUND)
|
if (status == EFI_NOT_FOUND)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Opening file %s", font_name);
|
CHECK_EFI_STATUS_OR_RETURN(status, L"Opening file %s", initrd_name);
|
||||||
|
|
||||||
char info[sizeof(EFI_FILE_INFO) + 100];
|
char info[sizeof(EFI_FILE_INFO) + 100];
|
||||||
size_t info_length = sizeof(info);
|
size_t info_length = sizeof(info);
|
||||||
@@ -60,16 +60,16 @@ loader_load_font(
|
|||||||
status = file->GetInfo(file, &guid_file_info, &info_length, info);
|
status = file->GetInfo(file, &guid_file_info, &info_length, info);
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Getting file info");
|
CHECK_EFI_STATUS_OR_RETURN(status, L"Getting file info");
|
||||||
|
|
||||||
data->font_length = ((EFI_FILE_INFO *)info)->FileSize;
|
data->initrd_length = ((EFI_FILE_INFO *)info)->FileSize;
|
||||||
|
|
||||||
status = loader_alloc_pages(
|
status = loader_alloc_pages(
|
||||||
bootsvc,
|
bootsvc,
|
||||||
KERNEL_FONT_MEMTYPE,
|
INITRD_MEMTYPE,
|
||||||
&data->font_length,
|
&data->initrd_length,
|
||||||
&data->font);
|
&data->initrd);
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating pages");
|
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating pages");
|
||||||
|
|
||||||
status = file->Read(file, &data->font_length, data->font);
|
status = file->Read(file, &data->initrd_length, data->initrd);
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
|
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
|
||||||
|
|
||||||
status = file->Close(file);
|
status = file->Close(file);
|
||||||
@@ -217,12 +217,12 @@ loader_load_kernel(
|
|||||||
|
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_elf: %s", kernel_name);
|
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_elf: %s", kernel_name);
|
||||||
|
|
||||||
data->font = (void *)((uint64_t)data->kernel + data->kernel_length);
|
data->initrd = (void *)((uint64_t)data->kernel + data->kernel_length);
|
||||||
status = loader_load_font(bootsvc, root, data);
|
status = loader_load_initrd(bootsvc, root, data);
|
||||||
|
|
||||||
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_file: %s", font_name);
|
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_file: %s", initrd_name);
|
||||||
|
|
||||||
data->data = (void *)((uint64_t)data->font + data->font_length);
|
data->data = (void *)((uint64_t)data->initrd + data->initrd_length);
|
||||||
data->data_length += PAGE_SIZE; // extra page for map growth
|
data->data_length += PAGE_SIZE; // extra page for map growth
|
||||||
status = loader_alloc_pages(
|
status = loader_alloc_pages(
|
||||||
bootsvc,
|
bootsvc,
|
||||||
|
|||||||
@@ -16,24 +16,20 @@
|
|||||||
#define KERNEL_MEMTYPE 0x80000000
|
#define KERNEL_MEMTYPE 0x80000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KERNEL_FONT_MEMTYPE
|
#ifndef INITRD_MEMTYPE
|
||||||
#define KERNEL_FONT_MEMTYPE 0x80000001
|
#define INITRD_MEMTYPE 0x80000001
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KERNEL_DATA_MEMTYPE
|
#ifndef KERNEL_DATA_MEMTYPE
|
||||||
#define KERNEL_DATA_MEMTYPE 0x80000002
|
#define KERNEL_DATA_MEMTYPE 0x80000002
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KERNEL_PT_MEMTYPE
|
|
||||||
#define KERNEL_PT_MEMTYPE 0x80000004
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef KERNEL_FILENAME
|
#ifndef KERNEL_FILENAME
|
||||||
#define KERNEL_FILENAME L"kernel.elf"
|
#define KERNEL_FILENAME L"kernel.elf"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef KERNEL_FONT
|
#ifndef INITRD_FILENAME
|
||||||
#define KERNEL_FONT L"screenfont.psf"
|
#define INITRD_FILENAME L"initrd.img"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct loader_data {
|
struct loader_data {
|
||||||
@@ -41,8 +37,8 @@ struct loader_data {
|
|||||||
void *kernel_entry;
|
void *kernel_entry;
|
||||||
size_t kernel_length;
|
size_t kernel_length;
|
||||||
|
|
||||||
void *font;
|
void *initrd;
|
||||||
size_t font_length;
|
size_t initrd_length;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
size_t data_length;
|
size_t data_length;
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
|||||||
status = loader_load_kernel(bootsvc, &load);
|
status = loader_load_kernel(bootsvc, &load);
|
||||||
CHECK_EFI_STATUS_OR_FAIL(status);
|
CHECK_EFI_STATUS_OR_FAIL(status);
|
||||||
|
|
||||||
con_printf(L" image bytes at 0x%x : %x\r\n", load.kernel, load.kernel_length);
|
con_printf(L" %u image bytes at 0x%x\r\n", load.kernel_length, load.kernel);
|
||||||
con_printf(L" font bytes at 0x%x : %x\r\n", load.font, load.font_length);
|
con_printf(L" %u initrd bytes at 0x%x\r\n", load.initrd_length, load.initrd);
|
||||||
con_printf(L" data bytes at 0x%x : %x\r\n", load.data, load.data_length);
|
con_printf(L" %u data bytes at 0x%x\r\n", load.data_length, load.data);
|
||||||
|
|
||||||
struct kernel_header *version = (struct kernel_header *)load.kernel;
|
struct kernel_header *version = (struct kernel_header *)load.kernel;
|
||||||
if (version->magic != KERNEL_HEADER_MAGIC) {
|
if (version->magic != KERNEL_HEADER_MAGIC) {
|
||||||
@@ -111,9 +111,9 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
|||||||
|
|
||||||
data_header->flags = 0;
|
data_header->flags = 0;
|
||||||
|
|
||||||
data_header->font = load.font;
|
data_header->initrd = load.initrd;
|
||||||
data_header->font_length = load.font_length;
|
data_header->initrd_length = load.initrd_length;
|
||||||
memory_mark_pointer_fixup((void **)&data_header->font);
|
memory_mark_pointer_fixup((void **)&data_header->initrd);
|
||||||
|
|
||||||
data_header->data = load.data;
|
data_header->data = load.data;
|
||||||
data_header->data_length = load.data_length;
|
data_header->data_length = load.data_length;
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map)
|
|||||||
while (d < end) {
|
while (d < end) {
|
||||||
switch (d->Type) {
|
switch (d->Type) {
|
||||||
case KERNEL_MEMTYPE:
|
case KERNEL_MEMTYPE:
|
||||||
case KERNEL_FONT_MEMTYPE:
|
case INITRD_MEMTYPE:
|
||||||
case KERNEL_DATA_MEMTYPE:
|
case KERNEL_DATA_MEMTYPE:
|
||||||
d->Attribute |= EFI_MEMORY_RUNTIME;
|
d->Attribute |= EFI_MEMORY_RUNTIME;
|
||||||
d->VirtualStart = d->PhysicalStart + KERNEL_VIRT_ADDRESS;
|
d->VirtualStart = d->PhysicalStart + KERNEL_VIRT_ADDRESS;
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ struct popcorn_data {
|
|||||||
uint32_t _reserved0;
|
uint32_t _reserved0;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
||||||
void *font;
|
void *initrd;
|
||||||
size_t font_length;
|
size_t initrd_length;
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
size_t data_length;
|
size_t data_length;
|
||||||
|
|||||||
@@ -41,19 +41,10 @@ struct acpi2_rsdp
|
|||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
uint8_t
|
|
||||||
acpi_checksum(const void *p, size_t len, size_t off = 0)
|
|
||||||
{
|
|
||||||
uint8_t sum = 0;
|
|
||||||
const uint8_t *c = reinterpret_cast<const uint8_t *>(p);
|
|
||||||
for (int i = off; i < len; ++i) sum += c[i];
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
acpi_table_header::validate(uint32_t expected_type) const
|
acpi_table_header::validate(uint32_t expected_type) const
|
||||||
{
|
{
|
||||||
if (acpi_checksum(this, length) != 0) return false;
|
if (kutil::checksum(this, length) != 0) return false;
|
||||||
return !expected_type || (expected_type == type);
|
return !expected_type || (expected_type == type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +77,7 @@ device_manager::device_manager(const void *root_table) :
|
|||||||
kassert(acpi1->signature[i] == expected_signature[i],
|
kassert(acpi1->signature[i] == expected_signature[i],
|
||||||
"ACPI RSDP table signature mismatch");
|
"ACPI RSDP table signature mismatch");
|
||||||
|
|
||||||
uint8_t sum = acpi_checksum(acpi1, sizeof(acpi1_rsdp), 0);
|
uint8_t sum = kutil::checksum(acpi1, sizeof(acpi1_rsdp), 0);
|
||||||
kassert(sum == 0, "ACPI 1.0 RSDP checksum mismatch.");
|
kassert(sum == 0, "ACPI 1.0 RSDP checksum mismatch.");
|
||||||
|
|
||||||
kassert(acpi1->revision > 1, "ACPI 1.0 not supported.");
|
kassert(acpi1->revision > 1, "ACPI 1.0 not supported.");
|
||||||
@@ -94,7 +85,7 @@ device_manager::device_manager(const void *root_table) :
|
|||||||
const acpi2_rsdp *acpi2 =
|
const acpi2_rsdp *acpi2 =
|
||||||
reinterpret_cast<const acpi2_rsdp *>(acpi1);
|
reinterpret_cast<const acpi2_rsdp *>(acpi1);
|
||||||
|
|
||||||
sum = acpi_checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp));
|
sum = kutil::checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp));
|
||||||
kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch.");
|
kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch.");
|
||||||
|
|
||||||
load_xsdt(reinterpret_cast<const acpi_xsdt *>(acpi2->xsdt_address));
|
load_xsdt(reinterpret_cast<const acpi_xsdt *>(acpi2->xsdt_address));
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "initrd/initrd.h"
|
||||||
#include "kutil/assert.h"
|
#include "kutil/assert.h"
|
||||||
#include "kutil/memory.h"
|
#include "kutil/memory.h"
|
||||||
#include "block_device.h"
|
#include "block_device.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
#include "font.h"
|
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
@@ -29,23 +29,11 @@ extern "C" {
|
|||||||
extern void __kernel_assert(const char *, unsigned, const char *);
|
extern void __kernel_assert(const char *, unsigned, const char *);
|
||||||
|
|
||||||
void
|
void
|
||||||
init_console(const popcorn_data *header)
|
init_console()
|
||||||
{
|
{
|
||||||
serial_port *com1 = new (&g_com1) serial_port(COM1);
|
serial_port *com1 = new (&g_com1) serial_port(COM1);
|
||||||
console *cons = new (&g_console) console(com1);
|
console *cons = new (&g_console) console(com1);
|
||||||
|
|
||||||
if (header->frame_buffer) {
|
|
||||||
screen *s = new screen(
|
|
||||||
header->frame_buffer,
|
|
||||||
header->hres,
|
|
||||||
header->vres,
|
|
||||||
header->rmask,
|
|
||||||
header->gmask,
|
|
||||||
header->bmask);
|
|
||||||
font *f = new font(header->font);
|
|
||||||
cons->init_screen(s, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
cons->set_color(0x21, 0x00);
|
cons->set_color(0x21, 0x00);
|
||||||
cons->puts("Popcorn OS ");
|
cons->puts("Popcorn OS ");
|
||||||
cons->set_color(0x08, 0x00);
|
cons->set_color(0x08, 0x00);
|
||||||
@@ -83,16 +71,20 @@ kernel_main(popcorn_data *header)
|
|||||||
&header->frame_buffer,
|
&header->frame_buffer,
|
||||||
header->frame_buffer_length);
|
header->frame_buffer_length);
|
||||||
|
|
||||||
init_console(header);
|
init_console();
|
||||||
|
|
||||||
log::debug(logs::boot, " Popcorn header is at: %016lx", header);
|
log::debug(logs::boot, " Popcorn header is at: %016lx", header);
|
||||||
log::debug(logs::boot, " Framebuffer is at: %016lx", header->frame_buffer);
|
log::debug(logs::boot, " Framebuffer is at: %016lx", header->frame_buffer);
|
||||||
log::debug(logs::boot, " Font data is at: %016lx", header->font);
|
|
||||||
log::debug(logs::boot, " Kernel data is at: %016lx", header->data);
|
log::debug(logs::boot, " Kernel data is at: %016lx", header->data);
|
||||||
log::debug(logs::boot, " Memory map is at: %016lx", header->memory_map);
|
log::debug(logs::boot, " Memory map is at: %016lx", header->memory_map);
|
||||||
log::debug(logs::boot, "ACPI root table is at: %016lx", header->acpi_table);
|
log::debug(logs::boot, "ACPI root table is at: %016lx", header->acpi_table);
|
||||||
log::debug(logs::boot, "Runtime service is at: %016lx", header->runtime);
|
log::debug(logs::boot, "Runtime service is at: %016lx", header->runtime);
|
||||||
|
|
||||||
|
initrd::disk ird(header->initrd);
|
||||||
|
log::info(logs::boot, "initrd loaded with %d files.", ird.files().count());
|
||||||
|
for (auto &f : ird.files())
|
||||||
|
log::info(logs::boot, " %s (%d bytes).", f.name(), f.size());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pager->dump_pml4(nullptr, 0);
|
pager->dump_pml4(nullptr, 0);
|
||||||
pager->dump_blocks(true);
|
pager->dump_blocks(true);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ def build(bld):
|
|||||||
name = 'kernel',
|
name = 'kernel',
|
||||||
includes = '.',
|
includes = '.',
|
||||||
target = bld.env.KERNEL_FILENAME,
|
target = bld.env.KERNEL_FILENAME,
|
||||||
use = 'kutil',
|
use = ['kutil', 'initrd'],
|
||||||
linkflags = "-T {}".format(lds),
|
linkflags = "-T {}".format(lds),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
38
src/libraries/initrd/headers.h
Normal file
38
src/libraries/initrd/headers.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "kutil/enum_bitfields.h"
|
||||||
|
|
||||||
|
namespace initrd {
|
||||||
|
|
||||||
|
|
||||||
|
enum class disk_flags : uint16_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct disk_header
|
||||||
|
{
|
||||||
|
uint16_t file_count;
|
||||||
|
disk_flags flags;
|
||||||
|
uint32_t length;
|
||||||
|
uint8_t checksum;
|
||||||
|
uint8_t reserved[3];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
|
enum class file_flags : uint16_t
|
||||||
|
{
|
||||||
|
executable = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
struct file_header
|
||||||
|
{
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t length;
|
||||||
|
uint16_t name_offset;
|
||||||
|
file_flags flags;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
} // namepsace initrd
|
||||||
|
|
||||||
|
IS_BITFIELD(initrd::disk_flags);
|
||||||
|
IS_BITFIELD(initrd::file_flags);
|
||||||
41
src/libraries/initrd/initrd.cpp
Normal file
41
src/libraries/initrd/initrd.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "initrd/initrd.h"
|
||||||
|
#include "kutil/assert.h"
|
||||||
|
#include "kutil/enum_bitfields.h"
|
||||||
|
#include "headers.h"
|
||||||
|
|
||||||
|
namespace initrd {
|
||||||
|
|
||||||
|
file::file(const file_header *header, const void *start) :
|
||||||
|
m_header(header)
|
||||||
|
{
|
||||||
|
m_data = kutil::offset_pointer(start, m_header->offset);
|
||||||
|
auto *name = kutil::offset_pointer(start, m_header->name_offset);
|
||||||
|
m_name = reinterpret_cast<const char *>(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * file::name() const { return m_name; }
|
||||||
|
const size_t file::size() const { return m_header->length; }
|
||||||
|
const void * file::data() const { return m_data; }
|
||||||
|
|
||||||
|
bool
|
||||||
|
file::executable() const {
|
||||||
|
return bitfield_has(m_header->flags, file_flags::executable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
disk::disk(const void *start)
|
||||||
|
{
|
||||||
|
auto *header = reinterpret_cast<const disk_header *>(start);
|
||||||
|
size_t length = header->length;
|
||||||
|
uint8_t sum = kutil::checksum(start, length);
|
||||||
|
kassert(sum == 0, "initrd checksum failed");
|
||||||
|
|
||||||
|
auto *files = reinterpret_cast<const file_header *>(header + 1);
|
||||||
|
|
||||||
|
m_files.ensure_capacity(header->file_count);
|
||||||
|
for (int i = 0; i < header->file_count; ++i) {
|
||||||
|
m_files.emplace(&files[i], start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace initrd
|
||||||
61
src/libraries/initrd/initrd.h
Normal file
61
src/libraries/initrd/initrd.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
/// \file initrd.h
|
||||||
|
/// Definitions defining the simple inital ramdisk file format used by the
|
||||||
|
/// popcorn kernel.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "kutil/vector.h"
|
||||||
|
|
||||||
|
// File format:
|
||||||
|
// 1x disk_header
|
||||||
|
// Nx file_header
|
||||||
|
// filename string data
|
||||||
|
// file data
|
||||||
|
|
||||||
|
namespace initrd {
|
||||||
|
|
||||||
|
struct disk_header;
|
||||||
|
struct file_header;
|
||||||
|
|
||||||
|
|
||||||
|
/// Encasulates methods for a file on the ramdisk
|
||||||
|
class file
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
file(const file_header *header, const void *start);
|
||||||
|
|
||||||
|
/// Get the filename
|
||||||
|
const char * name() const;
|
||||||
|
|
||||||
|
/// Get the file size
|
||||||
|
const size_t size() const;
|
||||||
|
|
||||||
|
/// Get a pointer to the file data
|
||||||
|
const void * data() const;
|
||||||
|
|
||||||
|
/// Whether this file is an executable
|
||||||
|
bool executable() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const file_header *m_header;
|
||||||
|
void const *m_data;
|
||||||
|
char const *m_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// Encasulates access methods for the ramdisk
|
||||||
|
class disk
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
/// \arg start The start of the initrd in memory
|
||||||
|
disk(const void *start);
|
||||||
|
|
||||||
|
/// Get the vector of files on the disk
|
||||||
|
const kutil::vector<file> & files() const { return m_files; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
kutil::vector<file> m_files;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace initrd
|
||||||
14
src/libraries/initrd/wscript
Normal file
14
src/libraries/initrd/wscript
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
def configure(ctx):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
sources = bld.path.ant_glob("**/*.cpp")
|
||||||
|
|
||||||
|
bld.stlib(
|
||||||
|
source = sources,
|
||||||
|
name = 'initrd',
|
||||||
|
target = 'initrd',
|
||||||
|
)
|
||||||
|
|
||||||
|
# vim: ft=python et
|
||||||
@@ -25,4 +25,13 @@ memcpy(void *dest, void *src, size_t n)
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
checksum(const void *p, size_t len, size_t off)
|
||||||
|
{
|
||||||
|
uint8_t sum = 0;
|
||||||
|
const uint8_t *c = reinterpret_cast<const uint8_t *>(p);
|
||||||
|
for (int i = off; i < len; ++i) sum += c[i];
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace kutil
|
} // namespace kutil
|
||||||
|
|||||||
@@ -66,4 +66,10 @@ inline T* mask_pointer(T *p, addr_t mask)
|
|||||||
return reinterpret_cast<T *>(reinterpret_cast<addr_t>(p) & ~mask);
|
return reinterpret_cast<T *>(reinterpret_cast<addr_t>(p) & ~mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do a simple byte-wise checksum of an area of memory.
|
||||||
|
/// \arg p The start of the memory region
|
||||||
|
/// \arg len The number of bytes in the region
|
||||||
|
/// \arg off An optional offset into the region
|
||||||
|
uint8_t checksum(const void *p, size_t len, size_t off = 0);
|
||||||
|
|
||||||
} // namespace kutil
|
} // namespace kutil
|
||||||
|
|||||||
10
src/tools/makerd/entry.cpp
Normal file
10
src/tools/makerd/entry.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "entry.h"
|
||||||
|
|
||||||
|
entry::entry(const std::string &in, const std::string &out) :
|
||||||
|
m_in(in), m_out(out), m_file(in, std::ios_base::binary)
|
||||||
|
{
|
||||||
|
m_file.seekg(0, std::ios_base::end);
|
||||||
|
m_size = m_file.tellg();
|
||||||
|
m_file.seekg(0);
|
||||||
|
}
|
||||||
|
|
||||||
23
src/tools/makerd/entry.h
Normal file
23
src/tools/makerd/entry.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
class entry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
entry(const std::string &in, const std::string &out);
|
||||||
|
|
||||||
|
inline const std::string & in() const { return m_in; }
|
||||||
|
inline const std::string & out() const { return m_out; }
|
||||||
|
inline const std::ifstream & file() const { return m_file; }
|
||||||
|
|
||||||
|
inline size_t size() const { return m_size; }
|
||||||
|
inline bool good() const { return m_file.good(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_in;
|
||||||
|
std::string m_out;
|
||||||
|
std::ifstream m_file;
|
||||||
|
size_t m_size;
|
||||||
|
};
|
||||||
|
|
||||||
115
src/tools/makerd/main.cpp
Normal file
115
src/tools/makerd/main.cpp
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "initrd/headers.h"
|
||||||
|
#include "entry.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " <manifest> <output>" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<entry> entries;
|
||||||
|
std::ifstream manifest(argv[1]);
|
||||||
|
|
||||||
|
size_t files_size = 0;
|
||||||
|
size_t names_size = 0;
|
||||||
|
|
||||||
|
while (manifest.good()) {
|
||||||
|
std::string in, out;
|
||||||
|
|
||||||
|
manifest >> in;
|
||||||
|
if (in.length() < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
manifest >> out;
|
||||||
|
if (in.front() == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
entries.emplace_back(in, out);
|
||||||
|
const entry &e = entries.back();
|
||||||
|
|
||||||
|
if (!e.good()) {
|
||||||
|
std::cerr << "Error reading file: " << in << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
files_size += e.size();
|
||||||
|
names_size += out.length() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fstream out(argv[2],
|
||||||
|
std::ios_base::binary |
|
||||||
|
std::ios_base::trunc |
|
||||||
|
std::ios_base::out |
|
||||||
|
std::ios_base::in);
|
||||||
|
|
||||||
|
if (!out.good()) {
|
||||||
|
std::cerr << "Error opening file: " << argv[2] << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t total_length =
|
||||||
|
sizeof(initrd::disk_header) +
|
||||||
|
sizeof(initrd::file_header) * entries.size() +
|
||||||
|
names_size + files_size;
|
||||||
|
|
||||||
|
initrd::disk_header dheader;
|
||||||
|
std::memset(&dheader, 0, sizeof(dheader));
|
||||||
|
|
||||||
|
dheader.file_count = entries.size();
|
||||||
|
dheader.length = total_length;
|
||||||
|
out.write(reinterpret_cast<const char *>(&dheader), sizeof(dheader));
|
||||||
|
|
||||||
|
size_t name_offset =
|
||||||
|
sizeof(initrd::disk_header) +
|
||||||
|
sizeof(initrd::file_header) * entries.size();
|
||||||
|
|
||||||
|
size_t file_offset = name_offset + names_size;
|
||||||
|
|
||||||
|
for (auto &e : entries) {
|
||||||
|
initrd::file_header fheader;
|
||||||
|
std::memset(&fheader, 0, sizeof(fheader));
|
||||||
|
fheader.offset = file_offset;
|
||||||
|
fheader.length = e.size();
|
||||||
|
fheader.name_offset = name_offset;
|
||||||
|
|
||||||
|
out.write(
|
||||||
|
reinterpret_cast<const char *>(&fheader),
|
||||||
|
sizeof(fheader));
|
||||||
|
|
||||||
|
name_offset += e.out().length() + 1;
|
||||||
|
file_offset += e.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &e : entries) {
|
||||||
|
out.write(e.out().c_str(), e.out().length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &e : entries) {
|
||||||
|
out << e.file().rdbuf();
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[1024];
|
||||||
|
uint8_t checksum = 0;
|
||||||
|
|
||||||
|
out.seekg(0);
|
||||||
|
while (true) {
|
||||||
|
size_t n = out.readsome(&buffer[0], 1024);
|
||||||
|
if (n == 0 || out.eof()) break;
|
||||||
|
|
||||||
|
for (size_t i=0; i<n; ++i)
|
||||||
|
checksum += static_cast<uint8_t>(buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
dheader.checksum = static_cast<uint8_t>(0 - checksum);
|
||||||
|
out.seekp(0);
|
||||||
|
out.write(reinterpret_cast<const char *>(&dheader), sizeof(dheader));
|
||||||
|
|
||||||
|
out.close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
15
src/tools/makerd/wscript
Normal file
15
src/tools/makerd/wscript
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
def configure(ctx):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
sources = bld.path.ant_glob("**/*.cpp")
|
||||||
|
|
||||||
|
bld.program(
|
||||||
|
source = sources,
|
||||||
|
name = 'makerd',
|
||||||
|
target = 'makerd',
|
||||||
|
use = 'initrd',
|
||||||
|
)
|
||||||
|
|
||||||
|
# vim: ft=python et
|
||||||
313
wscript
313
wscript
@@ -2,12 +2,6 @@ top = '.'
|
|||||||
out = 'build'
|
out = 'build'
|
||||||
|
|
||||||
|
|
||||||
from waflib.Build import BuildContext
|
|
||||||
class TestContext(BuildContext):
|
|
||||||
cmd = 'test'
|
|
||||||
variant = 'tests'
|
|
||||||
|
|
||||||
|
|
||||||
def options(opt):
|
def options(opt):
|
||||||
opt.load("nasm clang clang++")
|
opt.load("nasm clang clang++")
|
||||||
|
|
||||||
@@ -28,29 +22,14 @@ def options(opt):
|
|||||||
help='Font for the console')
|
help='Font for the console')
|
||||||
|
|
||||||
|
|
||||||
def configure(ctx):
|
def common_configure(ctx):
|
||||||
import os
|
from os import listdir
|
||||||
import subprocess
|
|
||||||
from os.path import join, exists
|
from os.path import join, exists
|
||||||
|
from subprocess import check_output
|
||||||
|
|
||||||
ctx.find_program("ld", var="LINK_CC")
|
version = check_output("git describe --always", shell=True).strip()
|
||||||
ctx.env.LINK_CXX = ctx.env.LINK_CC
|
git_sha = check_output("git rev-parse --short HEAD", shell=True).strip()
|
||||||
|
|
||||||
ctx.load("nasm clang clang++")
|
|
||||||
ctx.find_program("objcopy", var="objcopy")
|
|
||||||
ctx.find_program("objdump", var="objdump")
|
|
||||||
ctx.find_program("mcopy", var="mcopy")
|
|
||||||
ctx.find_program("dd", var="dd")
|
|
||||||
|
|
||||||
# Override the gcc/g++ tools setting these assuming LD is gcc/g++
|
|
||||||
ctx.env.SHLIB_MARKER = '-Bdynamic'
|
|
||||||
ctx.env.STLIB_MARKER = '-Bstatic'
|
|
||||||
ctx.env.LINKFLAGS_cstlib = ['-Bstatic']
|
|
||||||
|
|
||||||
version = subprocess.check_output("git describe --always", shell=True).strip()
|
|
||||||
git_sha = subprocess.check_output("git rev-parse --short HEAD", shell=True).strip()
|
|
||||||
|
|
||||||
env = ctx.env
|
|
||||||
major, minor, patch_dirty = version.split(".")
|
major, minor, patch_dirty = version.split(".")
|
||||||
dirty = 'dirty' in patch_dirty
|
dirty = 'dirty' in patch_dirty
|
||||||
patch = patch_dirty.split('-')[0]
|
patch = patch_dirty.split('-')[0]
|
||||||
@@ -71,17 +50,66 @@ def configure(ctx):
|
|||||||
|
|
||||||
libraries = []
|
libraries = []
|
||||||
mod_root = join("src", "libraries")
|
mod_root = join("src", "libraries")
|
||||||
for module in os.listdir(mod_root):
|
for module in listdir(mod_root):
|
||||||
mod_path = join(mod_root, module)
|
mod_path = join(mod_root, module)
|
||||||
if exists(join(mod_path, "wscript")):
|
if exists(join(mod_path, "wscript")):
|
||||||
libraries.append(mod_path)
|
libraries.append(mod_path)
|
||||||
|
ctx.env.LIBRARIES = libraries
|
||||||
|
|
||||||
|
tools = []
|
||||||
|
mod_root = join("src", "tools")
|
||||||
|
for module in listdir(mod_root):
|
||||||
|
mod_path = join(mod_root, module)
|
||||||
|
if exists(join(mod_path, "wscript")):
|
||||||
|
tools.append(mod_path)
|
||||||
|
ctx.env.TOOLS = tools
|
||||||
|
|
||||||
drivers = []
|
drivers = []
|
||||||
mod_root = join("src", "drivers")
|
mod_root = join("src", "drivers")
|
||||||
for module in os.listdir(mod_root):
|
for module in listdir(mod_root):
|
||||||
mod_path = join(mod_root, module)
|
mod_path = join(mod_root, module)
|
||||||
if exists(join(mod_path, "wscript")):
|
if exists(join(mod_path, "wscript")):
|
||||||
drivers.append(mod_path)
|
drivers.append(mod_path)
|
||||||
|
ctx.env.DRIVERS = drivers
|
||||||
|
|
||||||
|
ctx.env.append_value('DEFINES', [
|
||||||
|
'GIT_VERSION="{}"'.format(version),
|
||||||
|
'GIT_VERSION_WIDE=L"{}"'.format(version),
|
||||||
|
"VERSION_MAJOR={}".format(major),
|
||||||
|
"VERSION_MINOR={}".format(minor),
|
||||||
|
"VERSION_PATCH={}".format(patch),
|
||||||
|
"VERSION_GITSHA=0x{}{}".format({True:1}.get(dirty, 0), git_sha),
|
||||||
|
])
|
||||||
|
|
||||||
|
ctx.env.append_value('QEMUOPTS', [
|
||||||
|
'-smp', '1',
|
||||||
|
'-m', '512',
|
||||||
|
'-d', 'mmu,int,guest_errors',
|
||||||
|
'-D', 'popcorn.log',
|
||||||
|
'-cpu', 'Broadwell',
|
||||||
|
'-M', 'q35',
|
||||||
|
'-no-reboot',
|
||||||
|
'-nographic',
|
||||||
|
])
|
||||||
|
|
||||||
|
if exists('/dev/kvm'):
|
||||||
|
ctx.env.append_value('QEMUOPTS', ['--enable-kvm'])
|
||||||
|
|
||||||
|
|
||||||
|
def configure(ctx):
|
||||||
|
from os.path import join, exists
|
||||||
|
|
||||||
|
ctx.find_program("ld", var="LINK_CC")
|
||||||
|
ctx.env.LINK_CXX = ctx.env.LINK_CC
|
||||||
|
|
||||||
|
ctx.load("nasm clang clang++")
|
||||||
|
ctx.find_program("objcopy", var="objcopy")
|
||||||
|
ctx.find_program("objdump", var="objdump")
|
||||||
|
|
||||||
|
# Override the gcc/g++ tools setting these assuming LD is gcc/g++
|
||||||
|
ctx.env.SHLIB_MARKER = '-Bdynamic'
|
||||||
|
ctx.env.STLIB_MARKER = '-Bstatic'
|
||||||
|
ctx.env.LINKFLAGS_cstlib = ['-Bstatic']
|
||||||
|
|
||||||
baseflags = [
|
baseflags = [
|
||||||
'-nostdlib',
|
'-nostdlib',
|
||||||
@@ -118,15 +146,6 @@ def configure(ctx):
|
|||||||
'error'
|
'error'
|
||||||
]]
|
]]
|
||||||
|
|
||||||
ctx.env.append_value('DEFINES', [
|
|
||||||
'GIT_VERSION="{}"'.format(version),
|
|
||||||
'GIT_VERSION_WIDE=L"{}"'.format(version),
|
|
||||||
"VERSION_MAJOR={}".format(major),
|
|
||||||
"VERSION_MINOR={}".format(minor),
|
|
||||||
"VERSION_PATCH={}".format(patch),
|
|
||||||
"VERSION_GITSHA=0x{}{}".format({True:1}.get(dirty, 0), git_sha),
|
|
||||||
])
|
|
||||||
|
|
||||||
ctx.env.append_value('CFLAGS', baseflags)
|
ctx.env.append_value('CFLAGS', baseflags)
|
||||||
ctx.env.append_value('CFLAGS', warnflags)
|
ctx.env.append_value('CFLAGS', warnflags)
|
||||||
ctx.env.append_value('CFLAGS', ['-ggdb', '-std=c11'])
|
ctx.env.append_value('CFLAGS', ['-ggdb', '-std=c11'])
|
||||||
@@ -150,95 +169,65 @@ def configure(ctx):
|
|||||||
'-nostartfiles',
|
'-nostartfiles',
|
||||||
])
|
])
|
||||||
|
|
||||||
ctx.env.append_value('QEMUOPTS', [
|
common_configure(ctx)
|
||||||
'-smp', '1',
|
base_bare = ctx.env
|
||||||
'-m', '512',
|
ctx.setenv('boot', env=base_bare)
|
||||||
'-d', 'mmu,int,guest_errors',
|
|
||||||
'-D', 'popcorn.log',
|
|
||||||
'-cpu', 'Broadwell',
|
|
||||||
'-M', 'q35',
|
|
||||||
'-no-reboot',
|
|
||||||
'-nographic',
|
|
||||||
])
|
|
||||||
|
|
||||||
if os.path.exists('/dev/kvm'):
|
|
||||||
ctx.env.append_value('QEMUOPTS', ['--enable-kvm'])
|
|
||||||
|
|
||||||
env = ctx.env
|
|
||||||
ctx.setenv('boot', env=env)
|
|
||||||
ctx.recurse(join("src", "boot"))
|
ctx.recurse(join("src", "boot"))
|
||||||
|
|
||||||
ctx.setenv('kernel', env=env)
|
ctx.setenv('kernel', env=base_bare)
|
||||||
ctx.env.append_value('CFLAGS', ['-mcmodel=large'])
|
ctx.env.append_value('CFLAGS', ['-mcmodel=large'])
|
||||||
ctx.env.append_value('CXXFLAGS', ['-mcmodel=large'])
|
ctx.env.append_value('CXXFLAGS', ['-mcmodel=large'])
|
||||||
|
|
||||||
ctx.env.LIBRARIES = libraries
|
|
||||||
for mod_path in ctx.env.LIBRARIES:
|
for mod_path in ctx.env.LIBRARIES:
|
||||||
ctx.recurse(mod_path)
|
ctx.recurse(mod_path)
|
||||||
|
|
||||||
ctx.env.DRIVERS = drivers
|
|
||||||
for mod_path in ctx.env.DRIVERS:
|
for mod_path in ctx.env.DRIVERS:
|
||||||
ctx.recurse(mod_path)
|
ctx.recurse(mod_path)
|
||||||
|
|
||||||
ctx.recurse(join("src", "kernel"))
|
ctx.recurse(join("src", "kernel"))
|
||||||
|
|
||||||
## Testing configuration
|
## Tools configuration
|
||||||
##
|
##
|
||||||
from waflib.ConfigSet import ConfigSet
|
from waflib.ConfigSet import ConfigSet
|
||||||
ctx.setenv('tests', env=ConfigSet())
|
ctx.setenv('tools', env=ConfigSet())
|
||||||
ctx.load("clang++")
|
ctx.load('clang++')
|
||||||
|
ctx.find_program("mcopy", var="mcopy")
|
||||||
ctx.env.append_value('INCLUDES', [
|
ctx.find_program("dd", var="dd")
|
||||||
join(ctx.path.abspath(), "src", "include"),
|
common_configure(ctx)
|
||||||
join(ctx.path.abspath(), "src", "libraries"),
|
|
||||||
])
|
ctx.env.CXXFLAGS = ['-g', '-std=c++14', '-fno-rtti']
|
||||||
|
ctx.env.LINKFLAGS = ['-g']
|
||||||
|
|
||||||
|
for mod_path in ctx.env.LIBRARIES:
|
||||||
|
ctx.recurse(mod_path)
|
||||||
|
|
||||||
|
for mod_path in ctx.env.LIBRARIES:
|
||||||
|
ctx.recurse(mod_path)
|
||||||
|
|
||||||
|
## Image configuration
|
||||||
|
##
|
||||||
|
ctx.setenv('image', env=ConfigSet())
|
||||||
|
ctx.find_program("mcopy", var="mcopy")
|
||||||
|
ctx.find_program("dd", var="dd")
|
||||||
|
common_configure(ctx)
|
||||||
|
|
||||||
|
## Testing configuration
|
||||||
|
##
|
||||||
|
from waflib.ConfigSet import ConfigSet
|
||||||
|
ctx.setenv('tests', env=ConfigSet())
|
||||||
|
ctx.load('clang++')
|
||||||
|
common_configure(ctx)
|
||||||
|
|
||||||
ctx.env.CXXFLAGS = ['-g', '-std=c++14', '-fno-rtti']
|
ctx.env.CXXFLAGS = ['-g', '-std=c++14', '-fno-rtti']
|
||||||
ctx.env.LINKFLAGS = ['-g']
|
ctx.env.LINKFLAGS = ['-g']
|
||||||
|
|
||||||
ctx.env.LIBRARIES = libraries
|
|
||||||
for mod_path in ctx.env.LIBRARIES:
|
for mod_path in ctx.env.LIBRARIES:
|
||||||
ctx.recurse(mod_path)
|
ctx.recurse(mod_path)
|
||||||
ctx.recurse(join("src", "tests"))
|
ctx.recurse(join("src", "tests"))
|
||||||
|
|
||||||
|
|
||||||
def build(bld):
|
from waflib.Task import Task
|
||||||
from os.path import join
|
class mcopy(Task):
|
||||||
|
|
||||||
if not bld.variant:
|
|
||||||
bld.env = bld.all_envs['boot']
|
|
||||||
bld.recurse(join("src", "boot"))
|
|
||||||
|
|
||||||
bld.env = bld.all_envs['kernel']
|
|
||||||
for mod_path in bld.env.LIBRARIES:
|
|
||||||
bld.recurse(mod_path)
|
|
||||||
for mod_path in bld.env.DRIVERS:
|
|
||||||
bld.recurse(mod_path)
|
|
||||||
|
|
||||||
bld.recurse(join("src", "kernel"))
|
|
||||||
|
|
||||||
src = bld.path
|
|
||||||
out = bld.path.get_bld()
|
|
||||||
kernel_name = bld.env.KERNEL_FILENAME
|
|
||||||
|
|
||||||
disk = out.make_node("popcorn.img")
|
|
||||||
disk1 = out.make_node("popcorn.fat")
|
|
||||||
font = out.make_node("screenfont.psf")
|
|
||||||
|
|
||||||
bld(
|
|
||||||
source = src.make_node(join("assets", "ovmf", "x64", "OVMF.fd")),
|
|
||||||
target = out.make_node("flash.img"),
|
|
||||||
rule = "cp ${SRC} ${TGT}",
|
|
||||||
)
|
|
||||||
|
|
||||||
bld(
|
|
||||||
source = src.make_node(join("assets", "fonts", bld.env.FONT_NAME)),
|
|
||||||
target = font,
|
|
||||||
rule = "cp ${SRC} ${TGT}",
|
|
||||||
)
|
|
||||||
|
|
||||||
from waflib.Task import Task
|
|
||||||
class mcopy(Task):
|
|
||||||
color = 'YELLOW'
|
color = 'YELLOW'
|
||||||
def keyword(self):
|
def keyword(self):
|
||||||
return "Updating"
|
return "Updating"
|
||||||
@@ -255,7 +244,7 @@ def build(bld):
|
|||||||
for inp in self.inputs[2:]:
|
for inp in self.inputs[2:]:
|
||||||
call(args + [inp.abspath(), "::/"])
|
call(args + [inp.abspath(), "::/"])
|
||||||
|
|
||||||
class addpart(Task):
|
class addpart(Task):
|
||||||
color = 'YELLOW'
|
color = 'YELLOW'
|
||||||
def keyword(self):
|
def keyword(self):
|
||||||
return "Updating"
|
return "Updating"
|
||||||
@@ -272,12 +261,89 @@ def build(bld):
|
|||||||
"bs=512", "count=91669", "seek=2048", "conv=notrunc"]
|
"bs=512", "count=91669", "seek=2048", "conv=notrunc"]
|
||||||
call(args)
|
call(args)
|
||||||
|
|
||||||
|
class makerd(Task):
|
||||||
|
color = 'YELLOW'
|
||||||
|
def keyword(self):
|
||||||
|
return "Creating"
|
||||||
|
def __str__(self):
|
||||||
|
node = self.outputs[0]
|
||||||
|
return node.path_from(node.ctx.launch_node())
|
||||||
|
def run(self):
|
||||||
|
from os.path import join
|
||||||
|
from subprocess import check_call as call
|
||||||
|
|
||||||
|
args = [
|
||||||
|
self.inputs[0].abspath(),
|
||||||
|
self.inputs[1].abspath(),
|
||||||
|
self.outputs[0].abspath(),
|
||||||
|
]
|
||||||
|
call(args)
|
||||||
|
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
from os.path import join
|
||||||
|
|
||||||
|
## Boot
|
||||||
|
#
|
||||||
|
if bld.variant == 'boot':
|
||||||
|
bld.recurse(join("src", "boot"))
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
#
|
||||||
|
elif bld.variant == 'tools':
|
||||||
|
for mod_path in bld.env.LIBRARIES:
|
||||||
|
bld.recurse(mod_path)
|
||||||
|
for mod_path in bld.env.TOOLS:
|
||||||
|
bld.recurse(mod_path)
|
||||||
|
|
||||||
|
## Kernel
|
||||||
|
#
|
||||||
|
elif bld.variant == 'kernel':
|
||||||
|
for mod_path in bld.env.LIBRARIES:
|
||||||
|
bld.recurse(mod_path)
|
||||||
|
for mod_path in bld.env.DRIVERS:
|
||||||
|
bld.recurse(mod_path)
|
||||||
|
|
||||||
|
bld.recurse(join("src", "kernel"))
|
||||||
|
|
||||||
|
## Image
|
||||||
|
#
|
||||||
|
elif bld.variant == 'image':
|
||||||
|
src = bld.path
|
||||||
|
root = bld.path.get_bld().parent
|
||||||
|
|
||||||
|
out = {
|
||||||
|
'boot': root.make_node('boot'),
|
||||||
|
'tools': root.make_node('tools'),
|
||||||
|
'kernel': root.make_node('kernel'),
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel_name = bld.env.KERNEL_FILENAME
|
||||||
|
|
||||||
|
disk = root.make_node("popcorn.img")
|
||||||
|
disk1 = root.make_node("popcorn.fat")
|
||||||
|
initrd = root.make_node("initrd.img")
|
||||||
|
|
||||||
|
bld(
|
||||||
|
source = src.make_node(join("assets", "ovmf", "x64", "OVMF.fd")),
|
||||||
|
target = root.make_node("flash.img"),
|
||||||
|
rule = "cp ${SRC} ${TGT}",
|
||||||
|
)
|
||||||
|
|
||||||
|
make_rd = makerd(env = bld.env)
|
||||||
|
make_rd.set_inputs([
|
||||||
|
out['tools'].make_node(join("src", "tools", "makerd", "makerd")),
|
||||||
|
src.make_node(join("assets", "initrd.manifest")),
|
||||||
|
])
|
||||||
|
make_rd.set_outputs([initrd])
|
||||||
|
bld.add_to_group(make_rd)
|
||||||
|
|
||||||
copy_img = mcopy(env = bld.env)
|
copy_img = mcopy(env = bld.env)
|
||||||
copy_img.set_inputs([
|
copy_img.set_inputs([
|
||||||
src.make_node(join("assets", "disk.fat")),
|
src.make_node(join("assets", "disk.fat")),
|
||||||
out.make_node(join("src", "boot", "boot.efi")),
|
out['boot'].make_node(join("src", "boot", "boot.efi")),
|
||||||
out.make_node(join("src", "kernel", kernel_name)),
|
out['kernel'].make_node(join("src", "kernel", kernel_name)),
|
||||||
font,
|
initrd,
|
||||||
])
|
])
|
||||||
copy_img.set_outputs([disk1])
|
copy_img.set_outputs([disk1])
|
||||||
bld.add_to_group(copy_img)
|
bld.add_to_group(copy_img)
|
||||||
@@ -290,13 +356,46 @@ def build(bld):
|
|||||||
copy_part.set_outputs([disk])
|
copy_part.set_outputs([disk])
|
||||||
bld.add_to_group(copy_part)
|
bld.add_to_group(copy_part)
|
||||||
|
|
||||||
elif bld.variant == 'tests':
|
|
||||||
|
def test(bld):
|
||||||
|
from os.path import join
|
||||||
for mod_path in bld.env.LIBRARIES:
|
for mod_path in bld.env.LIBRARIES:
|
||||||
bld.recurse(mod_path)
|
bld.recurse(mod_path)
|
||||||
|
|
||||||
bld.recurse(join("src", "tests"))
|
bld.recurse(join("src", "tests"))
|
||||||
|
|
||||||
|
|
||||||
|
def build_all(ctx):
|
||||||
|
from waflib import Options
|
||||||
|
Options.commands = ['tools', 'kernel', 'boot', 'image'] + Options.commands
|
||||||
|
|
||||||
|
|
||||||
|
from waflib.Build import BuildContext
|
||||||
|
class TestContext(BuildContext):
|
||||||
|
cmd = 'test'
|
||||||
|
variant = 'tests'
|
||||||
|
|
||||||
|
class ToolsContext(BuildContext):
|
||||||
|
cmd = 'tools'
|
||||||
|
variant = 'tools'
|
||||||
|
|
||||||
|
class KernelContext(BuildContext):
|
||||||
|
cmd = 'kernel'
|
||||||
|
variant = 'kernel'
|
||||||
|
|
||||||
|
class BootContext(BuildContext):
|
||||||
|
cmd = 'boot'
|
||||||
|
variant = 'boot'
|
||||||
|
|
||||||
|
class ImageContext(BuildContext):
|
||||||
|
cmd = 'image'
|
||||||
|
variant = 'image'
|
||||||
|
|
||||||
|
class BuildAllContext(BuildContext):
|
||||||
|
cmd = 'build'
|
||||||
|
fun = 'build_all'
|
||||||
|
|
||||||
|
|
||||||
class QemuContext(BuildContext):
|
class QemuContext(BuildContext):
|
||||||
cmd = 'qemu'
|
cmd = 'qemu'
|
||||||
fun = 'qemu'
|
fun = 'qemu'
|
||||||
|
|||||||
Reference in New Issue
Block a user