// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * An HTTP driver
 *
 * HTTP_PROTOCOL
 * HTTP_SERVICE_BINDING_PROTOCOL
 * IP4_CONFIG2_PROTOCOL
 */

#include <charset.h>
#include <efi_loader.h>
#include <image.h>
#include <malloc.h>
#include <mapmem.h>
#include <net.h>

static const efi_guid_t efi_http_service_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
static const efi_guid_t efi_http_guid = EFI_HTTP_PROTOCOL_GUID;

/**
 * struct efi_http_instance - EFI object representing an HTTP protocol instance
 *
 * @http:			EFI_HTTP_PROTOCOL interface
 * @handle:			handle to efi object
 * @configured:			configuration status
 * @http_load_addr:		data buffer
 * @file_size:			size of data
 * @current_offset:		offset in data buffer
 * @status_code:		HTTP status code
 * @num_headers:		number of received headers
 * @headers:			array of headers
 * @headers_buffer:		raw buffer with headers
 */
struct efi_http_instance {
	struct efi_http_protocol http;
	efi_handle_t handle;
	bool configured;
	void *http_load_addr;
	ulong file_size;
	ulong current_offset;
	u32 status_code;
	ulong num_headers;
	struct http_header headers[MAX_HTTP_HEADERS];
	char headers_buffer[MAX_HTTP_HEADERS_SIZE];
};

static int num_instances;

/*
 * efi_u32_to_httpstatus() - convert u32 to status
 *
 */
enum efi_http_status_code efi_u32_to_httpstatus(u32 status);

/*
 * efi_http_send_data() - sends data to client
 *
 *
 * @client_buffer:		client buffer to send data to
 * @client_buffer_size:		size of the client buffer
 * @inst:			HTTP instance for which to send data
 *
 * Return:	status code
 */
static efi_status_t efi_http_send_data(void *client_buffer,
				       efi_uintn_t *client_buffer_size,
				       struct efi_http_instance *inst)
{
	efi_status_t ret = EFI_SUCCESS;
	ulong total_size, transfer_size;
	uchar *ptr;

	// Amount of data left;
	total_size = inst->file_size;
	transfer_size = total_size - inst->current_offset;
	debug("efi_http: sending data to client, total size %lu\n", total_size);
	// Amount of data the client is willing to receive
	if (transfer_size > *client_buffer_size)
		transfer_size = *client_buffer_size;
	else
		*client_buffer_size = transfer_size;
	debug("efi_http: transfer size %lu\n", transfer_size);
	if (!transfer_size) // Ok, only headers
		goto out;

	if (!client_buffer) {
		ret = EFI_INVALID_PARAMETER;
		goto out;
	}

	// Send data
	ptr = (uchar *)inst->http_load_addr + inst->current_offset;
	memcpy(client_buffer, ptr, transfer_size);

	inst->current_offset += transfer_size;

	// Whole file served, clean the buffer:
	if (inst->current_offset == inst->file_size) {
		efi_free_pool(inst->http_load_addr);
		inst->http_load_addr = NULL;
		inst->current_offset = 0;
		inst->file_size = 0;
	}

out:
	return ret;
}

/* EFI_HTTP_PROTOCOL */

/*
 * efi_http_get_mode_data() - Gets the current operational status.
 *
 * This function implements EFI_HTTP_PROTOCOL.GetModeData().
 * See the Unified Extensible Firmware Interface
 * (UEFI) specification for details.
 *
 * @this:	pointer to the protocol instance
 * @data:	pointer to the buffer for operational parameters
 *		of this HTTP instance
 * Return:	status code
 */
static efi_status_t EFIAPI efi_http_get_mode_data(struct efi_http_protocol *this,
						  struct efi_http_config_data *data)
{
	EFI_ENTRY("%p, %p", this, data);

	efi_status_t ret = EFI_UNSUPPORTED;

	return EFI_EXIT(ret);
}

/*
 * efi_http_configure() - Initializes operational status for this
 * EFI HTTP instance.
 *
 * This function implements EFI_HTTP_PROTOCOL.Configure().
 * See the Unified Extensible Firmware Interface
 * (UEFI) specification for details.
 *
 * @this:	pointer to the protocol instance
 * @data:	pointer to the buffer for operational parameters of
 *		this HTTP instance
 * Return:	status code
 */
static efi_status_t EFIAPI efi_http_configure(struct efi_http_protocol *this,
					      struct efi_http_config_data *data)
{
	EFI_ENTRY("%p, %p", this, data);

	efi_status_t ret = EFI_SUCCESS;
	enum efi_http_version http_version;
	struct efi_httpv4_access_point *ipv4_node;
	struct efi_http_instance *http_instance;

