Initial Commit

This commit is contained in:
Charlotte 🦝 Delenk 2022-02-27 10:36:59 +01:00
commit 8d16acb191
Signed by: darkkirb
GPG key ID: AB2BD8DAF2E37122
9 changed files with 320 additions and 0 deletions

17
bin0/README.md Normal file
View file

@ -0,0 +1,17 @@
# Bin0
The binary seed for bootstrapping
It is meant to be the smallest feasible self-hosted binary. The supported language is target-dependent
## Supported Targets
- armv7l-linux
- aarch64-linux
- powerpc-linux
- powerpc64-linux
- powerpc64le-linux
- riscv32-linux
- riscv64-linux
- x86_64-linux
- i686-linux

View file

@ -0,0 +1,18 @@
# Bin0 for armv7l-linux
- 32 bit words
- little endian
This is compatible with:
- aarch64
- powerpc64le
- riscv32
- riscv64
## Syscalls of interest
- `exit` - 1
- `read` - 3
- `write` - 4
- `openat` - 322

BIN
bin0/armv7l-linux/bin0 Executable file

Binary file not shown.

66
bin0/armv7l-linux/bin0.S Normal file
View file

@ -0,0 +1,66 @@
.section .text
.global _start
_start:
ldr r0, [sp, 0] // Get argc
cmp r0, #3 // Check if argc is 3
movlt r7, #1 // exit(1)
svclt #0
mov r0, #-100 // AT_FDCWD
ldr r1, [sp, 8] // first argument
mov r2, #0 // O_RDONLY
mov r3, #0 // no mode
mov r7, #322 // openat
svc #0
cmp r0, #0 // Check if failed
movlt r7, #1 // exit(1)
svclt #0
mov r8, r0
mov r0, #-100 // AT_FDCWD
ldr r1, [sp, 12] // second argument
mov r2, #577 // O_TRUNC | O_CREAT | O_WRONLY
mov r3, #493 // rwxr-xr-x
mov r7, #322 // openat
svc #0
cmp r0, #0 // Check if failed
movlt r0, #3 // Return an error otherwise
movlt r7, #1 // exit(1)
svclt #0
mov r9, r0
.Lloop_init:
mov r10, #1 // load accumulator
.Lread_loop:
mov r0, r8 // Source FD
mov r1, sp // Destination buffer
mov r2, #1 // Number of bytes to read
mov r7, #3 // read()
svc #0
cmp r0, #0 // Check if failed or end of file
movle r7, #1
svcle #0 // exit
// read the byte
ldrb r0, [sp]
and r0, r0, #0xFE // remove bottom bit
cmp r0, #0x30 // Check if it's a number
bne .Lread_loop // If not, go back to read again
ldrb r0, [sp]
and r0, r0, #0x1 // Mask the bottom bit
orrs r10, r0, r10, lsl #1 // Add the number to the accumulator
bcc .Lread_loop // We havent finished reading
str r10, [sp] // Store the accumulator
mov r0, r9 // Destination FD
mov r1, sp // Source buffer
mov r2, #4 // Number of bytes to write
mov r7, #4 // write()
svc #0
cmp r0, #0 // Check if failed
movlt r7, #1 // exit(1)
svclt #0
b .Lloop_init

View file

