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; }