	if (!this) {
		ret = EFI_INVALID_PARAMETER;
		goto out;
	}

	http_instance = (struct efi_http_instance *)this;

	if (!data) {
		efi_free_pool(http_instance->http_load_addr);
		http_instance->http_load_addr = NULL;
		http_instance->current_offset = 0;
		http_instance->configured = false;

		goto out;
	}

	if (http_instance->configured) {
		ret = EFI_ALREADY_STARTED;
		goto out;
	}

	http_version = data->http_version;
	ipv4_node = data->access_point.ipv4_node;

	if ((http_version != HTTPVERSION10 &&
	    http_version != HTTPVERSION11) ||
	    data->is_ipv6 || !ipv4_node) { /* Only support ipv4 */
		ret = EFI_UNSUPPORTED;
		goto out;
	}

	if (!ipv4_node->use_default_address) {
		efi_net_set_addr((struct efi_ipv4_address *)&ipv4_node->local_address,
				 (struct efi_ipv4_address *)&ipv4_node->local_subnet, NULL);
	}

	http_instance->current_offset = 0;
	http_instance->configured = true;

out:
	return EFI_EXIT(ret);
}

/*
 * efi_http_request() - Queues an HTTP request to this HTTP instance
 *
 * This function implements EFI_HTTP_PROTOCOL.Request().
 * See the Unified Extensible Firmware Interface
 * (UEFI) specification for details.
 *
 * @this:	pointer to the protocol instance
 * @token:	pointer to storage containing HTTP request token
 * Return:	status code
 */
static efi_status_t EFIAPI efi_http_request(struct efi_http_protocol *this,
					    struct efi_http_token *token)
{
	EFI_ENTRY("%p, %p", this, token);

	efi_status_t ret = EFI_SUCCESS;
	u8 *tmp;
	u8 url_8[1024];
	u16 *url_16;
	enum efi_http_method current_method;
	struct efi_http_instance *http_instance;

	if (!token || !this || !token->message ||
	    !token->message->data.request) {
		ret = EFI_INVALID_PARAMETER;
		goto out;
	}

	http_instance = (struct efi_http_instance *)this;

	if (!http_instance->configured) {
		ret = EFI_NOT_STARTED;
		goto out;
	}

	current_method = token->message->data.request->method;
	url_16 = token->message->data.request->url;

	/* Parse URL. It comes in UCS-2 encoding and follows RFC3986 */
	tmp = url_8;
	utf16_utf8_strncpy((char **)&tmp, url_16, 1024);

	ret = efi_net_do_request(url_8, current_method, &http_instance->http_load_addr,
				 &http_instance->status_code, &http_instance->file_size,
				 http_instance->headers_buffer);
	if (ret != EFI_SUCCESS)
		goto out;

	// We have a successful request
	efi_net_parse_headers(&http_instance->num_headers, http_instance->headers);
	http_instance->current_offset = 0;
	token->status = EFI_SUCCESS;
	goto out_signal;

out_signal:
	efi_signal_event(token->event);
out:
	return EFI_EXIT(ret);
}

/*
 * efi_http_cancel() - Abort an asynchronous HTTP request or response token
 *
 * This function implements EFI_HTTP_PROTOCOL.Cancel().
 * See the Unified Extensible Firmware Interface
 * (UEFI) specification for details.
 *
 * @this:	pointer to the protocol instance
 * @token:	pointer to storage containing HTTP request token
 * Return:	status code
 */
static efi_status_t EFIAPI efi_http_cancel(struct efi_http_protocol *this,
					   struct efi_http_token *token)
{
	EFI_ENTRY("%p, %p", this, token);

	efi_status_t ret = EFI_UNSUPPORTED;

	return EFI_EXIT(ret);
}

/*
 * efi_http_response() -  Queues an HTTP response to this HTTP instance
 *
 * This function implements EFI_HTTP_PROTOCOL.Response().
 * See the Unified Extensible Firmware Interface
 * (UEFI) specification for details.
 *
 * @this:	pointer to the protocol instance
 * @token:	pointer to storage containing HTTP request token
 * Return:	status code
 */
static efi_status_t EFIAPI efi_http_response(struct efi_http_protocol *this,
					     struct efi_http_token *token)
{
	EFI_ENTRY("%p, %p", this, token);

	efi_status_t ret = EFI_SUCCESS;
	struct efi_http_instance *http_instance;
	struct efi_http_header **client_headers;
	struct efi_http_response_data *response;

	if (!token || !this || !token->message) {
		ret = EFI_INVALID_PARAMETER;
		goto out;
	}