@ -0,0 +1,89 @@
01000110 01001100 01000101 01111111 # ELF Magic
00000000 00000001 00000001 00000001 # 32 bit little endian elf
00000000000000000000000000000000
00000000000000000000000000000000 # padding
0000000000101000 0000000000000010 # ARM ELF
00000000000000000000000000000001 # original version ELF
00000000001000000000000001010100 # Program Entry position
00000000000000000000000000110100 # Program header table position
00000000000000000000000001010100 # Section Header table position
00000000000000000000000000000000 # Flags
0000000000100000 0000000000110100 # Header Size, Size of an entry in the program header table
0000000000101000 0000000000000001 # One program header, section header size
0000000000000000 0000000000000000 # no section headers, no section name section
00000000000000000000000000000001 # PT_LOAD
00000000000000000000000000000000 # Load from ZERO
00000000001000000000000000000000 # Load at 2MB
00000000001000000000000000000000 # Who cares about physical address
00000000000000000000000100100000 # size
00000000000000000000000100100000 # memory size
00000000000000000000000000000111 # rwx
00000000000000000000000000000100 # align 4 bytes
#.section .text
#.global _start
#
#_start:
1110 010 1 1 0 0 1 1101 0000 0000 0000 0000 # ldr rO, [sp, O] // Get argc
1110 00 1 1010 1 0000 0000 0000 0000 0011 # cmp rO, #3 // Check if argc is 3
1011 0011 0000 0000 0111 0000 0000 0001 # movlt r7, #l // exit(l)
1011 1111 0000 0000 0000 0000 0000 0000 # svclt #O
#
1110 00 1 1111 0 0000 0000 0000 0110 0011 # mov rO, #-lOO // AT_FDCWD
1110 010 1 1 0 0 1 1101 0001 0000 0000 1000 # ldr rl, [sp, 8] // first argument
1110 00 1 1101 0 0000 0010 0000 0000 0000 # mov r2, #O // O_RDONLY
1110 00 1 1101 0 0000 0011 0000 0000 0000 # mov r3, #O // no mode
1110 0011 0000 0000 0111 0001 0100 0010 # mov r7, #322 // openat
1110 1111 0000 0000 0000 0000 0000 0000 # svc #O
1110 00 1 1010 1 0000 0000 0000 0000 0000 # cmp rO, #O // Check if failed
1011 0011 0000 0000 0111 0000 0000 0001 # movlt r7, #l // exit(l)
1011 1111 0000 0000 0000 0000 0000 0000 # svclt #O
1110 00 0 1101 0 0000 1000 00000000 0000 # mov r8, rO
#
1110 00 1 1111 0 0000 0000 0000 0110 0011 # mov rO, #-lOO // AT_FDCWD
1110 010 1 1 0 0 1 1101 0001 0000 0000 1100 # ldr rl, [sp, l2] // first argument
1110 0011 0000 0000 0010 0010 0100 0001 # mov r2, #577 // O_TRUNC | O_CREAT | O_WRONLY
1110 0011 0000 0000 0011 0001 1110 1101 # mov r3, #493 // rwxr-xr-x
1110 0011 0000 0000 0111 0001 0100 0010 # mov r7, #322 // openat
1110 1111 0000 0000 0000 0000 0000 0000 # svc #O
1110 00 1 1010 1 0000 0000 0000 0000 0000 # cmp rO, #O // Check if failed
1011 0011 0000 0000 0111 0000 0000 0001 # movlt r7, #l // exit(l)
1011 1111 0000 0000 0000 0000 0000 0000 # svclt #O
1110 00 0 1101 0 0000 1001 00000000 0000 # mov r9, rO
#
#.Lloop_init:
1110 00 1 1101 0 0000 1010 0000 0000 0001 # mov rlO, #l // load accumulator
#.Lread_loop:
1110 00 0 1101 0 0000 0000 00000000 1000 # mov rO, r8 // Source FD
1110 00 0 1101 0 0000 0001 00000000 1101 # mov rl, sp // Destination buffer
1110 00 1 1101 0 0000 0010 0000 0000 0001 # mov r2, #l // Number of bytes to read
1110 00 1 1101 0 0000 0111 0000 0000 0011 # mov r7, #3 // read()
1110 1111 0000 0000 0000 0000 0000 0000 # svc #O
1110 00 1 1010 1 0000 0000 0000 0000 0000 # cmp rO, #O // Check if failed or end of file
1101 0011 0000 0000 0111 0000 0000 0001 # movle r7, #l // exit(l)
1101 1111 0000 0000 0000 0000 0000 0000 # svcle #O
#
# // read the byte
1110 010 1 1 1 0 1 1101 0000 0000 0000 0000 # ldrb rO, [sp]
1110 00 1 0000 0 0000 0000 0000 1111 1110 # and rO, rO, #OxFE // remove bottom bit
1110 00 1 1010 1 0000 0000 0000 0011 0000 # cmp rO, #Ox3O // Check if it's a number
0001 1010 1111 1111 1111 1111 1111 0011 # bne .Lread_loop // If not, go back to read again
#
1110 010 1 1 1 0 1 1101 0000 0000 0000 0000 # ldrb rO, [sp]
1110 00 1 0000 0 0000 0000 0000 0000 0001 # and rO, rO, #OxOl // mask the bottom bit
1110 00 0 1100 1 0000 1010 00001 00 0 1010 # orrs rlO, rO, rlO, lsl #l // Add the number to the accumulator
0011 1010 1111 1111 1111 1111 1110 1111 # bcc .Lread_loop // We havent finished reading
#
1110 010 1 1 0 0 0 1101 1010 0000 0000 0000 # str rlO, [sp] // Store the accumulator
1110 00 0 1101 0 0000 0000 00000000 1001 # mov rO, r9 // Destination FD
1110 00 0 1101 0 0000 0001 00000000 1101 # mov rl, sp // Source buffer
1110 00 1 1101 0 0000 0010 0000 0000 0100 # mov r2, #4 // Number of bytes to write
1110 00 1 1101 0 0000 0111 0000 0000 0100 # mov r7, #4 // write()
1110 1111 0000 0000 0000 0000 0000 0000 # svc #O
1110 00 1 1010 1 0000 0000 0000 0000 0000 # cmp rO, #O // Check if failed
1011 0011 0000 0000 0111 0000 0000 0001 # movlt r7, #l // exit(l)
1011 1111 0000 0000 0000 0000 0000 0000 # svclt #O
#
1110 1010 1111 1111 1111 1111 1110 0100 # b .Lloop_init

