/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "2common.h"
#include "2sysincludes.h"
#include "cgptlib.h"
#include "cgptlib_internal.h"
#include "crc32.h"
#include "gpt.h"
#include "utility.h"
#include "vboot_api.h"

/**
 * Allocate and read GPT data from the drive.
 *
 * The sector_bytes and gpt_drive_sectors fields should be filled on input.  The
 * primary and secondary header and entries are filled on output.
 *
 * Returns 0 if successful, 1 if error.
 */
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{
	int primary_valid = 0, secondary_valid = 0;

	/* No data to be written yet */
	gptdata->modified = 0;
	/* This should get overwritten by GptInit() */
	gptdata->ignored = 0;

	/* Allocate all buffers */
	gptdata->primary_header = (uint8_t *)malloc(gptdata->sector_bytes);
	gptdata->secondary_header =
		(uint8_t *)malloc(gptdata->sector_bytes);
	gptdata->primary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE);
	gptdata->secondary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE);

	if (gptdata->primary_header == NULL ||
	    gptdata->secondary_header == NULL ||
	    gptdata->primary_entries == NULL ||
	    gptdata->secondary_entries == NULL)
		return 1;

	/* Read primary header from the drive, skipping the protective MBR */
	if (0 != VbExDiskRead(disk_handle, 1, 1, gptdata->primary_header)) {
		VB2_DEBUG("Read error in primary GPT header\n");
		memset(gptdata->primary_header, 0, gptdata->sector_bytes);
	}

	/* Only read primary GPT if the primary header is valid */
	GptHeader* primary_header = (GptHeader*)gptdata->primary_header;
	if (0 == CheckHeader(primary_header, 0,
			gptdata->streaming_drive_sectors,
			gptdata->gpt_drive_sectors,
			gptdata->flags,
			gptdata->sector_bytes)) {
		primary_valid = 1;
		uint64_t entries_bytes =
				(uint64_t)primary_header->number_of_entries
				* primary_header->size_of_entry;
		uint64_t entries_sectors =
				(entries_bytes + gptdata->sector_bytes - 1)
				/ gptdata->sector_bytes;
		if (0 != VbExDiskRead(disk_handle,
				      primary_header->entries_lba,
				      entries_sectors,
				      gptdata->primary_entries)) {
			VB2_DEBUG("Read error in primary GPT entries\n");
			primary_valid = 0;
		}
	} else {
		VB2_DEBUG("Primary GPT header is %s\n",
			  memcmp(primary_header->signature,
				 GPT_HEADER_SIGNATURE_IGNORED,
				 GPT_HEADER_SIGNATURE_SIZE)
			  ? "invalid" : "being ignored");
	}

	/* Read secondary header from the end of the drive */
	if (0 != VbExDiskRead(disk_handle, gptdata->gpt_drive_sectors - 1, 1,
			      gptdata->secondary_header)) {
		VB2_DEBUG("Read error in secondary GPT header\n");
		memset(gptdata->secondary_header, 0, gptdata->sector_bytes);
	}

	/* Only read secondary GPT if the secondary header is valid */
	GptHeader* secondary_header = (GptHeader*)gptdata->secondary_header;
	if (0 == CheckHeader(secondary_header, 1,
			gptdata->streaming_drive_sectors,
			gptdata->gpt_drive_sectors,
			gptdata->flags,
			gptdata->sector_bytes)) {
		secondary_valid = 1;
		uint64_t entries_bytes =
				(uint64_t)secondary_header->number_of_entries
				* secondary_header->size_of_entry;
		uint64_t entries_sectors =
				(entries_bytes + gptdata->sector_bytes - 1)
				/ gptdata->sector_bytes;
		if (0 != VbExDiskRead(disk_handle,
				      secondary_header->entries_lba,
				      entries_sectors,
				      gptdata->secondary_entries)) {
			VB2_DEBUG("Read error in secondary GPT entries\n");
			secondary_valid = 0;
		}
	} else {
		VB2_DEBUG("Secondary GPT header is %s\n",
			  memcmp(secondary_header->signature,
				 GPT_HEADER_SIGNATURE_IGNORED,
				 GPT_HEADER_SIGNATURE_SIZE)
			  ? "invalid" : "being ignored");
	}

	/* Return 0 if least one GPT header was valid */
	return (primary_valid || secondary_valid) ? 0 : 1;
}

