Initial Commit
This commit is contained in:
commit
8d16acb191
9 changed files with 320 additions and 0 deletions
17
bin0/README.md
Normal file
17
bin0/README.md
Normal 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
|
18
bin0/armv7l-linux/README.md
Normal file
18
bin0/armv7l-linux/README.md
Normal 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
BIN
bin0/armv7l-linux/bin0
Executable file
Binary file not shown.
66
bin0/armv7l-linux/bin0.S
Normal file
66
bin0/armv7l-linux/bin0.S
Normal 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 haven’t 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
|
89
bin0/armv7l-linux/bin0.bin0
Normal file
89
bin0/armv7l-linux/bin0.bin0
Normal 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 haven’t 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
17
bin0/default.nix
Normal 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
41
flake.lock
Normal 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
27
flake.nix
Normal 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
45
lib/default.nix
Normal 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) ];
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue