/*
 * Copyright (c) 2026 The Fuchsia Authors
 *
 * SPDX-License-Identifier:	BSD-3-Clause
 */

#include <common.h>
#include <efi_loader.h>
#include <gbl_efi_fastboot_protocol.h>
#include <mmc.h>
#include <amlogic/aml_mmc.h>
#include <version.h>
#include <g_dnl.h>
#include <fb_fastboot.h>
#include <partition_table.h>

static efi_status_t EFIAPI get_var(struct GblEfiFastbootProtocol *self,
				   size_t num_args, const char *const *args,
				   size_t *buffer_size, char *buffer)
{
	EFI_ENTRY("%p, %zu, %p, %p, %p", self, num_args, args, buffer_size, buffer);
	if (num_args == 0 || !args || !buffer_size || (*buffer_size > 0 && !buffer))
		return EFI_EXIT(EFI_INVALID_PARAMETER);

	char cmd_buf[RESPONSE_LEN];
	char resp_buf[RESPONSE_LEN] = "";
	snprintf(cmd_buf, sizeof(cmd_buf), "%s", args[0]);

	if (fastboot_get_var(cmd_buf, resp_buf, sizeof(resp_buf) - 1) != 0)
		return EFI_EXIT(EFI_NOT_FOUND);

	size_t len = strlen(resp_buf);
	if (*buffer_size < len + 1) {
		*buffer_size = len + 1;
		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
	}

	strncpy(buffer, resp_buf, *buffer_size);
	*buffer_size = len;
	return EFI_EXIT(EFI_SUCCESS);
}

static efi_status_t EFIAPI get_var_all(struct GblEfiFastbootProtocol *self,
				       void *context, GetVarAllCallback cb)
{
	EFI_ENTRY("%p, %p, %p", self, context, cb);
	if (!cb)
		return EFI_EXIT(EFI_INVALID_PARAMETER);

	const char (*var_list)[RESPONSE_LEN];
	size_t var_list_size;

	if (has_boot_slot == 1) {
		var_list = fastboot_getvar_list_ab_gbl_limited;
		var_list_size = fastboot_getvar_list_ab_gbl_limited_size;
	} else if (dynamic_partition) {
		var_list = fastboot_getvar_list_dynamic;
		var_list_size = fastboot_getvar_list_dynamic_size;
	} else {
		var_list = fastboot_getvar_list;
		var_list_size = fastboot_getvar_list_size;
	}

	for (size_t i = 0; i < var_list_size; i++) {
		const char *name = var_list[i];
		char cmd_buf[RESPONSE_LEN];
		char resp_buf[RESPONSE_LEN] = "";
		snprintf(cmd_buf, sizeof(cmd_buf), "%s", name);
		if (fastboot_get_var(cmd_buf, resp_buf, sizeof(resp_buf) - 1) == 0 &&
		    strncmp(resp_buf, "FAIL", 4) != 0) {
			const char *const args[] = { name };
			cb(context, 1, args, resp_buf);
		}
	}
	return EFI_EXIT(EFI_SUCCESS);
}

static efi_status_t EFIAPI get_staged(struct GblEfiFastbootProtocol *self,
				      size_t *buffer_size, size_t *buffer_remains,
				      uint8_t *buffer)
{
	return EFI_UNSUPPORTED;
}

static efi_status_t EFIAPI get_partition_type(struct GblEfiFastbootProtocol *self,
					      const char *part_name,
					      size_t *part_type_len, char *part_type)
{
	EFI_ENTRY("%p, %s, %p, %p", self, part_name, part_type_len, part_type);
	if (!part_name || !part_type_len || (*part_type_len > 0 && !part_type))
		return EFI_EXIT(EFI_INVALID_PARAMETER);

	char cmd_buf[RESPONSE_LEN];
	snprintf(cmd_buf, sizeof(cmd_buf), "partition-type:%s", part_name);
	const char *part = parse_fb_cmd_partition(cmd_buf);
	if (!part)
		return EFI_EXIT(EFI_NOT_FOUND);

	const char *type_str = "raw";
	size_t len = strlen(type_str);
	if (*part_type_len < len + 1) {
		*part_type_len = len + 1;
		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
	}

	strncpy(part_type, type_str, *part_type_len);
	*part_type_len = len;
	return EFI_EXIT(EFI_SUCCESS);
}

static efi_status_t handle_flash_bootloader(size_t download_buffer_used_size,
					    uint8_t *download_buffer,
					    FastbootMessageSender sender, void *context)
{
	if (sender) {
		const char *msg = "Flashing bootloader via amlmmc...\n";
		sender(context, GBL_EFI_FASTBOOT_MESSAGE_TYPE_INFO, strlen(msg), msg);
	}

	// Call amlmmc_write_bootloader
	// We use AML_BL_BOOT to write to both boot0 and boot1
	int ret = amlmmc_write_bootloader(CONFIG_FASTBOOT_FLASH_MMC_DEV,
					  AML_BL_BOOT,
					  download_buffer_used_size,
					  download_buffer);
	if (ret) {
		if (sender) {
			const char *msg = "Flash bootloader failed\n";
			sender(context, GBL_EFI_FASTBOOT_MESSAGE_TYPE_FAIL, strlen(msg), msg);
		}
		return EFI_DEVICE_ERROR;
	}

	if (sender) {
		const char *msg = "Flash bootloader success\n";
		sender(context, GBL_EFI_FASTBOOT_MESSAGE_TYPE_OKAY, strlen(msg), msg);
	}
	return EFI_SUCCESS;
}

