Bootloader: Add .data section
This commit is contained in:
parent
7adc7e55a5
commit
7e36a0be75
|
@ -156,6 +156,8 @@ enable_a20:
|
||||||
popw %ax
|
popw %ax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
a20_line_disabled_msg:
|
a20_line_disabled_msg:
|
||||||
.asciz "A20 line disabled. Trying to enable it"
|
.asciz "A20 line disabled. Trying to enable it"
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,8 @@ enter_unreal_mode:
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
hello_msg:
|
hello_msg:
|
||||||
.asciz "This is banan-os bootloader"
|
.asciz "This is banan-os bootloader"
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,8 @@ read_user_command_line:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
command_line_enter_msg:
|
command_line_enter_msg:
|
||||||
.asciz "cmdline: "
|
.asciz "cmdline: "
|
||||||
|
|
||||||
|
|
|
@ -470,6 +470,7 @@ print_root_partition_info:
|
||||||
popw %ax
|
popw %ax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
# These will be patched during bootloader installation
|
# These will be patched during bootloader installation
|
||||||
root_disk_guid:
|
root_disk_guid:
|
||||||
|
|
|
@ -196,6 +196,7 @@ elf_read_kernel_to_memory:
|
||||||
movw $elf_read_kernel_to_memory_not_loadable_header_msg, %si
|
movw $elf_read_kernel_to_memory_not_loadable_header_msg, %si
|
||||||
jmp print_and_halt
|
jmp print_and_halt
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
elf_validate_file_header_invalid_magic_msg:
|
elf_validate_file_header_invalid_magic_msg:
|
||||||
.asciz "ELF: file has invalid ELF magic"
|
.asciz "ELF: file has invalid ELF magic"
|
||||||
|
|
|
@ -692,6 +692,7 @@ ext2_find_kernel:
|
||||||
movw $ext2_kernel_not_reg_msg, %si
|
movw $ext2_kernel_not_reg_msg, %si
|
||||||
jmp print_and_halt
|
jmp print_and_halt
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
kernel_path:
|
kernel_path:
|
||||||
.short kernel_path1
|
.short kernel_path1
|
||||||
|
@ -704,7 +705,6 @@ kernel_path2:
|
||||||
.short 15
|
.short 15
|
||||||
.asciz "banan-os.kernel"
|
.asciz "banan-os.kernel"
|
||||||
|
|
||||||
|
|
||||||
root_partition_does_not_fit_ext2_filesystem_msg:
|
root_partition_does_not_fit_ext2_filesystem_msg:
|
||||||
.asciz "Root partition is too small to contain ext2 filesystem"
|
.asciz "Root partition is too small to contain ext2 filesystem"
|
||||||
root_partition_has_invalid_ext2_magic_msg:
|
root_partition_has_invalid_ext2_magic_msg:
|
||||||
|
|
|
@ -185,6 +185,7 @@ vesa_set_video_mode:
|
||||||
popw %ax
|
popw %ax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
vesa_error_msg:
|
vesa_error_msg:
|
||||||
.asciz "VESA error"
|
.asciz "VESA error"
|
||||||
|
|
|
@ -8,6 +8,8 @@ SECTIONS
|
||||||
. = ALIGN(512);
|
. = ALIGN(512);
|
||||||
stage2_start = .;
|
stage2_start = .;
|
||||||
.stage2 : { *(.stage2) }
|
.stage2 : { *(.stage2) }
|
||||||
|
. = ALIGN(512);
|
||||||
|
.data : { *(.data) }
|
||||||
stage2_end = .;
|
stage2_end = .;
|
||||||
|
|
||||||
. = ALIGN(512);
|
. = ALIGN(512);
|
||||||
|
|
|
@ -114,6 +114,7 @@ print_memory_map:
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
|
||||||
memory_map_msg:
|
memory_map_msg:
|
||||||
.asciz "memmap:"
|
.asciz "memmap:"
|
||||||
|
|
|
@ -99,33 +99,33 @@ bool GPTFile::install_stage1(std::span<const uint8_t> stage1)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPTFile::install_stage2(std::span<const uint8_t> stage2, const GUID& root_partition_guid)
|
bool GPTFile::install_stage2(std::span<const uint8_t> stage2, std::span<const uint8_t> data, const GUID& root_partition_guid)
|
||||||
{
|
{
|
||||||
if (stage2.size() < 16)
|
if (data.size() < 16)
|
||||||
{
|
{
|
||||||
std::cerr << m_path << ": contains invalid .stage2 section, too small for patches" << std::endl;
|
std::cerr << m_path << ": contains invalid .data section, too small for patches" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find GUID patch offsets
|
// find GUID patch offsets
|
||||||
std::size_t disk_guid_offset(-1);
|
std::size_t disk_guid_offset(-1);
|
||||||
std::size_t part_guid_offset(-1);
|
std::size_t part_guid_offset(-1);
|
||||||
for (std::size_t i = 0; i < stage2.size() - 16; i++)
|
for (std::size_t i = 0; i < data.size() - 16; i++)
|
||||||
{
|
{
|
||||||
if (memcmp(stage2.data() + i, "root disk guid ", 16) == 0)
|
if (memcmp(data.data() + i, "root disk guid ", 16) == 0)
|
||||||
{
|
{
|
||||||
if (disk_guid_offset != std::size_t(-1))
|
if (disk_guid_offset != std::size_t(-1))
|
||||||
{
|
{
|
||||||
std::cerr << m_path << ": contains invalid .stage2 section, multiple patchable disk guids" << std::endl;
|
std::cerr << m_path << ": contains invalid .data section, multiple patchable disk guids" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
disk_guid_offset = i;
|
disk_guid_offset = i;
|
||||||
}
|
}
|
||||||
if (memcmp(stage2.data() + i, "root part guid ", 16) == 0)
|
if (memcmp(data.data() + i, "root part guid ", 16) == 0)
|
||||||
{
|
{
|
||||||
if (part_guid_offset != std::size_t(-1))
|
if (part_guid_offset != std::size_t(-1))
|
||||||
{
|
{
|
||||||
std::cerr << m_path << ": contains invalid .stage2 section, multiple patchable partition guids" << std::endl;
|
std::cerr << m_path << ": contains invalid .data section, multiple patchable partition guids" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
part_guid_offset = i;
|
part_guid_offset = i;
|
||||||
|
@ -133,15 +133,14 @@ bool GPTFile::install_stage2(std::span<const uint8_t> stage2, const GUID& root_p
|
||||||
}
|
}
|
||||||
if (disk_guid_offset == std::size_t(-1))
|
if (disk_guid_offset == std::size_t(-1))
|
||||||
{
|
{
|
||||||
std::cerr << m_path << ": contains invalid .stage2 section, no patchable disk guid" << std::endl;
|
std::cerr << m_path << ": contains invalid .data section, no patchable disk guid" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (part_guid_offset == std::size_t(-1))
|
if (part_guid_offset == std::size_t(-1))
|
||||||
{
|
{
|
||||||
std::cerr << m_path << ": contains invalid .stage2 section, no patchable partition guid" << std::endl;
|
std::cerr << m_path << ": contains invalid .data section, no patchable partition guid" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto partition = find_partition_with_type(bios_boot_guid);
|
auto partition = find_partition_with_type(bios_boot_guid);
|
||||||
if (!partition.has_value())
|
if (!partition.has_value())
|
||||||
|
@ -152,23 +151,28 @@ bool GPTFile::install_stage2(std::span<const uint8_t> stage2, const GUID& root_p
|
||||||
|
|
||||||
const std::size_t partition_size = (partition->ending_lba - partition->starting_lba + 1) * SECTOR_SIZE;
|
const std::size_t partition_size = (partition->ending_lba - partition->starting_lba + 1) * SECTOR_SIZE;
|
||||||
|
|
||||||
if (stage2.size() > partition_size)
|
std::size_t data_offset = stage2.size();
|
||||||
|
if (std::size_t rem = data_offset % 512)
|
||||||
|
data_offset += 512 - rem;
|
||||||
|
|
||||||
|
if (data_offset + data.size() > partition_size)
|
||||||
{
|
{
|
||||||
std::cerr << m_path << ": can't fit " << stage2.size() << " bytes of data to partition of size " << partition_size << std::endl;
|
std::cerr << m_path << ": can't fit " << stage2.size() + data.size() << " bytes of data to partition of size " << partition_size << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* partition_start = m_mmap + partition->starting_lba * SECTOR_SIZE;
|
uint8_t* partition_start = m_mmap + partition->starting_lba * SECTOR_SIZE;
|
||||||
memcpy(partition_start, stage2.data(), stage2.size());
|
memcpy(partition_start, stage2.data(), stage2.size());
|
||||||
|
memcpy(partition_start + data_offset, data.data(), data.size());
|
||||||
|
|
||||||
// patch GUIDs
|
// patch GUIDs
|
||||||
*reinterpret_cast<GUID*>(partition_start + disk_guid_offset) = gpt_header().disk_guid;
|
*reinterpret_cast<GUID*>(partition_start + data_offset + disk_guid_offset) = gpt_header().disk_guid;
|
||||||
*reinterpret_cast<GUID*>(partition_start + part_guid_offset) = root_partition_guid;
|
*reinterpret_cast<GUID*>(partition_start + data_offset + part_guid_offset) = root_partition_guid;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPTFile::install_bootloader(std::span<const uint8_t> stage1, std::span<const uint8_t> stage2, const GUID& root_partition_guid)
|
bool GPTFile::install_bootloader(std::span<const uint8_t> stage1, std::span<const uint8_t> stage2, std::span<const uint8_t> data, const GUID& root_partition_guid)
|
||||||
{
|
{
|
||||||
if (!find_partition_with_guid(root_partition_guid).has_value())
|
if (!find_partition_with_guid(root_partition_guid).has_value())
|
||||||
{
|
{
|
||||||
|
@ -177,7 +181,7 @@ bool GPTFile::install_bootloader(std::span<const uint8_t> stage1, std::span<cons
|
||||||
}
|
}
|
||||||
if (!install_stage1(stage1))
|
if (!install_stage1(stage1))
|
||||||
return false;
|
return false;
|
||||||
if (!install_stage2(stage2, root_partition_guid))
|
if (!install_stage2(stage2, data, root_partition_guid))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ public:
|
||||||
GPTFile(std::string_view path);
|
GPTFile(std::string_view path);
|
||||||
~GPTFile();
|
~GPTFile();
|
||||||
|
|
||||||
bool install_bootloader(std::span<const uint8_t> stage1, std::span<const uint8_t> stage2, const GUID& root_partition_guid);
|
bool install_bootloader(std::span<const uint8_t> stage1, std::span<const uint8_t> stage2, std::span<const uint8_t> data, const GUID& root_partition_guid);
|
||||||
|
|
||||||
const GPTHeader& gpt_header() const;
|
const GPTHeader& gpt_header() const;
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ private:
|
||||||
std::optional<GPTPartitionEntry> find_partition_with_type(const GUID& type_guid) const;
|
std::optional<GPTPartitionEntry> find_partition_with_type(const GUID& type_guid) const;
|
||||||
|
|
||||||
bool install_stage1(std::span<const uint8_t> stage1);
|
bool install_stage1(std::span<const uint8_t> stage1);
|
||||||
bool install_stage2(std::span<const uint8_t> stage2, const GUID& root_partition_guid);
|
bool install_stage2(std::span<const uint8_t> stage2, std::span<const uint8_t> data, const GUID& root_partition_guid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string m_path;
|
const std::string m_path;
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
g++ -O2 -std=c++20 main.cpp crc32.cpp ELF.cpp GPT.cpp GUID.cpp -o install-bootloader
|
|
|
@ -26,9 +26,10 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
auto stage1 = bootloader.find_section(".stage1"sv);
|
auto stage1 = bootloader.find_section(".stage1"sv);
|
||||||
auto stage2 = bootloader.find_section(".stage2"sv);
|
auto stage2 = bootloader.find_section(".stage2"sv);
|
||||||
if (!stage1.has_value() || !stage2.has_value())
|
auto data = bootloader.find_section(".data"sv);
|
||||||
|
if (!stage1.has_value() || !stage2.has_value() || !data.has_value())
|
||||||
{
|
{
|
||||||
std::cerr << bootloader.path() << " doesn't contain .stage1 and .stage2 sections" << std::endl;
|
std::cerr << bootloader.path() << " doesn't contain .stage1, .stage2 and .data sections" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ int main(int argc, char** argv)
|
||||||
if (!disk_image.success())
|
if (!disk_image.success())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!disk_image.install_bootloader(*stage1, *stage2, *root_partition_guid))
|
if (!disk_image.install_bootloader(*stage1, *stage2, *data, *root_partition_guid))
|
||||||
return 1;
|
return 1;
|
||||||
std::cout << "bootloader installed" << std::endl;
|
std::cout << "bootloader installed" << std::endl;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue