1
0
Fork 0

Initial commit

This commit is contained in:
Shawn Nock 2020-01-10 16:07:14 -05:00
commit ae24ebf247
4 changed files with 175 additions and 0 deletions

BIN
mtd-rw.ko Normal file

Binary file not shown.

69
mtd-rw.zig Normal file
View File

@ -0,0 +1,69 @@
const std = @import("std");
const os = std.os;
const mtd_rw_ko = @embedFile("mtd-rw.ko");
const InitModuleError = error {
ModuleSignatureMisformatted,
TimeoutResolvingSymbol,
BadAddress,
ModuleSigInvalid,
OutOfMemory,
PermissionDenied,
AlreadyLoaded,
BadParams,
InvalidModule,
};
const DeleteModuleError = error {
ModuleNotLive,
BadAddress,
ModuleNotFound,
PermissionDenied,
ModuleInUse,
};
pub fn load() !void {
try insmod(mtd_rw_ko, "i_want_a_brick=1");
}
pub fn unload() void {
rmmod("mtd_rw", os.O_NONBLOCK) catch |err| {
std.debug.warn("Failed to unload module: {}\n", .{err});
};
}
pub fn insmod(buf: []const u8, args: [*:0]const u8) !void {
const errno = os.linux.getErrno(
os.linux.syscall3(
os.linux.SYS_init_module, @ptrToInt(&buf[0]), buf.len, @ptrToInt(args)));
switch (errno) {
0 => return,
os.EEXIST => return, // It's not a failure if we have what we need
os.EBADMSG => return InitModuleError.ModuleSignatureMisformatted,
os.EBUSY => return InitModuleError.TimeoutResolvingSymbol,
os.EFAULT => return InitModuleError.BadAddress,
// os.ENOKEY => return InitModuleError.ModuleSigInvalid,
os.ENOMEM => return InitModuleError.OutOfMemory,
os.EPERM => return InitModuleError.PermissionDenied,
os.EINVAL => return InitModuleError.BadParams,
os.ENOEXEC => return InitModuleError.InvalidModule,
else => |err| return os.unexpectedErrno(err),
}
}
pub fn rmmod(mod_name: [*:0]const u8, flags: u32) !void {
const errno = os.linux.getErrno(
std.os.linux.syscall2(
std.os.linux.SYS_delete_module, @ptrToInt(mod_name), flags));
switch (errno) {
0 => return,
os.EBUSY => return DeleteModuleError.ModuleNotLive,
os.EFAULT => return DeleteModuleError.BadAddress,
os.ENOENT => return DeleteModuleError.ModuleNotFound,
os.EPERM => return DeleteModuleError.PermissionDenied,
os.EWOULDBLOCK => return DeleteModuleError.ModuleInUse,
else => |err| return os.unexpectedErrno(err),
}
}

BIN
uboot-feb2019.bin Normal file

Binary file not shown.

106
update-uboot.zig Normal file
View File

@ -0,0 +1,106 @@
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;
}