	http_instance = (struct efi_http_instance *)this;

	// Set HTTP status code
	if (token->message->data.response) { // TODO extra check, see spec.
		response = token->message->data.response;
		response->status_code = efi_u32_to_httpstatus(http_instance->status_code);
	}

	client_headers = &token->message->headers;

	ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA,
				(http_instance->num_headers) * sizeof(struct efi_http_header),
				(void **)client_headers); // This is deallocated by the client.
	if (ret != EFI_SUCCESS)
		goto out_bad_signal;

	// Send headers
	token->message->header_count = http_instance->num_headers;
	for (int i = 0; i < http_instance->num_headers; i++) {
		(*client_headers)[i].field_name = http_instance->headers[i].name;
		(*client_headers)[i].field_value = http_instance->headers[i].value;
	}

	ret = efi_http_send_data(token->message->body, &token->message->body_length, http_instance);
	if (ret != EFI_SUCCESS)
		goto out_bad_signal;

	token->status = EFI_SUCCESS;
	goto out_signal;

out_bad_signal:
	token->status = EFI_ABORTED;
out_signal:
	efi_signal_event(token->event);
out:
	return EFI_EXIT(ret);
}

/*
 * efi_http_poll() -  Polls for incoming data packets and processes outgoing data packets
 *
 * This function implements EFI_HTTP_PROTOCOL.Poll().
 * See the Unified Extensible Firmware Interface
 * (UEFI) specification for details.
 *
 * @this:	pointer to the protocol instance
 * @token:	pointer to storage containing HTTP request token
 * Return:	status code
 */
static efi_status_t EFIAPI efi_http_poll(struct efi_http_protocol *this)
{
	EFI_ENTRY("%p", this);

	efi_status_t ret = EFI_UNSUPPORTED;

	return EFI_EXIT(ret);
}

/* EFI_HTTP_SERVICE_BINDING_PROTOCOL */

/*
 * efi_http_service_binding_create_child() -  Creates a child handle
 * and installs a protocol
 *
 * This function implements EFI_HTTP_SERVICE_BINDING.CreateChild().
 * See the Unified Extensible Firmware Interface
 * (UEFI) specification for details.
 *
 * @this:		pointer to the protocol instance
 * @child_handle:	pointer to child handle
 * Return:		status code
 */
static efi_status_t EFIAPI efi_http_service_binding_create_child(
			struct efi_service_binding_protocol *this,
			efi_handle_t *child_handle)
{
	EFI_ENTRY("%p, %p", this, child_handle);

	efi_status_t ret = EFI_SUCCESS;
	struct efi_http_instance *new_instance;

	if (!child_handle)
		return EFI_EXIT(EFI_INVALID_PARAMETER);

	new_instance = calloc(1, sizeof(struct efi_http_instance));
	if (!new_instance) {
		ret = EFI_OUT_OF_RESOURCES;
		goto failure_to_add_protocol;
	}

	if (*child_handle) {
		new_instance->handle = *child_handle;
		goto install;
	}

	new_instance->handle = calloc(1, sizeof(struct efi_object));
	if (!new_instance->handle) {
		efi_free_pool((void *)new_instance);
		ret = EFI_OUT_OF_RESOURCES;
		goto failure_to_add_protocol;
	}

	efi_add_handle(new_instance->handle);
	*child_handle = new_instance->handle;

install:
	ret = efi_add_protocol(new_instance->handle, &efi_http_guid,
			       &new_instance->http);
	if (ret != EFI_SUCCESS)
		goto failure_to_add_protocol;

	new_instance->http.get_mode_data = efi_http_get_mode_data;
	new_instance->http.configure = efi_http_configure;
	new_instance->http.request = efi_http_request;
	new_instance->http.cancel = efi_http_cancel;
	new_instance->http.response = efi_http_response;
	new_instance->http.poll = efi_http_poll;
	++num_instances;

	return EFI_EXIT(EFI_SUCCESS);

failure_to_add_protocol:
	return EFI_EXIT(ret);
}

/*
 * efi_http_service_binding_destroy_child() -  Destroys a child handle with
 * a protocol installed on it
 *
 * This function implements EFI_HTTP_SERVICE_BINDING.DestroyChild().
 * See the Unified Extensible Firmware Interface
 * (UEFI) specification for details.
 *
 * @this:		pointer to the protocol instance
 * @child_handle:	child handle
 * Return:		status code
 */
