/*
 * Copyright (C) 2010 VMware, Inc.  All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */

FILE_LICENCE ( GPL2_OR_LATER );

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ipxe/open.h>
#include <ipxe/process.h>
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_snp.h>
#include <ipxe/efi/efi_download.h>

/** iPXE download protocol GUID */
static EFI_GUID ipxe_download_protocol_guid
	= IPXE_DOWNLOAD_PROTOCOL_GUID;

/** A single in-progress file */
struct efi_download_file {
	/** Data transfer interface that provides downloaded data */
	struct interface xfer;

	/** Current file position */
	size_t pos;

	/** Data callback */
	IPXE_DOWNLOAD_DATA_CALLBACK data_callback;

	/** Finish callback */
	IPXE_DOWNLOAD_FINISH_CALLBACK finish_callback;

	/** Callback context */
	void *context;
};

/* xfer interface */

/**
 * Transfer finished or was aborted
 *
 * @v file		Data transfer file
 * @v rc		Reason for close
 */
static void efi_download_close ( struct efi_download_file *file, int rc ) {

	file->finish_callback ( file->context, EFIRC ( rc ) );

	intf_shutdown ( &file->xfer, rc );

	efi_snp_release();
}

/**
 * Process received data
 *
 * @v file		Data transfer file
 * @v iobuf		I/O buffer
 * @v meta		Data transfer metadata
 * @ret rc		Return status code
 */
static int efi_download_deliver_iob ( struct efi_download_file *file,
				      struct io_buffer *iobuf,
				      struct xfer_metadata *meta ) {
	EFI_STATUS efirc;
	size_t len = iob_len ( iobuf );
	int rc;

	/* Calculate new buffer position */
	if ( meta->flags & XFER_FL_ABS_OFFSET )
		file->pos = 0;
	file->pos += meta->offset;

	/* Call out to the data handler */
	if ( ( efirc = file->data_callback ( file->context, iobuf->data,
					     len, file->pos ) ) != 0 ) {
		rc = -EEFI ( efirc );
		goto err_callback;
	}

	/* Update current buffer position */
	file->pos += len;

	/* Success */
	rc = 0;

 err_callback:
	free_iob ( iobuf );
	return rc;
}

/** Data transfer interface operations */
static struct interface_operation efi_xfer_operations[] = {
	INTF_OP ( xfer_deliver, struct efi_download_file *, efi_download_deliver_iob ),
	INTF_OP ( intf_close, struct efi_download_file *, efi_download_close ),
};

/** EFI download data transfer interface descriptor */
static struct interface_descriptor efi_download_file_xfer_desc =
	INTF_DESC ( struct efi_download_file, xfer, efi_xfer_operations );

/**
 * Start downloading a file, and register callback functions to handle the
 * download.
 *
 * @v This		iPXE Download Protocol instance
 * @v Url		URL to download from
 * @v DataCallback	Callback that will be invoked when data arrives
 * @v FinishCallback	Callback that will be invoked when the download ends
 * @v Context		Context passed to the Data and Finish callbacks
 * @v File		Token that can be used to abort the download
 * @ret Status		EFI status code
 */
static EFI_STATUS EFIAPI
efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused,
		     CHAR8 *Url,
		     IPXE_DOWNLOAD_DATA_CALLBACK DataCallback,
		     IPXE_DOWNLOAD_FINISH_CALLBACK FinishCallback,
		     VOID *Context,
		     IPXE_DOWNLOAD_FILE *File ) {
	struct efi_download_file *file;
	int rc;

	efi_snp_claim();

	file = malloc ( sizeof ( struct efi_download_file ) );
	if ( file == NULL ) {
		efi_snp_release();
		return EFI_OUT_OF_RESOURCES;
	}

	intf_init ( &file->xfer, &efi_download_file_xfer_desc, NULL );
	rc = xfer_open ( &file->xfer, LOCATION_URI_STRING, Url );
	if ( rc ) {
		free ( file );
		efi_snp_release();
		return EFIRC ( rc );
	}

	file->pos = 0;
	file->data_callback = DataCallback;
	file->finish_callback = FinishCallback;
	file->context = Context;
	*File = file;
	return EFI_SUCCESS;
}

/**
 * Forcibly abort downloading a file that is currently in progress.
 *
 * It is not safe to call this function after the Finish callback has executed.
 *
 * @v This		iPXE Download Protocol instance
 * @v File		Token obtained from Start
 * @v Status		Reason for aborting the download
 * @ret Status		EFI status code
 */
static EFI_STATUS EFIAPI
efi_download_abort ( IPXE_DOWNLOAD_PROTOCOL *This __unused,
		     IPXE_DOWNLOAD_FILE File,
		     EFI_STATUS Status ) {
	struct efi_download_file *file = File;

	efi_download_close ( file, -EEFI ( Status ) );
	return EFI_SUCCESS;
}

/**
 * Poll for more data from iPXE. This function will invoke the registered
 * callbacks if data is available or if downloads complete.
 *
 * @v This		iPXE Download Protocol instance
 * @ret Status		EFI status code
 */
static EFI_STATUS EFIAPI
efi_download_poll ( IPXE_DOWNLOAD_PROTOCOL *This __unused ) {
	step();
	return EFI_SUCCESS;
}

/** Publicly exposed iPXE download protocol */
static IPXE_DOWNLOAD_PROTOCOL ipxe_download_protocol_interface = {
	.Start = efi_download_start,
	.Abort = efi_download_abort,
	.Poll = efi_download_poll
};

/**
 * Install iPXE download protocol
 *
 * @v handle		EFI handle
 * @ret rc		Return status code
 */
int efi_download_install ( EFI_HANDLE handle ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
	EFI_STATUS efirc;
	int rc;

	efirc = bs->InstallMultipleProtocolInterfaces (
			&handle,
			&ipxe_download_protocol_guid,
			&ipxe_download_protocol_interface,
			NULL );
	if ( efirc ) {
		rc = -EEFI ( efirc );
		DBG ( "Could not install download protocol: %s\n",
		      strerror ( rc ) );
		return rc;
	}

	return 0;
}

/**
 * Uninstall iPXE download protocol
 *
 * @v handle		EFI handle
 */
void efi_download_uninstall ( EFI_HANDLE handle ) {
	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;

	bs->UninstallMultipleProtocolInterfaces (
			handle,
			&ipxe_download_protocol_guid,
			&ipxe_download_protocol_interface, NULL );
}