17
bin0/default.nix Normal file
View file

@ -0,0 +1,17 @@
system: { self, nixpkgs, ... } @ args: with self.lib.${system}; with nixpkgs.lib; if lists.any (s: system == s) [ "armv7l-linux" ] then
rec {
bin0-bin = baseDerivation {
name = "bin0-bin";
script = ''
set -ex
cp ${./. + "/${system}/bin0"} $out
'';
};
bin0 = baseDerivation {
name = "bin0";
script = ''
set -ex
${bin0-bin} ${./. + "/${system}/bin0.bin0"} $out
'';
};
} else { }

41
flake.lock Normal file
View file

@ -0,0 +1,41 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1645765209,
"narHash": "sha256-tLpNZlpCjWpbbxhDgQ/e5z2fL1RZGLYJWkkCOJNqlcI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "056c34167d3210a674ef21691afbbce1ed63f8ca",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

27
flake.nix Normal file
View file

@ -0,0 +1,27 @@
{
description = "Bootstrap Flake";
inputs = {
flake-utils.url = github:numtide/flake-utils;
};
outputs = { self, nixpkgs, flake-utils } @ args: with nixpkgs.lib; with flake-utils.lib; eachSystem [
"armv7l-linux"
"aarch64-linux"
"powerpc-linux"
"powerpc64-linux"
"powerpc64le-linux"
"riscv32-linux"
"riscv64-linux"
"x86_64-linux"
"i686-linux"
]
(system: rec {
packages = lists.foldl (a: b: a // b) { }
(builtins.map (f: import f system args) [
./bin0
]);
lib = import ./lib system args;
hydraJobs = packages;
});
}

45
lib/default.nix Normal file
View file

@ -0,0 +1,45 @@
system: { nixpkgs, ... } @ args: rec {
pkgs = import nixpkgs { inherit system; };
inherit (builtins) toFile;
runCommandBasic = script: builtins.derivation {
inherit system;
name = "runCommandBasic";
builder = "${pkgs.busybox}/bin/sh";
args = [ (toFile "builder.sh" script) ];
};
writeTextFile =
{ name
, text
, executable ? false
, destination ? ""
, checkPhase ? ""
}: runCommandBasic ''
target=$out${destination}
mkdir -p "$(dirname "$target")"
if [ -e "$textPath" ]; then
mv "$textPath" "$target"
else
echo -n "$text" > "$target"
fi
eval "$checkPhase"
(test -n "$executable" && chmod +x "$target") || true
'';
writeText = name: text: writeTextFile { inherit name text; };
writeTextDir = path: text: writeTextFile {
inherit text;
name = builtins.baseNameOf path;
destination = "/${path}";
};
writeScript = name: text: writeTextFile { inherit name text; executable = true; };
writeScriptBin = name: text: writeTextFile { inherit name text; executable = true; destination = "/bin/${name}"; };
baseDerivation = { script, ... } @args: builtins.derivation (args // {
inherit system;
builder = "${pkgs.busybox}/bin/sh";
args = [ (writeScript "${args.name}-builder.sh" script) ];
});
}