107 lines
3.1 KiB
Zig
107 lines
3.1 KiB
Zig
const std = @import("std");
|
|
const math = std.math;
|
|
const mtd_user = @cImport(@cInclude("mtd/mtd-user.h"));
|
|
|
|
const uboot = @embedFile("uboot-feb2019.bin");
|
|
const mtd_rw = @import("mtd-rw.zig");
|
|
|
|
const Allocator = std.heap.c_allocator;
|
|
|
|
const c_allocator = std.heap.c_allocator;
|
|
|
|
fn stripTrailingNulls(buf: []const u8) []const u8 {
|
|
var end: usize = buf.len;
|
|
while (true) {
|
|
if (end > 0) {
|
|
const new_end = end - 1;
|
|
if (buf[new_end] == 0) {
|
|
end = new_end;
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return buf[0..end];
|
|
}
|
|
|
|
test "stripTrailingNulls" {
|
|
const farts0: []const u8 = "farts\x00";
|
|
const farts: []const u8 = "farts";
|
|
var farts0_stripped = stripTrailingNulls(farts0);
|
|
var farts_stripped = stripTrailingNulls(farts);
|
|
std.debug.assert(farts0_stripped.len == 5);
|
|
std.debug.assert(farts_stripped.len == 5);
|
|
std.debug.assert(std.mem.eql(u8, farts0_stripped, farts));
|
|
std.debug.assert(std.mem.eql(u8, farts_stripped, farts));
|
|
}
|
|
|
|
fn mtd_info_get(name: []const u8, out: []u8) !void {
|
|
var path_buf: [64]u8 = undefined;
|
|
const path = try std.fmt.bufPrint(path_buf[0..], "{}/{}", .{"/sys/class/mtd/mtd0/", name});
|
|
|
|
//const path = try std.fmt.allocPrint(
|
|
// c_allocator, "{}/{}", .{"/sys/class/mtd/mtd0", name});
|
|
//defer c_allocator.free(path);
|
|
|
|
var f = try std.fs.openFileAbsolute(path, .{.read = true});
|
|
defer f.close();
|
|
const num_read = try f.read(out);
|
|
out = out[0..num_read-1];
|
|
}
|
|
|
|
fn mtd_info_get_usize(name: []const u8) !usize {
|
|
var buf: [64]u8 = undefined;
|
|
var buf_sl = buf[0..];
|
|
try mtd_info_get(name, buf_sl);
|
|
return try std.fmt.parseUnsigned(usize, buf_sl, 10);
|
|
}
|
|
|
|
pub fn main() !u8 {
|
|
try mtd_rw.load();
|
|
defer mtd_rw.unload();
|
|
|
|
// Read and hash mtd0
|
|
|
|
const mtd0_size = try mtd_info_get_usize("size");
|
|
|
|
if (uboot.len > mtd0_size) {
|
|
std.debug.warn("Error: mtd0 isn\'t large enough to hold the new image ({} > {})\n",
|
|
.{uboot.len, mtd0_size});
|
|
return 1;
|
|
}
|
|
var current_uboot = try Allocator.alloc(u8, mtd0_size);
|
|
var f = try std.fs.openFileAbsolute("/dev/mtd0", .{.read = true});
|
|
defer f.close();
|
|
const num_read = try f.read(current_uboot[0..]);
|
|
if (num_read != mtd0_size) {
|
|
std.debug.warn("Failed to read /dev/mtd0", .{});
|
|
return 2;
|
|
}
|
|
|
|
var current_digest: [std.crypto.Md5.digest_length]u8 = undefined;
|
|
std.crypto.Md5.hash(current_uboot, current_digest[0..]);
|
|
|
|
var embedded_digest: [std.crypto.Md5.digest_length]u8 = undefined;
|
|
std.crypto.Md5.hash(uboot, embedded_digest[0..]);
|
|
|
|
// Compare against payload
|
|
if (std.mem.eql(u8, current_digest[0..], embedded_digest[0..])) {
|
|
std.debug.warn("U-Boot is up to date. Exiting.\n", .{});
|
|
return 0;
|
|
}
|
|
|
|
// Erase mtd0
|
|
const mtd0_erasesize = try mtd_info_get_usize("erasesize");
|
|
var erased = 0;
|
|
while (erased < mtd0_size) {
|
|
//erase page
|
|
erased += mtd0_erasesize;
|
|
}
|
|
// Write mtd0
|
|
|
|
// Verify mtd0
|
|
|
|
std.debug.warn("Done\n", .{});
|
|
return 0;
|
|
}
|