/*
 * Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
 *
 * 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 Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 * You can also choose to distribute this program under the terms of
 * the Unmodified Binary Distribution Licence (as given in the file
 * COPYING.UBDL), provided that you have satisfied its requirements.
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FILE_SECBOOT ( PERMITTED );

#include <string.h>
#include <errno.h>
#include <ipxe/timer.h>
#include <ipxe/image.h>
#include <ipxe/netdevice.h>
#include <ipxe/uri.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_utils.h>
#include <ipxe/efi/efi_autoexec.h>
#include <ipxe/efi/mnpnet.h>
#include <usr/imgmgmt.h>
#include <usr/sync.h>

/** @file
 *
 * EFI autoexec script
 *
 */

/** Timeout for autoexec script downloads */
#define EFI_AUTOEXEC_TIMEOUT ( 30 * TICKS_PER_SEC )

/** Timeout for autoexec pending operation completion */
#define EFI_AUTOEXEC_SYNC_TIMEOUT ( 1 * TICKS_PER_SEC )

/** Autoexec script image name */
#define EFI_AUTOEXEC_NAME "autoexec.ipxe"

/** An EFI autoexec script loader */
struct efi_autoexec_loader {
	/** Required protocol GUID */
	EFI_GUID *protocol;
	/**
	 * Load autoexec script
	 *
	 * @v handle		Handle on which protocol was found
	 * @v image		Image to fill in
	 * @ret rc		Return status code
	 */
	int ( * load ) ( EFI_HANDLE handle, struct image **image );
};

/**
 * Load autoexec script from filesystem
 *
 * @v handle		Simple filesystem protocol handle
 * @v image		Image to fill in
 * @ret rc		Return status code
 */
static int efi_autoexec_filesystem ( EFI_HANDLE handle, struct image **image ) {
	EFI_HANDLE device = efi_loaded_image->DeviceHandle;
	int rc;

	/* Check that we were loaded from a filesystem */
	if ( handle != device ) {
		DBGC ( device, "EFI %s is not the file system handle\n",
		       efi_handle_name ( device ) );
		return -ENOTTY;
	}

	/* Try loading from loaded image directory, if supported */
	if ( ( rc = imgacquire ( "file:" EFI_AUTOEXEC_NAME,
				 EFI_AUTOEXEC_TIMEOUT, image ) ) == 0 )
		return 0;

	/* Try loading from root directory, if supported */
	if ( ( rc = imgacquire ( "file:/" EFI_AUTOEXEC_NAME,
				 EFI_AUTOEXEC_TIMEOUT, image ) ) == 0 )
		return 0;

	return rc;
}

/**
 * Load autoexec script via temporary network device
 *
 * @v handle		Managed network protocol service binding handle
 * @v image		Image to fill in
 * @ret rc		Return status code
 */
static int efi_autoexec_network ( EFI_HANDLE handle, struct image **image ) {
	EFI_HANDLE device = efi_loaded_image->DeviceHandle;
	struct net_device *netdev;
	int rc;

	/* Create temporary network device */
	if ( ( rc = mnptemp_create ( handle, &netdev ) ) != 0 ) {
		DBGC ( device, "EFI %s could not create net device: %s\n",
		       efi_handle_name ( device ), strerror ( rc ) );
		goto err_create;
	}

	/* Do nothing unless we have a usable current working URI */
	if ( ! cwuri ) {
		DBGC ( device, "EFI %s has no current working URI\n",
		       efi_handle_name ( device ) );
		rc = -ENOTTY;
		goto err_cwuri;
	}

	/* Open network device */
	if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
		DBGC ( device, "EFI %s could not open net device: %s\n",
		       efi_handle_name ( device ), strerror ( rc ) );
		goto err_open;
	}

	/* Attempt download from current working URI, then from root */
	if ( ( ( rc = imgacquire ( EFI_AUTOEXEC_NAME, EFI_AUTOEXEC_TIMEOUT,
				   image ) ) != 0 ) &&
	     ( ( rc = imgacquire ( "/" EFI_AUTOEXEC_NAME, EFI_AUTOEXEC_TIMEOUT,
				   image ) ) != 0 ) ) {
		DBGC ( device, "EFI %s could not download [/]%s: %s\n",
		       efi_handle_name ( device ), EFI_AUTOEXEC_NAME,
		       strerror ( rc ) );
		goto err_acquire;
	}

 err_acquire:
	/* Ensure network exchanges have completed */
	sync ( EFI_AUTOEXEC_SYNC_TIMEOUT );
 err_open:
 err_cwuri:
	mnptemp_destroy ( netdev );
 err_create:
	return rc;
}

/** Autoexec script loaders */
static struct efi_autoexec_loader efi_autoexec_loaders[] = {
	{
		.protocol = &efi_simple_file_system_protocol_guid,
		.load = efi_autoexec_filesystem,
	},
	{
		.protocol = &efi_managed_network_service_binding_protocol_guid,
		.load = efi_autoexec_network,
	},
};

/**
 * Load autoexec script
 *
 * @ret rc		Return status code
 */
int efi_autoexec_load ( void ) {
	EFI_HANDLE device = efi_loaded_image->DeviceHandle;
	EFI_HANDLE handle;
	struct efi_autoexec_loader *loader;
	struct image *image;
	unsigned int i;
	int rc;

	/* Use first applicable loader */
	for ( i = 0 ; i < ( sizeof ( efi_autoexec_loaders ) /
			    sizeof ( efi_autoexec_loaders[0] ) ) ; i ++ ) {

		/* Locate required protocol for this loader */
		loader = &efi_autoexec_loaders[i];
		if ( ( rc = efi_locate_device ( device, loader->protocol,
						&handle, 0 ) ) != 0 ) {
			DBGC ( device, "EFI %s found no %s: %s\n",
			       efi_handle_name ( device ),
			       efi_guid_ntoa ( loader->protocol ),
			       strerror ( rc ) );
			continue;
		}
		DBGC ( device, "EFI %s found %s on ",
		       efi_handle_name ( device ),
		       efi_guid_ntoa ( loader->protocol ) );
		DBGC ( device, "%s\n", efi_handle_name ( handle ) );

		/* Try loading */
		if ( ( rc = loader->load ( handle, &image ) ) != 0 )
			continue;

		/* Discard zero-length images */
		if ( ! image->len ) {
			DBGC ( device, "EFI %s discarding zero-length %s\n",
			       efi_handle_name ( device ), image->name );
			unregister_image ( image );
			return -ENOENT;
		}

		DBGC ( device, "EFI %s loaded %s (%zd bytes)\n",
		       efi_handle_name ( device ), image->name, image->len );
		return 0;
	}

	return -ENOENT;
}
