Skip to content

Instantly share code, notes, and snippets.

@soulik
Created June 2, 2014 13:20
Show Gist options
  • Save soulik/66a39834c86248f7cab6 to your computer and use it in GitHub Desktop.
Save soulik/66a39834c86248f7cab6 to your computer and use it in GitHub Desktop.
Android boot image: boot.img unpacker tool written in LuaJIT
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