Compare commits
4 Commits
343512ee2f
...
2bcfd294be
Author | SHA1 | Date |
---|---|---|
anna | 2bcfd294be | 12 months ago |
anna | 43d454e9fe | 12 months ago |
anna | bfc2b5cb7c | 12 months ago |
anna | fb36d1f949 | 12 months ago |
@ -1,10 +1,30 @@
|
||||
[package]
|
||||
name = "bussy"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"stage1"
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
repository = "https://git.bsd.gay/fef/bussy"
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
opt-level = "s"
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
debug = true
|
||||
overflow-checks = true
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
opt-level = "s"
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
debug = true
|
||||
overflow-checks = false
|
||||
|
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# DISCLAIMER: I don't know python. And i don't like python.
|
||||
# This is only written in python because pretty much everyone already has it
|
||||
# installed and rust doesn't support post-build scripts for some reason.
|
||||
|
||||
import sys
|
||||
from utils import crc32, run_sync
|
||||
|
||||
if len(sys.argv) >= 2:
|
||||
PROFILE = sys.argv[1]
|
||||
else:
|
||||
PROFILE = "debug"
|
||||
|
||||
|
||||
def finalize_stage1(filename: str):
|
||||
run_sync(
|
||||
"objcopy", "-O", "binary",
|
||||
"target/x86-pc-none/" + PROFILE + "/bussy-stage1",
|
||||
filename
|
||||
)
|
||||
|
||||
with open(filename, "r+b") as file:
|
||||
data = bytearray(file.read())
|
||||
|
||||
size = len(data)
|
||||
if size > 0x8000:
|
||||
print("stage1 is too big (greater than 32 K)")
|
||||
exit(1)
|
||||
data[2] = size & 0xff
|
||||
data[3] = size >> 8
|
||||
|
||||
csum = crc32(data)
|
||||
print("CRC32 checksum of stage1 is " + hex(csum))
|
||||
data[4] = csum & 0xff
|
||||
data[5] = (csum >> 8) & 0xff
|
||||
data[6] = (csum >> 16) & 0xff
|
||||
data[7] = csum >> 24
|
||||
|
||||
file.seek(2)
|
||||
file.write(data[2:8])
|
||||
|
||||
|
||||
print("Running cargo")
|
||||
if PROFILE == "debug":
|
||||
run_sync("cargo", "build", "--workspace")
|
||||
elif PROFILE == "release":
|
||||
run_sync("cargo", "build", "--workspace", "--release")
|
||||
else:
|
||||
run_sync("cargo", "build", "--workspace", "--profile", PROFILE)
|
||||
|
||||
print("Finalizing stage1")
|
||||
finalize_stage1("target/x86-pc-none/" + PROFILE + "/stage1.bin")
|
@ -0,0 +1,49 @@
|
||||
# Miscellaneous utilities, meant to be included from build.py
|
||||
|
||||
import os
|
||||
|
||||
|
||||
# Do a fork/execl because that way all children get the same stdout,
|
||||
# i.e. if it's a tty the executed program should behave appropriately.
|
||||
# Python probably has an idiomatic way to do this, but frankly idc.
|
||||
def run_sync(program: str, *args):
|
||||
path = os.popen("which " + program).read().strip()
|
||||
child = os.fork()
|
||||
if child == 0:
|
||||
os.execl(path, program, *args)
|
||||
print("execl() failed")
|
||||
exit(1)
|
||||
elif child == -1:
|
||||
print("fork() failed")
|
||||
exit(1)
|
||||
status = os.waitpid(child, 0)
|
||||
if status[1] != 0:
|
||||
print(program + " exited with status code " + str(status[1]))
|
||||
exit(1)
|
||||
|
||||
|
||||
def generate_crc_tab(poly_reverse: int):
|
||||
tab = []
|
||||
for crc in range(256):
|
||||
for _ in range(8):
|
||||
lsb = crc % 2
|
||||
crc >>= 1
|
||||
if lsb == 1:
|
||||
crc ^= poly_reverse
|
||||
tab.append(crc)
|
||||
return tab
|
||||
|
||||
|
||||
def do_crc(data, table):
|
||||
crc = 0xffffffff
|
||||
for byte in data:
|
||||
crc = (crc >> 8) ^ table[(crc ^ byte) & 0xff]
|
||||
return ~crc & 0xffffffff
|
||||
|
||||
|
||||
CCITT32_TAB = generate_crc_tab(0xedb88320)
|
||||
|
||||
|
||||
def crc32(data: bytes):
|
||||
global CCITT32_TAB
|
||||
return do_crc(data, CCITT32_TAB)
|
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "stage1"
|
||||
version = "0.1.0"
|
@ -0,0 +1,5 @@
|
||||
[package]
|
||||
name = "bussy-stage1"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
repository.workspace = true
|
@ -0,0 +1,19 @@
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||
|
||||
let ld_script_path = manifest_dir.join("stage1.ld");
|
||||
println!("cargo:rustc-link-arg=--script={}", ld_script_path.display());
|
||||
println!("cargo:rerun-if-changed={}", ld_script_path.display());
|
||||
|
||||
let asm_dir = manifest_dir.join("src").join("asm");
|
||||
let files = asm_dir.read_dir().unwrap();
|
||||
for entry in files {
|
||||
let path = entry.unwrap().path();
|
||||
if path.extension() == Some(OsStr::new("s")) {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* This is the first file to be included in mod.rs,
|
||||
* which exposes its contents to all following files
|
||||
*/
|
||||
|
||||
.macro LOCAL name, type=function
|
||||
.type \name , @\type
|
||||
\name :
|
||||
.endm
|
||||
|
||||
.macro GLOBL name, type=function
|
||||
.global \name
|
||||
.type \name , %\type
|
||||
\name :
|
||||
.endm
|
||||
|
||||
.macro END name
|
||||
.size \name , . - \name
|
||||
.endm
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This sits at the very beginning of the stage1 image, which in turn is
|
||||
* located at the beginning of the bussy boot partition. stage0 always reads
|
||||
* the first 32 K of that partition to 0x0500, validates the magic number and
|
||||
* checksum, and then jumps to the entry point at 0x0510.
|
||||
*
|
||||
* ATTENTION: if you change the structure of this header, you must
|
||||
* also change the (hardcoded) offsets in stage0.s and build.py!
|
||||
*/
|
||||
|
||||
.extern _stage1_start /* stage1.ld */
|
||||
.extern _stage1_end /* stage1.ld */
|
||||
|
||||
.section .header, "awx"
|
||||
.code16
|
||||
|
||||
/*
|
||||
* offset 0x00 (loaded at 0x0500)
|
||||
* stage1 magic number. stage0 checks this.
|
||||
*/
|
||||
GLOBL _stage1_magic, object
|
||||
.word 0xacab
|
||||
END _stage1_magic
|
||||
|
||||
/*
|
||||
* offset 0x02 (loaded at 0x0502)
|
||||
* Length of the entire stage1 image in bytes, excluding bss.
|
||||
* Hardcoded during image build. Must not exceed 32 K.
|
||||
*/
|
||||
GLOBL _stage1_len, object
|
||||
.word 0x8000
|
||||
END _stage1_len
|
||||
|
||||
/*
|
||||
* offset 0x04 (loaded at 0x0504)
|
||||
* CRC32 (polynomial 0x04c11db7) checksum of the entire stage1 image
|
||||
* as defined by the length field at offset 0x02. Must be zeroed for
|
||||
* checksum calculation. stage0 checks AND CLEARS this.
|
||||
* Hardcoded during image build.
|
||||
*/
|
||||
GLOBL _stage1_csum, object
|
||||
.long 0
|
||||
END _stage1_csum
|
||||
|
||||
/*
|
||||
* offset 0x08 (loaded at 0x0508)
|
||||
* Reserved; MUST be set to 0. stage0 ignores this.
|
||||
*/
|
||||
.quad 0
|
||||
|
||||
/*
|
||||
* offset 0x10 (loaded at 0x0510)
|
||||
* stage1 entry point. stage0 jumps here.
|
||||
*/
|
||||
GLOBL _start
|
||||
1: jmp 1b
|
||||
END _start
|
@ -0,0 +1,21 @@
|
||||
macro_rules! include_asm {
|
||||
($name:literal) => {
|
||||
::core::arch::global_asm!(
|
||||
::core::concat!(".file \"", $name, "\""), // for better debugging
|
||||
::core::include_str!($name),
|
||||
::core::concat!(".file \"", ::core::file!(), "\""),
|
||||
options(raw, att_syntax),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
// common macros for the other assembly files, keep at the beginning
|
||||
include_asm!("common.s");
|
||||
|
||||
// stage1 header containing its magic, size, checksum, and entry point
|
||||
include_asm!("header.s");
|
||||
extern "C" {
|
||||
pub static _stage1_magic: u16;
|
||||
pub static _stage1_len: u16;
|
||||
pub static _stage1_csum: u32;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::arch::asm;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
mod asm;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
pub fn rust_panic(_info: &PanicInfo) -> ! {
|
||||
loop {
|
||||
unsafe {
|
||||
asm!("cli", "hlt");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x0500;
|
||||
|
||||
_stage1_start = .;
|
||||
|
||||
.header : {
|
||||
KEEP(*(.header))
|
||||
}
|
||||
|
||||
.text : ALIGN(8) {
|
||||
*(.text .text.*)
|
||||
}
|
||||
|
||||
.data : ALIGN(8) {
|
||||
*(.data .data.*)
|
||||
}
|
||||
|
||||
.rodata : ALIGN(8) {
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
|
||||
_stage1_end = .;
|
||||
|
||||
.bss(NOLOAD) : ALIGN(8) {
|
||||
_bss_start = .;
|
||||
*(.bss .bss.*)
|
||||
_bss_end = .;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue