diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 0000000..15c6ad8
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,5 @@
+[target.aarch64-unknown-linux-musl]
+linker = "aarch64-linux-musl-gcc"
+
+[target.armv7-unknown-linux-musleabihf]
+linker = "rust-lld"
diff --git a/.gitignore b/.gitignore
index 7c69e09..759b73c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..ec8c142
--- /dev/null
+++ b/.vscode/settings.json
@@ -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
+
+}
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..e635832
--- /dev/null
+++ b/Cargo.toml
@@ -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"
diff --git a/Makefile b/Makefile
index c80b0ed..72d9783 100644
--- a/Makefile
+++ b/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
diff --git a/docs/BUILDING.md b/docs/BUILDING.md
index 416f891..57a9df4 100644
--- a/docs/BUILDING.md
+++ b/docs/BUILDING.md
@@ -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
-```
\ No newline at end of file
+make kvg # final binary will be at ./build/bin/kvg
+```
+
+# Cross-compiling
+See [cross-compilation.md](cross-compilation.md).
\ No newline at end of file
diff --git a/docs/USAGE.md b/docs/USAGE.md
new file mode 100644
index 0000000..4313cb7
--- /dev/null
+++ b/docs/USAGE.md
@@ -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>
diff --git a/docs/cross-compilation.md b/docs/cross-compilation.md
new file mode 100644
index 0000000..532a414
--- /dev/null
+++ b/docs/cross-compilation.md
@@ -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`
\ No newline at end of file
diff --git a/src/KVG/main.rs b/src/KVG/main.rs
new file mode 100644
index 0000000..68ad9cd
--- /dev/null
+++ b/src/KVG/main.rs
@@ -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);
+    }
+}