1
0

Added workflow?

This commit is contained in:
Mark 2025-02-25 19:17:29 -08:00
parent 9c515cfab0
commit c19af78ae2
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
12 changed files with 222 additions and 38 deletions

View File

@ -9,4 +9,8 @@ trim_trailing_whitespace = false
insert_final_newline = false insert_final_newline = false
[*.asm] [*.asm]
indent_style = space indent_style = space
[*.yml]
indent_size = space
indent_size = 2

82
.gitea/workflows/ci.yml Normal file
View File

@ -0,0 +1,82 @@
name: CI
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
jobs:
typos:
name: "Typos"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check typos
uses: crate-ci/typos@master
with:
config: ./tools/typos.toml
clippy:
name: "Clippy"
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: "Install Rust"
run: |
sudo apt update
DEBIAN_FRONTEND=noninteractive \
sudo apt install --yes \
rustup
- name: Run clippy
working-directory: ./tetros
run: cargo clippy --all-targets --all-features
build:
name: "Build"
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: "Install Rust"
run: |
sudo apt update
DEBIAN_FRONTEND=noninteractive \
sudo apt install --yes \
rustup nasm python3-requests
- name: Build
run: make
# Upload build output
- name: "Save output"
uses: actions/upload-artifact@v3
with:
name: "Build output"
path: "build/*"
retention-days: 7
- name: "Publish package (hash)"
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
run: |
PUBLISH_USER="${{ secrets.PUBLISH_USER }}" \
PUBLISH_KEY="${{ secrets.PUBLISH_KEY }}" \
VERSION="${{ github.sha }}" \
PACKAGE="${{ vars.PACKAGE }}" \
python tools/scripts/publish.py
- name: "Publish package (latest)"
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
run: |
PUBLISH_USER="${{ secrets.PUBLISH_USER }}" \
PUBLISH_KEY="${{ secrets.PUBLISH_KEY }}" \
VERSION="latest" \
PACKAGE="${{ vars.PACKAGE }}" \
python tools/scripts/publish.py

View File

@ -1,6 +1,6 @@
SECTION .text ; cannot use .data SECTION .text ; cannot use .data
struc GDTEntry struc GDTEntry ; spell:disable-line
.limitl resw 1 .limitl resw 1
.basel resw 1 .basel resw 1
.basem resb 1 .basem resb 1
@ -26,21 +26,21 @@ gdt_attr:
.accessed equ 1 << 0 .accessed equ 1 << 0
;system ;system
; legacy ; legacy
.tssAvailabe16 equ 0x1 .tssAvailabe16 equ 0x1 ; spell:disable-line
.ldt equ 0x2 .ldt equ 0x2
.tssBusy16 equ 0x3 .tssBusy16 equ 0x3
.call16 equ 0x4 .call16 equ 0x4
.task equ 0x5 .task equ 0x5
.interrupt16 equ 0x6 .interrupt16 equ 0x6
.trap16 equ 0x7 .trap16 equ 0x7
.tssAvailabe32 equ 0x9 .tssAvailabe32 equ 0x9 ; spell:disable-line
.tssBusy32 equ 0xB .tssBusy32 equ 0xB
.call32 equ 0xC .call32 equ 0xC
.interrupt32 equ 0xE .interrupt32 equ 0xE
.trap32 equ 0xF .trap32 equ 0xF
; long mode ; long mode
.ldt32 equ 0x2 .ldt32 equ 0x2
.tssAvailabe64 equ 0x9 .tssAvailabe64 equ 0x9 ; spell:disable-line
.tssBusy64 equ 0xB .tssBusy64 equ 0xB
.call64 equ 0xC .call64 equ 0xC
.interrupt64 equ 0xE .interrupt64 equ 0xE

View File

@ -61,6 +61,7 @@ impl<T> fmt::Debug for Entry<T> {
} }
} }
// spell:off
impl<F> Entry<F> { impl<F> Entry<F> {
/// Create a valid non-present IDT entry. /// Create a valid non-present IDT entry.
#[inline] #[inline]
@ -111,7 +112,9 @@ impl<F> Entry<F> {
)) ))
} }
} }
// spell:on
// spell:off
impl<F: HandlerFuncType> Entry<F> { impl<F: HandlerFuncType> Entry<F> {
/// Sets the handler address for the IDT entry and sets the following defaults: /// Sets the handler address for the IDT entry and sets the following defaults:
/// - The code selector is the code segment currently active in the CPU /// - The code selector is the code segment currently active in the CPU
@ -125,3 +128,4 @@ impl<F: HandlerFuncType> Entry<F> {
unsafe { self.set_handler_addr(handler.to_virt_addr()) } unsafe { self.set_handler_addr(handler.to_virt_addr()) }
} }
} }
// spell:on

