boot: Recover BIOS loader.
This commit is contained in:
parent
62e9138e5d
commit
074728b5ff
3
.gitignore
vendored
3
.gitignore
vendored
@ -26,3 +26,6 @@
|
|||||||
/base/usr/bin/*
|
/base/usr/bin/*
|
||||||
/base/usr/lib/*
|
/base/usr/lib/*
|
||||||
/.make/
|
/.make/
|
||||||
|
/cdrom
|
||||||
|
/fatbase
|
||||||
|
/image.iso
|
||||||
|
27
Makefile
27
Makefile
@ -238,3 +238,30 @@ SOURCE_FILES += $(wildcard kuroko/src/*.c kuroko/src/*.h kuroko/src/*/*.c kuroko
|
|||||||
SOURCE_FILES += $(wildcard $(BASE)/usr/include/*.h $(BASE)/usr/include/*/*.h $(BASE)/usr/include/*/*/*.h)
|
SOURCE_FILES += $(wildcard $(BASE)/usr/include/*.h $(BASE)/usr/include/*/*.h $(BASE)/usr/include/*/*/*.h)
|
||||||
tags: $(SOURCE_FILES)
|
tags: $(SOURCE_FILES)
|
||||||
ctags -f tags $(SOURCE_FILES)
|
ctags -f tags $(SOURCE_FILES)
|
||||||
|
|
||||||
|
# Loader stuff, legacy CDs
|
||||||
|
fatbase/ramdisk.igz: ramdisk.igz
|
||||||
|
cp $< $@
|
||||||
|
fatbase/kernel: misaka-kernel
|
||||||
|
cp $< $@
|
||||||
|
strip $@
|
||||||
|
|
||||||
|
cdrom/fat.img: fatbase/ramdisk.igz fatbase/kernel util/mkdisk.sh | dirs
|
||||||
|
util/mkdisk.sh $@ fatbase
|
||||||
|
|
||||||
|
cdrom/boot.sys: boot/boot.o boot/cstuff.o boot/link.ld | dirs
|
||||||
|
${LD} -melf_i386 -T boot/link.ld -o $@ boot/boot.o boot/cstuff.o
|
||||||
|
|
||||||
|
boot/cstuff.o: boot/cstuff.c boot/*.h
|
||||||
|
${CC} -m32 -c -Os -fno-strict-aliasing -finline-functions -ffreestanding -mgeneral-regs-only -o $@ $<
|
||||||
|
|
||||||
|
boot/boot.o: boot/boot.S
|
||||||
|
${AS} --32 -o $@ $<
|
||||||
|
|
||||||
|
image.iso: cdrom/fat.img cdrom/boot.sys util/update-extents.py
|
||||||
|
xorriso -as mkisofs -R -J -c bootcat \
|
||||||
|
-b boot.sys -no-emul-boot -boot-load-size full \
|
||||||
|
-eltorito-alt-boot -e fat.img -no-emul-boot -isohybrid-gpt-basdat \
|
||||||
|
-o image.iso cdrom
|
||||||
|
python3 util/update-extents.py
|
||||||
|
|
||||||
|
196
boot/cstuff.c
196
boot/cstuff.c
@ -1,99 +1,40 @@
|
|||||||
#ifdef EFI_PLATFORM
|
#include <stdint.h>
|
||||||
# include <efi.h>
|
#include <stddef.h>
|
||||||
# include <efilib.h>
|
|
||||||
EFI_HANDLE ImageHandleIn;
|
|
||||||
#else
|
|
||||||
# include <stdint.h>
|
|
||||||
# include <stddef.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _BOOT_LOADER
|
#define _BOOT_LOADER
|
||||||
#include "ata.h"
|
#include "ata.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#ifndef EFI_PLATFORM
|
|
||||||
#include "atapi_imp.h"
|
#include "atapi_imp.h"
|
||||||
#include "iso9660.h"
|
#include "iso9660.h"
|
||||||
#endif
|
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
#include "kbd.h"
|
#include "kbd.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "inflate.h"
|
|
||||||
|
|
||||||
/* Basic text strings */
|
/* Basic text strings */
|
||||||
#define BASE_VERSION "ToaruOS Bootloader v2.1"
|
#define BASE_VERSION "ToaruOS Bootloader v3.0"
|
||||||
#ifdef EFI_PLATFORM
|
#define VERSION_TEXT BASE_VERSION " (BIOS)"
|
||||||
# if defined(__x86_64__)
|
|
||||||
# define VERSION_TEXT BASE_VERSION " (EFI, X64)"
|
|
||||||
# else
|
|
||||||
# define VERSION_TEXT BASE_VERSION " (EFI, IA32)"
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define VERSION_TEXT BASE_VERSION " (BIOS)"
|
|
||||||
#endif
|
|
||||||
#define HELP_TEXT "Press <Enter> or select a menu option with \030/\031/\032/\033."
|
#define HELP_TEXT "Press <Enter> or select a menu option with \030/\031/\032/\033."
|
||||||
#define COPYRIGHT_TEXT "ToaruOS is free software under the NCSA license."
|
#define COPYRIGHT_TEXT "ToaruOS is free software under the NCSA license."
|
||||||
#define LINK_TEXT "https://toaruos.org - https://github.com/klange/toaruos"
|
#define LINK_TEXT "https://toaruos.org - https://github.com/klange/toaruos"
|
||||||
|
|
||||||
/* Boot command line strings */
|
/* Boot command line strings */
|
||||||
#define DEFAULT_ROOT_CMDLINE "root=/dev/ram0 root_type=tar "
|
#define DEFAULT_ROOT_CMDLINE "root=/dev/ram0 "
|
||||||
#define DEFAULT_GRAPHICAL_CMDLINE "start=live-session "
|
#define DEFAULT_GRAPHICAL_CMDLINE "start=live-session "
|
||||||
#define DEFAULT_SINGLE_CMDLINE "start=terminal\037-F "
|
#define DEFAULT_SINGLE_CMDLINE "start=terminal\037-F "
|
||||||
#define DEFAULT_TEXT_CMDLINE "start=--vga "
|
#define DEFAULT_TEXT_CMDLINE "start=--vga "
|
||||||
#define DEFAULT_VID_CMDLINE "vid=auto,1440,900 "
|
#define DEFAULT_VID_CMDLINE "vid=auto,1440,900 "
|
||||||
#define DEFAULT_PRESET_VID_CMDLINE "vid=preset "
|
#define DEFAULT_PRESET_VID_CMDLINE "vid=preset "
|
||||||
#define DEFAULT_NETINIT_CMDLINE "init=/dev/ram0 "
|
|
||||||
#define NETINIT_REMOTE_URL "args=http://toaruos.org/ramdisk-1.9.3.img "
|
|
||||||
#define MIGRATE_CMDLINE "migrate "
|
#define MIGRATE_CMDLINE "migrate "
|
||||||
#define DEBUG_LOG_CMDLINE "logtoserial=warning "
|
|
||||||
#define DEBUG_SERIAL_CMDLINE "kdebug "
|
|
||||||
#define DEFAULT_HEADLESS_CMDLINE "start=--headless "
|
#define DEFAULT_HEADLESS_CMDLINE "start=--headless "
|
||||||
|
|
||||||
char * module_dir = "MOD";
|
|
||||||
char * kernel_path = "KERNEL.";
|
char * kernel_path = "KERNEL.";
|
||||||
char * ramdisk_path = "RAMDISK.IGZ";
|
char * ramdisk_path = "RAMDISK.IGZ";
|
||||||
|
|
||||||
#ifdef EFI_PLATFORM
|
|
||||||
int _efi_do_mode_set = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Module file names - need to be ordered. */
|
|
||||||
static char * modules[] = {
|
|
||||||
"ZERO.KO", // 0
|
|
||||||
"RANDOM.KO", // 1
|
|
||||||
"SERIAL.KO", // 2
|
|
||||||
"DEBUG_SH.KO", // 3
|
|
||||||
"PROCFS.KO", // 4
|
|
||||||
"TMPFS.KO", // 5
|
|
||||||
"ATA.KO", // 6
|
|
||||||
"EXT2.KO", // 7
|
|
||||||
"ISO9660.KO", // 8
|
|
||||||
"PS2KBD.KO", // 9
|
|
||||||
"PS2MOUSE.KO", // 10
|
|
||||||
"LFBVIDEO.KO", // 11
|
|
||||||
"VBOX.KO", // 12
|
|
||||||
"VMWARE.KO", // 13
|
|
||||||
"VIDSET.KO", // 14
|
|
||||||
"PACKETFS.KO", // 15
|
|
||||||
"SND.KO", // 16
|
|
||||||
"AC97.KO", // 17
|
|
||||||
"NET.KO", // 18
|
|
||||||
"PCNET.KO", // 19
|
|
||||||
"RTL.KO", // 20
|
|
||||||
"E1000.KO", // 21
|
|
||||||
"PCSPKR.KO", // 22
|
|
||||||
"PORTIO.KO", // 23
|
|
||||||
"TARFS.KO", // 24
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Names of the available boot modes. */
|
/* Names of the available boot modes. */
|
||||||
static struct bootmode boot_mode_names[] = {
|
static struct bootmode boot_mode_names[] = {
|
||||||
{1, "normal", "Normal Boot"},
|
{1, "normal", "Normal Boot"},
|
||||||
#ifndef EFI_PLATFORM
|
|
||||||
{2, "vga", "VGA Text Mode"},
|
|
||||||
#endif
|
|
||||||
{3, "single", "Single-User Graphical Terminal"},
|
{3, "single", "Single-User Graphical Terminal"},
|
||||||
{4, "headless", "Headless"},
|
{4, "headless", "Headless"},
|
||||||
};
|
};
|
||||||
@ -101,40 +42,19 @@ static struct bootmode boot_mode_names[] = {
|
|||||||
/* More bootloader implementation that depends on the module config */
|
/* More bootloader implementation that depends on the module config */
|
||||||
#include "moremultiboot.h"
|
#include "moremultiboot.h"
|
||||||
|
|
||||||
#ifdef EFI_PLATFORM
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
|
||||||
{
|
|
||||||
InitializeLib(ImageHandle, SystemTable);
|
|
||||||
ST = SystemTable;
|
|
||||||
ImageHandleIn = ImageHandle;
|
|
||||||
#else
|
|
||||||
extern char _bss_start[];
|
extern char _bss_start[];
|
||||||
extern char _bss_end[];
|
extern char _bss_end[];
|
||||||
|
|
||||||
int kmain() {
|
int kmain() {
|
||||||
memset(&_bss_start,0,(uintptr_t)&_bss_end-(uintptr_t)&_bss_start);
|
memset(&_bss_start,0,(uintptr_t)&_bss_end-(uintptr_t)&_bss_start);
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOT_OPTION(_debug, 0, "Debug output",
|
BOOT_OPTION(_debug, 0, "Debug output",
|
||||||
"Enable debug output in the bootloader and enable the",
|
"Enable debug output in the bootloader and enable the",
|
||||||
"serial debug log in the operating system itself.");
|
"serial debug log in the operating system itself.");
|
||||||
|
|
||||||
BOOT_OPTION(_legacy_ata, 0, "Legacy ATA driver",
|
BOOT_OPTION(_nosmp, 1, "Disable SMP",
|
||||||
"Enable the legacy ATA driver, which does not support",
|
"SMP support is experimental and buggy.",
|
||||||
"ATAPI or use DMA. May be necessary in some virtual machines.");
|
"");
|
||||||
|
|
||||||
BOOT_OPTION(_normal_ata, 1, "DMA ATA driver",
|
|
||||||
"Enable the normal, DMA-capable ATA driver. This is the default.",
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
BOOT_OPTION(_debug_shell, 1, "Debug shell",
|
|
||||||
"Enable the kernel debug shell. This can be accessed using",
|
|
||||||
"the `kdebug` application.");
|
|
||||||
|
|
||||||
BOOT_OPTION(_video, 1, "Video modules",
|
|
||||||
"Enable the video modules. These are needed to modeset",
|
|
||||||
"and provide a framebuffer for the UI.");
|
|
||||||
|
|
||||||
BOOT_OPTION(_vbox, 1, "VirtualBox Guest Additions",
|
BOOT_OPTION(_vbox, 1, "VirtualBox Guest Additions",
|
||||||
"Enable integration with VirtualBox, including",
|
"Enable integration with VirtualBox, including",
|
||||||
@ -156,73 +76,21 @@ int kmain() {
|
|||||||
"(Requires VMware driver) Enables support for",
|
"(Requires VMware driver) Enables support for",
|
||||||
"automatically setting display size in VMware");
|
"automatically setting display size in VMware");
|
||||||
|
|
||||||
BOOT_OPTION(_sound, 1, "Audio drivers",
|
|
||||||
"Enable the audio subsystem and AC'97 drivers.",
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
BOOT_OPTION(_net, 1, "Network drivers",
|
|
||||||
"Enable the IPv4 network subsystem and various",
|
|
||||||
"network interface drivers.");
|
|
||||||
|
|
||||||
BOOT_OPTION(_migrate, 1, "Writable root",
|
BOOT_OPTION(_migrate, 1, "Writable root",
|
||||||
"Migrates the ramdisk from tarball to an in-memory",
|
"Migrates the ramdisk from tarball to an in-memory",
|
||||||
"temporary filesystem at boot. Needed for packages.");
|
"temporary filesystem at boot. Needed for packages.");
|
||||||
|
|
||||||
BOOT_OPTION(_serialshell, 0, "Debug on serial",
|
|
||||||
"Start a kernel debug shell on the first",
|
|
||||||
"serial port.");
|
|
||||||
|
|
||||||
BOOT_OPTION(_netinit, 0, "Netinit (QEMU local)",
|
|
||||||
"Downloads a userspace filesystem from a local",
|
|
||||||
"HTTP server and extracts it at boot.");
|
|
||||||
|
|
||||||
BOOT_OPTION(_netinitr, 0, "Netinit (toaruos.org)",
|
|
||||||
"Downloads a userspace filesystem from a remote",
|
|
||||||
"HTTP server and extracts it at boot.");
|
|
||||||
|
|
||||||
#ifdef EFI_PLATFORM
|
|
||||||
BOOT_OPTION(_efilargest, 0, "Prefer largest mode.",
|
|
||||||
"When using EFI mode setting, use the largest mode.",
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
BOOT_OPTION(_efi1024, 0, "Prefer 1024x768",
|
|
||||||
"If a 1024x768x32 mode is found, set that.",
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
BOOT_OPTION(_efi1080p, 0, "Prefer 1080p",
|
|
||||||
"If a 1920x1080 mode is found, set that.",
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
BOOT_OPTION(_efiask, 0, "Ask for input on each mode.",
|
|
||||||
"Displays a y/n prompt for each possible mode.",
|
|
||||||
NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Loop over rendering the menu */
|
/* Loop over rendering the menu */
|
||||||
show_menu();
|
show_menu();
|
||||||
|
|
||||||
/* Build our command line. */
|
/* Build our command line. */
|
||||||
if (_netinit || _netinitr) {
|
|
||||||
strcat(cmdline, DEFAULT_NETINIT_CMDLINE);
|
|
||||||
ramdisk_path = "NETINIT.";
|
|
||||||
if (_netinitr) {
|
|
||||||
strcat(cmdline, NETINIT_REMOTE_URL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strcat(cmdline, DEFAULT_ROOT_CMDLINE);
|
strcat(cmdline, DEFAULT_ROOT_CMDLINE);
|
||||||
}
|
|
||||||
|
|
||||||
if (_migrate) {
|
if (_migrate) {
|
||||||
strcat(cmdline, MIGRATE_CMDLINE);
|
strcat(cmdline, MIGRATE_CMDLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * _video_command_line = DEFAULT_VID_CMDLINE;
|
char * _video_command_line = DEFAULT_VID_CMDLINE;
|
||||||
#ifdef EFI_PLATFORM
|
|
||||||
_efi_do_mode_set = (_efilargest ? 1 : (_efi1024 ? 2 : (_efi1080p ? 3 : (_efiask ? 4 : 0))));
|
|
||||||
if (_efi_do_mode_set) {
|
|
||||||
_video_command_line = DEFAULT_PRESET_VID_CMDLINE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (boot_mode == 1) {
|
if (boot_mode == 1) {
|
||||||
strcat(cmdline, DEFAULT_GRAPHICAL_CMDLINE);
|
strcat(cmdline, DEFAULT_GRAPHICAL_CMDLINE);
|
||||||
@ -237,12 +105,11 @@ int kmain() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_debug) {
|
if (_debug) {
|
||||||
strcat(cmdline, DEBUG_LOG_CMDLINE);
|
|
||||||
txt_debug = 1;
|
txt_debug = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_serialshell) {
|
if (!_vbox) {
|
||||||
strcat(cmdline, DEBUG_SERIAL_CMDLINE);
|
strcat(cmdline, "novbox ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_vbox && !_vboxrects) {
|
if (_vbox && !_vboxrects) {
|
||||||
@ -257,45 +124,8 @@ int kmain() {
|
|||||||
strcat(cmdline, "novmwareresset ");
|
strcat(cmdline, "novmwareresset ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure modules */
|
if (_nosmp) {
|
||||||
if (!_normal_ata) {
|
strcat(cmdline, "nosmp ");
|
||||||
modules[6] = "NONE";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_legacy_ata) {
|
|
||||||
modules[6] = "ATAOLD.KO";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_debug_shell) {
|
|
||||||
modules[3] = "NONE";
|
|
||||||
modules[14] = "NONE";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_video) {
|
|
||||||
modules[11] = "NONE";
|
|
||||||
modules[12] = "NONE";
|
|
||||||
modules[13] = "NONE";
|
|
||||||
modules[14] = "NONE";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_vmware) {
|
|
||||||
modules[13] = "NONE";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_vbox) {
|
|
||||||
modules[12] = "NONE";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_sound) {
|
|
||||||
modules[16] = "NONE";
|
|
||||||
modules[17] = "NONE";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_net) {
|
|
||||||
modules[18] = "NONE";
|
|
||||||
modules[19] = "NONE";
|
|
||||||
modules[20] = "NONE";
|
|
||||||
modules[21] = "NONE";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boot();
|
boot();
|
||||||
|
467
boot/inflate.h
467
boot/inflate.h
@ -1,467 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
static uint8_t bit_buffer = 0;
|
|
||||||
static char buffer_size = 0;
|
|
||||||
|
|
||||||
static uint8_t * inputPtr = NULL;
|
|
||||||
static uint8_t * outputPtr = NULL;
|
|
||||||
|
|
||||||
static uint8_t read_byte(void);
|
|
||||||
static void _write(unsigned int sym);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decoded Huffman table
|
|
||||||
*/
|
|
||||||
struct huff {
|
|
||||||
uint16_t counts[16]; /* Number of symbols of each length */
|
|
||||||
uint16_t symbols[288]; /* Ordered symbols */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixed Huffman code tables, generated later.
|
|
||||||
*/
|
|
||||||
struct huff fixed_lengths;
|
|
||||||
struct huff fixed_dists;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a little-endian short from the input.
|
|
||||||
*/
|
|
||||||
static uint16_t read_16le(void) {
|
|
||||||
uint16_t a, b;
|
|
||||||
a = read_byte();
|
|
||||||
b = read_byte();
|
|
||||||
return (a << 0) | (b << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a single bit from the source.
|
|
||||||
* Fills the byte buffer with one byte when it runs out.
|
|
||||||
*/
|
|
||||||
static _Bool read_bit(void) {
|
|
||||||
|
|
||||||
/* When we run out of bits... */
|
|
||||||
if (buffer_size == 0) {
|
|
||||||
/* Refill from the next input byte */
|
|
||||||
bit_buffer = read_byte();
|
|
||||||
/* And restore bit buffer size to 8 bits */
|
|
||||||
buffer_size = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the next available bit */
|
|
||||||
int out = bit_buffer & 1;
|
|
||||||
|
|
||||||
/* Shift the bit buffer forward */
|
|
||||||
bit_buffer >>= 1;
|
|
||||||
|
|
||||||
/* There is now one less bit available */
|
|
||||||
buffer_size--;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read multible bits, in bit order, from the source.
|
|
||||||
*/
|
|
||||||
static uint32_t read_bits(unsigned int count) {
|
|
||||||
uint32_t out = 0;
|
|
||||||
for (unsigned int bit = 0; bit < count; bit++) {
|
|
||||||
/* Read one bit at a time, from least to most significant */
|
|
||||||
out |= (read_bit() << bit);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a Huffman table from an array of lengths.
|
|
||||||
*/
|
|
||||||
static void build_huffman(uint8_t * lengths, size_t size, struct huff * out) {
|
|
||||||
|
|
||||||
uint16_t offsets[16];
|
|
||||||
unsigned int count = 0;
|
|
||||||
|
|
||||||
/* Zero symbol counts */
|
|
||||||
for (unsigned int i = 0; i < 16; ++i) out->counts[i] = 0;
|
|
||||||
|
|
||||||
/* Count symbols */
|
|
||||||
for (unsigned int i = 0; i < size; ++i) out->counts[lengths[i]]++;
|
|
||||||
|
|
||||||
/* Special case... */
|
|
||||||
out->counts[0] = 0;
|
|
||||||
|
|
||||||
/* Figure out offsets */
|
|
||||||
for (unsigned int i = 0; i < 16; ++i) {
|
|
||||||
offsets[i] = count;
|
|
||||||
count += out->counts[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build symbol ordering */
|
|
||||||
for (unsigned int i = 0; i < size; ++i) {
|
|
||||||
if (lengths[i]) out->symbols[offsets[lengths[i]]++] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the fixed Huffman tables
|
|
||||||
*/
|
|
||||||
static void build_fixed(void) {
|
|
||||||
/* From 3.2.6:
|
|
||||||
* Lit Value Bits Codes
|
|
||||||
* --------- ---- -----
|
|
||||||
* 0 - 143 8 00110000 through
|
|
||||||
* 10111111
|
|
||||||
* 144 - 255 9 110010000 through
|
|
||||||
* 111111111
|
|
||||||
* 256 - 279 7 0000000 through
|
|
||||||
* 0010111
|
|
||||||
* 280 - 287 8 11000000 through
|
|
||||||
* 11000111
|
|
||||||
*/
|
|
||||||
uint8_t lengths[288];
|
|
||||||
for (int i = 0; i < 144; ++i) lengths[i] = 8;
|
|
||||||
for (int i = 144; i < 256; ++i) lengths[i] = 9;
|
|
||||||
for (int i = 256; i < 280; ++i) lengths[i] = 7;
|
|
||||||
for (int i = 280; i < 288; ++i) lengths[i] = 8;
|
|
||||||
build_huffman(lengths, 288, &fixed_lengths);
|
|
||||||
|
|
||||||
/* Continued from 3.2.6:
|
|
||||||
* Distance codes 0-31 are represented by (fixed-length) 5-bit
|
|
||||||
* codes, with possible additional bits as shown in the table
|
|
||||||
* shown in Paragraph 3.2.5, above. Note that distance codes 30-
|
|
||||||
* 31 will never actually occur in the compressed data.
|
|
||||||
*/
|
|
||||||
for (int i = 0; i < 30; ++i) lengths[i] = 5;
|
|
||||||
build_huffman(lengths, 30, &fixed_dists);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode a symbol from the source using a Huffman table.
|
|
||||||
*/
|
|
||||||
static int decode(struct huff * huff) {
|
|
||||||
int count = 0, cur = 0;
|
|
||||||
for (int i = 1; cur >= 0; i++) {
|
|
||||||
cur = (cur << 1) | read_bit(); /* Shift */
|
|
||||||
count += huff->counts[i];
|
|
||||||
cur -= huff->counts[i];
|
|
||||||
}
|
|
||||||
return huff->symbols[count + cur];
|
|
||||||
}
|
|
||||||
|
|
||||||
struct huff_ring {
|
|
||||||
size_t pointer;
|
|
||||||
uint8_t data[32768];
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct huff_ring data = {0, {0}};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emit one byte to the output, maintaining the ringbuffer.
|
|
||||||
* The ringbuffer ensures we can always look back 32K bytes
|
|
||||||
* while keeping output streaming.
|
|
||||||
*/
|
|
||||||
static void emit(unsigned char byte) {
|
|
||||||
data.data[data.pointer++] = byte;
|
|
||||||
data.pointer &= 0x7FFF;
|
|
||||||
_write(byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Look backwards in the output ring buffer.
|
|
||||||
*/
|
|
||||||
static void peek(unsigned int offset) {
|
|
||||||
data.data[data.pointer] = data.data[(data.pointer + 0x8000 - offset) & 0x7FFF];
|
|
||||||
_write(data.data[data.pointer++]);
|
|
||||||
data.pointer &= 0x7FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decompress a block of Huffman-encoded data.
|
|
||||||
*/
|
|
||||||
static int inflate(struct huff * huff_len, struct huff * huff_dist) {
|
|
||||||
|
|
||||||
/* These are the extra bits for lengths from the tables in section 3.2.5
|
|
||||||
* Extra Extra Extra
|
|
||||||
* Code Bits Length(s) Code Bits Lengths Code Bits Length(s)
|
|
||||||
* ---- ---- ------ ---- ---- ------- ---- ---- -------
|
|
||||||
* 257 0 3 267 1 15,16 277 4 67-82
|
|
||||||
* 258 0 4 268 1 17,18 278 4 83-98
|
|
||||||
* 259 0 5 269 2 19-22 279 4 99-114
|
|
||||||
* 260 0 6 270 2 23-26 280 4 115-130
|
|
||||||
* 261 0 7 271 2 27-30 281 5 131-162
|
|
||||||
* 262 0 8 272 2 31-34 282 5 163-194
|
|
||||||
* 263 0 9 273 3 35-42 283 5 195-226
|
|
||||||
* 264 0 10 274 3 43-50 284 5 227-257
|
|
||||||
* 265 1 11,12 275 3 51-58 285 0 258
|
|
||||||
* 266 1 13,14 276 3 59-66
|
|
||||||
*/
|
|
||||||
static const uint16_t lens[] = {
|
|
||||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
|
|
||||||
59, 67, 83, 99, 115, 131, 163, 195, 227, 258
|
|
||||||
};
|
|
||||||
static const uint16_t lext[] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
|
|
||||||
4, 5, 5, 5, 5, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Extra bits for distances....
|
|
||||||
* Extra Extra Extra
|
|
||||||
* Code Bits Dist Code Bits Dist Code Bits Distance
|
|
||||||
* ---- ---- ---- ---- ---- ------ ---- ---- --------
|
|
||||||
* 0 0 1 10 4 33-48 20 9 1025-1536
|
|
||||||
* 1 0 2 11 4 49-64 21 9 1537-2048
|
|
||||||
* 2 0 3 12 5 65-96 22 10 2049-3072
|
|
||||||
* 3 0 4 13 5 97-128 23 10 3073-4096
|
|
||||||
* 4 1 5,6 14 6 129-192 24 11 4097-6144
|
|
||||||
* 5 1 7,8 15 6 193-256 25 11 6145-8192
|
|
||||||
* 6 2 9-12 16 7 257-384 26 12 8193-12288
|
|
||||||
* 7 2 13-16 17 7 385-512 27 12 12289-16384
|
|
||||||
* 8 3 17-24 18 8 513-768 28 13 16385-24576
|
|
||||||
* 9 3 25-32 19 8 769-1024 29 13 24577-32768
|
|
||||||
*/
|
|
||||||
static const uint16_t dists[] = {
|
|
||||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
|
|
||||||
513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
|
|
||||||
};
|
|
||||||
static const uint16_t dext[] = {
|
|
||||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
|
|
||||||
10, 11, 11, 12, 12, 13, 13
|
|
||||||
};
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
unsigned int symbol = decode(huff_len);
|
|
||||||
if (symbol < 256) {
|
|
||||||
emit(symbol);
|
|
||||||
} else if (symbol == 256) {
|
|
||||||
/* "The literal/length symbol 256 (end of data), ..." */
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
unsigned int length, distance, offset;
|
|
||||||
symbol -= 257;
|
|
||||||
length = read_bits(lext[symbol]) + lens[symbol];
|
|
||||||
distance = decode(huff_dist);
|
|
||||||
offset = read_bits(dext[distance]) + dists[distance];
|
|
||||||
for (unsigned int i = 0; i < length; ++i) {
|
|
||||||
peek(offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode a dynamic Huffman block.
|
|
||||||
*/
|
|
||||||
static void decode_huffman(void) {
|
|
||||||
|
|
||||||
/* Ordering of code length codes:
|
|
||||||
* (HCLEN + 4) x 3 bits: code lengths for the code length
|
|
||||||
* alphabet given just above, in the order: ...
|
|
||||||
*/
|
|
||||||
static const uint8_t clens[] = {
|
|
||||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned int literals, distances, clengths;
|
|
||||||
uint8_t lengths[320] = {0};
|
|
||||||
|
|
||||||
literals = 257 + read_bits(5); /* 5 Bits: HLIT ... 257 */
|
|
||||||
distances = 1 + read_bits(5); /* 5 Bits: HDIST ... 1 */
|
|
||||||
clengths = 4 + read_bits(4); /* 4 Bits: HCLEN ... 4 */
|
|
||||||
|
|
||||||
/* (HCLEN + 4) x 3 bits... */
|
|
||||||
for (unsigned int i = 0; i < clengths; ++i) {
|
|
||||||
lengths[clens[i]] = read_bits(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct huff codes;
|
|
||||||
build_huffman(lengths, 19, &codes);
|
|
||||||
|
|
||||||
/* Decode symbols:
|
|
||||||
* HLIT + 257 code lengths for the literal/length alphabet...
|
|
||||||
* HDIST + 1 code lengths for the distance alphabet...
|
|
||||||
*/
|
|
||||||
unsigned int count = 0;
|
|
||||||
while (count < literals + distances) {
|
|
||||||
int symbol = decode(&codes);
|
|
||||||
int rep = 0, length;
|
|
||||||
switch (symbol) {
|
|
||||||
case 16:
|
|
||||||
/* 16: Copy the previous code length 3-6 times */
|
|
||||||
rep = lengths[count-1];
|
|
||||||
length = read_bits(2) + 3; /* The next 2 bits indicate repeat length */
|
|
||||||
break;
|
|
||||||
case 17:
|
|
||||||
/* Repeat a code length of 0 for 3 - 10 times */
|
|
||||||
length = read_bits(3) + 3; /* 3 bits of length */
|
|
||||||
break;
|
|
||||||
case 18:
|
|
||||||
/* Repeat a code length of 0 for 11 - 138 times */
|
|
||||||
length = read_bits(7) + 11; /* 7 bits of length */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
length = 1;
|
|
||||||
rep = symbol;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (length--) {
|
|
||||||
lengths[count++] = rep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build tables from lenghts decoded above */
|
|
||||||
struct huff huff_len;
|
|
||||||
build_huffman(lengths, literals, &huff_len);
|
|
||||||
struct huff huff_dist;
|
|
||||||
build_huffman(lengths + literals, distances, &huff_dist);
|
|
||||||
|
|
||||||
inflate(&huff_len, &huff_dist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode an uncompressed block.
|
|
||||||
*/
|
|
||||||
static int uncompressed(void) {
|
|
||||||
/* Reset byte alignment */
|
|
||||||
bit_buffer = 0;
|
|
||||||
buffer_size = 0;
|
|
||||||
|
|
||||||
/* "The rest of the block consists of the following information:"
|
|
||||||
* 0 1 2 3 4...
|
|
||||||
* +---+---+---+---+================================+
|
|
||||||
* | LEN | NLEN |... LEN bytes of literal data...|
|
|
||||||
* +---+---+---+---+================================+
|
|
||||||
*/
|
|
||||||
uint16_t len = read_16le(); /* "the number of data bytes in the block" */
|
|
||||||
uint16_t nlen = read_16le(); /* "the one's complement of LEN */
|
|
||||||
|
|
||||||
/* Sanity check - does the ones-complement length actually match? */
|
|
||||||
if ((nlen & 0xFFFF) != (~len & 0xFFFF)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Emit LEN bytes from the source to the output */
|
|
||||||
for (int i = 0; i < len; ++i) {
|
|
||||||
emit(read_byte());
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decompress DEFLATE-compressed data.
|
|
||||||
*/
|
|
||||||
__attribute__((optimize("O2")))
|
|
||||||
__attribute__((hot))
|
|
||||||
int deflate_decompress(void) {
|
|
||||||
bit_buffer = 0;
|
|
||||||
buffer_size = 0;
|
|
||||||
|
|
||||||
build_fixed();
|
|
||||||
|
|
||||||
/* read compressed data */
|
|
||||||
while (1) {
|
|
||||||
/* Read bit */
|
|
||||||
|
|
||||||
int is_final = read_bit();
|
|
||||||
int type = read_bits(2);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 0x00: /* BTYPE=00 Non-compressed blocks */
|
|
||||||
uncompressed();
|
|
||||||
break;
|
|
||||||
case 0x01: /* BYTPE=01 Compressed with fixed Huffman codes */
|
|
||||||
inflate(&fixed_lengths, &fixed_dists);
|
|
||||||
break;
|
|
||||||
case 0x02: /* BTYPE=02 Compression with dynamic Huffman codes */
|
|
||||||
decode_huffman();
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
__builtin_unreachable();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_final) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GZIP_FLAG_TEXT (1 << 0)
|
|
||||||
#define GZIP_FLAG_HCRC (1 << 1)
|
|
||||||
#define GZIP_FLAG_EXTR (1 << 2)
|
|
||||||
#define GZIP_FLAG_NAME (1 << 3)
|
|
||||||
#define GZIP_FLAG_COMM (1 << 4)
|
|
||||||
|
|
||||||
static unsigned int read_32le(void) {
|
|
||||||
unsigned int a, b, c, d;
|
|
||||||
a = read_byte();
|
|
||||||
b = read_byte();
|
|
||||||
c = read_byte();
|
|
||||||
d = read_byte();
|
|
||||||
|
|
||||||
return (d << 24) | (c << 16) | (b << 8) | (a << 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int gzip_decompress(void) {
|
|
||||||
|
|
||||||
/* Read gzip headers */
|
|
||||||
if (read_byte() != 0x1F) return 1;
|
|
||||||
if (read_byte() != 0x8B) return 1;
|
|
||||||
|
|
||||||
unsigned int cm = read_byte();
|
|
||||||
if (cm != 8) return 1;
|
|
||||||
|
|
||||||
unsigned int flags = read_byte();
|
|
||||||
|
|
||||||
/* Read mtime */
|
|
||||||
unsigned int mtime = read_32le();
|
|
||||||
(void)mtime;
|
|
||||||
|
|
||||||
/* Read extra flags */
|
|
||||||
unsigned int xflags = read_byte();
|
|
||||||
(void)xflags;
|
|
||||||
|
|
||||||
/* Read and discord OS flag */
|
|
||||||
unsigned int os = read_byte();
|
|
||||||
(void)os;
|
|
||||||
|
|
||||||
/* Extra bytes */
|
|
||||||
if (flags & GZIP_FLAG_EXTR) {
|
|
||||||
unsigned short size = read_16le();
|
|
||||||
for (unsigned int i = 0; i < size; ++i) read_byte();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & GZIP_FLAG_NAME) {
|
|
||||||
unsigned int c;
|
|
||||||
while ((c = read_byte()) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & GZIP_FLAG_COMM) {
|
|
||||||
unsigned int c;
|
|
||||||
while ((c = read_byte()) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int crc16 = 0;
|
|
||||||
if (flags & GZIP_FLAG_HCRC) {
|
|
||||||
crc16 = read_16le();
|
|
||||||
}
|
|
||||||
(void)crc16;
|
|
||||||
|
|
||||||
int status = deflate_decompress();
|
|
||||||
|
|
||||||
/* Read CRC and decompressed size from end of input */
|
|
||||||
unsigned int crc32 = read_32le();
|
|
||||||
unsigned int dsize = read_32le();
|
|
||||||
|
|
||||||
(void)crc32;
|
|
||||||
(void)dsize;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
static mboot_mod_t modules_mboot[sizeof(modules)/sizeof(*modules)] = {
|
static mboot_mod_t modules_mboot[1] = {
|
||||||
{0,0,0,1}
|
{0,0,0,1}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ static struct multiboot multiboot_header = {
|
|||||||
/* mem_upper; */ 0x640000,
|
/* mem_upper; */ 0x640000,
|
||||||
/* boot_device; */ 0,
|
/* boot_device; */ 0,
|
||||||
/* cmdline; */ 0,
|
/* cmdline; */ 0,
|
||||||
/* mods_count; */ sizeof(modules)/sizeof(*modules),
|
/* mods_count; */ 1,
|
||||||
/* mods_addr; */ 0,
|
/* mods_addr; */ 0,
|
||||||
/* num; */ 0,
|
/* num; */ 0,
|
||||||
/* size; */ 0,
|
/* size; */ 0,
|
||||||
@ -60,13 +60,7 @@ static int strlen(char * s) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EFI_PLATFORM
|
|
||||||
static EFI_GUID efi_graphics_output_protocol_guid =
|
|
||||||
{0x9042a9de,0x23dc,0x4a38, {0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a}};
|
|
||||||
#define KERNEL_LOAD_START 0x1600000
|
|
||||||
#else
|
|
||||||
#define KERNEL_LOAD_START 0x300000
|
#define KERNEL_LOAD_START 0x300000
|
||||||
#endif
|
|
||||||
|
|
||||||
static void move_kernel(void) {
|
static void move_kernel(void) {
|
||||||
clear();
|
clear();
|
||||||
@ -95,14 +89,6 @@ static void move_kernel(void) {
|
|||||||
print(" ");
|
print(" ");
|
||||||
print_hex(phdr->p_filesz);
|
print_hex(phdr->p_filesz);
|
||||||
print("\n");
|
print("\n");
|
||||||
#ifdef EFI_PLATFORM
|
|
||||||
EFI_PHYSICAL_ADDRESS addr = phdr->p_vaddr;
|
|
||||||
EFI_STATUS status = uefi_call_wrapper(ST->BootServices->AllocatePages, 3, AllocateAddress, EfiLoaderData, phdr->p_memsz / 4096 + 1, &addr);
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Failed to allocate memory to load kernel.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
memcpy((uint8_t*)(uintptr_t)phdr->p_vaddr, (uint8_t*)KERNEL_LOAD_START + phdr->p_offset, phdr->p_filesz);
|
memcpy((uint8_t*)(uintptr_t)phdr->p_vaddr, (uint8_t*)KERNEL_LOAD_START + phdr->p_offset, phdr->p_filesz);
|
||||||
long r = phdr->p_filesz;
|
long r = phdr->p_filesz;
|
||||||
while (r < phdr->p_memsz) {
|
while (r < phdr->p_memsz) {
|
||||||
@ -113,201 +99,6 @@ static void move_kernel(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
print("Setting up memory map...\n");
|
print("Setting up memory map...\n");
|
||||||
#ifdef EFI_PLATFORM
|
|
||||||
mboot_memmap_t * mmap = (void*)KERNEL_LOAD_START;
|
|
||||||
memset((void*)KERNEL_LOAD_START, 0x00, 1024);
|
|
||||||
multiboot_header.mmap_addr = (uint32_t)(uintptr_t)mmap;
|
|
||||||
|
|
||||||
EFI_STATUS e;
|
|
||||||
UINTN mapSize = 0, mapKey, descriptorSize;
|
|
||||||
UINT32 descriptorVersion;
|
|
||||||
e = uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, NULL);
|
|
||||||
|
|
||||||
print_("Memory map size is "); print_hex_(mapSize); print_("\n");
|
|
||||||
|
|
||||||
EFI_MEMORY_DESCRIPTOR * efi_memory = (void*)(final_offset);
|
|
||||||
final_offset += mapSize;
|
|
||||||
while ((uintptr_t)final_offset & 0x3ff) final_offset++;
|
|
||||||
|
|
||||||
e = uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, efi_memory, &mapKey, &descriptorSize, NULL);
|
|
||||||
|
|
||||||
if (EFI_ERROR(e)) {
|
|
||||||
print_("EFI error.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t upper_mem = 0;
|
|
||||||
int descriptors = mapSize / descriptorSize;
|
|
||||||
for (int i = 0; i < descriptors; ++i) {
|
|
||||||
EFI_MEMORY_DESCRIPTOR * d = efi_memory;
|
|
||||||
|
|
||||||
mmap->size = sizeof(uint64_t) * 2 + sizeof(uint32_t);
|
|
||||||
mmap->base_addr = d->PhysicalStart;
|
|
||||||
mmap->length = d->NumberOfPages * 4096;
|
|
||||||
switch (d->Type) {
|
|
||||||
case EfiConventionalMemory:
|
|
||||||
case EfiLoaderCode:
|
|
||||||
case EfiLoaderData:
|
|
||||||
case EfiBootServicesCode:
|
|
||||||
case EfiBootServicesData:
|
|
||||||
case EfiRuntimeServicesCode:
|
|
||||||
case EfiRuntimeServicesData:
|
|
||||||
case EfiACPIReclaimMemory:
|
|
||||||
mmap->type = 1;
|
|
||||||
break;
|
|
||||||
case EfiReservedMemoryType:
|
|
||||||
case EfiUnusableMemory:
|
|
||||||
case EfiMemoryMappedIO:
|
|
||||||
case EfiMemoryMappedIOPortSpace:
|
|
||||||
case EfiPalCode:
|
|
||||||
case EfiACPIMemoryNVS:
|
|
||||||
default:
|
|
||||||
mmap->type = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (mmap->type == 1 && mmap->base_addr >= 0x100000) {
|
|
||||||
upper_mem += mmap->length;
|
|
||||||
}
|
|
||||||
mmap = (mboot_memmap_t *) ((uintptr_t)mmap + mmap->size + sizeof(uint32_t));
|
|
||||||
efi_memory = (EFI_MEMORY_DESCRIPTOR *)((char *)efi_memory + descriptorSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
multiboot_header.mmap_length = (uintptr_t)mmap - multiboot_header.mmap_addr;
|
|
||||||
|
|
||||||
multiboot_header.mem_lower = 1024;
|
|
||||||
multiboot_header.mem_upper = upper_mem / 1024;
|
|
||||||
|
|
||||||
/* Set up framebuffer */
|
|
||||||
if (_efi_do_mode_set) {
|
|
||||||
UINTN count;
|
|
||||||
EFI_HANDLE * handles;
|
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL * gfx;
|
|
||||||
EFI_STATUS status;
|
|
||||||
|
|
||||||
status = uefi_call_wrapper(ST->BootServices->LocateHandleBuffer,
|
|
||||||
5, ByProtocol, &efi_graphics_output_protocol_guid, NULL, &count, &handles);
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Error getting graphics device handle.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
|
|
||||||
3, handles[0], &efi_graphics_output_protocol_guid, (void **)&gfx);
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Error getting graphics device.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
print_("Attempting to set a sane mode (32bit color, etc.)\n");
|
|
||||||
print_("There are 0x"); print_hex_(gfx->Mode->MaxMode); print_(" modes available.\n");
|
|
||||||
print_("This is mode 0x"); print_hex_(gfx->Mode->Mode); print_(".\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int biggest = gfx->Mode->Mode;
|
|
||||||
int big_width = 0;
|
|
||||||
int big_height = 0;
|
|
||||||
|
|
||||||
clear_();
|
|
||||||
|
|
||||||
for (int i = 0; i < gfx->Mode->MaxMode; ++i) {
|
|
||||||
EFI_STATUS status;
|
|
||||||
UINTN size;
|
|
||||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * info;
|
|
||||||
|
|
||||||
status = uefi_call_wrapper(gfx->QueryMode,
|
|
||||||
4, gfx, i, &size, &info);
|
|
||||||
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Error getting gfx mode 0x"); print_hex_(i); print_("\n");
|
|
||||||
} else {
|
|
||||||
print_("Mode "); print_int_(i); print_(" "); print_int_(info->HorizontalResolution);
|
|
||||||
print_("x"); print_int_(info->VerticalResolution); print_(" ");
|
|
||||||
print_int_(info->PixelFormat); print_("\n");
|
|
||||||
if (_efi_do_mode_set == 1) {
|
|
||||||
if (info->PixelFormat == 1 && info->HorizontalResolution >= big_width) {
|
|
||||||
biggest = i;
|
|
||||||
big_width = info->HorizontalResolution;
|
|
||||||
}
|
|
||||||
} else if (_efi_do_mode_set == 2) {
|
|
||||||
if (info->PixelFormat == 1 && info->HorizontalResolution == 1024 &&
|
|
||||||
info->VerticalResolution == 768) {
|
|
||||||
biggest = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (_efi_do_mode_set == 3) {
|
|
||||||
if (info->PixelFormat == 1 && info->HorizontalResolution == 1920 &&
|
|
||||||
info->VerticalResolution == 1080) {
|
|
||||||
biggest = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (_efi_do_mode_set == 4) {
|
|
||||||
while (1) {
|
|
||||||
print_("y/n? ");
|
|
||||||
int resp = read_scancode();
|
|
||||||
if (resp == 'y') {
|
|
||||||
print_("y\n");
|
|
||||||
biggest = i;
|
|
||||||
goto done_video;
|
|
||||||
} else if (resp == 'n') {
|
|
||||||
print_("n\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
print_("?\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
done_video:
|
|
||||||
print_("Selected video mode was "); print_int_(biggest); print_("\n");
|
|
||||||
uefi_call_wrapper(gfx->SetMode, 2, gfx, biggest);
|
|
||||||
|
|
||||||
uint32_t high = gfx->Mode->FrameBufferBase >> 32;
|
|
||||||
uint32_t low = gfx->Mode->FrameBufferBase & 0xFFFFFFFF;
|
|
||||||
|
|
||||||
print_("Framebuffer address is 0x"); print_hex_(high); print_hex_(low); print_("\n");
|
|
||||||
|
|
||||||
if (high) {
|
|
||||||
clear_();
|
|
||||||
print_("Framebuffer is outside of 32-bit memory range.\n");
|
|
||||||
print_("EFI mode setting is not available - and graphics may not work in general.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
multiboot_header.flags |= (1 << 12); /* Enable framebuffer flag */
|
|
||||||
multiboot_header.framebuffer_addr = low;
|
|
||||||
multiboot_header.framebuffer_width = gfx->Mode->Info->HorizontalResolution;
|
|
||||||
multiboot_header.framebuffer_height = gfx->Mode->Info->VerticalResolution;
|
|
||||||
multiboot_header.framebuffer_pitch = gfx->Mode->Info->PixelsPerScanLine * 4;
|
|
||||||
|
|
||||||
print_("Mode information passed to multiboot:\n");
|
|
||||||
print_(" Address: 0x"); print_hex_(multiboot_header.framebuffer_addr); print_("\n");
|
|
||||||
print_(" Width: "); print_int_(multiboot_header.framebuffer_width); print_("\n");
|
|
||||||
print_(" Height: "); print_int_(multiboot_header.framebuffer_height); print_("\n");
|
|
||||||
print_("\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(final_offset, cmdline, strlen(cmdline)+1);
|
|
||||||
multiboot_header.cmdline = (uintptr_t)final_offset;
|
|
||||||
final_offset += strlen(cmdline)+1;
|
|
||||||
memcpy(final_offset, VERSION_TEXT, strlen(VERSION_TEXT)+1);
|
|
||||||
multiboot_header.boot_loader_name = (uintptr_t)final_offset;
|
|
||||||
final_offset += strlen(VERSION_TEXT)+1;
|
|
||||||
while ((uintptr_t)final_offset & 0x3ff) final_offset++;
|
|
||||||
|
|
||||||
multiboot_header.mods_addr = (uintptr_t)final_offset;
|
|
||||||
memcpy(final_offset, &modules_mboot, sizeof(modules_mboot));
|
|
||||||
final_offset += sizeof(modules_mboot);
|
|
||||||
while ((uintptr_t)final_offset & 0x3ff) final_offset++;
|
|
||||||
|
|
||||||
memcpy(final_offset, &multiboot_header, sizeof(multiboot_header));
|
|
||||||
_ebx = (uintptr_t)final_offset;
|
|
||||||
|
|
||||||
|
|
||||||
print("Jumping to main, good luck.\n");
|
|
||||||
#else
|
|
||||||
print_hex(mmap_ent);
|
print_hex(mmap_ent);
|
||||||
print("\n");
|
print("\n");
|
||||||
memset((void*)KERNEL_LOAD_START, 0x00, 1024);
|
memset((void*)KERNEL_LOAD_START, 0x00, 1024);
|
||||||
@ -346,53 +137,11 @@ done_video:
|
|||||||
multiboot_header.mem_upper = upper_mem / 1024;
|
multiboot_header.mem_upper = upper_mem / 1024;
|
||||||
|
|
||||||
_ebx = (unsigned int)&multiboot_header;
|
_ebx = (unsigned int)&multiboot_header;
|
||||||
#endif
|
|
||||||
|
|
||||||
_eax = MULTIBOOT_EAX_MAGIC;
|
_eax = MULTIBOOT_EAX_MAGIC;
|
||||||
_xmain = entry;
|
_xmain = entry;
|
||||||
|
|
||||||
#ifdef EFI_PLATFORM
|
print_("Jumping...\n");
|
||||||
//print_("\nExiting boot services and jumping to ");
|
|
||||||
//print_hex_(_xmain);
|
|
||||||
//print_(" with mboot_mag=");
|
|
||||||
//print_hex_(_eax);
|
|
||||||
//print_(" and mboot_ptr=");
|
|
||||||
//print_hex_(_ebx);
|
|
||||||
//print_("...\n");
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
//print_("&_xmain = "); print_hex_(((uintptr_t)&_xmain) >> 32); print_hex_((uint32_t)(uintptr_t)&_xmain); print_("\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (1) {
|
|
||||||
EFI_STATUS e;
|
|
||||||
UINTN mapSize = 0, mapKey, descriptorSize;
|
|
||||||
UINT32 descriptorVersion;
|
|
||||||
uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, NULL);
|
|
||||||
e = uefi_call_wrapper(ST->BootServices->ExitBootServices, 2, ImageHandleIn, mapKey);
|
|
||||||
|
|
||||||
if (e != EFI_SUCCESS) {
|
|
||||||
print_("Exit services failed. \n");
|
|
||||||
print_hex_(e);
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
uint64_t foobar = ((uint32_t)(uintptr_t)&do_the_nasty) | (0x10L << 32L);
|
|
||||||
|
|
||||||
uint32_t * foo = (uint32_t *)0x7c00;
|
|
||||||
|
|
||||||
foo[0] = _eax;
|
|
||||||
foo[1] = _ebx;
|
|
||||||
foo[2] = _xmain;
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"push %0\n"
|
|
||||||
"retf\n"
|
|
||||||
: : "g"(foobar));
|
|
||||||
#else
|
|
||||||
uint32_t foo[3];
|
uint32_t foo[3];
|
||||||
foo[0] = _eax;
|
foo[0] = _eax;
|
||||||
foo[1] = _ebx;
|
foo[1] = _ebx;
|
||||||
@ -410,49 +159,8 @@ done_video:
|
|||||||
"mov %2,%%ebx \n"
|
"mov %2,%%ebx \n"
|
||||||
"jmp *%0" : : "g"(foo[2]), "g"(foo[0]), "g"(foo[1]) : "eax", "ebx"
|
"jmp *%0" : : "g"(foo[2]), "g"(foo[0]), "g"(foo[1]) : "eax", "ebx"
|
||||||
);
|
);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
__asm__ (
|
|
||||||
"do_the_nasty:\n"
|
|
||||||
"cli\n"
|
|
||||||
//"mov 0x08, %ax\n"
|
|
||||||
//"mov %ax, %ds\n"
|
|
||||||
//"mov %ax, %es\n"
|
|
||||||
//"mov %ax, %fs\n"
|
|
||||||
//"mov %ax, %gs\n"
|
|
||||||
//"mov %ax, %ss\n"
|
|
||||||
".code32\n"
|
|
||||||
"mov %cr0, %eax\n"
|
|
||||||
"and $0x7FFeFFFF, %eax\n"
|
|
||||||
"mov %eax, %cr0\n"
|
|
||||||
// Paging is disabled
|
|
||||||
"mov $0xc0000080, %ecx\n"
|
|
||||||
"rdmsr\n"
|
|
||||||
"and $0xfffffeff, %eax\n"
|
|
||||||
"wrmsr\n"
|
|
||||||
"mov $0x640, %eax\n"
|
|
||||||
"mov %eax, %cr4\n"
|
|
||||||
"mov 0x7c00, %eax\n"
|
|
||||||
"mov 0x7c04, %ebx\n"
|
|
||||||
"mov 0x7c08, %ecx\n"
|
|
||||||
"jmp *%ecx\n"
|
|
||||||
"target: jmp target\n"
|
|
||||||
".code64\n"
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__attribute__((always_inline))
|
|
||||||
static inline uint8_t read_byte(void) {
|
|
||||||
return *inputPtr++;
|
|
||||||
}
|
|
||||||
__attribute__((always_inline))
|
|
||||||
static inline void _write(unsigned int sym) {
|
|
||||||
*outputPtr++ = sym;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef EFI_PLATFORM
|
|
||||||
static void do_it(struct ata_device * _device) {
|
static void do_it(struct ata_device * _device) {
|
||||||
device = _device;
|
device = _device;
|
||||||
if (device->atapi_sector_size != 2048) {
|
if (device->atapi_sector_size != 2048) {
|
||||||
@ -482,89 +190,45 @@ done:
|
|||||||
print_hex(dir_entry->extent_length_LSB); print("\n");
|
print_hex(dir_entry->extent_length_LSB); print("\n");
|
||||||
long offset = 0;
|
long offset = 0;
|
||||||
for (int i = dir_entry->extent_start_LSB; i < dir_entry->extent_start_LSB + dir_entry->extent_length_LSB / 2048 + 1; ++i, offset += 2048) {
|
for (int i = dir_entry->extent_start_LSB; i < dir_entry->extent_start_LSB + dir_entry->extent_length_LSB / 2048 + 1; ++i, offset += 2048) {
|
||||||
|
|
||||||
ata_device_read_sector_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset);
|
ata_device_read_sector_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset);
|
||||||
}
|
}
|
||||||
while (offset % 4096) offset++;
|
while (offset % 4096) offset++;
|
||||||
restore_root();
|
restore_root();
|
||||||
if (navigate(module_dir)) {
|
|
||||||
memcpy(mod_dir, dir_entry, sizeof(iso_9660_directory_entry_t));
|
|
||||||
print("Scanning modules...\n");
|
|
||||||
char ** c = modules;
|
|
||||||
int j = 0;
|
|
||||||
while (*c) {
|
|
||||||
print("load "); print(*c); print("\n");
|
|
||||||
if (!navigate(*c)) {
|
|
||||||
print("Failed to locate module! [");
|
|
||||||
print(*c);
|
|
||||||
multiboot_header.mods_count--;
|
|
||||||
print("]\n");
|
|
||||||
} else {
|
|
||||||
modules_mboot[j].mod_start = KERNEL_LOAD_START + offset;
|
|
||||||
modules_mboot[j].mod_end = KERNEL_LOAD_START + offset + dir_entry->extent_length_LSB;
|
|
||||||
for (int i = dir_entry->extent_start_LSB; i < dir_entry->extent_start_LSB + dir_entry->extent_length_LSB / 2048 + 1; ++i, offset += 2048) {
|
|
||||||
ata_device_read_sector_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset);
|
|
||||||
}
|
|
||||||
while (offset % 4096) offset++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
c++;
|
|
||||||
restore_mod();
|
|
||||||
}
|
|
||||||
print("Done.\n");
|
|
||||||
restore_root();
|
|
||||||
if (navigate(ramdisk_path)) {
|
|
||||||
//clear_();
|
|
||||||
ramdisk_off = KERNEL_LOAD_START + offset;
|
|
||||||
|
|
||||||
print_("Loading ramdisk");
|
print_("Loading ramdisk");
|
||||||
|
if (navigate(ramdisk_path)) {
|
||||||
|
ramdisk_off = KERNEL_LOAD_START + offset;
|
||||||
|
ramdisk_len = dir_entry->extent_length_LSB;
|
||||||
|
modules_mboot[0].mod_start = ramdisk_off;
|
||||||
|
modules_mboot[0].mod_end = ramdisk_off + ramdisk_len;
|
||||||
int i = dir_entry->extent_start_LSB;
|
int i = dir_entry->extent_start_LSB;
|
||||||
int sectors = dir_entry->extent_length_LSB / 2048 + 1;
|
int sectors = dir_entry->extent_length_LSB / 2048 + 1;
|
||||||
size_t off = 0;
|
|
||||||
#define RAMDISK_OFFSET 0x5000000
|
|
||||||
#define SECTORS 512
|
#define SECTORS 512
|
||||||
while (sectors >= SECTORS) {
|
while (sectors >= SECTORS) {
|
||||||
print_(".");
|
print_(".");
|
||||||
ata_device_read_sectors_atapi(device, i, (uint8_t *)RAMDISK_OFFSET + off, SECTORS);
|
ata_device_read_sectors_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset, SECTORS);
|
||||||
|
|
||||||
sectors -= SECTORS;
|
sectors -= SECTORS;
|
||||||
off += 2048 * SECTORS;
|
offset += 2048 * SECTORS;
|
||||||
i += SECTORS;
|
i += SECTORS;
|
||||||
}
|
}
|
||||||
if (sectors > 0) {
|
if (sectors > 0) {
|
||||||
print_("!");
|
print_("!");
|
||||||
ata_device_read_sectors_atapi(device, i, (uint8_t *)RAMDISK_OFFSET + off, sectors);
|
ata_device_read_sectors_atapi(device, i, (uint8_t *)KERNEL_LOAD_START + offset, sectors);
|
||||||
off += 2048 * sectors;
|
offset += 2048 * sectors;
|
||||||
}
|
}
|
||||||
|
print_("\n");
|
||||||
inputPtr = (uint8_t*)RAMDISK_OFFSET;
|
final_offset = (uint8_t *)KERNEL_LOAD_START + offset;
|
||||||
outputPtr = (uint8_t*)ramdisk_off;
|
|
||||||
print_("\nDecompressing ramdisk... ");
|
|
||||||
if (gzip_decompress()) {
|
|
||||||
print_("Failed?\n");
|
|
||||||
}
|
|
||||||
ramdisk_len = (uint32_t)outputPtr - ramdisk_off;
|
|
||||||
|
|
||||||
modules_mboot[multiboot_header.mods_count-1].mod_start = ramdisk_off;
|
|
||||||
modules_mboot[multiboot_header.mods_count-1].mod_end = ramdisk_off + ramdisk_len;
|
|
||||||
|
|
||||||
final_offset = (outputPtr) + ((uintptr_t)outputPtr) % 4096;
|
|
||||||
|
|
||||||
set_attr(0x07);
|
set_attr(0x07);
|
||||||
print("Done.\n");
|
|
||||||
move_kernel();
|
move_kernel();
|
||||||
|
} else {
|
||||||
|
print_("... failed to locate ramdisk.\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print("No mod directory?\n");
|
print("... failed to locate kernel.\n");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print("boo\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
struct fw_cfg_file {
|
struct fw_cfg_file {
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
@ -602,11 +266,6 @@ void show_menu(void) {
|
|||||||
bytes[i] = inportb(0x511);
|
bytes[i] = inportb(0x511);
|
||||||
}
|
}
|
||||||
swap_bytes(&count, 4);
|
swap_bytes(&count, 4);
|
||||||
#if 0
|
|
||||||
print_("there are ");
|
|
||||||
print_hex_(count);
|
|
||||||
print_(" entries\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned int bootmode_size = 0;
|
unsigned int bootmode_size = 0;
|
||||||
int bootmode_index = -1;
|
int bootmode_index = -1;
|
||||||
@ -622,10 +281,6 @@ void show_menu(void) {
|
|||||||
bootmode_size = file.size;
|
bootmode_size = file.size;
|
||||||
bootmode_index = file.select;
|
bootmode_index = file.select;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
print_("selector "); print_hex_(file.select); print_(" is "); print_hex_(file.size); print_(" bytes\n");
|
|
||||||
print_("and its name is: "); print_(file.name); print_("\n");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bootmode_index != -1) {
|
if (bootmode_index != -1) {
|
||||||
@ -647,7 +302,6 @@ void show_menu(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Determine number of options */
|
/* Determine number of options */
|
||||||
sel_max = 0;
|
sel_max = 0;
|
||||||
while (boot_options[sel_max].value) {
|
while (boot_options[sel_max].value) {
|
||||||
@ -655,7 +309,6 @@ void show_menu(void) {
|
|||||||
}
|
}
|
||||||
sel_max += BASE_SEL + 1;
|
sel_max += BASE_SEL + 1;
|
||||||
|
|
||||||
#ifndef EFI_PLATFORM
|
|
||||||
outportb(0x3D4, 14);
|
outportb(0x3D4, 14);
|
||||||
outportb(0x3D5, 0xFF);
|
outportb(0x3D5, 0xFF);
|
||||||
outportb(0x3D4, 15);
|
outportb(0x3D4, 15);
|
||||||
@ -666,7 +319,6 @@ void show_menu(void) {
|
|||||||
char b = inportb(0x3C1);
|
char b = inportb(0x3C1);
|
||||||
b &= ~8;
|
b &= ~8;
|
||||||
outportb(0x3c0, b);
|
outportb(0x3c0, b);
|
||||||
#endif
|
|
||||||
|
|
||||||
clear_();
|
clear_();
|
||||||
|
|
||||||
@ -753,232 +405,10 @@ void show_menu(void) {
|
|||||||
boot_mode = boot_mode_names[i].index;
|
boot_mode = boot_mode_names[i].index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
} else {
|
|
||||||
print_hex_(s);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EFI_PLATFORM
|
|
||||||
/* EFI boot uses simple filesystem driver */
|
|
||||||
static EFI_GUID efi_simple_file_system_protocol_guid =
|
|
||||||
{0x0964e5b22,0x6459,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b};
|
|
||||||
|
|
||||||
static EFI_GUID efi_loaded_image_protocol_guid =
|
|
||||||
{0x5B1B31A1,0x9562,0x11d2, {0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B}};
|
|
||||||
|
|
||||||
static char space[4096];
|
|
||||||
static void boot(void) {
|
|
||||||
UINTN count;
|
|
||||||
EFI_HANDLE * handles;
|
|
||||||
EFI_LOADED_IMAGE * loaded_image;
|
|
||||||
EFI_FILE_IO_INTERFACE *efi_simple_filesystem;
|
|
||||||
EFI_FILE *root;
|
|
||||||
EFI_STATUS status;
|
|
||||||
|
|
||||||
uefi_call_wrapper(ST->BootServices->SetWatchdogTimer, 4, 0, 0, 0, NULL);
|
|
||||||
|
|
||||||
clear_();
|
|
||||||
|
|
||||||
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
|
|
||||||
3, ImageHandleIn, &efi_loaded_image_protocol_guid,
|
|
||||||
(void **)&loaded_image);
|
|
||||||
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Could not obtain loaded_image_protocol\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
print("Found loaded image...\n");
|
|
||||||
|
|
||||||
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
|
|
||||||
3, loaded_image->DeviceHandle, &efi_simple_file_system_protocol_guid,
|
|
||||||
(void **)&efi_simple_filesystem);
|
|
||||||
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Could not obtain simple_file_system_protocol.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
status = uefi_call_wrapper(efi_simple_filesystem->OpenVolume,
|
|
||||||
2, efi_simple_filesystem, &root);
|
|
||||||
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Could not open volume.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
EFI_FILE * file;
|
|
||||||
|
|
||||||
CHAR16 kernel_name[16] = {0};
|
|
||||||
{
|
|
||||||
char * c = kernel_path;
|
|
||||||
char * ascii = c;
|
|
||||||
int i = 0;
|
|
||||||
while (*ascii) {
|
|
||||||
kernel_name[i] = *ascii;
|
|
||||||
i++;
|
|
||||||
ascii++;
|
|
||||||
}
|
|
||||||
if (kernel_name[i-1] == L'.') {
|
|
||||||
kernel_name[i-1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load kernel */
|
|
||||||
status = uefi_call_wrapper(root->Open,
|
|
||||||
5, root, &file, kernel_name, EFI_FILE_MODE_READ, 0);
|
|
||||||
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Error opening kernel.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
EFI_PHYSICAL_ADDRESS addr = KERNEL_LOAD_START;
|
|
||||||
EFI_ALLOCATE_TYPE type = AllocateAddress;
|
|
||||||
EFI_MEMORY_TYPE memtype = EfiLoaderData;
|
|
||||||
UINTN pages = 8192;
|
|
||||||
EFI_STATUS status = 0;
|
|
||||||
status = uefi_call_wrapper(ST->BootServices->AllocatePages, 4, type, memtype, pages, &addr);
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Could not allocate space to load boot payloads: ");
|
|
||||||
print_hex_(status);
|
|
||||||
print_(" ");
|
|
||||||
print_hex_(addr);
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int offset = 0;
|
|
||||||
UINTN bytes = 134217728;
|
|
||||||
status = uefi_call_wrapper(file->Read,
|
|
||||||
3, file, &bytes, (void *)KERNEL_LOAD_START);
|
|
||||||
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Error loading kernel.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
print("Read "); print_hex(bytes); print(" bytes\n");
|
|
||||||
|
|
||||||
offset += bytes;
|
|
||||||
while (offset % 4096) offset++;
|
|
||||||
|
|
||||||
print("Reading modules...\n");
|
|
||||||
|
|
||||||
char ** c = modules;
|
|
||||||
int j = 0;
|
|
||||||
while (*c) {
|
|
||||||
if (strcmp(*c, "NONE")) {
|
|
||||||
/* Try to load module */
|
|
||||||
CHAR16 name[16] = {0};
|
|
||||||
name[0] = L'm';
|
|
||||||
name[1] = L'o';
|
|
||||||
name[2] = L'd';
|
|
||||||
name[3] = L'\\';
|
|
||||||
char * ascii = *c;
|
|
||||||
int i = 0;
|
|
||||||
while (*ascii) {
|
|
||||||
name[i+4] = (*ascii >= 'A' && *ascii <= 'Z') ? (*ascii - 'A' + 'a') : *ascii;
|
|
||||||
name[i+5] = 0;
|
|
||||||
i++;
|
|
||||||
ascii++;
|
|
||||||
}
|
|
||||||
for (int i = 0; name[i]; ++i) {
|
|
||||||
char c[] = {name[i], 0};
|
|
||||||
print(c);
|
|
||||||
}
|
|
||||||
print("\n");
|
|
||||||
bytes = 2097152;
|
|
||||||
_try_module_again:
|
|
||||||
status = uefi_call_wrapper(root->Open,
|
|
||||||
5, root, &file, name, EFI_FILE_MODE_READ, 0);
|
|
||||||
if (!EFI_ERROR(status)) {
|
|
||||||
status = uefi_call_wrapper(file->Read,
|
|
||||||
3, file, &bytes, (void *)(KERNEL_LOAD_START + (uintptr_t)offset));
|
|
||||||
if (!EFI_ERROR(status)) {
|
|
||||||
print("Loaded "); print(*c); print("\n");
|
|
||||||
modules_mboot[j].mod_start = KERNEL_LOAD_START + offset;
|
|
||||||
modules_mboot[j].mod_end = KERNEL_LOAD_START + offset + bytes;
|
|
||||||
j++;
|
|
||||||
offset += bytes;
|
|
||||||
while (offset % 4096) offset++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print_("Error opening "); print_(*c); print_(" "); print_hex_(status); print_("\n");
|
|
||||||
while (1) { };
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
multiboot_header.mods_count--;
|
|
||||||
}
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_("Loading ramdisk...\n");
|
|
||||||
{
|
|
||||||
char * c = ramdisk_path;
|
|
||||||
CHAR16 name[16] = {0};
|
|
||||||
char * ascii = c;
|
|
||||||
int i = 0;
|
|
||||||
while (*ascii) {
|
|
||||||
name[i] = *ascii;
|
|
||||||
i++;
|
|
||||||
ascii++;
|
|
||||||
}
|
|
||||||
if (name[i-1] == L'.') {
|
|
||||||
name[i-1] == 0;
|
|
||||||
}
|
|
||||||
bytes = 134217728;
|
|
||||||
status = uefi_call_wrapper(root->Open,
|
|
||||||
5, root, &file, name, EFI_FILE_MODE_READ, 0);
|
|
||||||
if (!EFI_ERROR(status)) {
|
|
||||||
uintptr_t RAMDISK_OFFSET;
|
|
||||||
{
|
|
||||||
EFI_PHYSICAL_ADDRESS addr;
|
|
||||||
EFI_STATUS status = uefi_call_wrapper(ST->BootServices->AllocatePages, 4, AllocateAnyPages, EfiLoaderData, 4096, &addr);
|
|
||||||
if (EFI_ERROR(status)) {
|
|
||||||
print_("Failed to allocate space for ramdisk.\n");
|
|
||||||
while (1) {};
|
|
||||||
}
|
|
||||||
print_("Placing ramdisk at ");
|
|
||||||
print_hex_(addr >> 32);
|
|
||||||
print_hex_(addr & 0xFFFFFFFF);
|
|
||||||
print_("\n");
|
|
||||||
RAMDISK_OFFSET = addr;
|
|
||||||
}
|
|
||||||
status = uefi_call_wrapper(file->Read,
|
|
||||||
3, file, &bytes, (void*)RAMDISK_OFFSET);
|
|
||||||
if (!EFI_ERROR(status)) {
|
|
||||||
print_("Read "); print_hex_(bytes); print_(" bytes.\n");
|
|
||||||
inputPtr = (uint8_t*)RAMDISK_OFFSET;
|
|
||||||
outputPtr = (uint8_t*)KERNEL_LOAD_START + offset;
|
|
||||||
print_("Decompressing ramdisk... ");
|
|
||||||
if (gzip_decompress()) {
|
|
||||||
print_("Failed?\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
print_("Loaded "); print_(c); print_("\n");
|
|
||||||
modules_mboot[multiboot_header.mods_count-1].mod_start = KERNEL_LOAD_START + offset;
|
|
||||||
modules_mboot[multiboot_header.mods_count-1].mod_end = (uintptr_t)outputPtr;
|
|
||||||
final_offset = (uint8_t *)outputPtr;
|
|
||||||
while ((uintptr_t)final_offset & 0xfff) final_offset++;
|
|
||||||
} else {
|
|
||||||
print_("Failed to read ramdisk\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print_("Error opening "); print_(c); print_("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
move_kernel();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
/* BIOS boot uses native ATAPI drivers, need to find boot drive. */
|
/* BIOS boot uses native ATAPI drivers, need to find boot drive. */
|
||||||
static void boot(void) {
|
static void boot(void) {
|
||||||
|
|
||||||
@ -1009,4 +439,3 @@ static void boot(void) {
|
|||||||
|
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#define MULTIBOOT_FLAG_LOADER 0x200
|
#define MULTIBOOT_FLAG_LOADER 0x200
|
||||||
#define MULTIBOOT_FLAG_APM 0x400
|
#define MULTIBOOT_FLAG_APM 0x400
|
||||||
#define MULTIBOOT_FLAG_VBE 0x800
|
#define MULTIBOOT_FLAG_VBE 0x800
|
||||||
|
#define MULTIBOOT_FLAG_FB 0x1000
|
||||||
|
|
||||||
struct multiboot
|
struct multiboot
|
||||||
{
|
{
|
||||||
@ -37,17 +38,16 @@ struct multiboot
|
|||||||
uint32_t apm_table;
|
uint32_t apm_table;
|
||||||
uint32_t vbe_control_info;
|
uint32_t vbe_control_info;
|
||||||
uint32_t vbe_mode_info;
|
uint32_t vbe_mode_info;
|
||||||
uint32_t vbe_mode;
|
uint16_t vbe_mode;
|
||||||
uint32_t vbe_interface_seg;
|
uint16_t vbe_interface_seg;
|
||||||
uint32_t vbe_interface_off;
|
uint16_t vbe_interface_off;
|
||||||
uint32_t vbe_interface_len;
|
uint16_t vbe_interface_len;
|
||||||
uint32_t framebuffer_addr;
|
uint64_t framebuffer_addr;
|
||||||
uint32_t framebuffer_pitch;
|
uint32_t framebuffer_pitch;
|
||||||
uint32_t framebuffer_width;
|
uint32_t framebuffer_width;
|
||||||
uint32_t framebuffer_height;
|
uint32_t framebuffer_height;
|
||||||
uint8_t framebuffer_bpp;
|
uint8_t framebuffer_bpp;
|
||||||
uint8_t framebuffer_type;
|
uint8_t framebuffer_type;
|
||||||
/* Palette stuff goes here but we don't use it */
|
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
54
util/mkdisk.sh
Executable file
54
util/mkdisk.sh
Executable file
@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
OUT=$1
|
||||||
|
IN=$2
|
||||||
|
|
||||||
|
OUTDIR=`dirname $1`
|
||||||
|
|
||||||
|
# Calculate required space
|
||||||
|
SPACE_REQ=$(du -sb "$DIR/../fatbase" | cut -f 1)
|
||||||
|
let "SIZE = ($SPACE_REQ / 1000000)"
|
||||||
|
|
||||||
|
# Minimum size
|
||||||
|
if [ $SIZE -lt 14 ]; then
|
||||||
|
SIZE=14
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use more sectors-per-cluster for larger disk sizes
|
||||||
|
if [ $SIZE -gt 128 ]; then
|
||||||
|
SPC=4
|
||||||
|
else
|
||||||
|
SPC=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create empty FAT image
|
||||||
|
rm -f $OUT
|
||||||
|
mkdir -p cdrom
|
||||||
|
fallocate -l ${SIZE}M $OUT || dd if=/dev/zero bs=1M count=${SIZE} of=$OUT
|
||||||
|
mkfs.fat -s $SPC -S 2048 $OUT
|
||||||
|
|
||||||
|
#echo "Turning $IN into $OUT"
|
||||||
|
|
||||||
|
# Add files
|
||||||
|
for i in $(find $IN)
|
||||||
|
do
|
||||||
|
if [[ $i == $IN ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
OUT_FILE=`echo $i | sed s"/^$IN/$OUTDIR/"`
|
||||||
|
IN_FILE=`echo $i | sed s"/^$IN//"`
|
||||||
|
#echo $IN_FILE $OUT_FILE
|
||||||
|
if [ -d "$i" ]; then
|
||||||
|
mmd -i $OUT $IN_FILE
|
||||||
|
mkdir -p $OUT_FILE
|
||||||
|
else
|
||||||
|
mcopy -i $OUT $i '::'$IN_FILE
|
||||||
|
touch $OUT_FILE
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -f cdrom/efi/boot/bootia32.efi # Otherwise virtualbox may erroneously try to load from this
|
||||||
|
rm -f cdrom/efi/boot/bootx64.efi # Same
|
||||||
|
|
303
util/update-extents.py
Executable file
303
util/update-extents.py
Executable file
@ -0,0 +1,303 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import array
|
||||||
|
import struct
|
||||||
|
|
||||||
|
def read_struct(fmt,buf,offset):
|
||||||
|
out, = struct.unpack_from(fmt,buf,offset)
|
||||||
|
return out, offset + struct.calcsize(fmt)
|
||||||
|
|
||||||
|
class ISO(object):
|
||||||
|
|
||||||
|
def __init__(self, path):
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
tmp = f.read()
|
||||||
|
self.data = array.array('b', tmp)
|
||||||
|
self.sector_size = 2048
|
||||||
|
o = 0x10 * self.sector_size
|
||||||
|
self.type, o = read_struct('B',self.data,o)
|
||||||
|
self.id, o = read_struct('5s',self.data,o)
|
||||||
|
self.version, o = read_struct('B',self.data,o)
|
||||||
|
_unused0, o = read_struct('B',self.data,o)
|
||||||
|
self.system_id, o = read_struct('32s',self.data,o)
|
||||||
|
self.volume_id, o = read_struct('32s',self.data,o)
|
||||||
|
_unused1, o = read_struct('8s',self.data,o)
|
||||||
|
self.volume_space_lsb, o = read_struct('<I',self.data,o)
|
||||||
|
self.volume_space_msb, o = read_struct('>I',self.data,o)
|
||||||
|
_unused2, o = read_struct('32s',self.data,o)
|
||||||
|
self.volume_set_lsb, o = read_struct('<H',self.data,o)
|
||||||
|
self.volume_set_msb, o = read_struct('>H',self.data,o)
|
||||||
|
self.volume_seq_lsb, o = read_struct('<H',self.data,o)
|
||||||
|
self.volume_seq_msb, o = read_struct('>H',self.data,o)
|
||||||
|
self.logical_block_size_lsb, o = read_struct('<H',self.data,o)
|
||||||
|
self.logical_block_size_msb, o = read_struct('>H',self.data,o)
|
||||||
|
self.path_table_size_lsb, o = read_struct('<I',self.data,o)
|
||||||
|
self.path_table_size_msb, o = read_struct('>I',self.data,o)
|
||||||
|
self.path_table_lsb, o = read_struct('<I',self.data,o)
|
||||||
|
self.optional_path_table_lsb, o = read_struct('<I',self.data,o)
|
||||||
|
self.path_table_msb, o = read_struct('>I',self.data,o)
|
||||||
|
self.optional_path_table_msb, o = read_struct('>I',self.data,o)
|
||||||
|
_offset = o
|
||||||
|
self.root_dir_entry, o = read_struct('34s',self.data,o)
|
||||||
|
|
||||||
|
self.root = ISOFile(self,_offset)
|
||||||
|
self._cache = {}
|
||||||
|
|
||||||
|
def get_file(self, path):
|
||||||
|
if path == '/':
|
||||||
|
return self.root
|
||||||
|
else:
|
||||||
|
if path in self._cache:
|
||||||
|
return self._cache[path]
|
||||||
|
units = path.split('/')
|
||||||
|
units = units[1:] # remove root
|
||||||
|
me = self.root
|
||||||
|
for i in units:
|
||||||
|
next_file = me.find(i)
|
||||||
|
if not next_file:
|
||||||
|
me = None
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
me = next_file
|
||||||
|
self._cache[path] = me
|
||||||
|
return me
|
||||||
|
|
||||||
|
class ISOFile(object):
|
||||||
|
|
||||||
|
def __init__(self, iso, offset):
|
||||||
|
self.iso = iso
|
||||||
|
self.offset = offset
|
||||||
|
|
||||||
|
o = offset
|
||||||
|
self.length, o = read_struct('B', self.iso.data, o)
|
||||||
|
if not self.length:
|
||||||
|
return
|
||||||
|
self.ext_length, o = read_struct('B', self.iso.data, o)
|
||||||
|
self.extent_start_lsb, o = read_struct('<I',self.iso.data, o)
|
||||||
|
self.extent_start_msb, o = read_struct('>I',self.iso.data, o)
|
||||||
|
self.extent_length_lsb, o = read_struct('<I',self.iso.data, o)
|
||||||
|
self.extent_length_msb, o = read_struct('>I',self.iso.data, o)
|
||||||
|
|
||||||
|
self.date_data, o = read_struct('7s', self.iso.data, o)
|
||||||
|
|
||||||
|
self.flags, o = read_struct('b', self.iso.data, o)
|
||||||
|
self.interleave_units, o = read_struct('b', self.iso.data, o)
|
||||||
|
self.interleave_gap, o = read_struct('b', self.iso.data, o)
|
||||||
|
|
||||||
|
self.volume_seq_lsb, o = read_struct('<H',self.iso.data, o)
|
||||||
|
self.volume_seq_msb, o = read_struct('>H',self.iso.data, o)
|
||||||
|
|
||||||
|
self.name_len, o = read_struct('b', self.iso.data, o)
|
||||||
|
self.name, o = read_struct('{}s'.format(self.name_len), self.iso.data, o)
|
||||||
|
self.name = self.name.decode('ascii')
|
||||||
|
|
||||||
|
def write_extents(self):
|
||||||
|
struct.pack_into('<I', self.iso.data, self.offset + 2, self.extent_start_lsb)
|
||||||
|
struct.pack_into('>I', self.iso.data, self.offset + 6, self.extent_start_lsb)
|
||||||
|
struct.pack_into('<I', self.iso.data, self.offset + 10, self.extent_length_lsb)
|
||||||
|
struct.pack_into('>I', self.iso.data, self.offset + 14, self.extent_length_lsb)
|
||||||
|
|
||||||
|
def readable_name(self):
|
||||||
|
if not ';' in self.name:
|
||||||
|
return self.name.lower()
|
||||||
|
else:
|
||||||
|
tmp, _ = self.name.split(';')
|
||||||
|
return tmp.lower()
|
||||||
|
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
sectors = self.iso.data[self.extent_start_lsb * self.iso.sector_size: self.extent_start_lsb * self.iso.sector_size+ 3 * self.iso.sector_size]
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
f = ISOFile(self.iso, self.extent_start_lsb * self.iso.sector_size + offset)
|
||||||
|
yield f
|
||||||
|
offset += f.length
|
||||||
|
if not f.length:
|
||||||
|
break
|
||||||
|
|
||||||
|
def find(self, name):
|
||||||
|
sectors = self.iso.data[self.extent_start_lsb * self.iso.sector_size: self.extent_start_lsb * self.iso.sector_size+ 3 * self.iso.sector_size]
|
||||||
|
offset = 0
|
||||||
|
if '.' in name and len(name.split('.')[0]) > 8:
|
||||||
|
a, b = name.split('.')
|
||||||
|
name = a[:8] + '.' + b
|
||||||
|
if '-' in name:
|
||||||
|
name = name.replace('-','_')
|
||||||
|
while 1:
|
||||||
|
f = ISOFile(self.iso, self.extent_start_lsb * self.iso.sector_size + offset)
|
||||||
|
if not f.length:
|
||||||
|
if offset < self.extent_length_lsb:
|
||||||
|
offset += 1
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if ';' in f.name:
|
||||||
|
tmp, _ = f.name.split(';')
|
||||||
|
if tmp.endswith('.'):
|
||||||
|
tmp = tmp[:-1]
|
||||||
|
if tmp.lower() == name.lower():
|
||||||
|
return f
|
||||||
|
elif f.name.lower() == name.lower():
|
||||||
|
return f
|
||||||
|
offset += f.length
|
||||||
|
return None
|
||||||
|
|
||||||
|
class FAT(object):
|
||||||
|
|
||||||
|
def __init__(self, iso, offset):
|
||||||
|
self.iso = iso
|
||||||
|
self.offset = offset
|
||||||
|
|
||||||
|
self.bytespersector, _ = read_struct('H', self.iso.data, offset + 11)
|
||||||
|
self.sectorspercluster, _ = read_struct('B', self.iso.data, offset + 13)
|
||||||
|
self.reservedsectors, _ = read_struct('H', self.iso.data, offset + 14)
|
||||||
|
self.numberoffats, _ = read_struct('B', self.iso.data, offset + 16)
|
||||||
|
self.numberofdirs, _ = read_struct('H', self.iso.data, offset + 17)
|
||||||
|
self.fatsize, _ = read_struct('H', self.iso.data, offset + 22)
|
||||||
|
|
||||||
|
self.root_dir_sectors = (self.numberofdirs * 32 + (self.bytespersector - 1)) // self.bytespersector
|
||||||
|
self.first_data_sector = self.reservedsectors + (self.numberoffats * self.fatsize) + self.root_dir_sectors
|
||||||
|
self.root_sector= self.first_data_sector - self.root_dir_sectors
|
||||||
|
self.root = FATDirectory(self, self.offset + self.root_sector * self.bytespersector)
|
||||||
|
|
||||||
|
def get_offset(self, cluster):
|
||||||
|
return self.offset + ((cluster - 2) * self.sectorspercluster + self.first_data_sector) * self.bytespersector
|
||||||
|
|
||||||
|
def get_file(self, path):
|
||||||
|
units = path.split('/')
|
||||||
|
units = units[1:]
|
||||||
|
|
||||||
|
me = self.root
|
||||||
|
out = None
|
||||||
|
for i in units:
|
||||||
|
for fatfile in me.list():
|
||||||
|
if fatfile.readable_name() == i:
|
||||||
|
me = fatfile.to_dir()
|
||||||
|
out = fatfile
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
return out
|
||||||
|
|
||||||
|
class FATDirectory(object):
|
||||||
|
|
||||||
|
def __init__(self, fat, offset):
|
||||||
|
|
||||||
|
self.fat = fat
|
||||||
|
self.offset = offset
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
|
||||||
|
o = self.offset
|
||||||
|
while 1:
|
||||||
|
out = FATFile(self.fat, o)
|
||||||
|
if out.name != '\0\0\0\0\0\0\0\0':
|
||||||
|
yield out
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
o += out.size
|
||||||
|
|
||||||
|
|
||||||
|
class FATFile(object):
|
||||||
|
|
||||||
|
def __init__(self, fat, offset):
|
||||||
|
|
||||||
|
self.fat = fat
|
||||||
|
self.offset = offset
|
||||||
|
self.magic_long = None
|
||||||
|
self.size = 0
|
||||||
|
self.long_name = ''
|
||||||
|
|
||||||
|
o = self.offset
|
||||||
|
self.actual_offset = o
|
||||||
|
|
||||||
|
self.attrib, _ = read_struct('B',self.fat.iso.data,o+11)
|
||||||
|
|
||||||
|
while (self.attrib & 0x0F) == 0x0F:
|
||||||
|
# Long file name entry
|
||||||
|
tmp = read_struct('10s',self.fat.iso.data,o+1)[0]
|
||||||
|
tmp += read_struct('12s',self.fat.iso.data,o+14)[0]
|
||||||
|
tmp += read_struct('4s',self.fat.iso.data,o+28)[0]
|
||||||
|
tmp = "".join([chr(x) for x in tmp[::2] if x != '\xFF']).strip('\x00')
|
||||||
|
self.long_name = tmp + self.long_name
|
||||||
|
self.size += 32
|
||||||
|
o = self.offset + self.size
|
||||||
|
self.actual_offset = o
|
||||||
|
self.attrib, _ = read_struct('B',self.fat.iso.data,o+11)
|
||||||
|
|
||||||
|
o = self.offset + self.size
|
||||||
|
|
||||||
|
self.name, o = read_struct('8s',self.fat.iso.data,o)
|
||||||
|
self.ext, o = read_struct('3s',self.fat.iso.data,o)
|
||||||
|
self.attrib, o = read_struct('B',self.fat.iso.data,o)
|
||||||
|
self.userattrib, o = read_struct('B',self.fat.iso.data,o)
|
||||||
|
self.undelete, o = read_struct('b',self.fat.iso.data,o)
|
||||||
|
self.createtime, o = read_struct('H',self.fat.iso.data,o)
|
||||||
|
self.createdate, o = read_struct('H',self.fat.iso.data,o)
|
||||||
|
self.accessdate, o = read_struct('H',self.fat.iso.data,o)
|
||||||
|
self.clusterhi, o = read_struct('H',self.fat.iso.data,o)
|
||||||
|
self.modifiedti, o = read_struct('H',self.fat.iso.data,o)
|
||||||
|
self.modifiedda, o = read_struct('H',self.fat.iso.data,o)
|
||||||
|
self.clusterlow, o = read_struct('H',self.fat.iso.data,o)
|
||||||
|
self.filesize, o = read_struct('I',self.fat.iso.data,o)
|
||||||
|
|
||||||
|
self.name = self.name.decode('ascii')
|
||||||
|
self.ext = self.ext.decode('ascii')
|
||||||
|
|
||||||
|
self.size += 32
|
||||||
|
|
||||||
|
self.cluster = (self.clusterhi << 16) + self.clusterlow
|
||||||
|
|
||||||
|
def is_dir(self):
|
||||||
|
return bool(self.attrib & 0x10)
|
||||||
|
|
||||||
|
def is_long(self):
|
||||||
|
return bool((self.attrib & 0x0F) == 0x0F)
|
||||||
|
|
||||||
|
def to_dir(self):
|
||||||
|
return FATDirectory(self.fat, self.fat.get_offset(self.cluster))
|
||||||
|
|
||||||
|
def get_offset(self):
|
||||||
|
return self.fat.get_offset(self.cluster)
|
||||||
|
|
||||||
|
def readable_name(self):
|
||||||
|
if self.long_name:
|
||||||
|
return self.long_name
|
||||||
|
if self.ext.strip():
|
||||||
|
return (self.name.strip() + '.' + self.ext.strip()).lower()
|
||||||
|
else:
|
||||||
|
return self.name.strip().lower()
|
||||||
|
|
||||||
|
|
||||||
|
image = ISO('image.iso')
|
||||||
|
fat = image.root.find('FAT.IMG')
|
||||||
|
|
||||||
|
fatfs = FAT(image, fat.extent_start_lsb * image.sector_size)
|
||||||
|
|
||||||
|
def process(fatfile, path):
|
||||||
|
if fatfile.is_long():
|
||||||
|
return
|
||||||
|
if fatfile.readable_name() == '.':
|
||||||
|
return
|
||||||
|
if fatfile.readable_name() == '..':
|
||||||
|
return
|
||||||
|
if fatfile.is_dir():
|
||||||
|
for i in fatfile.to_dir().list():
|
||||||
|
process(i, path + fatfile.readable_name() + '/')
|
||||||
|
else:
|
||||||
|
cdfile = image.get_file(path + fatfile.readable_name())
|
||||||
|
if not cdfile:
|
||||||
|
if fatfile.readable_name() != 'bootia32.efi' and fatfile.readable_name() != 'bootx64.efi':
|
||||||
|
print("Warning:", fatfile.readable_name(), "not found in ISO")
|
||||||
|
else:
|
||||||
|
cdfile.extent_start_lsb = fatfile.get_offset() // 2048
|
||||||
|
cdfile.extent_length_lsb = fatfile.filesize
|
||||||
|
cdfile.write_extents()
|
||||||
|
|
||||||
|
|
||||||
|
for i in fatfs.root.list():
|
||||||
|
process(i,'/')
|
||||||
|
|
||||||
|
with open('image.iso','wb') as f:
|
||||||
|
f.write(image.data)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user