/*
 * Copyright 2016 Google Inc.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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 (at your option) 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

#include "base/container_of.h"
#include "base/die.h"
#include "base/hexdump.h"
#include "base/init_funcs.h"
#include "base/list.h"
#include "base/xalloc.h"
#include "drivers/net/net.h"
#include "net/ethernet.h"

#include "uefi/edk/Protocol/SimpleNetwork.h"
#include "uefi/uefi.h"

static EFI_GUID uefi_simple_network_protocol_guid =
	EFI_SIMPLE_NETWORK_PROTOCOL_GUID;

typedef struct {
	NetDevice dev;
	ListNode list_node;

	int initialized;

	EFI_SIMPLE_NETWORK_PROTOCOL *snp;
	MacAddress mac;
} UefiNetDevice;

ListNode uefinet_devices;



static int uefinet_initialize(UefiNetDevice *dev)
{
	if (dev->initialized)
		return 0;

	EFI_SIMPLE_NETWORK_PROTOCOL *snp = dev->snp;
	EFI_SIMPLE_NETWORK_MODE *mode = snp->Mode;

	EFI_STATUS status;

	if (mode->State == EfiSimpleNetworkStopped) {
		status = snp->Start(snp);
		if (status != EFI_SUCCESS) {
			printf("Failed to start network device.\n");
			return 1;
		}
	}

	if (mode->State == EfiSimpleNetworkStarted) {
		status = snp->Initialize(snp, 0, 0);
		if (status != EFI_SUCCESS) {
			printf("Failed to initialize network device.\n");
			return 1;
		}
	}

	if (mode->State != EfiSimpleNetworkInitialized) {
		printf("Device was not initialized as expected.\n");
		return 1;
	}

	mode->ReceiveFilterSetting =
		EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
		EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
		EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
		EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
		EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;

	if (mode->HwAddressSize != sizeof(dev->mac)) {
		printf("Unexpected MAC size %d.\n", mode->HwAddressSize);
		return 1;
	}
	memcpy(&dev->mac, &mode->CurrentAddress, sizeof(dev->mac));

	dev->initialized = 1;
	return 0;
}

static int uefinet_ready(NetDevice *net_dev, int *ready)
{
	UefiNetDevice *dev = container_of(net_dev, UefiNetDevice, dev);
	EFI_SIMPLE_NETWORK_PROTOCOL *snp = dev->snp;

	if (uefinet_initialize(dev))
		return 1;

	UINT32 intStatus;
	VOID *txbufPtr;
	EFI_STATUS status = snp->GetStatus(snp, &intStatus, &txbufPtr);
	if (status != EFI_SUCCESS) {
		printf("Failed to get network device status.\n");
		return 1;
	}

	if (snp->Mode->MediaPresentSupported) {
		*ready = snp->Mode->MediaPresent;
	} else {
		printf("Device doesn't support the MediaPresent field.\n");
		*ready = 1;
	}

	return 0;
}

static int uefinet_recv(NetDevice *net_dev, void *buf, uint16_t *len,
			int maxlen)
{
	UefiNetDevice *dev = container_of(net_dev, UefiNetDevice, dev);
	EFI_SIMPLE_NETWORK_PROTOCOL *snp = dev->snp;

	if (uefinet_initialize(dev))
		return 1;

	// Try to receive until there's some data to return.
	UINTN buf_size = maxlen;
	EFI_STATUS status = snp->Receive(snp, NULL, &buf_size, buf,
					 NULL, NULL, NULL);
	if (status == EFI_NOT_READY) {
		*len = 0;
		return 0;
	} else {
		*len = buf_size;
	}

	if (status == EFI_BUFFER_TOO_SMALL) {
		printf("Packet receive buffer too small.\n");
		return 1;
	} else if (status != EFI_SUCCESS) {
		printf("Failed to receive packets from the device.\n");
		return 1;
	}

	return 0;
}

static int uefinet_send(NetDevice *net_dev, void *buf, uint16_t len)
{
	UefiNetDevice *dev = container_of(net_dev, UefiNetDevice, dev);
	EFI_SIMPLE_NETWORK_PROTOCOL *snp = dev->snp;

	if (uefinet_initialize(dev))
		return 1;

	EFI_STATUS status;
	// Try to send until the transmit request is accepted.
	do {
		status = snp->Transmit(snp, 0, len, buf, NULL, NULL, NULL);
	} while (status == EFI_NOT_READY);

	UINT32 intStatus;
	VOID *txbufPtr;
	do {
		status = snp->GetStatus(snp, &intStatus, &txbufPtr);
		if (status != EFI_SUCCESS) {
			printf("Failed to get network device status.\n");
			return 1;
		}
	} while (txbufPtr != buf);
	

	if (status != EFI_SUCCESS) {
		printf("Failed to transmit packets with the device.\n");
		return 1;
	}

	return 0;
}

static const MacAddress *uefinet_get_mac(NetDevice *net_dev)
{
	UefiNetDevice *dev = container_of(net_dev, UefiNetDevice, dev);

	if (uefinet_initialize(dev))
		return NULL;

	return &dev->mac;
}



static void uefi_net_create(EFI_SIMPLE_NETWORK_PROTOCOL *snp)
{
	UefiNetDevice *net = xzalloc(sizeof(*net));

	net->dev.ready = &uefinet_ready;
	net->dev.recv = &uefinet_recv;
	net->dev.send = &uefinet_send;
	net->dev.get_mac = &uefinet_get_mac;

	net->snp = snp;

	list_insert_after(&net->list_node, &uefinet_devices);
	net_add_device(&net->dev);
}

static void uefi_net_destroy(UefiNetDevice *net)
{
	net_remove_device(&net->dev);
	list_remove(&net->list_node);
	free(net);
}

static void uefi_net_poll(NetPoller *poller)
{
	// Destroy all the existing devices and recreate them. This is the
	// easiest way to ensure stale devices go away and new ones are found.
	UefiNetDevice *prev_dev = NULL;
	UefiNetDevice *net_dev;
	list_for_each(net_dev, uefinet_devices, list_node) {
		if (prev_dev)
			uefi_net_destroy(prev_dev);
		prev_dev = net_dev;
	}
	if (prev_dev)
		uefi_net_destroy(prev_dev);

	EFI_SYSTEM_TABLE *sys = uefi_system_table_ptr();
	assert(sys);
	EFI_BOOT_SERVICES *bs = sys->BootServices;

	UINTN buf_size = 0;
	EFI_HANDLE dummy_handle;
	EFI_STATUS status = bs->LocateHandle(
		ByProtocol, &uefi_simple_network_protocol_guid, NULL,
		&buf_size, &dummy_handle);

	// If no network devices were found, there's nothing more to do.
	if (status == EFI_NOT_FOUND)
		return;
	die_if(status != EFI_BUFFER_TOO_SMALL,
	       "Error retrieving network protocol handles.\n");

	EFI_HANDLE *handles = xmalloc(buf_size);

	status = bs->LocateHandle(
		ByProtocol, &uefi_simple_network_protocol_guid, NULL,
		&buf_size, handles);
	die_if(status != EFI_SUCCESS,
	       "Failed to retrieve network protocol handles.\n");

	int handle_count = buf_size / sizeof(dummy_handle);
	for (int i = 0; i < handle_count; i++) {
		EFI_SIMPLE_NETWORK_PROTOCOL *snp;
		status = bs->HandleProtocol(handles[i],
			&uefi_simple_network_protocol_guid, (void **)&snp);
		die_if(status != EFI_SUCCESS,
		       "Failed to get network protocol.\n");
		uefi_net_create(snp);
	}
}

static NetPoller uefinet_poller = {
	.poll = &uefi_net_poll,
};

static int uefinet_install_poller(void)
{
	list_insert_after(&uefinet_poller.list_node, &net_pollers);
	return 0;
}

INIT_FUNC(uefinet_install_poller);
