summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Impl.c4
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c77
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c84
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h10
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c6
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.c52
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h10
7 files changed, 186 insertions, 57 deletions
diff --git a/MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Impl.c b/MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Impl.c
index c190a1df80..4b281bb283 100644
--- a/MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Impl.c
+++ b/MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Impl.c
@@ -1,6 +1,6 @@
/** @file
-Copyright (c) 2006 - 2007, Intel Corporation
+Copyright (c) 2006 - 2008, Intel Corporation
All rights reserved. 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
@@ -306,7 +306,7 @@ Udp4CheckTimeout (
//
// Iterate all the rxdatas belonging to this udp instance.
//
- Wrap = NET_LIST_USER_STRUCT (Entry, UDP4_RXDATA_WRAP, Link);
+ Wrap = NET_LIST_USER_STRUCT (WrapEntry, UDP4_RXDATA_WRAP, Link);
if (Wrap->TimeoutTick <= UDP4_TIMEOUT_INTERVAL / 1000) {
//
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c
index 9d26b135f5..845b7c0fd6 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c
@@ -270,17 +270,20 @@ PxeBcDriverBindingStart (
ControllerHandle,
This->DriverBindingHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
- &Private->Udp4Child
+ &Private->Udp4ReadChild
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
+ //
+ // The UDP instance for EfiPxeBcUdpRead
+ //
Status = gBS->OpenProtocol (
- Private->Udp4Child,
+ Private->Udp4ReadChild,
&gEfiUdp4ProtocolGuid,
- (VOID **) &Private->Udp4,
+ (VOID **) &Private->Udp4Read,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
@@ -290,18 +293,42 @@ PxeBcDriverBindingStart (
goto ON_ERROR;
}
+ //
+ // The UDP instance for EfiPxeBcUdpWrite
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiUdp4ServiceBindingProtocolGuid,
+ &Private->Udp4WriteChild
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ Private->Udp4WriteChild,
+ &gEfiUdp4ProtocolGuid,
+ (VOID **) &Private->Udp4Write,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
ZeroMem (&Private->Udp4CfgData, sizeof (EFI_UDP4_CONFIG_DATA));
Private->Udp4CfgData.AcceptBroadcast = FALSE;
Private->Udp4CfgData.AcceptPromiscuous = FALSE;
- Private->Udp4CfgData.AcceptAnyPort = FALSE;
+ Private->Udp4CfgData.AcceptAnyPort = TRUE;
Private->Udp4CfgData.AllowDuplicatePort = TRUE;
Private->Udp4CfgData.TypeOfService = DEFAULT_ToS;
Private->Udp4CfgData.TimeToLive = DEFAULT_TTL;
Private->Udp4CfgData.DoNotFragment = FALSE;
- Private->Udp4CfgData.ReceiveTimeout = 10000; // 10 milliseconds
+ Private->Udp4CfgData.ReceiveTimeout = 50000; // 50 milliseconds
Private->Udp4CfgData.UseDefaultAddress = FALSE;
- PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4);
+ PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4Read);
Private->MacLen = Private->SeedPacket.Dhcp4.Header.HwAddrLen;
CopyMem (&Private->Mac, &Private->SeedPacket.Dhcp4.Header.ClientHwAddr[0], Private->MacLen);
@@ -330,9 +357,24 @@ PxeBcDriverBindingStart (
ON_ERROR:
- if (Private->Udp4Child != NULL) {
+ if (Private->Udp4WriteChild != NULL) {
+ gBS->CloseProtocol (
+ Private->Udp4WriteChild,
+ &gEfiUdp4ProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ NetLibDestroyServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiUdp4ServiceBindingProtocolGuid,
+ Private->Udp4WriteChild
+ );
+ }
+
+ if (Private->Udp4ReadChild != NULL) {
gBS->CloseProtocol (
- Private->Udp4Child,
+ Private->Udp4ReadChild,
&gEfiUdp4ProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
@@ -341,7 +383,7 @@ ON_ERROR:
ControllerHandle,
This->DriverBindingHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
- Private->Udp4Child
+ Private->Udp4ReadChild
);
}
@@ -491,7 +533,20 @@ PxeBcDriverBindingStop (
if (!EFI_ERROR (Status)) {
gBS->CloseProtocol (
- Private->Udp4Child,
+ Private->Udp4WriteChild,
+ &gEfiUdp4ProtocolGuid,
+ This->DriverBindingHandle,
+ NicHandle
+ );
+ NetLibDestroyServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiUdp4ServiceBindingProtocolGuid,
+ Private->Udp4WriteChild
+ );
+
+ gBS->CloseProtocol (
+ Private->Udp4ReadChild,
&gEfiUdp4ProtocolGuid,
This->DriverBindingHandle,
NicHandle
@@ -500,7 +555,7 @@ PxeBcDriverBindingStop (
NicHandle,
This->DriverBindingHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
- Private->Udp4Child
+ Private->Udp4ReadChild
);
gBS->CloseProtocol (
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c
index c0fff3d547..8fc528f316 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c
@@ -272,7 +272,7 @@ EfiPxeBcStart (
//
// Configure the udp4 instance to let it receive data
//
- Status = Private->Udp4->Configure (Private->Udp4, &Private->Udp4CfgData);
+ Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -421,13 +421,9 @@ EfiPxeBcStop (
Mode->Started = FALSE;
-
- //
- // Reset and leave joined groups
- //
- Private->Udp4->Groups (Private->Udp4, FALSE, NULL);
-
- Private->Udp4->Configure (Private->Udp4, NULL);
+ Private->CurrentUdpSrcPort = 0;
+ Private->Udp4Write->Configure (Private->Udp4Write, NULL);
+ Private->Udp4Read->Configure (Private->Udp4Read, NULL);
Private->Dhcp4->Stop (Private->Dhcp4);
Private->Dhcp4->Configure (Private->Dhcp4, NULL);
@@ -1076,7 +1072,6 @@ EfiPxeBcUdpWrite (
EFI_UDP4_SESSION_DATA Udp4Session;
EFI_STATUS Status;
BOOLEAN IsDone;
- UINT16 RandomSrcPort;
EFI_PXE_BASE_CODE_MODE *Mode;
EFI_MAC_ADDRESS TempMacAddr;
@@ -1106,8 +1101,11 @@ EfiPxeBcUdpWrite (
}
Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
- Udp4 = Private->Udp4;
+ Udp4 = Private->Udp4Write;
Mode = &Private->Mode;
+ if (!Mode->Started) {
+ return EFI_NOT_STARTED;
+ }
if (!Private->AddressIsOk && (SrcIp == NULL)) {
return EFI_INVALID_PARAMETER;
@@ -1125,23 +1123,25 @@ EfiPxeBcUdpWrite (
Mode->IcmpErrorReceived = FALSE;
- if (SrcIp == NULL) {
- SrcIp = &Private->StationIp;
-
- if (GatewayIp == NULL) {
- GatewayIp = &Private->GatewayIp;
+ if ((Private->CurrentUdpSrcPort == 0) ||
+ ((SrcPort != NULL) && (*SrcPort != Private->CurrentUdpSrcPort))) {
+ //
+ // Port is changed, (re)configure the Udp4Write instance
+ //
+ if (SrcPort != NULL) {
+ Private->CurrentUdpSrcPort = *SrcPort;
}
- }
-
- if ((SrcPort == NULL) || (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT)) {
- RandomSrcPort = (UINT16) (NET_RANDOM (NetRandomInitSeed ()) % 10000 + 1024);
-
- if (SrcPort == NULL) {
- SrcPort = &RandomSrcPort;
- } else {
-
- *SrcPort = RandomSrcPort;
+ Status = PxeBcConfigureUdpWriteInstance (
+ Udp4,
+ &Private->StationIp.v4,
+ &Private->SubnetMask.v4,
+ &Private->GatewayIp.v4,
+ &Private->CurrentUdpSrcPort
+ );
+ if (EFI_ERROR (Status)) {
+ Private->CurrentUdpSrcPort = 0;
+ return EFI_INVALID_PARAMETER;
}
}
@@ -1150,8 +1150,12 @@ EfiPxeBcUdpWrite (
CopyMem (&Udp4Session.DestinationAddress, DestIp, sizeof (EFI_IPv4_ADDRESS));
Udp4Session.DestinationPort = *DestPort;
- CopyMem (&Udp4Session.SourceAddress, SrcIp, sizeof (EFI_IPv4_ADDRESS));
- Udp4Session.SourcePort = *SrcPort;
+ if (SrcIp != NULL) {
+ CopyMem (&Udp4Session.SourceAddress, SrcIp, sizeof (EFI_IPv4_ADDRESS));
+ }
+ if (SrcPort != NULL) {
+ Udp4Session.SourcePort = *SrcPort;
+ }
FragCount = (HeaderSize != NULL) ? 2 : 1;
Udp4TxData = (EFI_UDP4_TRANSMIT_DATA *) AllocatePool (sizeof (EFI_UDP4_TRANSMIT_DATA) + (FragCount - 1) * sizeof (EFI_UDP4_FRAGMENT_DATA));
@@ -1171,7 +1175,9 @@ EfiPxeBcUdpWrite (
DataLength += (UINT32) *HeaderSize;
}
- Udp4TxData->GatewayAddress = (EFI_IPv4_ADDRESS *) GatewayIp;
+ if (GatewayIp != NULL) {
+ Udp4TxData->GatewayAddress = (EFI_IPv4_ADDRESS *) GatewayIp;
+ }
Udp4TxData->UdpSessionData = &Udp4Session;
Udp4TxData->DataLength = DataLength;
Token.Packet.TxData = Udp4TxData;
@@ -1344,7 +1350,7 @@ EfiPxeBcUdpRead (
return EFI_INVALID_PARAMETER;
}
- if (((HeaderSize != NULL) && (*HeaderSize == 0)) || ((HeaderPtr == NULL) && (*HeaderSize != 0))) {
+ if (((HeaderSize != NULL) && (*HeaderSize == 0)) || ((HeaderSize != NULL) && (HeaderPtr == NULL))) {
return EFI_INVALID_PARAMETER;
}
@@ -1354,7 +1360,7 @@ EfiPxeBcUdpRead (
Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
Mode = Private->PxeBc.Mode;
- Udp4 = Private->Udp4;
+ Udp4 = Private->Udp4Read;
if (!Mode->Started) {
return EFI_NOT_STARTED;
@@ -1373,6 +1379,8 @@ EfiPxeBcUdpRead (
return EFI_OUT_OF_RESOURCES;
}
+TRY_AGAIN:
+
IsDone = FALSE;
Status = Udp4->Receive (Udp4, &Token);
if (EFI_ERROR (Status)) {
@@ -1410,6 +1418,8 @@ EfiPxeBcUdpRead (
}
if (Matched) {
+ Matched = FALSE;
+
//
// Match the destination ip of the received udp dgram
//
@@ -1510,6 +1520,10 @@ EfiPxeBcUdpRead (
// Recycle the RxData
//
gBS->SignalEvent (RxData->RecycleSignal);
+
+ if (!Matched) {
+ goto TRY_AGAIN;
+ }
}
ON_EXIT:
@@ -1594,7 +1608,7 @@ EfiPxeBcSetIpFilter (
// Clear the UDP instance configuration, all joined groups will be left
// during the operation.
//
- Private->Udp4->Configure (Private->Udp4, NULL);
+ Private->Udp4Read->Configure (Private->Udp4Read, NULL);
Private->Udp4CfgData.AcceptPromiscuous = FALSE;
Private->Udp4CfgData.AcceptBroadcast = FALSE;
@@ -1610,7 +1624,7 @@ EfiPxeBcSetIpFilter (
//
// Configure the UDP instance with the new configuration.
//
- Status = Private->Udp4->Configure (Private->Udp4, &Private->Udp4CfgData);
+ Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1627,7 +1641,7 @@ EfiPxeBcSetIpFilter (
//
// Configure the UDP instance with the new configuration.
//
- Status = Private->Udp4->Configure (Private->Udp4, &Private->Udp4CfgData);
+ Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -1639,7 +1653,7 @@ EfiPxeBcSetIpFilter (
//
// Join the mutilcast group
//
- Status = Private->Udp4->Groups (Private->Udp4, TRUE, &NewFilter->IpList[Index].v4);
+ Status = Private->Udp4Read->Groups (Private->Udp4Read, TRUE, &NewFilter->IpList[Index].v4);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2448,7 +2462,7 @@ EfiPxeLoadFile (
switch (Status) {
case EFI_SUCCESS:
- break;
+ return EFI_SUCCESS;
case EFI_BUFFER_TOO_SMALL:
if (Buffer != NULL) {
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h
index 4fbdcad5eb..df77c5da49 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h
@@ -1,6 +1,6 @@
/** @file
-Copyright (c) 2007, Intel Corporation
+Copyright (c) 2007 - 2008, Intel Corporation
All rights reserved. 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
@@ -64,8 +64,8 @@ struct _PXEBC_PRIVATE_DATA {
EFI_HANDLE Dhcp4Child;
EFI_HANDLE Ip4Child;
EFI_HANDLE Mtftp4Child;
- EFI_HANDLE Udp4Child;
-
+ EFI_HANDLE Udp4ReadChild;
+ EFI_HANDLE Udp4WriteChild;
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
@@ -78,7 +78,9 @@ struct _PXEBC_PRIVATE_DATA {
EFI_IP4_PROTOCOL *Ip4;
EFI_IP4_CONFIG_DATA Ip4ConfigData;
EFI_MTFTP4_PROTOCOL *Mtftp4;
- EFI_UDP4_PROTOCOL *Udp4;
+ EFI_UDP4_PROTOCOL *Udp4Read;
+ EFI_UDP4_PROTOCOL *Udp4Write;
+ UINT16 CurrentUdpSrcPort;
EFI_UDP4_CONFIG_DATA Udp4CfgData;
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c
index 3b2eb5b422..b49ff2d52c 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c
@@ -254,7 +254,7 @@ PxeBcTftpReadFile (
if (BlockSize != NULL) {
- ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
+ ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
ReqOpt[0].ValueStr = OptBuf;
UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);
OptCnt++;
@@ -336,7 +336,7 @@ PxeBcTftpWriteFile (
if (BlockSize != NULL) {
- ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
+ ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
ReqOpt[0].ValueStr = OptBuf;
UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);
OptCnt++;
@@ -410,7 +410,7 @@ PxeBcTftpReadDirectory (
if (BlockSize != NULL) {
- ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
+ ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
ReqOpt[0].ValueStr = OptBuf;
UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);
OptCnt++;
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.c
index 200d43141e..0e42b5c69b 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.c
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.c
@@ -1,6 +1,6 @@
/** @file
-Copyright (c) 2007, Intel Corporation
+Copyright (c) 2007 - 2008, Intel Corporation
All rights reserved. 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
@@ -162,6 +162,56 @@ PxeBcCommonNotify (
*((BOOLEAN *) Context) = TRUE;
}
+EFI_STATUS
+PxeBcConfigureUdpWriteInstance (
+ IN EFI_UDP4_PROTOCOL *Udp4,
+ IN EFI_IPv4_ADDRESS *StationIp,
+ IN EFI_IPv4_ADDRESS *SubnetMask,
+ IN EFI_IPv4_ADDRESS *Gateway,
+ IN OUT UINT16 *SrcPort
+ )
+{
+ EFI_UDP4_CONFIG_DATA Udp4CfgData;
+ EFI_STATUS Status;
+
+ ZeroMem (&Udp4CfgData, sizeof (Udp4CfgData));
+
+ Udp4CfgData.ReceiveTimeout = 1000;
+ Udp4CfgData.TypeOfService = DEFAULT_ToS;
+ Udp4CfgData.TimeToLive = DEFAULT_TTL;
+
+ CopyMem (&Udp4CfgData.StationAddress, StationIp, sizeof (*StationIp));
+ CopyMem (&Udp4CfgData.SubnetMask, SubnetMask, sizeof (*SubnetMask));
+
+ Udp4CfgData.StationPort = *SrcPort;
+
+ //
+ // Reset the instance.
+ //
+ Udp4->Configure (Udp4, NULL);
+
+ Status = Udp4->Configure (Udp4, &Udp4CfgData);
+ if (!EFI_ERROR (Status) && (Gateway->Addr[0] != 0)) {
+ //
+ // basic configuration OK, need to add the default route entry
+ //
+ Status = Udp4->Routes (Udp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, Gateway);
+ if (EFI_ERROR (Status)) {
+ //
+ // roll back
+ //
+ Udp4->Configure (Udp4, NULL);
+ }
+ }
+
+ if (!EFI_ERROR (Status) && (*SrcPort == 0)) {
+ Udp4->GetModeData (Udp4, &Udp4CfgData, NULL, NULL, NULL);
+ *SrcPort = Udp4CfgData.StationPort;
+ }
+
+ return Status;
+}
+
/**
Convert number to ASCII value
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h
index 202f115516..47c2a06889 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h
@@ -1,6 +1,6 @@
/** @file
-Copyright (c) 2007, Intel Corporation
+Copyright (c) 2007 - 2008, Intel Corporation
All rights reserved. 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
@@ -46,6 +46,14 @@ PxeBcCommonNotify (
)
;
+EFI_STATUS
+PxeBcConfigureUdpWriteInstance (
+ IN EFI_UDP4_PROTOCOL *Udp4,
+ IN EFI_IPv4_ADDRESS *StationIp,
+ IN EFI_IPv4_ADDRESS *SubnetMask,
+ IN EFI_IPv4_ADDRESS *Gateway,
+ IN OUT UINT16 *SrcPort
+ );
VOID
CvtNum (
IN UINTN Number,