/*
 * loki_unlok
 *
 * A utility to revert the changes made by loki_patch.
 *
 * by Dan Rosenberg (@djrbliss)
 *
 */

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "loki.h"

static unsigned char patch[] = PATCH;

/* Find the original address of the ramdisk, which
 * was embedded in the shellcode. */
int find_ramdisk_addr(void *img, int sz)
{

	int i, ramdisk = 0;

	for (i = 0; i < sz - (sizeof(patch) - 9); i++) {
		if (!memcmp((char *)img + i, patch, sizeof(patch)-9)) {
			ramdisk = *(int *)(img + i + sizeof(patch) - 5);
			break;
		}
	}

	return ramdisk;
}

int loki_unlok(const char* in_image, const char* out_image)
{
	int ifd, ofd;
	unsigned int orig_ramdisk_size, orig_kernel_size, orig_ramdisk_addr;
	unsigned int page_kernel_size, page_ramdisk_size, page_size, page_mask, fake_size;
	void *orig;
	struct stat st;
	struct boot_img_hdr *hdr;
	struct loki_hdr *loki_hdr;

	ifd = open(in_image, O_RDONLY);
	if (ifd < 0) {
		printf("[-] Failed to open %s for reading.\n", in_image);
		return 1;
	}

	ofd = open(out_image, O_WRONLY|O_CREAT|O_TRUNC, 0644);
	if (ofd < 0) {
		printf("[-] Failed to open %s for writing.\n", out_image);
		return 1;
	}

	/* Map the original boot/recovery image */
	if (fstat(ifd, &st)) {
		printf("[-] fstat() failed.\n");
		return 1;
	}

	orig = mmap(0, (st.st_size + 0x2000 + 0xfff) & ~0xfff, PROT_READ|PROT_WRITE, MAP_PRIVATE, ifd, 0);
	if (orig == MAP_FAILED) {
		printf("[-] Failed to mmap input file.\n");
		return 1;
	}

	hdr = orig;
	loki_hdr = orig + 0x400;

	if (memcmp(loki_hdr->magic, "LOKI", 4)) {
		printf("[-] Input file is not a Loki image.\n");

		/* Copy the entire file to the output transparently */
		if (write(ofd, orig, st.st_size) != st.st_size) {
			printf("[-] Failed to copy Loki image.\n");
			return 1;
		}

		printf("[+] Copied Loki image to %s.\n", out_image);

		return 0;
	}

	page_size = hdr->page_size;
	page_mask = hdr->page_size - 1;

	/* Infer the size of the fake block based on the newer ramdisk address */
	if (hdr->ramdisk_addr > 0x88f00000 || hdr->ramdisk_addr < 0xfa00000)
		fake_size = page_size;
	else
		fake_size = 0x200;

	orig_ramdisk_addr = find_ramdisk_addr(orig, st.st_size);
	if (orig_ramdisk_addr == 0) {
		printf("[-] Failed to find original ramdisk address.\n");
		return 1;
	}

	/* Restore the original header values */
	hdr->ramdisk_addr = orig_ramdisk_addr;
	hdr->kernel_size = orig_kernel_size = loki_hdr->orig_kernel_size;
	hdr->ramdisk_size = orig_ramdisk_size = loki_hdr->orig_ramdisk_size;

	/* Erase the loki header */
	memset(loki_hdr, 0, sizeof(*loki_hdr));

	/* Write the image header */
	if (write(ofd, orig, page_size) != page_size) {
		printf("[-] Failed to write header to output file.\n");
		return 1;
	}

	page_kernel_size = (orig_kernel_size + page_mask) & ~page_mask;

	/* Write the kernel */
	if (write(ofd, orig + page_size, page_kernel_size) != page_kernel_size) {
		printf("[-] Failed to write kernel to output file.\n");
		return 1;
	}

	page_ramdisk_size = (orig_ramdisk_size + page_mask) & ~page_mask;

	/* Write the ramdisk */
	if (write(ofd, orig + page_size + page_kernel_size, page_ramdisk_size) != page_ramdisk_size) {
		printf("[-] Failed to write ramdisk to output file.\n");
		return 1;
	}

	/* Write the device tree if needed */
	if (hdr->dt_size) {

		printf("[+] Writing device tree.\n");

		/* Skip an additional fake_size (page_size of 0x200) bytes */
		if (write(ofd, orig + page_size + page_kernel_size + page_ramdisk_size + fake_size, hdr->dt_size) != hdr->dt_size) {
			printf("[-] Failed to write device tree to output file.\n");
			return 1;
		}
	}

	close(ifd);
	close(ofd);

	printf("[+] Output file written to %s\n", out_image);

	return 0;
}