View File

@ -50,9 +50,9 @@ bitflags! {
} }
} }
/// //
/// MARK: types // MARK: types
/// //
/// A handler function for an interrupt or an exception without error code. /// A handler function for an interrupt or an exception without error code.
pub type HandlerFunc = extern "x86-interrupt" fn(InterruptStackFrame); pub type HandlerFunc = extern "x86-interrupt" fn(InterruptStackFrame);
@ -84,6 +84,7 @@ pub unsafe trait HandlerFuncType {
unsafe impl HandlerFuncType for HandlerFunc { unsafe impl HandlerFuncType for HandlerFunc {
#[inline] #[inline]
fn to_virt_addr(self) -> VirtAddr { fn to_virt_addr(self) -> VirtAddr {
#[expect(clippy::fn_to_numeric_cast_with_truncation)]
VirtAddr::new(self as u32) VirtAddr::new(self as u32)
} }
} }
@ -91,6 +92,7 @@ unsafe impl HandlerFuncType for HandlerFunc {
unsafe impl HandlerFuncType for HandlerFuncWithErrCode { unsafe impl HandlerFuncType for HandlerFuncWithErrCode {
#[inline] #[inline]
fn to_virt_addr(self) -> VirtAddr { fn to_virt_addr(self) -> VirtAddr {
#[expect(clippy::fn_to_numeric_cast_with_truncation)]
VirtAddr::new(self as u32) VirtAddr::new(self as u32)
} }
} }
@ -98,6 +100,7 @@ unsafe impl HandlerFuncType for HandlerFuncWithErrCode {
unsafe impl HandlerFuncType for DivergingHandlerFunc { unsafe impl HandlerFuncType for DivergingHandlerFunc {
#[inline] #[inline]
fn to_virt_addr(self) -> VirtAddr { fn to_virt_addr(self) -> VirtAddr {
#[expect(clippy::fn_to_numeric_cast_with_truncation)]
VirtAddr::new(self as u32) VirtAddr::new(self as u32)
} }
} }
@ -105,6 +108,7 @@ unsafe impl HandlerFuncType for DivergingHandlerFunc {
unsafe impl HandlerFuncType for DivergingHandlerFuncWithErrCode { unsafe impl HandlerFuncType for DivergingHandlerFuncWithErrCode {
#[inline] #[inline]
fn to_virt_addr(self) -> VirtAddr { fn to_virt_addr(self) -> VirtAddr {
#[expect(clippy::fn_to_numeric_cast_with_truncation)]
VirtAddr::new(self as u32) VirtAddr::new(self as u32)
} }
} }
@ -112,6 +116,7 @@ unsafe impl HandlerFuncType for DivergingHandlerFuncWithErrCode {
unsafe impl HandlerFuncType for PageFaultHandlerFunc { unsafe impl HandlerFuncType for PageFaultHandlerFunc {
#[inline] #[inline]
fn to_virt_addr(self) -> VirtAddr { fn to_virt_addr(self) -> VirtAddr {
#[expect(clippy::fn_to_numeric_cast_with_truncation)]
VirtAddr::new(self as u32) VirtAddr::new(self as u32)
} }
} }

View File

@ -7,7 +7,7 @@ use super::{
// TODO: comments // TODO: comments
#[repr(C, packed(2))] #[repr(C, packed(2))]
struct IDTR { struct Idtr {
size: u16, size: u16,
offset: u32, offset: u32,
} }
@ -16,6 +16,7 @@ struct IDTR {
// MARK: idt // MARK: idt
// //
// spell:off
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[repr(C)] #[repr(C)]
#[repr(align(8))] #[repr(align(8))]
@ -410,6 +411,7 @@ pub struct InterruptDescriptorTable {
/// instruction pointer points to the instruction after the INTn. /// instruction pointer points to the instruction after the INTn.
interrupts: [Entry<HandlerFunc>; 256 - 32], interrupts: [Entry<HandlerFunc>; 256 - 32],
} }
// spell:on
// //
// MARK: impl // MARK: impl
@ -469,7 +471,7 @@ impl InterruptDescriptorTable {
#[inline] #[inline]
pub unsafe fn load_unsafe(&self) { pub unsafe fn load_unsafe(&self) {
let idtr = { let idtr = {
IDTR { Idtr {
size: (size_of::<InterruptDescriptorTable>() - 1) as u16, size: (size_of::<InterruptDescriptorTable>() - 1) as u16,
offset: self as *const _ as u32, offset: self as *const _ as u32,
} }

View File

@ -21,7 +21,6 @@ pub fn rust_begin_unwind(info: &PanicInfo<'_>) -> ! {
} }
} }
#[allow(non_snake_case)]
#[no_mangle] #[no_mangle]
/// Required to handle panics /// Required to handle panics
pub extern "C" fn _Unwind_Resume() -> ! { pub extern "C" fn _Unwind_Resume() -> ! {

View File

@ -2,7 +2,6 @@ use core::ptr;
use super::THUNK_STACK_ADDR; use super::THUNK_STACK_ADDR;
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[repr(C, packed)] #[repr(C, packed)]
pub struct ThunkData { pub struct ThunkData {

View File

@ -1,28 +1,28 @@
{ {
"llvm-target": "i686-unknown-none", "llvm-target": "i686-unknown-none",
"target-endian": "little", "target-endian": "little",
"target-pointer-width": "32", "target-pointer-width": "32",
"target-c-int-width": "32", "target-c-int-width": "32",
"data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
"arch": "x86", "arch": "x86",
"os": "none", "os": "none",
"env": "", "env": "",
"vendor": "unknown", "vendor": "unknown",
"linker-flavor": "gcc", "linker-flavor": "gcc",
"panic-strategy": "abort", "panic-strategy": "abort",
"pre-link-args": { "pre-link-args": {
"gcc": ["-m32", "-nostdlib", "-static"] "gcc": ["-m32", "-nostdlib", "-static"]
}, },
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float", "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float",
"dynamic-linking": false, "dynamic-linking": false,
"executables": false, "executables": false,
"relocation-model": "static", "relocation-model": "static",
"code-model": "large", "code-model": "large",
"disable-redzone": true, "disable-redzone": true,
"frame-pointer": "always", "frame-pointer": "always",
"exe-suffix": "", "exe-suffix": "",
"has-rpath": false, "has-rpath": false,
"no-default-libraries": true, "no-default-libraries": true,
"position-independent-executables": false, "position-independent-executables": false,
"tls-model": "global-dynamic" "tls-model": "global-dynamic"
} }

63
tools/scripts/publish.py Normal file
View File

@ -0,0 +1,63 @@
# Publish the output of `build.py`
# as a Gitea package.
from pathlib import Path
import requests
import os
import re
URL = "https://git.betalupi.com"
USER = os.environ["PUBLISH_USER"]
PACKAGE = os.environ["PACKAGE"]
VERSION = os.environ["VERSION"]
AUTH = requests.auth.HTTPBasicAuth(USER, os.environ["PUBLISH_KEY"])
ROOT: Path = Path(os.getcwd())
def log(msg):
print(f"[PUBLISH.PY] {msg}")
log(f"Version is {VERSION}")
log(f"Package is {PACKAGE}")
log(f"Running in {ROOT}")
if not ROOT.is_dir():
log("Root is not a directory, cannot continue")
exit(1)
def del_package():
log(f"Deleting package {PACKAGE}/{VERSION}")
res = requests.delete(
f"{URL}/api/packages/{USER}/generic/{PACKAGE}/{VERSION}",
auth=AUTH,
)
if res.status_code != 204 and res.status_code != 404:
log(f"Deletion failed with code {res.status_code}")
# Delete if already exists
# (important for the `latest` package)
del_package()
def upload(data, target: str):
target = re.sub("[^A-Za-z0-9_. -]+", "", target)
res = requests.put(
f"{URL}/api/packages/{USER}/generic/{PACKAGE}/{VERSION}/{target}",
auth=AUTH,
data=data,
)
if res.status_code != 201:
log(f"Upload failed with code {res.status_code}")
del_package() # Do not keep partial package if upload fails
exit(1)
return f"{URL}/api/packages/{USER}/generic/{PACKAGE}/{VERSION}/{target}"
log("Uploading disk.img")
upload(Path("./build/disk.img").open("rb").read(), "disk.img")

18
tools/scripts/ruff.toml Normal file
View File

@ -0,0 +1,18 @@
exclude = ["venv"]
line-length = 88
indent-width = 4
target-version = "py39"
include = ["scripts/**/*.py"]
[lint]
select = ["E4", "E7", "E9", "F"]
ignore = []
fixable = ["ALL"]
unfixable = []
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
[format]
quote-style = "double"
indent-style = "tab"
skip-magic-trailing-comma = false
line-ending = "lf"

8
tools/typos.toml Normal file
View File

@ -0,0 +1,8 @@
[default]
extend-ignore-re = [
# spell:disable-line
"(?Rm)^.*(%|#|//|;)\\s*spell:disable-line$",
# spell:<on|off>
"(?s)(%|#|//|;)\\s*spell:off.*?\\n\\s*(%|#|//)\\s*spell:on",
]