static efi_status_t EFIAPI efi_http_service_binding_destroy_child(
			struct efi_service_binding_protocol *this,
			efi_handle_t child_handle)
{
	EFI_ENTRY("%p, %p", this, child_handle);
	efi_status_t ret = EFI_SUCCESS;
	struct efi_http_instance *http_instance;
	struct efi_handler *phandler;
	void *protocol_interface;

	if (num_instances == 0)
		return EFI_EXIT(EFI_NOT_FOUND);

	if (!child_handle)
		return EFI_EXIT(EFI_INVALID_PARAMETER);

	efi_search_protocol(child_handle, &efi_http_guid, &phandler);

	if (phandler)
		protocol_interface = phandler->protocol_interface;

	ret = efi_delete_handle(child_handle);
	if (ret != EFI_SUCCESS)
		return EFI_EXIT(ret);

	http_instance = (struct efi_http_instance *)protocol_interface;
	efi_free_pool(http_instance->http_load_addr);
	http_instance->http_load_addr = NULL;

	free(protocol_interface);

	num_instances--;

	return EFI_EXIT(EFI_SUCCESS);
}

/**
 * efi_http_register() - register the http protocol
 *
 */
efi_status_t efi_http_register(const efi_handle_t handle,
			       struct efi_service_binding_protocol *http_service_binding)
{
	efi_status_t r = EFI_SUCCESS;

	r = efi_add_protocol(handle, &efi_http_service_binding_guid,
			     http_service_binding);
	if (r != EFI_SUCCESS)
		goto failure_to_add_protocol;

	http_service_binding->create_child = efi_http_service_binding_create_child;
	http_service_binding->destroy_child = efi_http_service_binding_destroy_child;

	return EFI_SUCCESS;
failure_to_add_protocol:
	return r;
}

enum efi_http_status_code efi_u32_to_httpstatus(u32 status)
{
	switch (status) {
	case 100: return HTTP_STATUS_100_CONTINUE;
	case 101: return HTTP_STATUS_101_SWITCHING_PROTOCOLS;
	case 200: return HTTP_STATUS_200_OK;
	case 201: return HTTP_STATUS_201_CREATED;
	case 202: return HTTP_STATUS_202_ACCEPTED;
	case 203: return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION;
	case 204: return HTTP_STATUS_204_NO_CONTENT;
	case 205: return HTTP_STATUS_205_RESET_CONTENT;
	case 206: return HTTP_STATUS_206_PARTIAL_CONTENT;
	case 300: return HTTP_STATUS_300_MULTIPLE_CHOICES;
	case 301: return HTTP_STATUS_301_MOVED_PERMANENTLY;
	case 302: return HTTP_STATUS_302_FOUND;
	case 303: return HTTP_STATUS_303_SEE_OTHER;
	case 304: return HTTP_STATUS_304_NOT_MODIFIED;
	case 305: return HTTP_STATUS_305_USE_PROXY;
	case 307: return HTTP_STATUS_307_TEMPORARY_REDIRECT;
	case 400: return HTTP_STATUS_400_BAD_REQUEST;
	case 401: return HTTP_STATUS_401_UNAUTHORIZED;
	case 402: return HTTP_STATUS_402_PAYMENT_REQUIRED;
	case 403: return HTTP_STATUS_403_FORBIDDEN;
	case 404: return HTTP_STATUS_404_NOT_FOUND;
	case 405: return HTTP_STATUS_405_METHOD_NOT_ALLOWED;
	case 406: return HTTP_STATUS_406_NOT_ACCEPTABLE;
	case 407: return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED;
	case 408: return HTTP_STATUS_408_REQUEST_TIME_OUT;
	case 409: return HTTP_STATUS_409_CONFLICT;
	case 410: return HTTP_STATUS_410_GONE;
	case 411: return HTTP_STATUS_411_LENGTH_REQUIRED;
	case 412: return HTTP_STATUS_412_PRECONDITION_FAILED;
	case 413: return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE;
	case 414: return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE;
	case 415: return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE;
	case 416: return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED;
	case 417: return HTTP_STATUS_417_EXPECTATION_FAILED;
	case 500: return HTTP_STATUS_500_INTERNAL_SERVER_ERROR;
	case 501: return HTTP_STATUS_501_NOT_IMPLEMENTED;
	case 502: return HTTP_STATUS_502_BAD_GATEWAY;
	case 503: return HTTP_STATUS_503_SERVICE_UNAVAILABLE;
	case 504: return HTTP_STATUS_504_GATEWAY_TIME_OUT;
	case 505: return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED;
	case 308: return HTTP_STATUS_308_PERMANENT_REDIRECT;
	default: return HTTP_STATUS_UNSUPPORTED_STATUS;
	}
}