static efi_status_t handle_run_staged_efi(size_t download_buffer_used_size,
					  uint8_t *download_buffer,
					  FastbootMessageSender sender, void *context)
{
	if (download_buffer_used_size == 0 || !download_buffer) {
		if (sender) {
			const char *msg = "No EFI image staged\n";
			sender(context, GBL_EFI_FASTBOOT_MESSAGE_TYPE_FAIL, strlen(msg), msg);
		}
		return EFI_NOT_FOUND;
	}

	if (sender) {
		const char *msg = "Running staged EFI image...\n";
		sender(context, GBL_EFI_FASTBOOT_MESSAGE_TYPE_INFO, strlen(msg), msg);
	}

	// We need to run the image.
	// Similar to cb_run_staged_efi, we can use bootefi command.
	char cmd[128];
	snprintf(cmd, sizeof(cmd), "bootefi 0x%lx:0x%lx ${dtb_mem_addr}",
		 (unsigned long)download_buffer,
		 (unsigned long)download_buffer_used_size);

	printf("Executing: %s\n", cmd);

	// This might not return if successful
	run_command(cmd, 0);

	// If it returns, it failed or exited
	if (sender) {
		const char *msg = "EFI image returned\n";
		sender(context, GBL_EFI_FASTBOOT_MESSAGE_TYPE_FAIL, strlen(msg), msg);
	}
	return EFI_DEVICE_ERROR;
}

typedef efi_status_t (*fastboot_cmd_handler_t)(size_t download_buffer_used_size,
					      uint8_t *download_buffer,
					      FastbootMessageSender sender, void *context);

struct fastboot_cmd_match {
	const char *const *args;
	size_t num_args;
	fastboot_cmd_handler_t handler;
};

#define CMD_ENTRIES_2(cb, w1, w2) \
	{ \
		.args = (const char*const[]){w1, w2}, \
		.num_args = 2, \
		.handler = cb, \
	}, \
	{ \
		.args = (const char*const[]){w1 " " w2}, \
		.num_args = 1, \
		.handler = cb, \
	}

static const struct fastboot_cmd_match cmd_matches[] = {
	CMD_ENTRIES_2(handle_flash_bootloader, "flash", "bootloader"),
	CMD_ENTRIES_2(handle_run_staged_efi, "oem", "run-staged-efi"),
};

static efi_status_t EFIAPI command_exec(struct GblEfiFastbootProtocol *self,
					size_t num_args, const char *const *args,
					size_t download_buffer_size,
					size_t download_buffer_used_size,
					uint8_t *download_buffer,
					GblEfiFastbootCommandExecResult *implementation,
					FastbootMessageSender sender, void *context)
{
	EFI_ENTRY("%p, %zu, %p, %zu, %zu, %p", self, num_args, args,
		  download_buffer_size, download_buffer_used_size, download_buffer);

	if (num_args == 0 || !args || !implementation)
		return EFI_EXIT(EFI_INVALID_PARAMETER);

	// Default to not implemented by us
	*implementation = GBL_EFI_FASTBOOT_COMMAND_EXEC_RESULT_DEFAULT_IMPL;

	for (size_t i = 0; i < ARRAY_SIZE(cmd_matches); i++) {
		const struct fastboot_cmd_match *match = &cmd_matches[i];
		if (num_args < match->num_args)
			continue;

		bool found = true;
		for (size_t j = 0; j < match->num_args; j++) {
			if (strcmp(args[j], match->args[j]) != 0) {
				found = false;
				break;
			}
		}

		if (found) {
			*implementation = GBL_EFI_FASTBOOT_COMMAND_EXEC_RESULT_CUSTOM_IMPL;
			return EFI_EXIT(match->handler(download_buffer_used_size,
						      download_buffer,
						      sender, context));
		}
	}

	return EFI_EXIT(EFI_SUCCESS);
}

static const efi_guid_t guid = GBL_EFI_FASTBOOT_PROTOCOL_GUID;

static GblEfiFastbootProtocol protocol = {
	.revision = GBL_EFI_FASTBOOT_PROTOCOL_REVISION,
	.serial_number = "VIM3-GBL-FASTBOOT",
	.get_var = get_var,
	.get_var_all = get_var_all,
	.get_staged = get_staged,
	.command_exec = command_exec,
	.get_partition_type = get_partition_type,
};

efi_status_t efi_gbl_fastboot_register(void)
{
	char *serial = getenv("serial#");
	if (serial) {
		strncpy(protocol.serial_number, serial, sizeof(protocol.serial_number) - 1);
		protocol.serial_number[sizeof(protocol.serial_number) - 1] = '\0';
	}

	efi_status_t ret = efi_add_protocol(efi_root, &guid, (void *)&protocol);
	if (ret != EFI_SUCCESS)
		printf("Cannot install GBL_EFI_FASTBOOT_PROTOCOL\n");
	return ret;
}
