Add NetworkPkg (P.UDK2010.UP3.Network.P1)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10986 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
308
NetworkPkg/Mtftp6Dxe/ComponentName.c
Normal file
308
NetworkPkg/Mtftp6Dxe/ComponentName.c
Normal file
@@ -0,0 +1,308 @@
|
||||
/** @file
|
||||
UEFI Component Name(2) protocol implementation for Mtftp6 driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp6Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user-readable name of the driver.
|
||||
|
||||
This function retrieves the user-readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user-readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, and it must match one of the
|
||||
languages specified in SupportedLanguages. The
|
||||
number of languages supported by a driver is up
|
||||
to the driver writer. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] DriverName A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
driver specified by This in the language
|
||||
specified by Language.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user-readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user-readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user-readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] ControllerHandle The handle of a controller that the driver
|
||||
specified by This is managing. This handle
|
||||
specifies the controller whose name is to be
|
||||
returned.
|
||||
|
||||
@param[in] ChildHandle The handle of the child controller to retrieve
|
||||
the name of. This is an optional parameter that
|
||||
may be NULL. It will be NULL for device
|
||||
drivers. It will also be NULL for bus drivers
|
||||
attempting to retrieve the name of the bus
|
||||
controller. It will not be NULL for a bus
|
||||
driver that attempts to retrieve the name of a
|
||||
child controller.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, and it must match one of the
|
||||
languages specified in SupportedLanguages. The
|
||||
number of languages supported by a driver is up
|
||||
to the driver writer. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] ControllerName A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
controller specified by ControllerHandle and
|
||||
ChildHandle in the language specified by
|
||||
Language from the point of view of the driver
|
||||
specified by This.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the user-readable name in
|
||||
the language specified by Language for the
|
||||
driver specified by This was returned in
|
||||
DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gMtftp6ComponentName = {
|
||||
Mtftp6ComponentNameGetDriverName,
|
||||
Mtftp6ComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gMtftp6ComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Mtftp6ComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) Mtftp6ComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mMtftp6DriverNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"MTFTP6 Network Service Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user-readable name of the driver.
|
||||
|
||||
This function retrieves the user-readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user-readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, and it must match one of the
|
||||
languages specified in SupportedLanguages. The
|
||||
number of languages supported by a driver is up
|
||||
to the driver writer. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] DriverName A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
driver specified by This in the language
|
||||
specified by Language.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mMtftp6DriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gMtftp6ComponentName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user-readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user-readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user-readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] ControllerHandle The handle of a controller that the driver
|
||||
specified by This is managing. This handle
|
||||
specifies the controller whose name is to be
|
||||
returned.
|
||||
|
||||
@param[in] ChildHandle The handle of the child controller to retrieve
|
||||
the name of. This is an optional parameter that
|
||||
may be NULL. It will be NULL for device
|
||||
drivers. It will also be NULL for a bus drivers
|
||||
attempting to retrieve the name of the bus
|
||||
controller. It will not be NULL for a bus
|
||||
driver that attempts to retrieve the name of a
|
||||
child controller.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, and it must match one of the
|
||||
languages specified in SupportedLanguages. The
|
||||
number of languages supported by a driver is up
|
||||
to the driver writer. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] ControllerName A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
controller specified by ControllerHandle and
|
||||
ChildHandle in the language specified by
|
||||
Language from the point of view of the driver
|
||||
specified by This.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the user-readable name in
|
||||
the language specified by Language for the
|
||||
driver specified by This was returned in
|
||||
DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
703
NetworkPkg/Mtftp6Dxe/Mtftp6Driver.c
Normal file
703
NetworkPkg/Mtftp6Dxe/Mtftp6Driver.c
Normal file
@@ -0,0 +1,703 @@
|
||||
/** @file
|
||||
Driver Binding functions and Service Binding functions
|
||||
implementation for Mtftp6 Driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp6Impl.h"
|
||||
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gMtftp6DriverBinding = {
|
||||
Mtftp6DriverBindingSupported,
|
||||
Mtftp6DriverBindingStart,
|
||||
Mtftp6DriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
EFI_SERVICE_BINDING_PROTOCOL gMtftp6ServiceBindingTemplate = {
|
||||
Mtftp6ServiceBindingCreateChild,
|
||||
Mtftp6ServiceBindingDestroyChild
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Destory the MTFTP6 service. The MTFTP6 service may be partly initialized,
|
||||
or partly destroyed. If a resource is destroyed, it is marked as such in
|
||||
case the destroy failed and is called again later.
|
||||
|
||||
@param[in] Service The MTFTP6 service to be destroyed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp6DestroyService (
|
||||
IN MTFTP6_SERVICE *Service
|
||||
)
|
||||
{
|
||||
//
|
||||
// Make sure all children instances have been already destoryed.
|
||||
//
|
||||
ASSERT (Service->ChildrenNum == 0);
|
||||
|
||||
if (Service->DummyUdpIo != NULL) {
|
||||
UdpIoFreeIo (Service->DummyUdpIo);
|
||||
}
|
||||
|
||||
if (Service->Timer != NULL) {
|
||||
gBS->CloseEvent (Service->Timer);
|
||||
}
|
||||
|
||||
FreePool (Service);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create then initialize a MTFTP6 service binding instance.
|
||||
|
||||
@param[in] Controller The controller to install the MTFTP6 service
|
||||
binding on.
|
||||
@param[in] Image The driver binding image of the MTFTP6 driver.
|
||||
@param[out] Service The variable to receive the created service
|
||||
binding instance.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources to create the instance
|
||||
@retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep connection with UDP.
|
||||
@retval EFI_SUCCESS The service instance is created for the controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6CreateService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE Image,
|
||||
OUT MTFTP6_SERVICE **Service
|
||||
)
|
||||
{
|
||||
MTFTP6_SERVICE *Mtftp6Srv;
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (Service != NULL);
|
||||
|
||||
*Service = NULL;
|
||||
Mtftp6Srv = AllocateZeroPool (sizeof (MTFTP6_SERVICE));
|
||||
|
||||
if (Mtftp6Srv == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Mtftp6Srv->Signature = MTFTP6_SERVICE_SIGNATURE;
|
||||
Mtftp6Srv->Controller = Controller;
|
||||
Mtftp6Srv->Image = Image;
|
||||
Mtftp6Srv->InDestory = FALSE;
|
||||
Mtftp6Srv->ChildrenNum = 0;
|
||||
|
||||
CopyMem (
|
||||
&Mtftp6Srv->ServiceBinding,
|
||||
&gMtftp6ServiceBindingTemplate,
|
||||
sizeof (EFI_SERVICE_BINDING_PROTOCOL)
|
||||
);
|
||||
|
||||
InitializeListHead (&Mtftp6Srv->Children);
|
||||
|
||||
//
|
||||
// Create a internal timer for all instances.
|
||||
//
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
||||
TPL_CALLBACK,
|
||||
Mtftp6OnTimerTick,
|
||||
Mtftp6Srv,
|
||||
&Mtftp6Srv->Timer
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Mtftp6Srv);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a dummy Udp6Io to build parent-child relationship between Udp6 driver
|
||||
// and Mtftp6 driver.
|
||||
//
|
||||
Mtftp6Srv->DummyUdpIo = UdpIoCreateIo (
|
||||
Controller,
|
||||
Image,
|
||||
Mtftp6ConfigDummyUdpIo,
|
||||
UDP_IO_UDP6_VERSION,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (Mtftp6Srv->DummyUdpIo == NULL) {
|
||||
gBS->CloseEvent (Mtftp6Srv->Timer);
|
||||
FreePool (Mtftp6Srv);
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
*Service = Mtftp6Srv;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destroy the MTFTP6 instance and recycle the resources.
|
||||
|
||||
@param[in] Instance The pointer to the MTFTP6 instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp6DestroyInstance (
|
||||
IN MTFTP6_INSTANCE *Instance
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
MTFTP6_BLOCK_RANGE *Block;
|
||||
|
||||
if (Instance->Config != NULL) {
|
||||
FreePool (Instance->Config);
|
||||
}
|
||||
|
||||
if (Instance->Token != NULL && Instance->Token->Event != NULL) {
|
||||
gBS->SignalEvent (Instance->Token->Event);
|
||||
}
|
||||
|
||||
if (Instance->LastPacket != NULL) {
|
||||
NetbufFree (Instance->LastPacket);
|
||||
}
|
||||
|
||||
if (Instance->UdpIo!= NULL) {
|
||||
UdpIoFreeIo (Instance->UdpIo);
|
||||
}
|
||||
|
||||
if (Instance->McastUdpIo != NULL) {
|
||||
UdpIoFreeIo (Instance->McastUdpIo);
|
||||
}
|
||||
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->BlkList) {
|
||||
Block = NET_LIST_USER_STRUCT (Entry, MTFTP6_BLOCK_RANGE, Link);
|
||||
RemoveEntryList (Entry);
|
||||
FreePool (Block);
|
||||
}
|
||||
|
||||
FreePool (Instance);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create the MTFTP6 instance and initialize it.
|
||||
|
||||
@param[in] Service The pointer to the MTFTP6 service.
|
||||
@param[out] Instance The pointer to the MTFTP6 instance.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
|
||||
@retval EFI_SUCCESS The MTFTP6 instance is created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6CreateInstance (
|
||||
IN MTFTP6_SERVICE *Service,
|
||||
OUT MTFTP6_INSTANCE **Instance
|
||||
)
|
||||
{
|
||||
MTFTP6_INSTANCE *Mtftp6Ins;
|
||||
|
||||
*Instance = NULL;
|
||||
Mtftp6Ins = AllocateZeroPool (sizeof (MTFTP6_INSTANCE));
|
||||
|
||||
if (Mtftp6Ins == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Mtftp6Ins->Signature = MTFTP6_INSTANCE_SIGNATURE;
|
||||
Mtftp6Ins->InDestory = FALSE;
|
||||
Mtftp6Ins->Service = Service;
|
||||
|
||||
CopyMem (
|
||||
&Mtftp6Ins->Mtftp6,
|
||||
&gMtftp6ProtocolTemplate,
|
||||
sizeof (EFI_MTFTP6_PROTOCOL)
|
||||
);
|
||||
|
||||
InitializeListHead (&Mtftp6Ins->Link);
|
||||
InitializeListHead (&Mtftp6Ins->BlkList);
|
||||
|
||||
*Instance = Mtftp6Ins;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This is the declaration of an EFI image entry point. This entry point is
|
||||
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
|
||||
both device drivers and bus drivers.
|
||||
|
||||
Entry point of the MTFTP6 driver to install various protocols.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the UEFI image.
|
||||
@param[in] SystemTable The pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
return EfiLibInstallDriverBindingComponentName2 (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gMtftp6DriverBinding,
|
||||
ImageHandle,
|
||||
&gMtftp6ComponentName,
|
||||
&gMtftp6ComponentName2
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle. This service
|
||||
is called by the EFI boot service ConnectController(). In
|
||||
order to make drivers as small as possible, there are calling
|
||||
restrictions for this service. ConnectController() must
|
||||
follow these calling restrictions. If any other agent wishes to call
|
||||
Supported(), it must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to test
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child.
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver supports this device.
|
||||
@retval Others This driver does not support this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
return gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiUdp6ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service ConnectController(). In order to make
|
||||
drivers as small as possible, there are calling restrictions for
|
||||
this service. ConnectController() must follow these
|
||||
calling restrictions. If any other agent wishes to call Start() it
|
||||
must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to.
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver is added to ControllerHandle.
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
|
||||
@retval Others This driver does not support this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
MTFTP6_SERVICE *Service;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Directly return if driver is already running on this Nic handle.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiMtftp6ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Create Mtftp6 service for this Nic handle
|
||||
//
|
||||
Status = Mtftp6CreateService (
|
||||
Controller,
|
||||
This->DriverBindingHandle,
|
||||
&Service
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ASSERT (Service != NULL);
|
||||
|
||||
//
|
||||
// Start the internal timer to track the packet retransmission.
|
||||
//
|
||||
Status = gBS->SetTimer (
|
||||
Service->Timer,
|
||||
TimerPeriodic,
|
||||
TICKS_PER_SECOND
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Mtftp6 service on the Nic handle.
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Controller,
|
||||
&gEfiMtftp6ServiceBindingProtocolGuid,
|
||||
&Service->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
Mtftp6DestroyService (Service);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service DisconnectController(). In order to
|
||||
make drivers as small as possible, there are a few calling
|
||||
restrictions for this service. DisconnectController()
|
||||
must follow these calling restrictions. If any other agent wishes
|
||||
to call Stop() it must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to stop driver on
|
||||
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
||||
children is zero, stop the entire bus driver.
|
||||
@param[in] ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCESS This driver is removed ControllerHandle.
|
||||
@retval EFI_DEVICE_ERROR An unexpected error.
|
||||
@retval Others This driver was not removed from this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
MTFTP6_SERVICE *Service;
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// Locate the Nic handle to retrieve the Mtftp6 private data.
|
||||
//
|
||||
NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp6ProtocolGuid);
|
||||
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiMtftp6ServiceBindingProtocolGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
NicHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Service = MTFTP6_SERVICE_FROM_THIS (ServiceBinding);
|
||||
|
||||
if (Service->InDestory) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
if (NumberOfChildren == 0) {
|
||||
//
|
||||
// Destory the Mtftp6 service if there is no Mtftp6 child instance left.
|
||||
//
|
||||
Service->InDestory = TRUE;
|
||||
|
||||
gBS->UninstallProtocolInterface (
|
||||
NicHandle,
|
||||
&gEfiMtftp6ServiceBindingProtocolGuid,
|
||||
ServiceBinding
|
||||
);
|
||||
|
||||
Mtftp6DestroyService (Service);
|
||||
|
||||
} else {
|
||||
//
|
||||
// Destory the Mtftp6 child instance one by one.
|
||||
//
|
||||
while (!IsListEmpty (&Service->Children)) {
|
||||
Instance = NET_LIST_HEAD (&Service->Children, MTFTP6_INSTANCE, Link);
|
||||
Mtftp6ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);
|
||||
}
|
||||
|
||||
if (Service->ChildrenNum != 0) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a child handle and installs a protocol.
|
||||
|
||||
The CreateChild() function installs a protocol on ChildHandle.
|
||||
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
|
||||
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
|
||||
|
||||
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,
|
||||
then a new handle is created. If it is a pointer to an existing
|
||||
UEFI handle, then the protocol is added to the existing UEFI handle.
|
||||
|
||||
@retval EFI_SUCCES The protocol was added to ChildHandle.
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
|
||||
@retval Others The child handle was not created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN OUT EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
MTFTP6_SERVICE *Service;
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
VOID *Udp6;
|
||||
|
||||
if (This == NULL || ChildHandle == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Service = MTFTP6_SERVICE_FROM_THIS (This);
|
||||
|
||||
Status = Mtftp6CreateInstance (Service, &Instance);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ASSERT (Instance != NULL);
|
||||
|
||||
//
|
||||
// Install the Mtftp6 protocol on the new child handle.
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
ChildHandle,
|
||||
&gEfiMtftp6ProtocolGuid,
|
||||
&Instance->Mtftp6,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Instance->Handle = *ChildHandle;
|
||||
|
||||
//
|
||||
// Open the Udp6 protocol by child.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Service->DummyUdpIo->UdpHandle,
|
||||
&gEfiUdp6ProtocolGuid,
|
||||
(VOID **) &Udp6,
|
||||
gMtftp6DriverBinding.DriverBindingHandle,
|
||||
Instance->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
Instance->Handle,
|
||||
&gEfiMtftp6ProtocolGuid,
|
||||
&Instance->Mtftp6,
|
||||
NULL
|
||||
);
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Add the new Mtftp6 instance into the children list of Mtftp6 service.
|
||||
//
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
InsertTailList (&Service->Children, &Instance->Link);
|
||||
Service->ChildrenNum++;
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
Mtftp6DestroyInstance (Instance);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destroys a child handle with a protocol installed on it.
|
||||
|
||||
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
|
||||
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
|
||||
last protocol on ChildHandle, then ChildHandle is destroyed.
|
||||
|
||||
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param[in] ChildHandle Handle of the child to destroy.
|
||||
|
||||
@retval EFI_SUCCES The protocol was removed from ChildHandle.
|
||||
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
|
||||
@retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
|
||||
@retval Others The child handle was not destroyed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
MTFTP6_SERVICE *Service;
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
EFI_MTFTP6_PROTOCOL *Mtftp6;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (This == NULL || ChildHandle == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Locate the Nic handle to retrieve the Mtftp6 private data.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiMtftp6ProtocolGuid,
|
||||
(VOID **) &Mtftp6,
|
||||
gMtftp6DriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Instance = MTFTP6_INSTANCE_FROM_THIS (Mtftp6);
|
||||
Service = MTFTP6_SERVICE_FROM_THIS (This);
|
||||
|
||||
if (Instance->Service != Service) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether the instance already in destory state.
|
||||
//
|
||||
if (Instance->InDestory) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
Instance->InDestory = TRUE;
|
||||
|
||||
gBS->CloseProtocol (
|
||||
Service->DummyUdpIo->UdpHandle,
|
||||
&gEfiUdp6ProtocolGuid,
|
||||
gMtftp6DriverBinding.DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Uninstall the MTFTP6 protocol first to enable a top down destruction.
|
||||
//
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
ChildHandle,
|
||||
&gEfiMtftp6ProtocolGuid,
|
||||
Mtftp6
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
Instance->InDestory = FALSE;
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the Mtftp6 instance from the children list of Mtftp6 service.
|
||||
//
|
||||
RemoveEntryList (&Instance->Link);
|
||||
Service->ChildrenNum --;
|
||||
|
||||
Mtftp6DestroyInstance (Instance);
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
151
NetworkPkg/Mtftp6Dxe/Mtftp6Driver.h
Normal file
151
NetworkPkg/Mtftp6Dxe/Mtftp6Driver.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/** @file
|
||||
Driver Binding functions and Service Binding functions
|
||||
declaration for Mtftp6 Driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_MTFTP6_DRIVER_H__
|
||||
#define __EFI_MTFTP6_DRIVER_H__
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gMtftp6ComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gMtftp6ComponentName2;
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle. This service
|
||||
is called by the EFI boot service ConnectController(). In
|
||||
order to make drivers as small as possible, there are a few calling
|
||||
restrictions for this service. ConnectController() must
|
||||
follow these calling restrictions. If any other agent wishes to call
|
||||
Supported(), it must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to test.
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver supports this device.
|
||||
@retval Others This driver does not support this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service ConnectController(). In order to make
|
||||
drivers as small as possible, there are calling restrictions for
|
||||
this service. ConnectController() must follow these
|
||||
calling restrictions. If any other agent wishes to call Start() it
|
||||
must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to.
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver is added to ControllerHandle.
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
|
||||
@retval Others This driver does not support this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service DisconnectController(). In order to
|
||||
make drivers as small as possible, there are calling
|
||||
restrictions for this service. DisconnectController()
|
||||
must follow these calling restrictions. If any other agent wishes
|
||||
to call Stop(), it must also follow these calling restrictions.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to stop driver on
|
||||
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
||||
children is zero, stop the entire bus driver.
|
||||
@param[in] ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCESS This driver is removed ControllerHandle.
|
||||
@retval EFI_DEVICE_ERROR An unexpected error.
|
||||
@retval Others This driver was not removed from this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
Creates a child handle and installs a protocol.
|
||||
|
||||
The CreateChild() function installs a protocol on ChildHandle.
|
||||
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
|
||||
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
|
||||
|
||||
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,
|
||||
then a new handle is created. If it is a pointer to an existing
|
||||
UEFI handle, then the protocol is added to the existing UEFI handle.
|
||||
|
||||
@retval EFI_SUCCES The protocol was added to ChildHandle.
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
|
||||
@retval Others The child handle was not created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN OUT EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
/**
|
||||
Destroys a child handle with a protocol installed on it.
|
||||
|
||||
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
|
||||
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
|
||||
last protocol on ChildHandle, then ChildHandle is destroyed.
|
||||
|
||||
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param[in] ChildHandle Handle of the child to destroy.
|
||||
|
||||
@retval EFI_SUCCES The protocol was removed from ChildHandle.
|
||||
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
|
||||
@retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
|
||||
@retval Others The child handle was not destroyed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
|
||||
#endif
|
69
NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf
Normal file
69
NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf
Normal file
@@ -0,0 +1,69 @@
|
||||
## @file
|
||||
# Component description file for Mtftp6 module.
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Mtftp6Dxe
|
||||
FILE_GUID = 99F03B99-98D8-49dd-A8D3-3219D0FFE41E
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = Mtftp6DriverEntryPoint
|
||||
UNLOAD_IMAGE = NetLibDefaultUnload
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
# DRIVER_BINDING = gMtftp6DriverBinding
|
||||
# COMPONENT_NAME = gMtftp6ComponentName
|
||||
# COMPONENT_NAME2 = gMtftp6ComponentName2
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Mtftp6Driver.c
|
||||
Mtftp6Driver.h
|
||||
Mtftp6Impl.c
|
||||
Mtftp6Impl.h
|
||||
Mtftp6Option.c
|
||||
Mtftp6Option.h
|
||||
Mtftp6Support.h
|
||||
Mtftp6Support.c
|
||||
Mtftp6Rrq.c
|
||||
Mtftp6Wrq.c
|
||||
ComponentName.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiBootServicesTableLib
|
||||
UefiRuntimeServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
NetLib
|
||||
UdpIoLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiUdp6ServiceBindingProtocolGuid
|
||||
gEfiUdp6ProtocolGuid
|
||||
gEfiMtftp6ServiceBindingProtocolGuid
|
||||
gEfiMtftp6ProtocolGuid
|
||||
|
634
NetworkPkg/Mtftp6Dxe/Mtftp6Impl.c
Normal file
634
NetworkPkg/Mtftp6Dxe/Mtftp6Impl.c
Normal file
@@ -0,0 +1,634 @@
|
||||
/** @file
|
||||
This EFI_MTFTP6_PROTOCOL interface implementation.
|
||||
|
||||
It supports the following RFCs:
|
||||
RFC1350 - THE TFTP PROTOCOL (REVISION 2)
|
||||
RFC2090 - TFTP Multicast Option
|
||||
RFC2347 - TFTP Option Extension
|
||||
RFC2348 - TFTP Blocksize Option
|
||||
RFC2349 - TFTP Timeout Interval and Transfer Size Options
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp6Impl.h"
|
||||
|
||||
EFI_MTFTP6_PROTOCOL gMtftp6ProtocolTemplate = {
|
||||
EfiMtftp6GetModeData,
|
||||
EfiMtftp6Configure,
|
||||
EfiMtftp6GetInfo,
|
||||
EfiMtftp6ParseOptions,
|
||||
EfiMtftp6ReadFile,
|
||||
EfiMtftp6WriteFile,
|
||||
EfiMtftp6ReadDirectory,
|
||||
EfiMtftp6Poll
|
||||
};
|
||||
|
||||
/**
|
||||
Returns the current operating mode data for the MTFTP6 instance.
|
||||
|
||||
The GetModeData() function returns the current operating mode and
|
||||
cached data packet for the MTFTP6 instance.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[out] ModeData The buffer in which the EFI MTFTPv6 Protocol driver mode
|
||||
data is returned.
|
||||
|
||||
@retval EFI_SUCCESS The configuration data was returned successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL or ModeData is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6GetModeData (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
OUT EFI_MTFTP6_MODE_DATA *ModeData
|
||||
)
|
||||
{
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (This == NULL || ModeData == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
Instance = MTFTP6_INSTANCE_FROM_THIS (This);
|
||||
|
||||
//
|
||||
// Copy back the configure data if the instance already configured.
|
||||
//
|
||||
if (Instance->Config != NULL) {
|
||||
CopyMem (
|
||||
&ModeData->ConfigData,
|
||||
Instance->Config,
|
||||
sizeof (EFI_MTFTP6_CONFIG_DATA)
|
||||
);
|
||||
} else {
|
||||
ZeroMem (
|
||||
&ModeData->ConfigData,
|
||||
sizeof (EFI_MTFTP6_CONFIG_DATA)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Set the current support options in mode data.
|
||||
//
|
||||
ModeData->SupportedOptionCount = MTFTP6_SUPPORTED_OPTIONS_NUM;
|
||||
ModeData->SupportedOptions = (UINT8 **) mMtftp6SupportedOptions;
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initializes, changes, or resets the default operational setting for
|
||||
this EFI MTFTPv6 Protocol driver instance.
|
||||
|
||||
The Configure() function is used to set and change the configuration
|
||||
data for this EFI MTFTPv6 Protocol driver instance. The configuration
|
||||
data can be reset to startup defaults by calling Configure() with
|
||||
MtftpConfigData set to NULL. Whenever the instance is reset, any
|
||||
pending operation is aborted. By changing the EFI MTFTPv6 Protocol
|
||||
driver instance configuration data, the client can connect to
|
||||
different MTFTPv6 servers. The configuration parameters in
|
||||
MtftpConfigData are used as the default parameters in later MTFTPv6
|
||||
operations and can be overridden in later operations.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] MtftpConfigData Pointer to the configuration data structure.
|
||||
|
||||
@retval EFI_SUCCESS The EFI MTFTPv6 Protocol instance was configured successfully.
|
||||
@retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
|
||||
- This is NULL.
|
||||
- MtftpConfigData.StationIp is neither zero nor one
|
||||
of the configured IP addresses in the underlying IPv6 driver.
|
||||
- MtftpCofigData.ServerIp is not a valid IPv6 unicast address.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_ACCESS_DENIED - The configuration could not be changed at this time because there
|
||||
is some MTFTP background operation in progress.
|
||||
- MtftpCofigData.LocalPort is already in use.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_OUT_OF_RESOURCES The EFI MTFTPv6 Protocol driver instance data could not be
|
||||
allocated.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI
|
||||
MTFTPv6 Protocol driver instance is not configured.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6Configure (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_CONFIG_DATA *MtftpConfigData OPTIONAL
|
||||
)
|
||||
{
|
||||
MTFTP6_SERVICE *Service;
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
EFI_UDP6_PROTOCOL *Udp6;
|
||||
EFI_UDP6_CONFIG_DATA Udp6Cfg;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (MtftpConfigData != NULL && !NetIp6IsValidUnicast (&MtftpConfigData->ServerIp)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
Instance = MTFTP6_INSTANCE_FROM_THIS (This);
|
||||
Service = Instance->Service;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
if (MtftpConfigData == NULL) {
|
||||
//
|
||||
// Configure the instance as NULL to abort the current session.
|
||||
//
|
||||
Mtftp6OperationClean (Instance, EFI_ABORTED);
|
||||
FreePool (Instance->Config);
|
||||
Instance->Config = NULL;
|
||||
} else {
|
||||
//
|
||||
// It's not allowed to configure one instance twice without configure null.
|
||||
//
|
||||
if (Instance->Config != NULL) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Allocate the configure buffer of the instance and store the user's data.
|
||||
//
|
||||
Instance->Config = AllocateZeroPool (sizeof (EFI_MTFTP6_CONFIG_DATA));
|
||||
|
||||
if (Instance->Config == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
CopyMem (Instance->Config, MtftpConfigData, sizeof (EFI_MTFTP6_CONFIG_DATA));
|
||||
|
||||
//
|
||||
// Don't configure the udpio here because each operation might override
|
||||
// the configuration, so delay udpio configuration in each operation.
|
||||
//
|
||||
Instance->UdpIo = UdpIoCreateIo (
|
||||
Service->Controller,
|
||||
Service->Image,
|
||||
Mtftp6ConfigDummyUdpIo,
|
||||
UDP_IO_UDP6_VERSION,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (Instance->UdpIo == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Continue to configure the downside Udp6 instance by user's data.
|
||||
//
|
||||
ZeroMem (&Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
|
||||
|
||||
Udp6Cfg.AcceptPromiscuous = FALSE;
|
||||
Udp6Cfg.AcceptAnyPort = FALSE;
|
||||
Udp6Cfg.AllowDuplicatePort = FALSE;
|
||||
Udp6Cfg.TrafficClass = 0;
|
||||
Udp6Cfg.HopLimit = 128;
|
||||
Udp6Cfg.ReceiveTimeout = 0;
|
||||
Udp6Cfg.TransmitTimeout = 0;
|
||||
Udp6Cfg.StationPort = Instance->Config->LocalPort;
|
||||
Udp6Cfg.RemotePort = Instance->Config->InitialServerPort;
|
||||
|
||||
CopyMem (
|
||||
&Udp6Cfg.StationAddress,
|
||||
&Instance->Config->StationIp,
|
||||
sizeof(EFI_IPv6_ADDRESS)
|
||||
);
|
||||
|
||||
CopyMem (
|
||||
&Udp6Cfg.RemoteAddress,
|
||||
&Instance->Config->ServerIp,
|
||||
sizeof (EFI_IPv6_ADDRESS)
|
||||
);
|
||||
|
||||
Udp6 = Instance->UdpIo->Protocol.Udp6;
|
||||
Status = Udp6->Configure (Udp6, &Udp6Cfg);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
if (EFI_ERROR (Status)) {
|
||||
if (Instance->Config != NULL) {
|
||||
FreePool (Instance->Config);
|
||||
Instance->Config = NULL;
|
||||
}
|
||||
if (Instance->UdpIo != NULL) {
|
||||
UdpIoFreeIo (Instance->UdpIo);
|
||||
Instance->UdpIo = NULL;
|
||||
}
|
||||
}
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the information of the download from the server.
|
||||
|
||||
The GetInfo() function assembles an MTFTPv6 request packet
|
||||
with options, sends it to the MTFTPv6 server, and may return
|
||||
an MTFTPv6 OACK, MTFTPv6 ERROR, or ICMP ERROR packet. Retries
|
||||
occur only if no response packets are received from the MTFTPv6
|
||||
server before the timeout expires.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] OverrideData Data that is used to override the existing parameters. If NULL, the
|
||||
default parameters that were set in the EFI_MTFTP6_PROTOCOL.Configure()
|
||||
function are used.
|
||||
@param[in] Filename Pointer to ASCIIZ file name string.
|
||||
@param[in] ModeStr Pointer to ASCIIZ mode string. If NULL, octet will be used.
|
||||
@param[in] OptionCount Number of option/value string pairs in OptionList.
|
||||
@param[in] OptionList Pointer to array of option/value string pairs. Ignored if
|
||||
OptionCount is zero.
|
||||
@param[out] PacketLength The number of bytes in the returned packet.
|
||||
@param[out] Packet The pointer to the received packet. This buffer must be freed by
|
||||
the caller.
|
||||
|
||||
@retval EFI_SUCCESS An MTFTPv6 OACK packet was received and is in the Packet.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Filename is NULL.
|
||||
- OptionCount is not zero and OptionList is NULL.
|
||||
- One or more options in OptionList have wrong format.
|
||||
- PacketLength is NULL.
|
||||
- OverrideData.ServerIp is not valid unicast IPv6 addresses.
|
||||
@retval EFI_UNSUPPORTED One or more options in the OptionList are unsupported by
|
||||
this implementation.
|
||||
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
|
||||
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
||||
@retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received and is in the Packet.
|
||||
@retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received and the Packet is set to NULL.
|
||||
Note: It is not defined in UEFI 2.3 Specification.
|
||||
@retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received and the Packet is set to NULL.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received and the Packet is set to NULL.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received and the Packet is set to NULL.
|
||||
@retval EFI_ICMP_ERROR Some other ICMP ERROR packet was received and the Packet is set to NULL.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received and is in the Packet.
|
||||
@retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
|
||||
@retval EFI_NO_MEDIA There was a media error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6GetInfo (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_OVERRIDE_DATA *OverrideData OPTIONAL,
|
||||
IN UINT8 *Filename,
|
||||
IN UINT8 *ModeStr OPTIONAL,
|
||||
IN UINT8 OptionCount,
|
||||
IN EFI_MTFTP6_OPTION *OptionList OPTIONAL,
|
||||
OUT UINT32 *PacketLength,
|
||||
OUT EFI_MTFTP6_PACKET **Packet OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_MTFTP6_TOKEN Token;
|
||||
MTFTP6_GETINFO_CONTEXT Context;
|
||||
|
||||
if (This == NULL ||
|
||||
Filename == NULL ||
|
||||
PacketLength == NULL ||
|
||||
(OptionCount != 0 && OptionList == NULL) ||
|
||||
(OverrideData != NULL && !NetIp6IsValidUnicast (&OverrideData->ServerIp))
|
||||
) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Packet != NULL) {
|
||||
*Packet = NULL;
|
||||
}
|
||||
|
||||
*PacketLength = 0;
|
||||
|
||||
Context.Packet = Packet;
|
||||
Context.PacketLen = PacketLength;
|
||||
Context.Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Fill fields of the Token for GetInfo operation.
|
||||
//
|
||||
Token.Status = EFI_SUCCESS;
|
||||
Token.Event = NULL;
|
||||
Token.OverrideData = OverrideData;
|
||||
Token.Filename = Filename;
|
||||
Token.ModeStr = ModeStr;
|
||||
Token.OptionCount = OptionCount;
|
||||
Token.OptionList = OptionList;
|
||||
Token.BufferSize = 0;
|
||||
Token.Buffer = NULL;
|
||||
Token.Context = &Context;
|
||||
Token.CheckPacket = Mtftp6CheckPacket;
|
||||
Token.TimeoutCallback = NULL;
|
||||
Token.PacketNeeded = NULL;
|
||||
|
||||
//
|
||||
// Start the GetInfo operation by issue the Token.
|
||||
//
|
||||
Status = Mtftp6OperationStart (This, &Token, EFI_MTFTP6_OPCODE_RRQ);
|
||||
|
||||
if (Status == EFI_ABORTED) {
|
||||
//
|
||||
// Return the status if failed to issue.
|
||||
//
|
||||
return Context.Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the options in an MTFTPv6 OACK packet.
|
||||
|
||||
The ParseOptions() function parses the option fields in an MTFTPv6 OACK
|
||||
packet and returns the number of options that were found, and optionally,
|
||||
a list of pointers to the options in the packet. If one or more of the
|
||||
option fields are not valid, then EFI_PROTOCOL_ERROR is returned and
|
||||
*OptionCount and *OptionList stop at the last valid option.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] PacketLen Length of the OACK packet to be parsed.
|
||||
@param[in] Packet Pointer to the OACK packet to be parsed.
|
||||
@param[out] OptionCount Pointer to the number of options in the following OptionList.
|
||||
@param[out] OptionList Pointer to EFI_MTFTP6_OPTION storage. Each pointer in the
|
||||
OptionList points to the corresponding MTFTP option buffer
|
||||
in the Packet. Call the EFI Boot Service FreePool() to
|
||||
release the OptionList if the options in this OptionList
|
||||
are not needed anymore.
|
||||
|
||||
@retval EFI_SUCCESS The OACK packet was valid and the OptionCount and
|
||||
OptionList parameters have been updated.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- PacketLen is 0.
|
||||
- Packet is NULL or Packet is not a valid MTFTPv6 packet.
|
||||
- OptionCount is NULL.
|
||||
@retval EFI_NOT_FOUND No options were found in the OACK packet.
|
||||
@retval EFI_OUT_OF_RESOURCES Storage for the OptionList array can not be allocated.
|
||||
@retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6ParseOptions (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN UINT32 PacketLen,
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
OUT UINT32 *OptionCount,
|
||||
OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
|
||||
)
|
||||
{
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return Mtftp6ParseStart (Packet, PacketLen, OptionCount, OptionList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Download a file from an MTFTPv6 server.
|
||||
|
||||
The ReadFile() function is used to initialize and start an MTFTPv6 download
|
||||
process, and optionally, wait for completion. When the download operation
|
||||
completes, whether successfully or not, the Token.Status field is updated
|
||||
by the EFI MTFTPv6 Protocol driver, and then Token.Event is signaled if it
|
||||
is not NULL.
|
||||
Data can be downloaded from the MTFTPv6 server into either of the following
|
||||
locations:
|
||||
- A fixed buffer that is pointed to by Token.Buffer
|
||||
- A download service function that is pointed to by Token.CheckPacket.
|
||||
If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
|
||||
will be called first. If the call is successful, the packet will be stored
|
||||
in Token.Buffer.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] Token Pointer to the token structure to provide the parameters that are
|
||||
used in this operation.
|
||||
|
||||
@retval EFI_SUCCESS The data file has been transferred successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
||||
@retval EFI_BUFFER_TOO_SMALL BufferSize is not zero but not large enough to hold the
|
||||
downloaded data in downloading process.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_ABORTED Current operation is aborted by user.
|
||||
@retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_ICMP_ERROR An ICMP ERROR packet was received.
|
||||
@retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
|
||||
@retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
|
||||
@retval EFI_NO_MEDIA There was a media error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6ReadFile (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_TOKEN *Token
|
||||
)
|
||||
{
|
||||
return Mtftp6OperationStart (This, Token, EFI_MTFTP6_OPCODE_RRQ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send a file to an MTFTPv6 server.
|
||||
|
||||
The WriteFile() function is used to initialize an uploading operation
|
||||
with the given option list and optionally wait for completion. If one
|
||||
or more of the options is not supported by the server, the unsupported
|
||||
options are ignored and a standard TFTP process starts instead. When
|
||||
the upload process completes, whether successfully or not, Token.Event
|
||||
is signaled, and the EFI MTFTPv6 Protocol driver updates Token.Status.
|
||||
The caller can supply the data to be uploaded in the following two modes:
|
||||
- Through the user-provided buffer
|
||||
- Through a callback function
|
||||
With the user-provided buffer, the Token.BufferSize field indicates
|
||||
the length of the buffer, and the driver will upload the data in the
|
||||
buffer. With an EFI_MTFTP6_PACKET_NEEDED callback function, the driver
|
||||
will call this callback function to get more data from the user to upload.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] Token Pointer to the token structure to provide the parameters that are
|
||||
used in this operation.
|
||||
|
||||
@retval EFI_SUCCESS The upload session has started.
|
||||
@retval EFI_UNSUPPORTED The operation is not supported by this implementation.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Token is NULL.
|
||||
- Token.Filename is NULL.
|
||||
- Token.OptionCount is not zero and Token.OptionList is NULL.
|
||||
- One or more options in Token.OptionList have wrong format.
|
||||
- Token.Buffer and Token.PacketNeeded are both NULL.
|
||||
- Token.OverrideData.ServerIp is not a valid unicast IPv6 address.
|
||||
@retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
|
||||
supported by this implementation.
|
||||
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
|
||||
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
||||
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6WriteFile (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_TOKEN *Token
|
||||
)
|
||||
{
|
||||
return Mtftp6OperationStart (This, Token, EFI_MTFTP6_OPCODE_WRQ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Download a data file directory from an MTFTPv6 server.
|
||||
|
||||
The ReadDirectory() function is used to return a list of files on the
|
||||
MTFTPv6 server that are logically (or operationally) related to
|
||||
Token.Filename. The directory request packet that is sent to the server
|
||||
is built with the option list that was provided by the caller, if present.
|
||||
The file information that the server returns is put into either of
|
||||
the following locations:
|
||||
- A fixed buffer that is pointed to by Token.Buffer.
|
||||
- A download service function that is pointed to by Token.CheckPacket.
|
||||
If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
|
||||
will be called first. If the call is successful, the packet will be stored
|
||||
in Token.Buffer.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] Token Pointer to the token structure to provide the parameters that are
|
||||
used in this operation.
|
||||
|
||||
@retval EFI_SUCCESS The MTFTPv6 related file "directory" has been downloaded.
|
||||
@retval EFI_UNSUPPORTED The EFI MTFTPv6 Protocol driver does not support this function.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Token is NULL.
|
||||
- Token.Filename is NULL.
|
||||
- Token.OptionCount is not zero and Token.OptionList is NULL.
|
||||
- One or more options in Token.OptionList have wrong format.
|
||||
- Token.Buffer and Token.CheckPacket are both NULL.
|
||||
- Token.OverrideData.ServerIp is not valid unicast IPv6 addresses.
|
||||
@retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
|
||||
supported by this implementation.
|
||||
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
|
||||
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
||||
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6ReadDirectory (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_TOKEN *Token
|
||||
)
|
||||
{
|
||||
return Mtftp6OperationStart (This, Token, EFI_MTFTP6_OPCODE_DIR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Polls for incoming data packets and processes outgoing data packets.
|
||||
|
||||
The Poll() function can be used by network drivers and applications
|
||||
to increase the rate that data packets are moved between the
|
||||
communications device and the transmit and receive queues. In some
|
||||
systems, the periodic timer event in the managed network driver may
|
||||
not poll the underlying communications device fast enough to transmit
|
||||
and/or receive all data packets without missing incoming packets or
|
||||
dropping outgoing packets. Drivers and applications that are
|
||||
experiencing packet loss should try calling the Poll() function
|
||||
more often.
|
||||
|
||||
@param[in] This The MTFTP6 protocol instance.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS Incoming or outgoing data was processed.
|
||||
@retval EFI_NOT_STARTED This EFI MTFTPv6 Protocol instance has not been started.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
@retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
|
||||
Consider increasing the polling rate.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6Poll (
|
||||
IN EFI_MTFTP6_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
EFI_UDP6_PROTOCOL *Udp6;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Instance = MTFTP6_INSTANCE_FROM_THIS (This);
|
||||
|
||||
//
|
||||
// Check the instance whether configured or in destory.
|
||||
//
|
||||
if (Instance->Config == NULL) {
|
||||
return EFI_NOT_STARTED;
|
||||
} else if (Instance->InDestory) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Udp6 = Instance->UdpIo->Protocol.Udp6;
|
||||
|
||||
return Udp6->Poll (Udp6);
|
||||
}
|
469
NetworkPkg/Mtftp6Dxe/Mtftp6Impl.h
Normal file
469
NetworkPkg/Mtftp6Dxe/Mtftp6Impl.h
Normal file
@@ -0,0 +1,469 @@
|
||||
/** @file
|
||||
Mtftp6 internal data structure and definition declaration.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_MTFTP6_IMPL_H__
|
||||
#define __EFI_MTFTP6_IMPL_H__
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/Udp6.h>
|
||||
#include <Protocol/Mtftp6.h>
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
#include <Protocol/DriverBinding.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/NetLib.h>
|
||||
|
||||
typedef struct _MTFTP6_SERVICE MTFTP6_SERVICE;
|
||||
typedef struct _MTFTP6_INSTANCE MTFTP6_INSTANCE;
|
||||
|
||||
#include "Mtftp6Driver.h"
|
||||
#include "Mtftp6Option.h"
|
||||
#include "Mtftp6Support.h"
|
||||
|
||||
#define MTFTP6_SERVICE_SIGNATURE SIGNATURE_32 ('M', 'F', '6', 'S')
|
||||
#define MTFTP6_INSTANCE_SIGNATURE SIGNATURE_32 ('M', 'F', '6', 'I')
|
||||
|
||||
#define MTFTP6_DEFAULT_SERVER_CMD_PORT 69
|
||||
#define MTFTP6_DEFAULT_TIMEOUT 3
|
||||
#define MTFTP6_GET_MAPPING_TIMEOUT 3
|
||||
#define MTFTP6_DEFAULT_MAX_RETRY 5
|
||||
#define MTFTP6_DEFAULT_BLK_SIZE 512
|
||||
#define MTFTP6_TICK_PER_SECOND 10000000U
|
||||
|
||||
#define MTFTP6_SERVICE_FROM_THIS(a) CR (a, MTFTP6_SERVICE, ServiceBinding, MTFTP6_SERVICE_SIGNATURE)
|
||||
#define MTFTP6_INSTANCE_FROM_THIS(a) CR (a, MTFTP6_INSTANCE, Mtftp6, MTFTP6_INSTANCE_SIGNATURE)
|
||||
|
||||
extern EFI_MTFTP6_PROTOCOL gMtftp6ProtocolTemplate;
|
||||
|
||||
typedef struct _MTFTP6_GETINFO_CONTEXT{
|
||||
EFI_MTFTP6_PACKET **Packet;
|
||||
UINT32 *PacketLen;
|
||||
EFI_STATUS Status;
|
||||
} MTFTP6_GETINFO_CONTEXT;
|
||||
|
||||
//
|
||||
// Control block for MTFTP6 instance, it's per configuration data.
|
||||
//
|
||||
struct _MTFTP6_INSTANCE {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE Handle;
|
||||
LIST_ENTRY Link;
|
||||
EFI_MTFTP6_PROTOCOL Mtftp6;
|
||||
MTFTP6_SERVICE *Service;
|
||||
EFI_MTFTP6_CONFIG_DATA *Config;
|
||||
|
||||
EFI_MTFTP6_TOKEN *Token;
|
||||
MTFTP6_EXT_OPTION_INFO ExtInfo;
|
||||
|
||||
UINT16 BlkSize;
|
||||
UINT16 LastBlk;
|
||||
LIST_ENTRY BlkList;
|
||||
|
||||
EFI_IPv6_ADDRESS ServerIp;
|
||||
UINT16 ServerCmdPort;
|
||||
UINT16 ServerDataPort;
|
||||
UDP_IO *UdpIo;
|
||||
|
||||
EFI_IPv6_ADDRESS McastIp;
|
||||
UINT16 McastPort;
|
||||
UDP_IO *McastUdpIo;
|
||||
|
||||
NET_BUF *LastPacket;
|
||||
UINT32 CurRetry;
|
||||
UINT32 MaxRetry;
|
||||
UINT32 PacketToLive;
|
||||
UINT32 Timeout;
|
||||
|
||||
EFI_TPL OldTpl;
|
||||
BOOLEAN IsTransmitted;
|
||||
BOOLEAN IsMaster;
|
||||
BOOLEAN InDestory;
|
||||
};
|
||||
|
||||
//
|
||||
// Control block for MTFTP6 service, it's per Nic handle.
|
||||
//
|
||||
struct _MTFTP6_SERVICE {
|
||||
UINT32 Signature;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
EFI_HANDLE Controller;
|
||||
EFI_HANDLE Image;
|
||||
|
||||
UINT16 ChildrenNum;
|
||||
LIST_ENTRY Children;
|
||||
//
|
||||
// It is used to be as internal calculagraph for all instances.
|
||||
//
|
||||
EFI_EVENT Timer;
|
||||
//
|
||||
// It is used to maintain the parent-child relationship between
|
||||
// mtftp driver and udp driver.
|
||||
//
|
||||
UDP_IO *DummyUdpIo;
|
||||
BOOLEAN InDestory;
|
||||
};
|
||||
|
||||
/**
|
||||
Returns the current operating mode data for the MTFTP6 instance.
|
||||
|
||||
The GetModeData() function returns the current operating mode and
|
||||
cached data packet for the MTFTP6 instance.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[out] ModeData The buffer in which the EFI MTFTPv6 Protocol driver mode
|
||||
data is returned.
|
||||
|
||||
@retval EFI_SUCCESS The configuration data was returned successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL, or ModeData is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6GetModeData (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
OUT EFI_MTFTP6_MODE_DATA *ModeData
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes, changes, or resets the default operational setting for
|
||||
this EFI MTFTPv6 Protocol driver instance.
|
||||
|
||||
The Configure() function is used to set and change the configuration
|
||||
data for this EFI MTFTPv6 Protocol driver instance. The configuration
|
||||
data can be reset to startup defaults by calling Configure() with
|
||||
MtftpConfigData set to NULL. Whenever the instance is reset, any
|
||||
pending operation is aborted. By changing the EFI MTFTPv6 Protocol
|
||||
driver instance configuration data, the client can connect to
|
||||
different MTFTPv6 servers. The configuration parameters in
|
||||
MtftpConfigData are used as the default parameters in later MTFTPv6
|
||||
operations and can be overridden in later operations.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] MtftpConfigData Pointer to the configuration data structure.
|
||||
|
||||
@retval EFI_SUCCESS The EFI MTFTPv6 Protocol instance was configured successfully.
|
||||
@retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
|
||||
- This is NULL.
|
||||
- MtftpConfigData.StationIp is neither zero nor one
|
||||
of the configured IP addresses in the underlying IPv6 driver.
|
||||
- MtftpCofigData.ServerIp is not a valid IPv6 unicast address.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_ACCESS_DENIED - The configuration could not be changed at this time because there
|
||||
is some MTFTP background operation in progress.
|
||||
- MtftpCofigData.LocalPort is already in use.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_OUT_OF_RESOURCES The EFI MTFTPv6 Protocol driver instance data could not be
|
||||
allocated.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI
|
||||
MTFTPv6 Protocol driver instance is not configured.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6Configure (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_CONFIG_DATA *MtftpConfigData OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Get the information of the download from the server.
|
||||
|
||||
The GetInfo() function assembles an MTFTPv6 request packet
|
||||
with options, sends it to the MTFTPv6 server, and may return
|
||||
an MTFTPv6 OACK, MTFTPv6 ERROR, or ICMP ERROR packet. Retries
|
||||
occur only if no response packets are received from the MTFTPv6
|
||||
server before the timeout expires.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] OverrideData Data that is used to override the existing parameters. If NULL, the
|
||||
default parameters that were set in the EFI_MTFTP6_PROTOCOL.Configure()
|
||||
function are used.
|
||||
@param[in] Filename Pointer to ASCIIZ file name string.
|
||||
@param[in] ModeStr Pointer to ASCIIZ mode string. If NULL, octet will be used
|
||||
@param[in] OptionCount Number of option/value string pairs in OptionList.
|
||||
@param[in] OptionList Pointer to array of option/value string pairs. Ignored if
|
||||
OptionCount is zero.
|
||||
@param[out] PacketLength The number of bytes in the returned packet.
|
||||
@param[out] Packet The pointer to the received packet. This buffer must be freed by
|
||||
the caller.
|
||||
|
||||
@retval EFI_SUCCESS An MTFTPv6 OACK packet was received and is in the Packet.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Filename is NULL.
|
||||
- OptionCount is not zero and OptionList is NULL.
|
||||
- One or more options in OptionList have wrong format.
|
||||
- PacketLength is NULL.
|
||||
- OverrideData.ServerIp is not a valid unicast IPv6 address.
|
||||
@retval EFI_UNSUPPORTED One or more options in the OptionList are unsupported by
|
||||
this implementation.
|
||||
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
|
||||
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
||||
@retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received and is in the Packet.
|
||||
@retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received, and the Packet is set to NULL.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received, and the Packet is set to NULL.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received, and the Packet is set to NULL.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received, and the Packet is set to NULL.
|
||||
@retval EFI_ICMP_ERROR Some other ICMP ERROR packet was received, and the Packet is set to NULL.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received and is in the Packet.
|
||||
@retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6GetInfo (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_OVERRIDE_DATA *OverrideData OPTIONAL,
|
||||
IN UINT8 *Filename,
|
||||
IN UINT8 *ModeStr OPTIONAL,
|
||||
IN UINT8 OptionCount,
|
||||
IN EFI_MTFTP6_OPTION *OptionList OPTIONAL,
|
||||
OUT UINT32 *PacketLength,
|
||||
OUT EFI_MTFTP6_PACKET **Packet OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Parse the options in an MTFTPv6 OACK packet.
|
||||
|
||||
The ParseOptions() function parses the option fields in an MTFTPv6 OACK
|
||||
packet and returns the number of options that were found, and optionally,
|
||||
a list of pointers to the options in the packet. If one or more of the
|
||||
option fields are not valid, then EFI_PROTOCOL_ERROR is returned and
|
||||
*OptionCount and *OptionList stop at the last valid option.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] PacketLen Length of the OACK packet to be parsed.
|
||||
@param[in] Packet Pointer to the OACK packet to be parsed.
|
||||
@param[out] OptionCount Pointer to the number of options in the following OptionList.
|
||||
@param[out] OptionList Pointer to EFI_MTFTP6_OPTION storage. Each pointer in the
|
||||
OptionList points to the corresponding MTFTP option buffer
|
||||
in the Packet. Call the EFI Boot Service FreePool() to
|
||||
release the OptionList if the options in this OptionList
|
||||
are not needed any more.
|
||||
|
||||
@retval EFI_SUCCESS The OACK packet was valid and the OptionCount, and
|
||||
OptionList parameters have been updated.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- PacketLen is 0.
|
||||
- Packet is NULL or Packet is not a valid MTFTPv6 packet.
|
||||
- OptionCount is NULL.
|
||||
@retval EFI_NOT_FOUND No options were found in the OACK packet.
|
||||
@retval EFI_OUT_OF_RESOURCES Storage for the OptionList array can not be allocated.
|
||||
@retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6ParseOptions (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN UINT32 PacketLen,
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
OUT UINT32 *OptionCount,
|
||||
OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Download a file from an MTFTPv6 server.
|
||||
|
||||
The ReadFile() function is used to initialize and start an MTFTPv6 download
|
||||
process and optionally wait for completion. When the download operation
|
||||
completes, whether successfully or not, the Token.Status field is updated
|
||||
by the EFI MTFTPv6 Protocol driver, and then Token.Event is signaled if it
|
||||
is not NULL.
|
||||
Data can be downloaded from the MTFTPv6 server into either of the following
|
||||
locations:
|
||||
- A fixed buffer that is pointed to by Token.Buffer.
|
||||
- A download service function that is pointed to by Token.CheckPacket.
|
||||
If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
|
||||
will be called first. If the call is successful, the packet will be stored
|
||||
in Token.Buffer.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] Token Pointer to the token structure to provide the parameters that are
|
||||
used in this operation.
|
||||
|
||||
@retval EFI_SUCCESS The data file has been transferred successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
||||
@retval EFI_BUFFER_TOO_SMALL BufferSize is not zero but not large enough to hold the
|
||||
downloaded data in downloading process.
|
||||
Note: It does not match the UEFI 2.3 Specification.
|
||||
@retval EFI_ABORTED Current operation is aborted by user.
|
||||
@retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received.
|
||||
Note: It is not defined in the UEFI 2.3 Specification.
|
||||
@retval EFI_ICMP_ERROR An ICMP ERROR packet was received.
|
||||
@retval EFI_TIMEOUT No responses were received from the MTFTPv6 server.
|
||||
@retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6ReadFile (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Send a file to an MTFTPv6 server.
|
||||
|
||||
The WriteFile() function is used to initialize an uploading operation
|
||||
with the given option list, and optionally, wait for completion. If one
|
||||
or more of the options is not supported by the server, the unsupported
|
||||
options are ignored and a standard TFTP process starts instead. When
|
||||
the upload process completes, whether successfully or not, Token.Event
|
||||
is signaled, and the EFI MTFTPv6 Protocol driver updates Token.Status.
|
||||
The caller can supply the data to be uploaded in the following two modes:
|
||||
- Through the user-provided buffer.
|
||||
- Through a callback function.
|
||||
With the user-provided buffer, the Token.BufferSize field indicates
|
||||
the length of the buffer, and the driver will upload the data in the
|
||||
buffer. With an EFI_MTFTP6_PACKET_NEEDED callback function, the driver
|
||||
will call this callback function to get more data from the user to upload.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] Token Pointer to the token structure to provide the parameters that are
|
||||
used in this operation.
|
||||
|
||||
@retval EFI_SUCCESS The upload session has started.
|
||||
@retval EFI_UNSUPPORTED The operation is not supported by this implementation.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Token is NULL.
|
||||
- Token.Filename is NULL.
|
||||
- Token.OptionCount is not zero and Token.OptionList is NULL.
|
||||
- One or more options in Token.OptionList have wrong format.
|
||||
- Token.Buffer and Token.PacketNeeded are both NULL.
|
||||
- Token.OverrideData.ServerIp is not valid unicast IPv6 addresses.
|
||||
@retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
|
||||
supported by this implementation.
|
||||
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
|
||||
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
||||
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6WriteFile (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Download a data file directory from an MTFTPv6 server.
|
||||
|
||||
The ReadDirectory() function is used to return a list of files on the
|
||||
MTFTPv6 server that are logically (or operationally) related to
|
||||
Token.Filename. The directory request packet that is sent to the server
|
||||
is built with the option list that was provided by caller, if present.
|
||||
The file information that the server returns is put into either of
|
||||
the following locations:
|
||||
- A fixed buffer that is pointed to by Token.Buffer.
|
||||
- A download service function that is pointed to by Token.CheckPacket.
|
||||
If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
|
||||
will be called first. If the call is successful, the packet will be stored
|
||||
in Token.Buffer.
|
||||
|
||||
@param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance.
|
||||
@param[in] Token Pointer to the token structure to provide the parameters that are
|
||||
used in this operation.
|
||||
|
||||
@retval EFI_SUCCESS The MTFTPv6 related file "directory" has been downloaded.
|
||||
@retval EFI_UNSUPPORTED The EFI MTFTPv6 Protocol driver does not support this function.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Token is NULL.
|
||||
- Token.Filename is NULL.
|
||||
- Token.OptionCount is not zero and Token.OptionList is NULL.
|
||||
- One or more options in Token.OptionList have wrong format.
|
||||
- Token.Buffer and Token.CheckPacket are both NULL.
|
||||
- Token.OverrideData.ServerIp is not valid unicast IPv6 addresses.
|
||||
@retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not
|
||||
supported by this implementation.
|
||||
@retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session.
|
||||
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
||||
@retval EFI_ACCESS_DENIED The previous operation has not completed yet.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6ReadDirectory (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Polls for incoming data packets and processes outgoing data packets.
|
||||
|
||||
The Poll() function can be used by network drivers and applications
|
||||
to increase the rate that data packets are moved between the
|
||||
communications device and the transmit and receive queues.In some
|
||||
systems, the periodic timer event in the managed network driver may
|
||||
not poll the underlying communications device fast enough to transmit
|
||||
and/or receive all data packets without missing incoming packets or
|
||||
dropping outgoing packets. Drivers and applications that are
|
||||
experiencing packet loss should try calling the Poll() function
|
||||
more often.
|
||||
|
||||
@param[in] This The MTFTP6 protocol instance.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS Incoming or outgoing data was processed.
|
||||
@retval EFI_NOT_STARTED This EFI MTFTPv6 Protocol instance has not been started.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
@retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
|
||||
Consider increasing the polling rate.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EfiMtftp6Poll (
|
||||
IN EFI_MTFTP6_PROTOCOL *This
|
||||
);
|
||||
|
||||
#endif
|
416
NetworkPkg/Mtftp6Dxe/Mtftp6Option.c
Normal file
416
NetworkPkg/Mtftp6Dxe/Mtftp6Option.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/** @file
|
||||
Mtftp6 option parse functions implementation.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp6Impl.h"
|
||||
|
||||
CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = {
|
||||
"blksize",
|
||||
"timeout",
|
||||
"tsize",
|
||||
"multicast"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Parse the NULL terminated ASCII string of multicast option.
|
||||
|
||||
@param[in] Str The pointer to the Ascii string of multicast option.
|
||||
@param[in] ExtInfo The pointer to the option information to be filled.
|
||||
|
||||
@retval EFI_SUCCESS Parse the multicast option successfully.
|
||||
@retval EFI_INVALID_PARAMETER The string is malformatted.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of
|
||||
resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ParseMcastOption (
|
||||
IN UINT8 *Str,
|
||||
IN MTFTP6_EXT_OPTION_INFO *ExtInfo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Num;
|
||||
CHAR8 *Ip6Str;
|
||||
CHAR8 *TempStr;
|
||||
|
||||
//
|
||||
// The multicast option is formated like "addr,port,mc"
|
||||
// The server can also omit the ip and port, use ",,1"
|
||||
//
|
||||
if (*Str == ',') {
|
||||
|
||||
ZeroMem (&ExtInfo->McastIp, sizeof (EFI_IPv6_ADDRESS));
|
||||
} else {
|
||||
|
||||
Ip6Str = (CHAR8 *) AllocateCopyPool (AsciiStrSize ((CHAR8 *) Str), Str);
|
||||
if (Ip6Str == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// The IPv6 address locates before comma in the input Str.
|
||||
//
|
||||
TempStr = Ip6Str;
|
||||
while ((*TempStr != '\0') && (*TempStr != ',')) {
|
||||
TempStr++;
|
||||
}
|
||||
|
||||
*TempStr = '\0';
|
||||
|
||||
Status = NetLibAsciiStrToIp6 (Ip6Str, &ExtInfo->McastIp);
|
||||
FreePool (Ip6Str);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
while ((*Str != '\0') && (*Str != ',')) {
|
||||
Str++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*Str != ',') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Str++;
|
||||
|
||||
//
|
||||
// Convert the port setting. the server can send us a port number or
|
||||
// empty string. such as the port in ",,1"
|
||||
//
|
||||
if (*Str == ',') {
|
||||
|
||||
ExtInfo->McastPort = 0;
|
||||
} else {
|
||||
|
||||
Num = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Str);
|
||||
|
||||
if (Num > 65535) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ExtInfo->McastPort = (UINT16) Num;
|
||||
|
||||
while (NET_IS_DIGIT (*Str)) {
|
||||
Str++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*Str != ',') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Str++;
|
||||
|
||||
//
|
||||
// Check the master/slave setting, 1 for master, 0 for slave.
|
||||
//
|
||||
Num = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Str);
|
||||
|
||||
if (Num != 0 && Num != 1) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ExtInfo->IsMaster = (BOOLEAN) (Num == 1);
|
||||
|
||||
while (NET_IS_DIGIT (*Str)) {
|
||||
Str++;
|
||||
}
|
||||
|
||||
if (*Str != '\0') {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the MTFTP6 extesion options.
|
||||
|
||||
@param[in] Options The pointer to the extension options list.
|
||||
@param[in] Count The num of the extension options.
|
||||
@param[in] IsRequest If FALSE, the extension options is included
|
||||
by a request packet.
|
||||
@param[in] ExtInfo The pointer to the option information to be filled.
|
||||
|
||||
@retval EFI_SUCCESS Parse the multicast option successfully.
|
||||
@retval EFI_INVALID_PARAMETER There is one option is malformatted at least.
|
||||
@retval EFI_UNSUPPORTED There is one option is not supported at least.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ParseExtensionOption (
|
||||
IN EFI_MTFTP6_OPTION *Options,
|
||||
IN UINT32 Count,
|
||||
IN BOOLEAN IsRequest,
|
||||
IN MTFTP6_EXT_OPTION_INFO *ExtInfo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_MTFTP6_OPTION *Opt;
|
||||
UINT32 Index;
|
||||
UINT32 Value;
|
||||
|
||||
ExtInfo->BitMap = 0;
|
||||
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
|
||||
Opt = Options + Index;
|
||||
|
||||
if (Opt->OptionStr == NULL || Opt->ValueStr == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "blksize") == 0) {
|
||||
//
|
||||
// block size option, valid value is between [8, 65464]
|
||||
//
|
||||
Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);
|
||||
|
||||
if ((Value < 8) || (Value > 65464)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ExtInfo->BlkSize = (UINT16) Value;
|
||||
ExtInfo->BitMap |= MTFTP6_OPT_BLKSIZE_BIT;
|
||||
|
||||
} else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "timeout") == 0) {
|
||||
//
|
||||
// timeout option, valid value is between [1, 255]
|
||||
//
|
||||
Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);
|
||||
|
||||
if (Value < 1 || Value > 255) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ExtInfo->Timeout = (UINT8) Value;
|
||||
ExtInfo->BitMap |= MTFTP6_OPT_TIMEOUT_BIT;
|
||||
|
||||
} else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "tsize") == 0) {
|
||||
//
|
||||
// tsize option, the biggest transfer supported is 4GB with block size option
|
||||
//
|
||||
ExtInfo->Tsize = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr);
|
||||
ExtInfo->BitMap |= MTFTP6_OPT_TSIZE_BIT;
|
||||
|
||||
} else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "multicast") == 0) {
|
||||
//
|
||||
// Multicast option, if it is a request, the value must be a zero string,
|
||||
// otherwise, it must be like "addr,port,mc" string, mc indicates master.
|
||||
//
|
||||
if (!IsRequest) {
|
||||
|
||||
Status = Mtftp6ParseMcastOption (Opt->ValueStr, ExtInfo);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
} else if (*(Opt->ValueStr) != '\0') {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ExtInfo->BitMap |= MTFTP6_OPT_MCAST_BIT;
|
||||
|
||||
} else if (IsRequest) {
|
||||
//
|
||||
// If it's a request, unsupported; else if it's a reply, ignore.
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Go through the packet to fill the options array with the start
|
||||
addresses of each MTFTP option name/value pair.
|
||||
|
||||
@param[in] Packet The packet to be checked.
|
||||
@param[in] PacketLen The length of the packet.
|
||||
@param[in, out] Count The num of the Options on input.
|
||||
The actual one on output.
|
||||
@param[in] Options The option array to be filled.
|
||||
It is optional.
|
||||
|
||||
@retval EFI_SUCCESS The packet has been parsed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformatted.
|
||||
@retval EFI_BUFFER_TOO_SMALL The Options array is too small.
|
||||
@retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ParsePacketOption (
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *Count,
|
||||
IN EFI_MTFTP6_OPTION *Options OPTIONAL
|
||||
)
|
||||
{
|
||||
UINT8 *Cur;
|
||||
UINT8 *Last;
|
||||
UINT8 Num;
|
||||
UINT8 *Name;
|
||||
UINT8 *Value;
|
||||
|
||||
Num = 0;
|
||||
Cur = (UINT8 *) Packet + MTFTP6_OPCODE_LEN;
|
||||
Last = (UINT8 *) Packet + PacketLen - 1;
|
||||
|
||||
//
|
||||
// process option name and value pairs.
|
||||
// The last byte is always zero.
|
||||
//
|
||||
while (Cur < Last) {
|
||||
Name = Cur;
|
||||
|
||||
while (*Cur != 0) {
|
||||
Cur++;
|
||||
}
|
||||
|
||||
if (Cur == Last) {
|
||||
return EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
Value = ++Cur;
|
||||
|
||||
while (*Cur != 0) {
|
||||
Cur++;
|
||||
}
|
||||
|
||||
Num++;
|
||||
|
||||
if (Options != NULL && Num <= *Count) {
|
||||
Options[Num - 1].OptionStr = Name;
|
||||
Options[Num - 1].ValueStr = Value;
|
||||
}
|
||||
|
||||
Cur++;
|
||||
}
|
||||
|
||||
//
|
||||
// Return buffer too small if the buffer passed-in isn't enough.
|
||||
//
|
||||
if (*Count < Num || Options == NULL) {
|
||||
*Count = Num;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*Count = Num;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Go through the packet, generate option list array and fill it
|
||||
by the result of parse options.
|
||||
|
||||
@param[in] Packet The packet to be checked.
|
||||
@param[in] PacketLen The length of the packet.
|
||||
@param[in, out] OptionCount The num of the Options on input.
|
||||
The actual one on output.
|
||||
@param[out] OptionList The option list array to be generated
|
||||
and filled. It is optional.
|
||||
|
||||
@retval EFI_SUCCESS The packet has been parsed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformatted.
|
||||
@retval EFI_PROTOCOL_ERROR There is one option is malformatted at least.
|
||||
@retval EFI_NOT_FOUND The packet has no options.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.
|
||||
@retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ParseStart (
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *OptionCount,
|
||||
OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (PacketLen == 0 || Packet == NULL || OptionCount == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*OptionCount = 0;
|
||||
|
||||
if (OptionList != NULL) {
|
||||
*OptionList = NULL;
|
||||
}
|
||||
|
||||
if (NTOHS (Packet->OpCode) != EFI_MTFTP6_OPCODE_OACK) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// The last byte must be zero to terminate the options.
|
||||
//
|
||||
if (*((UINT8 *) Packet + PacketLen - 1) != 0) {
|
||||
return EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse packet with NULL buffer for the first time to get the number
|
||||
// of options in the packet.
|
||||
//
|
||||
Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, NULL);
|
||||
|
||||
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Return not found if there is no option parsed.
|
||||
//
|
||||
if (*OptionCount == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Only need parse out the number of options.
|
||||
//
|
||||
if (OptionList == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate the buffer according to the option number parsed before.
|
||||
//
|
||||
*OptionList = AllocateZeroPool (*OptionCount * sizeof (EFI_MTFTP6_OPTION));
|
||||
|
||||
if (*OptionList == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse packet with allocated buffer for the second time to fill the pointer array
|
||||
// of the options in the packet.
|
||||
//
|
||||
Status = Mtftp6ParsePacketOption (Packet, PacketLen, OptionCount, *OptionList);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
148
NetworkPkg/Mtftp6Dxe/Mtftp6Option.h
Normal file
148
NetworkPkg/Mtftp6Dxe/Mtftp6Option.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/** @file
|
||||
Mtftp6 option parse functions declaration.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_MTFTP6_OPTION_H__
|
||||
#define __EFI_MTFTP6_OPTION_H__
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/UdpIoLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
#define MTFTP6_SUPPORTED_OPTIONS_NUM 4
|
||||
#define MTFTP6_OPCODE_LEN 2
|
||||
#define MTFTP6_ERRCODE_LEN 2
|
||||
#define MTFTP6_BLKNO_LEN 2
|
||||
#define MTFTP6_DATA_HEAD_LEN 4
|
||||
|
||||
//
|
||||
// The bit map definition for Mtftp6 extension options.
|
||||
//
|
||||
#define MTFTP6_OPT_BLKSIZE_BIT 0x01
|
||||
#define MTFTP6_OPT_TIMEOUT_BIT 0x02
|
||||
#define MTFTP6_OPT_TSIZE_BIT 0x04
|
||||
#define MTFTP6_OPT_MCAST_BIT 0x08
|
||||
|
||||
extern CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM];
|
||||
|
||||
typedef struct {
|
||||
UINT16 BlkSize;
|
||||
UINT8 Timeout;
|
||||
UINT32 Tsize;
|
||||
EFI_IPv6_ADDRESS McastIp;
|
||||
UINT16 McastPort;
|
||||
BOOLEAN IsMaster;
|
||||
UINT32 BitMap;
|
||||
} MTFTP6_EXT_OPTION_INFO;
|
||||
|
||||
/**
|
||||
Parse the Ascii string of multi-cast option.
|
||||
|
||||
@param[in] Str The pointer to the Ascii string of multi-cast option.
|
||||
@param[in] ExtInfo The pointer to the option information to be filled.
|
||||
|
||||
@retval EFI_SUCCESS Parse the multicast option successfully.
|
||||
@retval EFI_INVALID_PARAMETER The string is malformatted.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ParseMcastOption (
|
||||
IN UINT8 *Str,
|
||||
IN MTFTP6_EXT_OPTION_INFO *ExtInfo
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Parse the MTFTP6 extesion options.
|
||||
|
||||
@param[in] Options The pointer to the extension options list.
|
||||
@param[in] Count The num of the extension options.
|
||||
@param[in] IsRequest If FALSE, the extension options is included
|
||||
by a request packet.
|
||||
@param[in] ExtInfo The pointer to the option information to be filled.
|
||||
|
||||
@retval EFI_SUCCESS Parse the multi-cast option successfully.
|
||||
@retval EFI_INVALID_PARAMETER An option is malformatted.
|
||||
@retval EFI_UNSUPPORTED An option is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ParseExtensionOption (
|
||||
IN EFI_MTFTP6_OPTION *Options,
|
||||
IN UINT32 Count,
|
||||
IN BOOLEAN IsRequest,
|
||||
IN MTFTP6_EXT_OPTION_INFO *ExtInfo
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Go through the packet to fill the options array with the start
|
||||
addresses of each MTFTP option name/value pair.
|
||||
|
||||
@param[in] Packet The packet to be checked.
|
||||
@param[in] PacketLen The length of the packet.
|
||||
@param[in, out] Count The num of the Options on input.
|
||||
The actual one on output.
|
||||
@param[in] Options The option array to be filled
|
||||
it's optional.
|
||||
|
||||
@retval EFI_SUCCESS The packet has been parsed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformatted
|
||||
@retval EFI_BUFFER_TOO_SMALL The Options array is too small
|
||||
@retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ParsePacketOption (
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *Count,
|
||||
IN EFI_MTFTP6_OPTION *Options OPTIONAL
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Go through the packet, generate option list array and fill it
|
||||
by the result of parse options.
|
||||
|
||||
@param[in] Packet The packet to be checked.
|
||||
@param[in] PacketLen The length of the packet.
|
||||
@param[in, out] OptionCount The num of the Options on input.
|
||||
The actual one on output.
|
||||
@param[out] OptionList The option list array to be generated
|
||||
and filled. It is optional.
|
||||
|
||||
@retval EFI_SUCCESS The packet has been parsed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The packet is malformatted.
|
||||
@retval EFI_PROTOCOL_ERROR An option is malformatted.
|
||||
@retval EFI_NOT_FOUND The packet has no options.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the array.
|
||||
@retval EFI_BUFFER_TOO_SMALL The size of option list array is too small.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ParseStart (
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 PacketLen,
|
||||
IN OUT UINT32 *OptionCount,
|
||||
OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL
|
||||
);
|
||||
|
||||
#endif
|
900
NetworkPkg/Mtftp6Dxe/Mtftp6Rrq.c
Normal file
900
NetworkPkg/Mtftp6Dxe/Mtftp6Rrq.c
Normal file
@@ -0,0 +1,900 @@
|
||||
/** @file
|
||||
Mtftp6 Rrq process functions implementation.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp6Impl.h"
|
||||
|
||||
|
||||
/**
|
||||
Build and send a ACK packet for download.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] BlockNum The block number to be acked.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet.
|
||||
@retval EFI_SUCCESS The ACK has been sent.
|
||||
@retval Others Failed to send the ACK.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6RrqSendAck (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN UINT16 BlockNum
|
||||
)
|
||||
{
|
||||
EFI_MTFTP6_PACKET *Ack;
|
||||
NET_BUF *Packet;
|
||||
|
||||
//
|
||||
// Allocate net buffer to create ack packet.
|
||||
//
|
||||
Packet = NetbufAlloc (sizeof (EFI_MTFTP6_ACK_HEADER));
|
||||
|
||||
if (Packet == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ack = (EFI_MTFTP6_PACKET *) NetbufAllocSpace (
|
||||
Packet,
|
||||
sizeof (EFI_MTFTP6_ACK_HEADER),
|
||||
FALSE
|
||||
);
|
||||
ASSERT (Ack != NULL);
|
||||
|
||||
Ack->Ack.OpCode = HTONS (EFI_MTFTP6_OPCODE_ACK);
|
||||
Ack->Ack.Block[0] = HTONS (BlockNum);
|
||||
|
||||
//
|
||||
// Reset current retry count of the instance.
|
||||
//
|
||||
Instance->CurRetry = 0;
|
||||
|
||||
return Mtftp6TransmitPacket (Instance, Packet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Deliver the received data block to the user, which can be saved
|
||||
in the user provide buffer or through the CheckPacket callback.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Packet The pointer to the received packet.
|
||||
@param[in] Len The packet length.
|
||||
@param[out] UdpPacket The net buf of the received packet.
|
||||
|
||||
@retval EFI_SUCCESS The data was saved successfully.
|
||||
@retval EFI_ABORTED The user tells to abort by return an error through
|
||||
CheckPacket.
|
||||
@retval EFI_BUFFER_TOO_SMALL The user's buffer is too small, and buffer length is
|
||||
updated to the actual buffer size needed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6RrqSaveBlock (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
OUT NET_BUF **UdpPacket
|
||||
)
|
||||
{
|
||||
EFI_MTFTP6_TOKEN *Token;
|
||||
EFI_STATUS Status;
|
||||
UINT16 Block;
|
||||
UINT64 Start;
|
||||
UINT32 DataLen;
|
||||
UINT64 TotalBlock;
|
||||
BOOLEAN Completed;
|
||||
|
||||
Completed = FALSE;
|
||||
Token = Instance->Token;
|
||||
Block = NTOHS (Packet->Data.Block);
|
||||
DataLen = Len - MTFTP6_DATA_HEAD_LEN;
|
||||
|
||||
//
|
||||
// This is the last block, save the block num
|
||||
//
|
||||
if (DataLen < Instance->BlkSize) {
|
||||
Completed = TRUE;
|
||||
Instance->LastBlk = Block;
|
||||
Mtftp6SetLastBlockNum (&Instance->BlkList, Block);
|
||||
}
|
||||
|
||||
//
|
||||
// Remove this block number from the file hole. If Mtftp6RemoveBlockNum
|
||||
// returns EFI_NOT_FOUND, the block has been saved, don't save it again.
|
||||
// Note that : For bigger files, allowing the block counter to roll over
|
||||
// to accept transfers of unlimited size. So TotalBlock is memorised as
|
||||
// continuous block counter.
|
||||
//
|
||||
Status = Mtftp6RemoveBlockNum (&Instance->BlkList, Block, Completed, &TotalBlock);
|
||||
|
||||
if (Status == EFI_NOT_FOUND) {
|
||||
return EFI_SUCCESS;
|
||||
} else if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Token->CheckPacket != NULL) {
|
||||
//
|
||||
// Callback to the check packet routine with the received packet.
|
||||
//
|
||||
Status = Token->CheckPacket (&Instance->Mtftp6, Token, (UINT16) Len, Packet);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the Udp6Io might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if user aborted the current session.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
|
||||
(UINT8 *) "User aborted download"
|
||||
);
|
||||
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (Token->Buffer != NULL) {
|
||||
|
||||
Start = MultU64x32 (TotalBlock - 1, Instance->BlkSize);
|
||||
if (Start + DataLen <= Token->BufferSize) {
|
||||
CopyMem ((UINT8 *) Token->Buffer + Start, Packet->Data.Data, DataLen);
|
||||
//
|
||||
// Update the file size when received the last block
|
||||
//
|
||||
if ((Instance->LastBlk == Block) && Completed) {
|
||||
Token->BufferSize = Start + DataLen;
|
||||
}
|
||||
} else if (Instance->LastBlk != 0) {
|
||||
//
|
||||
// Don't save the data if the buffer is too small, return
|
||||
// EFI_BUFFER_TOO_SMALL if received the last packet. This
|
||||
// will give a accurate file length.
|
||||
//
|
||||
Token->BufferSize = Start + DataLen;
|
||||
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if no enough buffer.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_DISK_FULL,
|
||||
(UINT8 *) "User provided memory block is too small"
|
||||
);
|
||||
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the received data packets. It will save the block
|
||||
then send back an ACK if it is active.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Packet The pointer to the received packet.
|
||||
@param[in] Len The length of the packet.
|
||||
@param[out] UdpPacket The net buf of received packet.
|
||||
@param[out] IsCompleted If TRUE, the download has been completed.
|
||||
Otherwise, the download has not been completed.
|
||||
|
||||
@retval EFI_SUCCESS The data packet was successfully processed.
|
||||
@retval EFI_ABORTED The download was aborted by the user.
|
||||
@retval EFI_BUFFER_TOO_SMALL The user-provided buffer is too small.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6RrqHandleData (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
OUT NET_BUF **UdpPacket,
|
||||
OUT BOOLEAN *IsCompleted
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT16 BlockNum;
|
||||
INTN Expected;
|
||||
|
||||
*IsCompleted = FALSE;
|
||||
BlockNum = NTOHS (Packet->Data.Block);
|
||||
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
|
||||
|
||||
ASSERT (Expected >= 0);
|
||||
|
||||
//
|
||||
// If we are active and received an unexpected packet, retransmit
|
||||
// the last ACK then restart receiving. If we are passive, save
|
||||
// the block.
|
||||
//
|
||||
if (Instance->IsMaster && (Expected != BlockNum)) {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
|
||||
Mtftp6TransmitPacket (Instance, Instance->LastPacket);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = Mtftp6RrqSaveBlock (Instance, Packet, Len, UdpPacket);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Reset the passive client's timer whenever it received a valid data packet.
|
||||
//
|
||||
if (!Instance->IsMaster) {
|
||||
Instance->PacketToLive = Instance->Timeout * 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether we have received all the blocks. Send the ACK if we
|
||||
// are active (unicast client or master client for multicast download).
|
||||
// If we have received all the blocks, send an ACK even if we are passive
|
||||
// to tell the server that we are done.
|
||||
//
|
||||
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
|
||||
|
||||
if (Instance->IsMaster || Expected < 0) {
|
||||
if (Expected < 0) {
|
||||
//
|
||||
// If we are passive client, then the just received Block maybe
|
||||
// isn't the last block. We need to send an ACK to the last block
|
||||
// to inform the server that we are done. If we are active client,
|
||||
// the Block == Instance->LastBlock.
|
||||
//
|
||||
BlockNum = Instance->LastBlk;
|
||||
*IsCompleted = TRUE;
|
||||
|
||||
} else {
|
||||
BlockNum = (UINT16) (Expected - 1);
|
||||
}
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
|
||||
Mtftp6RrqSendAck (Instance, BlockNum);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Validate whether the options received in the server's OACK packet is valid.
|
||||
The options are valid only if:
|
||||
1. The server doesn't include options not requested by us.
|
||||
2. The server can only use smaller blksize than that is requested.
|
||||
3. The server can only use the same timeout as requested.
|
||||
4. The server doesn't change its multicast channel.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] ReplyInfo The pointer to options information in reply packet.
|
||||
@param[in] RequestInfo The pointer to requested options info.
|
||||
|
||||
@retval TRUE If the option in the OACK is valid.
|
||||
@retval FALSE If the option is invalid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Mtftp6RrqOackValid (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN MTFTP6_EXT_OPTION_INFO *ReplyInfo,
|
||||
IN MTFTP6_EXT_OPTION_INFO *RequestInfo
|
||||
)
|
||||
{
|
||||
//
|
||||
// It is invalid for server to return options we don't request
|
||||
//
|
||||
if ((ReplyInfo->BitMap & ~RequestInfo->BitMap) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Server can only specify a smaller block size to be used and
|
||||
// return the timeout matches that requested.
|
||||
//
|
||||
if ((((ReplyInfo->BitMap & MTFTP6_OPT_BLKSIZE_BIT) != 0) && (ReplyInfo->BlkSize > RequestInfo->BlkSize)) ||
|
||||
(((ReplyInfo->BitMap & MTFTP6_OPT_TIMEOUT_BIT) != 0) && (ReplyInfo->Timeout != RequestInfo->Timeout))
|
||||
) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// The server can send ",,master" to client to change its master
|
||||
// setting. But if it use the specific multicast channel, it can't
|
||||
// change the setting.
|
||||
//
|
||||
if (((ReplyInfo->BitMap & MTFTP6_OPT_MCAST_BIT) != 0) && !NetIp6IsUnspecifiedAddr (&Instance->McastIp)) {
|
||||
|
||||
if (!NetIp6IsUnspecifiedAddr (&ReplyInfo->McastIp) && CompareMem (
|
||||
&ReplyInfo->McastIp,
|
||||
&Instance->McastIp,
|
||||
sizeof (EFI_IPv6_ADDRESS)
|
||||
) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((ReplyInfo->McastPort != 0) && (ReplyInfo->McastPort != Instance->McastPort)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure Udp6Io to receive a packet from a multicast address.
|
||||
|
||||
@param[in] McastIo The pointer to the mcast Udp6Io.
|
||||
@param[in] Context The pointer to the context.
|
||||
|
||||
@retval EFI_SUCCESS The mcast Udp6Io was successfully configured.
|
||||
@retval Others Failed to configure the Udp6Io.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6RrqConfigMcastUdpIo (
|
||||
IN UDP_IO *McastIo,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_UDP6_PROTOCOL *Udp6;
|
||||
EFI_UDP6_CONFIG_DATA *Udp6Cfg;
|
||||
EFI_IPv6_ADDRESS Group;
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
|
||||
Udp6 = McastIo->Protocol.Udp6;
|
||||
Udp6Cfg = &(McastIo->Config.Udp6);
|
||||
Instance = (MTFTP6_INSTANCE *) Context;
|
||||
|
||||
//
|
||||
// Set the configure data for the mcast Udp6Io.
|
||||
//
|
||||
ZeroMem (Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
|
||||
|
||||
Udp6Cfg->AcceptPromiscuous = FALSE;
|
||||
Udp6Cfg->AcceptAnyPort = FALSE;
|
||||
Udp6Cfg->AllowDuplicatePort = FALSE;
|
||||
Udp6Cfg->TrafficClass = 0;
|
||||
Udp6Cfg->HopLimit = 128;
|
||||
Udp6Cfg->ReceiveTimeout = 0;
|
||||
Udp6Cfg->TransmitTimeout = 0;
|
||||
Udp6Cfg->StationPort = Instance->McastPort;
|
||||
Udp6Cfg->RemotePort = 0;
|
||||
|
||||
CopyMem (
|
||||
&Udp6Cfg->RemoteAddress,
|
||||
&Instance->ServerIp,
|
||||
sizeof (EFI_IPv6_ADDRESS)
|
||||
);
|
||||
|
||||
//
|
||||
// Configure the mcast Udp6Io.
|
||||
//
|
||||
Status = Udp6->Configure (Udp6, Udp6Cfg);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Join the multicast group
|
||||
//
|
||||
CopyMem (&Group, &Instance->McastIp, sizeof (EFI_IPv6_ADDRESS));
|
||||
|
||||
return Udp6->Groups (Udp6, TRUE, &Group);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the OACK packet for Rrq.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Packet The pointer to the received packet.
|
||||
@param[in] Len The length of the packet.
|
||||
@param[out] UdpPacket The net buf of received packet.
|
||||
@param[out] IsCompleted If TRUE, the download has been completed.
|
||||
Otherwise, the download has not been completed.
|
||||
|
||||
@retval EFI_DEVICE_ERROR Failed to create/start a multicast Udp6 child.
|
||||
@retval EFI_TFTP_ERROR An error happened during the process.
|
||||
@retval EFI_SUCCESS The OACK packet successfully processed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6RrqHandleOack (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
OUT NET_BUF **UdpPacket,
|
||||
OUT BOOLEAN *IsCompleted
|
||||
)
|
||||
{
|
||||
EFI_MTFTP6_OPTION *Options;
|
||||
UINT32 Count;
|
||||
MTFTP6_EXT_OPTION_INFO ExtInfo;
|
||||
EFI_STATUS Status;
|
||||
INTN Expected;
|
||||
|
||||
*IsCompleted = FALSE;
|
||||
|
||||
//
|
||||
// If already started the master download, don't change the
|
||||
// setting. Master download always succeeds.
|
||||
//
|
||||
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
|
||||
ASSERT (Expected != -1);
|
||||
|
||||
if (Instance->IsMaster && Expected != 1) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
ZeroMem (&ExtInfo, sizeof (MTFTP6_EXT_OPTION_INFO));
|
||||
|
||||
//
|
||||
// Parse the options in the packet.
|
||||
//
|
||||
Status = Mtftp6ParseStart (Packet, Len, &Count, &Options);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the extensive options in the packet.
|
||||
//
|
||||
Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, &ExtInfo);
|
||||
|
||||
if (EFI_ERROR (Status) || !Mtftp6RrqOackValid (Instance, &ExtInfo, &Instance->ExtInfo)) {
|
||||
//
|
||||
// Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.
|
||||
//
|
||||
if (Status != EFI_OUT_OF_RESOURCES) {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if invalid packet.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
|
||||
(UINT8 *) "Mal-formated OACK packet"
|
||||
);
|
||||
}
|
||||
|
||||
return EFI_TFTP_ERROR;
|
||||
}
|
||||
|
||||
if ((ExtInfo.BitMap & MTFTP6_OPT_MCAST_BIT) != 0) {
|
||||
|
||||
//
|
||||
// Save the multicast info. Always update the Master, only update the
|
||||
// multicast IP address, block size, timeoute at the first time. If IP
|
||||
// address is updated, create a UDP child to receive the multicast.
|
||||
//
|
||||
Instance->IsMaster = ExtInfo.IsMaster;
|
||||
|
||||
if (NetIp6IsUnspecifiedAddr (&Instance->McastIp)) {
|
||||
if (NetIp6IsUnspecifiedAddr (&ExtInfo.McastIp) || ExtInfo.McastPort == 0) {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if invalid multi-cast setting.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
|
||||
(UINT8 *) "Illegal multicast setting"
|
||||
);
|
||||
|
||||
return EFI_TFTP_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a UDP child then start receive the multicast from it.
|
||||
//
|
||||
CopyMem (
|
||||
&Instance->McastIp,
|
||||
&ExtInfo.McastIp,
|
||||
sizeof (EFI_IP_ADDRESS)
|
||||
);
|
||||
|
||||
Instance->McastPort = ExtInfo.McastPort;
|
||||
Instance->McastUdpIo = UdpIoCreateIo (
|
||||
Instance->Service->Controller,
|
||||
Instance->Service->Image,
|
||||
Mtftp6RrqConfigMcastUdpIo,
|
||||
UDP_IO_UDP6_VERSION,
|
||||
Instance
|
||||
);
|
||||
|
||||
if (Instance->McastUdpIo == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Status = UdpIoRecvDatagram (
|
||||
Instance->McastUdpIo,
|
||||
Mtftp6RrqInput,
|
||||
Instance,
|
||||
0
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if failed to create Udp6Io to receive.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_ACCESS_VIOLATION,
|
||||
(UINT8 *) "Failed to create socket to receive multicast packet"
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the parameters used.
|
||||
//
|
||||
if (ExtInfo.BlkSize != 0) {
|
||||
Instance->BlkSize = ExtInfo.BlkSize;
|
||||
}
|
||||
|
||||
if (ExtInfo.Timeout != 0) {
|
||||
Instance->Timeout = ExtInfo.Timeout;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Instance->IsMaster = TRUE;
|
||||
|
||||
if (ExtInfo.BlkSize != 0) {
|
||||
Instance->BlkSize = ExtInfo.BlkSize;
|
||||
}
|
||||
|
||||
if (ExtInfo.Timeout != 0) {
|
||||
Instance->Timeout = ExtInfo.Timeout;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
//
|
||||
// Send an ACK to (Expected - 1) which is 0 for unicast download,
|
||||
// or tell the server we want to receive the Expected block.
|
||||
//
|
||||
return Mtftp6RrqSendAck (Instance, (UINT16) (Expected - 1));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The packet process callback for Mtftp6 download.
|
||||
|
||||
@param[in] UdpPacket The pointer to the packet received.
|
||||
@param[in] UdpEpt The pointer to the Udp6 access point.
|
||||
@param[in] IoStatus The status from Udp6 instance.
|
||||
@param[in] Context The pointer to the context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Mtftp6RrqInput (
|
||||
IN NET_BUF *UdpPacket,
|
||||
IN UDP_END_POINT *UdpEpt,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
EFI_MTFTP6_PACKET *Packet;
|
||||
BOOLEAN IsCompleted;
|
||||
BOOLEAN IsMcast;
|
||||
EFI_STATUS Status;
|
||||
UINT16 Opcode;
|
||||
UINT32 TotalNum;
|
||||
UINT32 Len;
|
||||
|
||||
Instance = (MTFTP6_INSTANCE *) Context;
|
||||
|
||||
NET_CHECK_SIGNATURE (Instance, MTFTP6_INSTANCE_SIGNATURE);
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Packet = NULL;
|
||||
IsCompleted = FALSE;
|
||||
IsMcast = FALSE;
|
||||
TotalNum = 0;
|
||||
|
||||
//
|
||||
// Return error status if Udp6 instance failed to receive.
|
||||
//
|
||||
if (EFI_ERROR (IoStatus)) {
|
||||
Status = IoStatus;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
ASSERT (UdpPacket != NULL);
|
||||
|
||||
if (UdpPacket->TotalSize < MTFTP6_OPCODE_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the port this packet is from to restart receive correctly.
|
||||
//
|
||||
if (CompareMem (
|
||||
Ip6Swap128 (&UdpEpt->LocalAddr.v6),
|
||||
&Instance->McastIp,
|
||||
sizeof (EFI_IPv6_ADDRESS)
|
||||
) == 0) {
|
||||
IsMcast = TRUE;
|
||||
} else {
|
||||
IsMcast = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Client send initial request to server's listening port. Server
|
||||
// will select a UDP port to communicate with the client. The server
|
||||
// is required to use the same port as RemotePort to multicast the
|
||||
// data.
|
||||
//
|
||||
if (UdpEpt->RemotePort != Instance->ServerDataPort) {
|
||||
if (Instance->ServerDataPort != 0) {
|
||||
goto ON_EXIT;
|
||||
} else {
|
||||
//
|
||||
// For the subsequent exchange of requests, reconfigure the udpio as
|
||||
// (serverip, serverport, localip, localport).
|
||||
// Ususally, the client set serverport as 0 to receive and reset it
|
||||
// once the first packet arrives to send ack.
|
||||
//
|
||||
Instance->ServerDataPort = UdpEpt->RemotePort;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the MTFTP packet to a continuous buffer if it isn't already so.
|
||||
//
|
||||
Len = UdpPacket->TotalSize;
|
||||
TotalNum = UdpPacket->BlockOpNum;
|
||||
|
||||
if (TotalNum > 1) {
|
||||
Packet = AllocateZeroPool (Len);
|
||||
|
||||
if (Packet == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);
|
||||
|
||||
} else {
|
||||
Packet = (EFI_MTFTP6_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
|
||||
ASSERT (Packet != NULL);
|
||||
}
|
||||
|
||||
Opcode = NTOHS (Packet->OpCode);
|
||||
|
||||
//
|
||||
// Callback to the user's CheckPacket if provided. Abort the transmission
|
||||
// if CheckPacket returns an EFI_ERROR code.
|
||||
//
|
||||
if ((Instance->Token->CheckPacket != NULL) &&
|
||||
(Opcode == EFI_MTFTP6_OPCODE_OACK || Opcode == EFI_MTFTP6_OPCODE_ERROR)
|
||||
) {
|
||||
|
||||
Status = Instance->Token->CheckPacket (
|
||||
&Instance->Mtftp6,
|
||||
Instance->Token,
|
||||
(UINT16) Len,
|
||||
Packet
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Send an error message to the server to inform it
|
||||
//
|
||||
if (Opcode != EFI_MTFTP6_OPCODE_ERROR) {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (UdpPacket);
|
||||
UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if user aborted the current session.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
|
||||
(UINT8 *) "User aborted the transfer"
|
||||
);
|
||||
}
|
||||
|
||||
Status = EFI_ABORTED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Switch the process routines by the operation code.
|
||||
//
|
||||
switch (Opcode) {
|
||||
case EFI_MTFTP6_OPCODE_DATA:
|
||||
if ((Len > (UINT32) (MTFTP6_DATA_HEAD_LEN + Instance->BlkSize)) || (Len < (UINT32) MTFTP6_DATA_HEAD_LEN)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Handle the data packet of Rrq.
|
||||
//
|
||||
Status = Mtftp6RrqHandleData (
|
||||
Instance,
|
||||
Packet,
|
||||
Len,
|
||||
&UdpPacket,
|
||||
&IsCompleted
|
||||
);
|
||||
break;
|
||||
|
||||
case EFI_MTFTP6_OPCODE_OACK:
|
||||
if (IsMcast || Len <= MTFTP6_OPCODE_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Handle the Oack packet of Rrq.
|
||||
//
|
||||
Status = Mtftp6RrqHandleOack (
|
||||
Instance,
|
||||
Packet,
|
||||
Len,
|
||||
&UdpPacket,
|
||||
&IsCompleted
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// Drop and return eror if received error message.
|
||||
//
|
||||
Status = EFI_TFTP_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
//
|
||||
// Free the resources, then if !EFI_ERROR (Status), restart the
|
||||
// receive, otherwise end the session.
|
||||
//
|
||||
if (Packet != NULL && TotalNum > 1) {
|
||||
FreePool (Packet);
|
||||
}
|
||||
if (UdpPacket != NULL) {
|
||||
NetbufFree (UdpPacket);
|
||||
}
|
||||
if (!EFI_ERROR (Status) && !IsCompleted) {
|
||||
if (IsMcast) {
|
||||
Status = UdpIoRecvDatagram (
|
||||
Instance->McastUdpIo,
|
||||
Mtftp6RrqInput,
|
||||
Instance,
|
||||
0
|
||||
);
|
||||
} else {
|
||||
Status = UdpIoRecvDatagram (
|
||||
Instance->UdpIo,
|
||||
Mtftp6RrqInput,
|
||||
Instance,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Clean up the current session if failed to continue.
|
||||
//
|
||||
if (EFI_ERROR (Status) || IsCompleted) {
|
||||
Mtftp6OperationClean (Instance, Status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start the Mtftp6 instance to download. It first initializes some
|
||||
of the internal states, then builds and sends an RRQ reqeuest packet.
|
||||
Finally, it starts receive for the downloading.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Operation The operation code of current packet.
|
||||
|
||||
@retval EFI_SUCCESS The Mtftp6 is started to download.
|
||||
@retval Others Failed to start to download.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6RrqStart (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN UINT16 Operation
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// The valid block number range are [1, 0xffff]. For example:
|
||||
// the client sends an RRQ request to the server, the server
|
||||
// transfers the DATA1 block. If option negoitation is ongoing,
|
||||
// the server will send back an OACK, then client will send ACK0.
|
||||
//
|
||||
Status = Mtftp6InitBlockRange (&Instance->BlkList, 1, 0xffff);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Mtftp6SendRequest (Instance, Operation);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return UdpIoRecvDatagram (
|
||||
Instance->UdpIo,
|
||||
Mtftp6RrqInput,
|
||||
Instance,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
1189
NetworkPkg/Mtftp6Dxe/Mtftp6Support.c
Normal file
1189
NetworkPkg/Mtftp6Dxe/Mtftp6Support.c
Normal file
File diff suppressed because it is too large
Load Diff
359
NetworkPkg/Mtftp6Dxe/Mtftp6Support.h
Normal file
359
NetworkPkg/Mtftp6Dxe/Mtftp6Support.h
Normal file
@@ -0,0 +1,359 @@
|
||||
/** @file
|
||||
Mtftp6 support functions declaration.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EFI_MTFTP6_SUPPORT_H__
|
||||
#define __EFI_MTFTP6_SUPPORT_H__
|
||||
|
||||
//
|
||||
// The structure representing a range of block numbers, [Start, End].
|
||||
// It is used to remember the holes in the MTFTP block space. If all
|
||||
// the holes are filled in, then the download or upload has completed.
|
||||
//
|
||||
typedef struct {
|
||||
LIST_ENTRY Link;
|
||||
INTN Start;
|
||||
INTN End;
|
||||
INTN Round;
|
||||
INTN Bound;
|
||||
} MTFTP6_BLOCK_RANGE;
|
||||
|
||||
|
||||
/**
|
||||
Initialize the block range for either RRQ or WRQ. RRQ and WRQ have
|
||||
different requirements for Start and End. For example, during startup,
|
||||
WRQ initializes its whole valid block range to [0, 0xffff]. This
|
||||
is because the server will send an ACK0 to inform the user to start the
|
||||
upload. When the client receives an ACK0, it will remove 0 from the range,
|
||||
get the next block number, which is 1, then upload the BLOCK1. For RRQ
|
||||
without option negotiation, the server will directly send us the BLOCK1
|
||||
in response to the client's RRQ. When BLOCK1 is received, the client will
|
||||
remove it from the block range and send an ACK. It also works if there
|
||||
is option negotiation.
|
||||
|
||||
@param[in] Head The block range head to initialize.
|
||||
@param[in] Start The Start block number.
|
||||
@param[in] End The last block number.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for initial block range.
|
||||
@retval EFI_SUCCESS The initial block range is created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6InitBlockRange (
|
||||
IN LIST_ENTRY *Head,
|
||||
IN UINT16 Start,
|
||||
IN UINT16 End
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Get the first valid block number on the range list.
|
||||
|
||||
@param[in] Head The block range head.
|
||||
|
||||
@retval ==-1 If the block range is empty.
|
||||
@retval >-1 The first valid block number.
|
||||
|
||||
**/
|
||||
INTN
|
||||
Mtftp6GetNextBlockNum (
|
||||
IN LIST_ENTRY *Head
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Set the last block number of the block range list. It
|
||||
removes all the blocks after the Last. MTFTP initialize the
|
||||
block range to the maximum possible range, such as [0, 0xffff]
|
||||
for WRQ. When it gets the last block number, it calls
|
||||
this function to set the last block number.
|
||||
|
||||
@param[in] Head The block range list.
|
||||
@param[in] Last The last block number.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp6SetLastBlockNum (
|
||||
IN LIST_ENTRY *Head,
|
||||
IN UINT16 Last
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Remove the block number from the block range list.
|
||||
|
||||
@param[in] Head The block range list to remove from.
|
||||
@param[in] Num The block number to remove.
|
||||
@param[in] Completed Whether Num is the last block number
|
||||
@param[out] TotalBlock The continuous block number in all
|
||||
|
||||
@retval EFI_NOT_FOUND The block number isn't in the block range list.
|
||||
@retval EFI_SUCCESS The block number has been removed from the list.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6RemoveBlockNum (
|
||||
IN LIST_ENTRY *Head,
|
||||
IN UINT16 Num,
|
||||
IN BOOLEAN Completed,
|
||||
OUT UINT64 *TotalBlock
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Build and transmit the request packet for the Mtftp6 instance.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Operation The operation code of this packet.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the request.
|
||||
@retval EFI_SUCCESS The request was built and sent.
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6SendRequest (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN UINT16 Operation
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Build and send an error packet.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] ErrCode The error code in the packet.
|
||||
@param[in] ErrInfo The error message in the packet.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the error packet.
|
||||
@retval EFI_SUCCESS The error packet was transmitted.
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6SendError (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN UINT16 ErrCode,
|
||||
IN UINT8* ErrInfo
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Send the packet for the Mtftp6 instance.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Packet The pointer to the packet to be sent.
|
||||
|
||||
@retval EFI_SUCCESS The packet was sent out
|
||||
@retval Others Failed to transmit the packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6TransmitPacket (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN NET_BUF *Packet
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Check packet for GetInfo callback routine.
|
||||
|
||||
@param[in] This The pointer to the Mtftp6 protocol.
|
||||
@param[in] Token The pointer to the Mtftp6 token.
|
||||
@param[in] PacketLen The length of the packet
|
||||
@param[in] Packet The pointer to the received packet.
|
||||
|
||||
@retval EFI_SUCCESS The check process passed successfully.
|
||||
@retval EFI_ABORTED Abort the Mtftp6 operation.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6CheckPacket (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_TOKEN *Token,
|
||||
IN UINT16 PacketLen,
|
||||
IN EFI_MTFTP6_PACKET *Packet
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
The dummy configure routine for create a new Udp6 Io.
|
||||
|
||||
@param[in] UdpIo The pointer to the Udp6 Io.
|
||||
@param[in] Context The pointer to the context.
|
||||
|
||||
@retval EFI_SUCCESS The value is always returned.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Mtftp6ConfigDummyUdpIo (
|
||||
IN UDP_IO *UdpIo,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
The configure routine for the Mtftp6 instance to transmit/receive.
|
||||
|
||||
@param[in] UdpIo The pointer to the Udp6 Io.
|
||||
@param[in] ServerIp The pointer to the server address.
|
||||
@param[in] ServerPort The pointer to the server port.
|
||||
@param[in] LocalIp The pointer to the local address.
|
||||
@param[in] LocalPort The pointer to the local port.
|
||||
|
||||
@retval EFI_SUCCESS Configure the Udp6 Io for Mtftp6 successfully.
|
||||
@retval EFI_NO_MAPPING The corresponding Ip6 instance has not been
|
||||
configured yet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6ConfigUdpIo (
|
||||
IN UDP_IO *UdpIo,
|
||||
IN EFI_IPv6_ADDRESS *ServerIp,
|
||||
IN UINT16 ServerPort,
|
||||
IN EFI_IPv6_ADDRESS *LocalIp,
|
||||
IN UINT16 LocalPort
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Clean up the current Mtftp6 operation.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Result The result to be returned to the user.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Mtftp6OperationClean (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN EFI_STATUS Result
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Start the Mtftp6 instance to perform the operation, such as read file,
|
||||
write file, and read directory.
|
||||
|
||||
@param[in] This The MTFTP session
|
||||
@param[in] Token The token that encapsulates the user's request.
|
||||
@param[in] OpCode The operation to perform.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Some of the parameters are invalid.
|
||||
@retval EFI_NOT_STARTED The MTFTP session hasn't been configured.
|
||||
@retval EFI_ALREADY_STARTED There is pending operation for the session.
|
||||
@retval EFI_SUCCESS The operation was successfully started.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6OperationStart (
|
||||
IN EFI_MTFTP6_PROTOCOL *This,
|
||||
IN EFI_MTFTP6_TOKEN *Token,
|
||||
IN UINT16 OpCode
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
The timer ticking routine for the Mtftp6 instance.
|
||||
|
||||
@param[in] Event The pointer to the ticking event.
|
||||
@param[in] Context The pointer to the context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Mtftp6OnTimerTick (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
The packet process callback for Mtftp6 upload.
|
||||
|
||||
@param[in] UdpPacket The pointer to the packet received.
|
||||
@param[in] UdpEpt The pointer to the Udp6 access point.
|
||||
@param[in] IoStatus The status from the Udp6 instance.
|
||||
@param[in] Context The pointer to the context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Mtftp6WrqInput (
|
||||
IN NET_BUF *UdpPacket,
|
||||
IN UDP_END_POINT *UdpEpt,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Start the Mtftp6 instance to upload. It will first init some states,
|
||||
then send the WRQ request packet, and start to receive the packet.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Operation The operation code of current packet.
|
||||
|
||||
@retval EFI_SUCCESS The Mtftp6 was started to upload.
|
||||
@retval Others Failed to start to upload.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6WrqStart (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN UINT16 Operation
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
The packet process callback for Mtftp6 download.
|
||||
|
||||
@param[in] UdpPacket The pointer to the packet received.
|
||||
@param[in] UdpEpt The pointer to the Udp6 access point.
|
||||
@param[in] IoStatus The status from Udp6 instance.
|
||||
@param[in] Context The pointer to the context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Mtftp6RrqInput (
|
||||
IN NET_BUF *UdpPacket,
|
||||
IN UDP_END_POINT *UdpEpt,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Start the Mtftp6 instance to download. It first initializes some
|
||||
of the internal states then builds and sends an RRQ reqeuest packet.
|
||||
Finally, it starts receive for the downloading.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Operation The operation code of current packet.
|
||||
|
||||
@retval EFI_SUCCESS The Mtftp6 was started to download.
|
||||
@retval Others Failed to start to download.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6RrqStart (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN UINT16 Operation
|
||||
);
|
||||
|
||||
#endif
|
602
NetworkPkg/Mtftp6Dxe/Mtftp6Wrq.c
Normal file
602
NetworkPkg/Mtftp6Dxe/Mtftp6Wrq.c
Normal file
@@ -0,0 +1,602 @@
|
||||
/** @file
|
||||
Mtftp6 Wrq process functions implementation.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "Mtftp6Impl.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Build and send a Mtftp6 data packet for upload.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] BlockNum The block num to be sent.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet.
|
||||
@retval EFI_SUCCESS The data packet was sent.
|
||||
@retval EFI_ABORTED The user aborted this process.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6WrqSendBlock (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN UINT16 BlockNum
|
||||
)
|
||||
{
|
||||
EFI_MTFTP6_PACKET *Packet;
|
||||
EFI_MTFTP6_TOKEN *Token;
|
||||
NET_BUF *UdpPacket;
|
||||
EFI_STATUS Status;
|
||||
UINT16 DataLen;
|
||||
UINT8 *DataBuf;
|
||||
UINT64 Start;
|
||||
|
||||
//
|
||||
// Allocate net buffer to create data packet.
|
||||
//
|
||||
UdpPacket = NetbufAlloc (Instance->BlkSize + MTFTP6_DATA_HEAD_LEN);
|
||||
|
||||
if (UdpPacket == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Packet = (EFI_MTFTP6_PACKET *) NetbufAllocSpace (
|
||||
UdpPacket,
|
||||
MTFTP6_DATA_HEAD_LEN,
|
||||
FALSE
|
||||
);
|
||||
ASSERT (Packet != NULL);
|
||||
|
||||
Packet->Data.OpCode = HTONS (EFI_MTFTP6_OPCODE_DATA);
|
||||
Packet->Data.Block = HTONS (BlockNum);
|
||||
|
||||
//
|
||||
// Read the block from either the buffer or PacketNeeded callback
|
||||
//
|
||||
Token = Instance->Token;
|
||||
DataLen = Instance->BlkSize;
|
||||
|
||||
if (Token->Buffer != NULL) {
|
||||
Start = MultU64x32 (BlockNum - 1, Instance->BlkSize);
|
||||
|
||||
if (Token->BufferSize < Start + Instance->BlkSize) {
|
||||
DataLen = (UINT16) (Token->BufferSize - Start);
|
||||
Instance->LastBlk = BlockNum;
|
||||
Mtftp6SetLastBlockNum (&Instance->BlkList, BlockNum);
|
||||
}
|
||||
|
||||
if (DataLen > 0) {
|
||||
NetbufAllocSpace (UdpPacket, DataLen, FALSE);
|
||||
CopyMem (Packet->Data.Data, (UINT8 *) Token->Buffer + Start, DataLen);
|
||||
}
|
||||
|
||||
} else {
|
||||
//
|
||||
// Get data from PacketNeeded
|
||||
//
|
||||
DataBuf = NULL;
|
||||
Status = Token->PacketNeeded (&Instance->Mtftp6, Token, &DataLen, (VOID*) &DataBuf);
|
||||
|
||||
if (EFI_ERROR (Status) || (DataLen > Instance->BlkSize)) {
|
||||
if (DataBuf != NULL) {
|
||||
gBS->FreePool (DataBuf);
|
||||
}
|
||||
//
|
||||
// The received packet has already been freed.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
|
||||
(UINT8 *) "User aborted the transfer"
|
||||
);
|
||||
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
if (DataLen < Instance->BlkSize) {
|
||||
Instance->LastBlk = BlockNum;
|
||||
Mtftp6SetLastBlockNum (&Instance->BlkList, BlockNum);
|
||||
}
|
||||
|
||||
if (DataLen > 0) {
|
||||
NetbufAllocSpace (UdpPacket, DataLen, FALSE);
|
||||
CopyMem (Packet->Data.Data, DataBuf, DataLen);
|
||||
gBS->FreePool (DataBuf);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Reset current retry count of the instance.
|
||||
//
|
||||
Instance->CurRetry = 0;
|
||||
|
||||
return Mtftp6TransmitPacket (Instance, UdpPacket);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function to handle received ACK packet. If the ACK number matches the
|
||||
expected block number, with more data pending, send the next
|
||||
block. Otherwise, tell the caller that we are done.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Packet The pointer to the received packet.
|
||||
@param[in] Len The length of the packet.
|
||||
@param[out] UdpPacket The net buf of received packet.
|
||||
@param[out] IsCompleted If TRUE, the upload has been completed.
|
||||
Otherwise, the upload has not been completed.
|
||||
|
||||
@retval EFI_SUCCESS The ACK packet successfully processed.
|
||||
@retval EFI_TFTP_ERROR The block number loops back.
|
||||
@retval Others Failed to transmit the next data packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6WrqHandleAck (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
OUT NET_BUF **UdpPacket,
|
||||
OUT BOOLEAN *IsCompleted
|
||||
)
|
||||
{
|
||||
UINT16 AckNum;
|
||||
INTN Expected;
|
||||
UINT64 TotalBlock;
|
||||
|
||||
*IsCompleted = FALSE;
|
||||
AckNum = NTOHS (Packet->Ack.Block[0]);
|
||||
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
|
||||
|
||||
ASSERT (Expected >= 0);
|
||||
|
||||
//
|
||||
// Get an unwanted ACK, return EFI_SUCCESS to let Mtftp6WrqInput
|
||||
// restart receive.
|
||||
//
|
||||
if (Expected != AckNum) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the acked block number, if this is the last block number,
|
||||
// tell the Mtftp6WrqInput to finish the transfer. This is the last
|
||||
// block number if the block range are empty..
|
||||
//
|
||||
Mtftp6RemoveBlockNum (&Instance->BlkList, AckNum, *IsCompleted, &TotalBlock);
|
||||
|
||||
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
|
||||
|
||||
if (Expected < 0) {
|
||||
//
|
||||
// The block range is empty. It may either because the the last
|
||||
// block has been ACKed, or the sequence number just looped back,
|
||||
// that is, there is more than 0xffff blocks.
|
||||
//
|
||||
if (Instance->LastBlk == AckNum) {
|
||||
ASSERT (Instance->LastBlk >= 1);
|
||||
*IsCompleted = TRUE;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if block number rolls back.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
|
||||
(UINT8 *) "Block number rolls back, not supported, try blksize option"
|
||||
);
|
||||
|
||||
return EFI_TFTP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Free the receive buffer before send new packet since it might need
|
||||
// reconfigure udpio.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
|
||||
return Mtftp6WrqSendBlock (Instance, (UINT16) Expected);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check whether the received OACK is valid. The OACK is valid
|
||||
only if:
|
||||
1. It only include options requested by us.
|
||||
2. It can only include a smaller block size.
|
||||
3. It can't change the proposed time out value.
|
||||
4. Other requirements of the individal MTFTP6 options as required.
|
||||
|
||||
@param[in] ReplyInfo The pointer to options information in reply packet.
|
||||
@param[in] RequestInfo The pointer to requested options information.
|
||||
|
||||
@retval TRUE If the option in OACK is valid.
|
||||
@retval FALSE If the option is invalid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Mtftp6WrqOackValid (
|
||||
IN MTFTP6_EXT_OPTION_INFO *ReplyInfo,
|
||||
IN MTFTP6_EXT_OPTION_INFO *RequestInfo
|
||||
)
|
||||
{
|
||||
//
|
||||
// It is invalid for server to return options we don't request
|
||||
//
|
||||
if ((ReplyInfo->BitMap & ~RequestInfo->BitMap) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Server can only specify a smaller block size to be used and
|
||||
// return the timeout matches that requested.
|
||||
//
|
||||
if ((((ReplyInfo->BitMap & MTFTP6_OPT_BLKSIZE_BIT) != 0) && (ReplyInfo->BlkSize > RequestInfo->BlkSize)) ||
|
||||
(((ReplyInfo->BitMap & MTFTP6_OPT_TIMEOUT_BIT) != 0) && (ReplyInfo->Timeout != RequestInfo->Timeout))
|
||||
) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Process the OACK packet for Wrq.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Packet The pointer to the received packet.
|
||||
@param[in] Len The length of the packet.
|
||||
@param[out] UdpPacket The net buf of received packet.
|
||||
@param[out] IsCompleted If TRUE, the upload has been completed.
|
||||
Otherwise, the upload has not been completed.
|
||||
|
||||
@retval EFI_SUCCESS The OACK packet successfully processed.
|
||||
@retval EFI_TFTP_ERROR An TFTP communication error happened.
|
||||
@retval Others Failed to process the OACK packet.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6WrqHandleOack (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN EFI_MTFTP6_PACKET *Packet,
|
||||
IN UINT32 Len,
|
||||
OUT NET_BUF **UdpPacket,
|
||||
OUT BOOLEAN *IsCompleted
|
||||
)
|
||||
{
|
||||
EFI_MTFTP6_OPTION *Options;
|
||||
UINT32 Count;
|
||||
MTFTP6_EXT_OPTION_INFO ExtInfo;
|
||||
EFI_MTFTP6_PACKET Dummy;
|
||||
EFI_STATUS Status;
|
||||
INTN Expected;
|
||||
|
||||
*IsCompleted = FALSE;
|
||||
|
||||
//
|
||||
// Ignore the OACK if already started the upload
|
||||
//
|
||||
Expected = Mtftp6GetNextBlockNum (&Instance->BlkList);
|
||||
|
||||
if (Expected != 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse and validate the options from server
|
||||
//
|
||||
ZeroMem (&ExtInfo, sizeof (MTFTP6_EXT_OPTION_INFO));
|
||||
|
||||
Status = Mtftp6ParseStart (Packet, Len, &Count, &Options);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, &ExtInfo);
|
||||
|
||||
if (EFI_ERROR(Status) || !Mtftp6WrqOackValid (&ExtInfo, &Instance->ExtInfo)) {
|
||||
//
|
||||
// Don't send a MTFTP error packet when out of resource, it can
|
||||
// only make it worse.
|
||||
//
|
||||
if (Status != EFI_OUT_OF_RESOURCES) {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (*UdpPacket);
|
||||
*UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if invalid Oack packet received.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
|
||||
(UINT8 *) "Mal-formated OACK packet"
|
||||
);
|
||||
}
|
||||
|
||||
return EFI_TFTP_ERROR;
|
||||
}
|
||||
|
||||
if (ExtInfo.BlkSize != 0) {
|
||||
Instance->BlkSize = ExtInfo.BlkSize;
|
||||
}
|
||||
|
||||
if (ExtInfo.Timeout != 0) {
|
||||
Instance->Timeout = ExtInfo.Timeout;
|
||||
}
|
||||
|
||||
//
|
||||
// Build a bogus ACK0 packet then pass it to the Mtftp6WrqHandleAck,
|
||||
// which will start the transmission of the first data block.
|
||||
//
|
||||
Dummy.Ack.OpCode = HTONS (EFI_MTFTP6_OPCODE_ACK);
|
||||
Dummy.Ack.Block[0] = 0;
|
||||
|
||||
return Mtftp6WrqHandleAck (
|
||||
Instance,
|
||||
&Dummy,
|
||||
sizeof (EFI_MTFTP6_ACK_HEADER),
|
||||
UdpPacket,
|
||||
IsCompleted
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The packet process callback for Mtftp6 upload.
|
||||
|
||||
@param[in] UdpPacket The pointer to the packet received.
|
||||
@param[in] UdpEpt The pointer to the Udp6 access point.
|
||||
@param[in] IoStatus The status from Udp6 instance.
|
||||
@param[in] Context The pointer to the context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
Mtftp6WrqInput (
|
||||
IN NET_BUF *UdpPacket,
|
||||
IN UDP_END_POINT *UdpEpt,
|
||||
IN EFI_STATUS IoStatus,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
MTFTP6_INSTANCE *Instance;
|
||||
EFI_MTFTP6_PACKET *Packet;
|
||||
BOOLEAN IsCompleted;
|
||||
EFI_STATUS Status;
|
||||
UINT32 TotalNum;
|
||||
UINT32 Len;
|
||||
UINT16 Opcode;
|
||||
|
||||
Instance = (MTFTP6_INSTANCE *) Context;
|
||||
|
||||
NET_CHECK_SIGNATURE (Instance, MTFTP6_INSTANCE_SIGNATURE);
|
||||
|
||||
IsCompleted = FALSE;
|
||||
Packet = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
TotalNum = 0;
|
||||
|
||||
//
|
||||
// Return error status if Udp6 instance failed to receive.
|
||||
//
|
||||
if (EFI_ERROR (IoStatus)) {
|
||||
Status = IoStatus;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
ASSERT (UdpPacket != NULL);
|
||||
|
||||
if (UdpPacket->TotalSize < MTFTP6_OPCODE_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Client send initial request to server's listening port. Server
|
||||
// will select a UDP port to communicate with the client.
|
||||
//
|
||||
if (UdpEpt->RemotePort != Instance->ServerDataPort) {
|
||||
if (Instance->ServerDataPort != 0) {
|
||||
goto ON_EXIT;
|
||||
} else {
|
||||
Instance->ServerDataPort = UdpEpt->RemotePort;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the MTFTP packet to a continuous buffer if it isn't already so.
|
||||
//
|
||||
Len = UdpPacket->TotalSize;
|
||||
TotalNum = UdpPacket->BlockOpNum;
|
||||
|
||||
if (TotalNum > 1) {
|
||||
Packet = AllocateZeroPool (Len);
|
||||
|
||||
if (Packet == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);
|
||||
|
||||
} else {
|
||||
Packet = (EFI_MTFTP6_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
|
||||
ASSERT (Packet != NULL);
|
||||
}
|
||||
|
||||
Opcode = NTOHS (Packet->OpCode);
|
||||
|
||||
//
|
||||
// Callback to the user's CheckPacket if provided. Abort the transmission
|
||||
// if CheckPacket returns an EFI_ERROR code.
|
||||
//
|
||||
if (Instance->Token->CheckPacket != NULL &&
|
||||
(Opcode == EFI_MTFTP6_OPCODE_OACK || Opcode == EFI_MTFTP6_OPCODE_ERROR)
|
||||
) {
|
||||
|
||||
Status = Instance->Token->CheckPacket (
|
||||
&Instance->Mtftp6,
|
||||
Instance->Token,
|
||||
(UINT16) Len,
|
||||
Packet
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Send an error message to the server to inform it
|
||||
//
|
||||
if (Opcode != EFI_MTFTP6_OPCODE_ERROR) {
|
||||
//
|
||||
// Free the received packet before send new packet in ReceiveNotify,
|
||||
// since the udpio might need to be reconfigured.
|
||||
//
|
||||
NetbufFree (UdpPacket);
|
||||
UdpPacket = NULL;
|
||||
//
|
||||
// Send the Mtftp6 error message if user aborted the current session.
|
||||
//
|
||||
Mtftp6SendError (
|
||||
Instance,
|
||||
EFI_MTFTP6_ERRORCODE_REQUEST_DENIED,
|
||||
(UINT8 *) "User aborted the transfer"
|
||||
);
|
||||
}
|
||||
|
||||
Status = EFI_ABORTED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Switch the process routines by the operation code.
|
||||
//
|
||||
switch (Opcode) {
|
||||
case EFI_MTFTP6_OPCODE_ACK:
|
||||
if (Len != MTFTP6_OPCODE_LEN + MTFTP6_BLKNO_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Handle the Ack packet of Wrq.
|
||||
//
|
||||
Status = Mtftp6WrqHandleAck (Instance, Packet, Len, &UdpPacket, &IsCompleted);
|
||||
break;
|
||||
|
||||
case EFI_MTFTP6_OPCODE_OACK:
|
||||
if (Len <= MTFTP6_OPCODE_LEN) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Handle the Oack packet of Wrq.
|
||||
//
|
||||
Status = Mtftp6WrqHandleOack (Instance, Packet, Len, &UdpPacket, &IsCompleted);
|
||||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// Drop and return eror if received error message.
|
||||
//
|
||||
Status = EFI_TFTP_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
//
|
||||
// Free the resources, then if !EFI_ERROR (Status) and not completed,
|
||||
// restart the receive, otherwise end the session.
|
||||
//
|
||||
if (Packet != NULL && TotalNum > 1) {
|
||||
FreePool (Packet);
|
||||
}
|
||||
|
||||
if (UdpPacket != NULL) {
|
||||
NetbufFree (UdpPacket);
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status) && !IsCompleted) {
|
||||
Status = UdpIoRecvDatagram (
|
||||
Instance->UdpIo,
|
||||
Mtftp6WrqInput,
|
||||
Instance,
|
||||
0
|
||||
);
|
||||
}
|
||||
//
|
||||
// Clean up the current session if failed to continue.
|
||||
//
|
||||
if (EFI_ERROR (Status) || IsCompleted) {
|
||||
Mtftp6OperationClean (Instance, Status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start the Mtftp6 instance to upload. It will first init some states,
|
||||
then send the WRQ request packet, and start to receive the packet.
|
||||
|
||||
@param[in] Instance The pointer to the Mtftp6 instance.
|
||||
@param[in] Operation The operation code of the current packet.
|
||||
|
||||
@retval EFI_SUCCESS The Mtftp6 was started to upload.
|
||||
@retval Others Failed to start to upload.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Mtftp6WrqStart (
|
||||
IN MTFTP6_INSTANCE *Instance,
|
||||
IN UINT16 Operation
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// The valid block number range are [0, 0xffff]. For example:
|
||||
// the client sends an WRQ request to the server, the server
|
||||
// ACK with an ACK0 to let client start transfer the first
|
||||
// packet.
|
||||
//
|
||||
Status = Mtftp6InitBlockRange (&Instance->BlkList, 0, 0xffff);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = Mtftp6SendRequest (Instance, Operation);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return UdpIoRecvDatagram (
|
||||
Instance->UdpIo,
|
||||
Mtftp6WrqInput,
|
||||
Instance,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user