Created
June 2, 2014 13:20
-
-
Save soulik/66a39834c86248f7cab6 to your computer and use it in GitHub Desktop.
Android boot image: boot.img unpacker tool written in LuaJIT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local ffi = require 'ffi' | |
local BOOT_MAGIC = [[ANDROID!]] | |
local BOOT_MAGIC_SIZE = 8 | |
local BOOT_NAME_SIZE = 16 | |
local BOOT_ARGS_SIZE = 512 | |
local BOOT_EXTRA_ARGS_SIZE = 1024 | |
local t_buf = ffi.new("unsigned char[8]") | |
local function unpack_number(str, len) | |
local len = len or #str | |
ffi.copy(t_buf, str, len) | |
return tonumber(ffi.cast('uint32_t *', t_buf)[0]) | |
end | |
local function fwrite(fname, content) | |
local f = assert(io.open(fname, "wb")) | |
f:write(content) | |
f:close() | |
end | |
local function loadImg(fname) | |
local f = assert(io.open(fname, "rb")) | |
local function uint32() | |
return unpack_number(f:read(4), 4) | |
end | |
local img = {} | |
local function loadImage(pages, offset_pages) | |
assert(img.header) | |
local page_size = img.header.page_size | |
if offset_pages then | |
f:seek('set', offset_pages*page_size) | |
end | |
return f:read(pages*page_size) | |
end | |
local function loadHeader() | |
local header = {} | |
f:seek('set', 0) | |
header.magic = f:read(BOOT_MAGIC_SIZE) | |
header.kernel_size = uint32() | |
header.kernel_addr = uint32() | |
header.ramdisk_size = uint32() | |
header.ramdisk_addr = uint32() | |
header.second_size = uint32() | |
header.second_addr = uint32() | |
header.tags_addr = uint32() | |
header.page_size = uint32() | |
header.unused = f:read(2) | |
header.name = f:read(BOOT_NAME_SIZE) | |
header.cmdline = f:read(BOOT_ARGS_SIZE) | |
header.id = f:read(8) | |
header.extra_cmdline = f:read(BOOT_EXTRA_ARGS_SIZE) | |
return header | |
end | |
img.header = loadHeader() | |
local page_size = img.header.page_size | |
local pages = { | |
kernel = math.floor((img.header.kernel_size + page_size - 1)/page_size), | |
ram_disk = math.floor((img.header.ramdisk_size + page_size - 1)/page_size), | |
second_stage = math.floor((img.header.second_size + page_size - 1)/page_size), | |
} | |
img.kernel = loadImage(pages.kernel, 1) | |
img.ram_disk = loadImage(pages.ram_disk, pages.kernel+1) | |
if img.header.second_size > 0 then | |
img.second_stage = loadImage(pages.second_stage, pages.ram_disk + pages.kernel + 1) | |
else | |
img.second_stage = '' | |
end | |
f:close() | |
return img | |
end | |
local arg = {...} | |
if #arg>0 then | |
local img = loadImg(arg[1]) | |
fwrite('kernel.img', img.kernel) | |
fwrite('ram_disk.cpio.gz', img.ram_disk) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment