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