Port KVG to Rust & write docs
Also, this patch adds a fix that gets rid of cursor offset for VSCode Web (e.g: vscode.dev, GH Codespaces) TEST=compile KVG on all architectures
This commit is contained in:
parent
8ac198052c
commit
bfb70c6ec9
5
.cargo/config.toml
Normal file
5
.cargo/config.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[target.aarch64-unknown-linux-musl]
|
||||
linker = "aarch64-linux-musl-gcc"
|
||||
|
||||
[target.armv7-unknown-linux-musleabihf]
|
||||
linker = "rust-lld"
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,5 +1,7 @@
|
||||
# nya
|
||||
build/
|
||||
target/
|
||||
Cargo.lock
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
@ -53,3 +55,8 @@ modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
|
||||
# Added by cargo
|
||||
|
||||
/target
|
||||
|
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"stdio.h": "c"
|
||||
},
|
||||
|
||||
// this setting isn't "unknown", its just for troubleshooting,
|
||||
// but it fixes the vscode.dev cursor on ChromeOS.
|
||||
"editor.disableMonospaceOptimizations": true
|
||||
|
||||
}
|
18
Cargo.toml
Normal file
18
Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "kvg-kvs"
|
||||
version = "0.1.0"
|
||||
authors = ["Katelyn"]
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.0", features = ["derive"] }
|
||||
|
||||
[[bin]]
|
||||
name = "KVG"
|
||||
path = "src/KVG/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "KVS"
|
||||
path = "src/KVS/main.rs"
|
29
Makefile
29
Makefile
@ -1,4 +1,6 @@
|
||||
CC := gcc
|
||||
CC ?= gcc
|
||||
ARCH ?= x86_64
|
||||
TOOLCHAIN ?= musl
|
||||
SHELL ?= /bin/sh
|
||||
KVSFLIST := \
|
||||
src/KVS/main.c \
|
||||
@ -13,10 +15,22 @@ CFLAGS := \
|
||||
-Llib \
|
||||
-static
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
CC := aarch64-linux-gnu-gcc
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH), armv7)
|
||||
CC := armv7-linux-gnu-gcc
|
||||
TOOLCHAIN := musleabihf
|
||||
endif
|
||||
|
||||
TARGET = ${ARCH}-unknown-linux-${TOOLCHAIN}
|
||||
|
||||
all: clean build kvs kvg
|
||||
|
||||
kvs: build build/bin/kvs
|
||||
kvg: build build/bin/kvg
|
||||
kvg-c: build build/bin/kvg-c
|
||||
|
||||
build:
|
||||
$(shell mkdir -p build/bin)
|
||||
@ -25,12 +39,19 @@ build/bin/kvs: src/KVS/main.c
|
||||
$(CC) $(KVSFLIST) -o build/bin/kvs $(CFLAGS)
|
||||
chmod +rx build/bin/kvs
|
||||
|
||||
build/bin/kvg: src/KVG/main.c
|
||||
$(CC) src/KVG/main.c -o build/bin/kvg $(CFLAGS)
|
||||
chmod +rx build/bin/kvg
|
||||
build/bin/kvg: src/KVG/main.rs
|
||||
cargo build --bin KVG --target=$(TARGET) --release
|
||||
cp target/$(TARGET)/release/KVG build/bin/kvg
|
||||
|
||||
# The C version of KVS, not normally built.
|
||||
# Also guaranteed to be out-of-date.
|
||||
build/bin/kvg-c: src/KVG/main.c
|
||||
$(CC) src/KVG/main.c -o build/bin/kvg-c $(CFLAGS)
|
||||
chmod +rx build/bin/kvg-c
|
||||
|
||||
install:
|
||||
cp -r build/* /usr/local/
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
rm -rf target
|
||||
|
@ -1,10 +1,10 @@
|
||||
# Building KVS:
|
||||
### Dependencies
|
||||
You only need gcc & make! All static libs are inside `lib/`
|
||||
You only need gcc, make, and musl-tools! All static libs are inside `lib/`
|
||||
|
||||
```
|
||||
Debian-based systems: sudo apt install gcc make
|
||||
Arch-based systems: sudo pacman -S gcc make
|
||||
Debian-based systems: sudo apt install gcc make musl-tools
|
||||
Arch-based systems: sudo pacman -S gcc make musl
|
||||
Alpine-based systems: apk add gcc make
|
||||
```
|
||||
|
||||
@ -19,8 +19,8 @@ git clone https://github.com/kxtzownsu/KVS
|
||||
cd KVS
|
||||
|
||||
# Third, run two command to compile the KVS & KVG binary
|
||||
make kvs # final binary is at ./build/kvs
|
||||
make kvg # final binary is at ./build/kvg
|
||||
make kvs # final binary is at ./build/bin/kvs
|
||||
make kvg # final binary is at ./build/bin/kvg
|
||||
|
||||
# (OPTIONAL) Fourth, run the shim builder
|
||||
sudo make shim-builder
|
||||
@ -35,11 +35,11 @@ Notes: KVS **requires** KVG or else the shim will not build successfully
|
||||
|
||||
# Building KVG:
|
||||
### Dependencies
|
||||
Same as KVS, you only need `gcc` and `make`
|
||||
Same as KVS, you only need `gcc`, `make`, and `musl`
|
||||
|
||||
```
|
||||
Debian-based systems: sudo apt install gcc make
|
||||
Arch-based systems: sudo pacman -S gcc make
|
||||
Debian-based systems: sudo apt install gcc make musl-tools
|
||||
Arch-based systems: sudo pacman -S gcc make musl
|
||||
Alpine-based systems: apk add gcc make
|
||||
```
|
||||
|
||||
@ -50,5 +50,8 @@ git clone https://github.com/kxtzownsu/KVS # insiders, use KVS-private
|
||||
|
||||
cd KVS
|
||||
|
||||
make kvg # final binary will be at ./build/kvg
|
||||
```
|
||||
make kvg # final binary will be at ./build/bin/kvg
|
||||
```
|
||||
|
||||
# Cross-compiling
|
||||
See [cross-compilation.md](cross-compilation.md).
|
67
docs/USAGE.md
Normal file
67
docs/USAGE.md
Normal file
@ -0,0 +1,67 @@
|
||||
# Using KVG (Kernel Version Generator)
|
||||
Using KVG is very simple, all you need to know is if your device has v0 or v1.
|
||||
|
||||
This can be figured out very easily, if your device is oldui (white mode) recovery, then its v0,
|
||||
|
||||
if your device is newui (dark mode) recovery, then its v1.<br><br>
|
||||
|
||||
CLI Args:
|
||||
```
|
||||
$ ./kvg
|
||||
USAGE: ./kvg <kernver> <optional flags>
|
||||
e.g.: ./kvg 0x00010001 --raw --ver=0
|
||||
--raw - prints the output as raw hex bytes
|
||||
--ver=<0/1> - specifies the kernver struct version to use
|
||||
--help - shows this message :3
|
||||
KVG was created by kxtzownsu
|
||||
(now written in Rust)
|
||||
$
|
||||
```
|
||||
|
||||
To use V0 recovery, pass `--ver=0` onto the END of the command, after putting the binary,
|
||||
|
||||
pass your flags, like this:
|
||||
|
||||
`./kvg 0x00010001 --ver=0 --raw`
|
||||
|
||||
NOT like this:
|
||||
|
||||
`./kvg --raw --ver=0 0x00010001`
|
||||
|
||||
Passing `--raw` will give you the raw hex output, instead of it printing like this `02 4c` it would print `\x2\x4c`.
|
||||
|
||||
# Using KVS (Kernel Version Switcher)
|
||||
One thing to note, if you aren't using cr50-hammer or RMASmoke, then you must be **UNENROLLED**!
|
||||
|
||||
If you *are* using RMASmoke, make sure you're on Cr50 RW Version 0.5.229 or lower.
|
||||
|
||||
If you *are* using cr50-hammer, make sure <fill in later when cr50-hammer patch>.
|
||||
|
||||
If you *aren't* using RMASmoke or cr50-hammer, make sure to use the `tpm0 flash` method!
|
||||
|
||||
## Examples:
|
||||
***Flashing via tpm0 flash***
|
||||
```
|
||||
KVS: Kernel Version Switcher (codename Maglev, bid: 2.0.0))
|
||||
FW Version: Google_Grunt.11031.149.0
|
||||
Kernel Version: 0x00010001
|
||||
TPM: 2.0
|
||||
FWMP: 0x1
|
||||
GSC RW Version: 0.5.229
|
||||
GSC Type: Cr50
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
1) Flash new kernver via /dev/tpm0 (REQ. UNENROLLED)
|
||||
2) Flash new kernver via RMASmoke (REQ. CR50 VER 0.5.229 OR LOWER)
|
||||
3) Make kernver index unwritable
|
||||
4) Shell
|
||||
5) Reboot
|
||||
> 1
|
||||
What kernver would you like to flash?
|
||||
> 0x00010001
|
||||
Does your device have lightmode (v0) or darkmode (v1) recovery? Please type either v0 or v1.
|
||||
> v0
|
||||
writing 13 bytes...
|
||||
Finished! Press ENTER to return to main menu
|
||||
```
|
||||
|
||||
<finish docs when RMASmoke & cr50-hammer release>
|
10
docs/cross-compilation.md
Normal file
10
docs/cross-compilation.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Cross-compiling the KVS project
|
||||
To cross-compile the KVS project, all you need to do is set `$ARCH` to a correct architecture,
|
||||
and also install the cross-compilation libraries for your target arch.
|
||||
|
||||
Heres an example:
|
||||
|
||||
`ARCH=aarch64 make all`
|
||||
|
||||
All architectures:
|
||||
`x86_64, armv7, aarch64`
|
185
src/KVG/main.rs
Normal file
185
src/KVG/main.rs
Normal file
@ -0,0 +1,185 @@
|
||||
use std::env;
|
||||
use std::process;
|
||||
use std::io::{self, Write};
|
||||
|
||||
const VB2_SHA256_DIGEST_SIZE: usize = 32;
|
||||
const MAX_HEX_LENGTH: usize = 10;
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct Vb2SecdataKernelV0 {
|
||||
struct_version: u8,
|
||||
uid: u32,
|
||||
kernver: u32,
|
||||
reserved: [u8; 3],
|
||||
crc8: u8,
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct Vb2SecdataKernelV1 {
|
||||
struct_version: u8,
|
||||
struct_size: u8,
|
||||
crc8: u8,
|
||||
flags: u8,
|
||||
kernver: u32,
|
||||
ec_hash: [u8; VB2_SHA256_DIGEST_SIZE],
|
||||
}
|
||||
|
||||
struct Vb2Context<'a> {
|
||||
secdata_kernel: &'a [u8],
|
||||
}
|
||||
|
||||
fn vb2_crc8(data: &[u8]) -> u8 {
|
||||
let mut crc: u16 = 0;
|
||||
for byte in data {
|
||||
crc ^= (*byte as u16) << 8;
|
||||
for _ in 0..8 {
|
||||
if crc & 0x8000 != 0 {
|
||||
crc ^= 0x1070 << 3;
|
||||
}
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
(crc >> 8) as u8
|
||||
}
|
||||
|
||||
fn is_v0(context: &Vb2Context) -> bool {
|
||||
let major_version = (context.secdata_kernel[0] & 0xf0) >> 4;
|
||||
major_version == 0
|
||||
}
|
||||
|
||||
fn secdata_kernel_crc(context: &Vb2Context) -> u8 {
|
||||
if is_v0(context) {
|
||||
let size = std::mem::size_of::<Vb2SecdataKernelV0>() - 1; // Exclude crc8
|
||||
vb2_crc8(&context.secdata_kernel[0..size])
|
||||
} else {
|
||||
let struct_size = context.secdata_kernel[1] as usize;
|
||||
let offset = 3; // Offset for flags in V1
|
||||
vb2_crc8(&context.secdata_kernel[offset..struct_size])
|
||||
}
|
||||
}
|
||||
|
||||
fn is_valid_hex(input: &str) -> bool {
|
||||
if input.len() > MAX_HEX_LENGTH {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(stripped) = input.strip_prefix("0x") {
|
||||
stripped.chars().all(|c| c.is_digit(16))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn sanitize_input(input: &str) -> String {
|
||||
input.replace('\n', "\0")
|
||||
}
|
||||
|
||||
fn convert_to_u32(input: &str) -> u32 {
|
||||
u32::from_str_radix(input.trim_start_matches("0x"), 16).unwrap_or_else(|_| {
|
||||
eprintln!(
|
||||
"The entered kernver, {}, was not valid hexadecimal. Please try again.",
|
||||
input
|
||||
);
|
||||
process::exit(1);
|
||||
})
|
||||
}
|
||||
|
||||
fn print_hex(data: &[u8]) {
|
||||
for byte in data {
|
||||
print!("{:02x} ", byte);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
if args.len() < 2 || args.contains(&"--help".to_string()) {
|
||||
println!(
|
||||
"USAGE: {} <kernver> <optional flags>\n\
|
||||
e.g.: {} 0x00010001 --raw\n\
|
||||
--raw - prints the output as raw hex bytes\n\
|
||||
--ver=<0/1> - specifies the kernver struct version to use\n\
|
||||
--help - shows this message :3\n\
|
||||
KVG was created by kxtzownsu\n\
|
||||
(now written in Rust)",
|
||||
args[0], args[0]
|
||||
);
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
let kernver = sanitize_input(&args[1]);
|
||||
if !is_valid_hex(&kernver) {
|
||||
eprintln!(
|
||||
"The entered kernver: {}, wasn't detected as valid hexadecimal (max 10 characters). Please try again.",
|
||||
kernver
|
||||
);
|
||||
process::exit(1);
|
||||
}
|
||||
let kvarg = convert_to_u32(&kernver);
|
||||
|
||||
let version = args.iter().find(|arg| arg.starts_with("--ver=")).map_or("", |v| &v[6..]);
|
||||
if version != "0" && version != "1" {
|
||||
eprintln!(
|
||||
"The entered struct version: {}, wasn't valid (see --help). Please try again.",
|
||||
version
|
||||
);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
if version == "0" {
|
||||
let mut secdata0 = Vb2SecdataKernelV0 {
|
||||
struct_version: 0x02,
|
||||
uid: 0x4752574c,
|
||||
kernver: kvarg,
|
||||
reserved: [0x00; 3],
|
||||
crc8: 0,
|
||||
};
|
||||
let ctx = Vb2Context {
|
||||
secdata_kernel: unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
&secdata0 as *const _ as *const u8,
|
||||
std::mem::size_of::<Vb2SecdataKernelV0>(),
|
||||
)
|
||||
},
|
||||
};
|
||||
secdata0.crc8 = secdata_kernel_crc(&ctx);
|
||||
buffer.extend_from_slice(unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
&secdata0 as *const _ as *const u8,
|
||||
std::mem::size_of::<Vb2SecdataKernelV0>(),
|
||||
)
|
||||
});
|
||||
} else if version == "1" {
|
||||
let mut secdata1 = Vb2SecdataKernelV1 {
|
||||
struct_version: 0x10,
|
||||
struct_size: std::mem::size_of::<Vb2SecdataKernelV1>() as u8,
|
||||
crc8: 0,
|
||||
flags: 0x0,
|
||||
kernver: kvarg,
|
||||
ec_hash: [0; VB2_SHA256_DIGEST_SIZE],
|
||||
};
|
||||
let ctx = Vb2Context {
|
||||
secdata_kernel: unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
&secdata1 as *const _ as *const u8,
|
||||
std::mem::size_of::<Vb2SecdataKernelV1>(),
|
||||
)
|
||||
},
|
||||
};
|
||||
secdata1.crc8 = secdata_kernel_crc(&ctx);
|
||||
buffer.extend_from_slice(unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
&secdata1 as *const _ as *const u8,
|
||||
std::mem::size_of::<Vb2SecdataKernelV1>(),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
if args.contains(&"--raw".to_string()) {
|
||||
io::stdout().write_all(&buffer).unwrap();
|
||||
} else {
|
||||
print_hex(&buffer);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user