/**
 * Write any changes for the GPT data back to the drive, then free the buffers.
 *
 * Returns 0 if successful, 1 if error.
 */
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{
	int skip_primary = 0;
	GptHeader *header;
	uint64_t entries_bytes, entries_sectors;
	int ret = 1;

	header = (GptHeader *)gptdata->primary_header;
	if (!header)
		header = (GptHeader *)gptdata->secondary_header;
	if (!header)
		return 1;  /* No headers at all, so nothing to write */

	entries_bytes = (uint64_t)header->number_of_entries
			* header->size_of_entry;
	entries_sectors = entries_bytes / gptdata->sector_bytes;

	/*
	 * TODO(namnguyen): Preserve padding between primary GPT header and
	 * its entries.
	 */
	uint64_t entries_lba = GPT_PMBR_SECTORS + GPT_HEADER_SECTORS;
	if (gptdata->primary_header) {
		GptHeader *h = (GptHeader *)(gptdata->primary_header);
		entries_lba = h->entries_lba;

		if (gptdata->ignored & MASK_PRIMARY) {
			VB2_DEBUG("Not updating primary GPT: "
				  "marked to be ignored.\n");
			skip_primary = 1;
		} else if (gptdata->modified & GPT_MODIFIED_HEADER1) {
			if (!memcmp(h->signature, GPT_HEADER_SIGNATURE2,
				    GPT_HEADER_SIGNATURE_SIZE)) {
				VB2_DEBUG("Not updating primary GPT: "
					  "legacy mode is enabled.\n");
				skip_primary = 1;
			} else {
				VB2_DEBUG("Updating GPT header 1\n");
				if (0 != VbExDiskWrite(disk_handle, 1, 1,
						       gptdata->primary_header))
					goto fail;
			}
		}
	}

	if (gptdata->primary_entries && !skip_primary) {
		if (gptdata->modified & GPT_MODIFIED_ENTRIES1) {
			VB2_DEBUG("Updating GPT entries 1\n");
			if (0 != VbExDiskWrite(disk_handle, entries_lba,
					       entries_sectors,
					       gptdata->primary_entries))
				goto fail;
		}
	}

	entries_lba = (gptdata->gpt_drive_sectors - entries_sectors -
		GPT_HEADER_SECTORS);
	if (gptdata->secondary_header && !(gptdata->ignored & MASK_SECONDARY)) {
		GptHeader *h = (GptHeader *)(gptdata->secondary_header);
		entries_lba = h->entries_lba;
		if (gptdata->modified & GPT_MODIFIED_HEADER2) {
			VB2_DEBUG("Updating GPT header 2\n");
			if (0 != VbExDiskWrite(disk_handle,
					       gptdata->gpt_drive_sectors - 1, 1,
					       gptdata->secondary_header))
				goto fail;
		}
	}

	if (gptdata->secondary_entries && !(gptdata->ignored & MASK_SECONDARY)){
		if (gptdata->modified & GPT_MODIFIED_ENTRIES2) {
			VB2_DEBUG("Updating GPT entries 2\n");
			if (0 != VbExDiskWrite(disk_handle,
					       entries_lba, entries_sectors,
					       gptdata->secondary_entries))
				goto fail;
		}
	}

	ret = 0;

fail:
	/* Avoid leaking memory on disk write failure */
	if (gptdata->primary_header)
		free(gptdata->primary_header);
	if (gptdata->primary_entries)
		free(gptdata->primary_entries);
	if (gptdata->secondary_entries)
		free(gptdata->secondary_entries);
	if (gptdata->secondary_header)
		free(gptdata->secondary_header);

	/* Success */
	return ret;
}

int IsUnusedEntry(const GptEntry *e)
{
	static Guid zero = {{{0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0}}}};
	return !memcmp(&zero, (const uint8_t*)(&e->type), sizeof(zero));
}

/*
 * Func: GptGetEntrySize
 * Desc: This function returns size(in lba) of a partition represented by
 * given GPT entry.
 */
size_t GptGetEntrySizeLba(const GptEntry *e)
{
	return (e->ending_lba - e->starting_lba + 1);
}

/*
 * Func: GptGetEntrySize
 * Desc: This function returns size(in bytes) of a partition represented by
 * given GPT entry.
 */
size_t GptGetEntrySizeBytes(const GptData *gpt, const GptEntry *e)
{
	return GptGetEntrySizeLba(e) * gpt->sector_bytes;
}
