Pete Batard
2016-Feb-24 13:02 UTC
[syslinux] [PATCH 2/5] ntfs: remove unused variable and have ntfssect use char API calls
The variable 'ok' is never used and generates a warning. Remove it. Also ntfssect.c is designed to be compiled in non Unicode mode when using MSVC compilers, so remove all ambiguity about it (LPCTSTR -> LPCSTR, use of 'A' API calls) so that it doesn't break when compiled in Unicode mode, which is what Rufus uses with MSVC. -------------- next part --------------
Shao Miller
2016-Feb-24 23:43 UTC
[syslinux] [PATCH 2/5] ntfs: remove unused variable and have ntfssect use char API calls
On 2/24/2016 08:02, Pete Batard via Syslinux wrote:> The variable 'ok' is never used and generates a warning. Remove it. Also > ntfssect.c is designed to be compiled in non Unicode mode when using > MSVC compilers, so remove all ambiguity about it (LPCTSTR -> LPCSTR, use > of 'A' API calls) so that it doesn't break when compiled in Unicode > mode, which is what Rufus uses with MSVC. >Did you happen to notice anything unusual when compiling with MinGW under Linux, once 'ok' was removed? I seem to recall warnings about unused results, but not of unused objects. Maybe that's an incorrect recollection or maybe it's ancient history, however. - Shao Miller Synthetel : https://www.synthetel.com
Pete Batard
2016-Feb-25 12:30 UTC
[syslinux] [PATCH 2/5] ntfs: remove unused variable and have ntfssect use char API calls
Hi Shao, On 2016.02.24 23:43, Shao Miller via Syslinux wrote:> Did you happen to notice anything unusual when compiling with MinGW > under Linux, once 'ok' was removed? I seem to recall warnings about > unused results, but not of unused objects. Maybe that's an incorrect > recollection or maybe it's ancient history, however.I got no warnings with the patch on Debian 8 + MinGW-w64. Here's the relevant compilation excerpt: make[3]: Entering directory '/usr/src/syslinux/bios/win64' x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o syslinux.obj /usr/src/syslinux/win64/../win/syslinux.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o ntfssect.obj /usr/src/syslinux/win64/../win/ntfssect.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o fs.obj /usr/src/syslinux/win64/../libinstaller/fs.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o syslxmod.obj /usr/src/syslinux/win64/../libinstaller/syslxmod.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o syslxopt.obj /usr/src/syslinux/win64/../libinstaller/syslxopt.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o setadv.obj /usr/src/syslinux/win64/../libinstaller/setadv.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o getopt_long.obj /usr/src/syslinux/win64/../libinstaller/getopt/getopt_long.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o bootsect_bin.obj /usr/src/syslinux/bios/win64/../libinstaller/bootsect_bin.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o ldlinux_bin.obj /usr/src/syslinux/bios/win64/../libinstaller/ldlinux_bin.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o ldlinuxc32_bin.obj /usr/src/syslinux/bios/win64/../libinstaller/ldlinuxc32_bin.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o mbr_bin.obj /usr/src/syslinux/bios/win64/../libinstaller/mbr_bin.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o cache.obj /usr/src/syslinux/win64/../libfat/cache.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o fatchain.obj /usr/src/syslinux/win64/../libfat/fatchain.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o open.obj /usr/src/syslinux/win64/../libfat/open.c x86_64-w64-mingw32-gcc -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 -I/usr/src/syslinux/win64 -I/usr/src/syslinux/win64/.. -I/usr/src/syslinux/win64/../win -I/usr/src/syslinux/bios -I/usr/src/syslinux/win64/../libfat -I/usr/src/syslinux/win64/../libinstaller -I/usr/src/syslinux/win64/../libinstaller/getopt -c -o searchdir.obj /usr/src/syslinux/win64/../libfat/searchdir.c rm -f syslinux.lib x86_64-w64-mingw32-ar cq syslinux.lib fs.obj syslxmod.obj syslxopt.obj setadv.obj getopt_long.obj bootsect_bin.obj ldlinux_bin.obj ldlinuxc32_bin.obj mbr_bin.obj cache.obj fatchain.obj open.obj searchdir.obj x86_64-w64-mingw32-ranlib syslinux.lib x86_64-w64-mingw32-gcc -Os -s -o syslinux64.exe syslinux.obj ntfssect.obj syslinux.lib make[3]: Leaving directory '/usr/src/syslinux/bios/win64' Regards, /Pete
Hi guys, I have re-implemented /efi/udp.c The new code fixes: 1) The low and decreasing throughput on TFTP transfers. 2) The added delay between consecutive TFTP transfers. 3) The TFTP errors induced by broadcast traffic like ARP. Initial tests on a 50MB transfer showed times going from 3 minutes to ~12 seconds, also tested OK with nested TFTP transfers (include command). This new code affects/fixes the problems reported at: a) "Problem with 90MB Initrd" http://www.syslinux.org/archives/2015-September/024236.html b) "UEFI: Failed to load ldlinux.e64/ldlinux.e32" http://www.syslinux.org/archives/2015-October/024341.html This report has led to Gene's patch: https://github.com/geneC/syslinux/commit/9e0926bb338deb5c634ccb4ee29eb4577158cfdc it was reported working but I think "it cannot work" if it has these lines + memcpy(&udata.StationAddress, &IPInfo.myip, sizeof(IPInfo.myip)); + memcpy(&udata.StationAddress, &IPInfo.netmask, sizeof(IPInfo.netmask)); the StationAddress gets overwritten by a netmask... There's a picture attached comparing performance between the old and new udp.c code. Testing reports are welcome. Best, Patrick Signed-off-by: Patrick Masotta <masottaus at yahoo.com> diff -uprN a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h --- a/core/fs/pxe/pxe.h 2014-10-06 10:27:44.000000000 -0600 +++ b/core/fs/pxe/pxe.h 2016-02-28 08:44:47.127996962 -0700 @@ -130,6 +130,7 @@ union net_private { struct net_private_efi { struct efi_binding *binding; /* EFI binding for protocol */ uint16_t localport; /* Local port number (0=not in use) */ + void* context; /* Holds the UDP_IO Instance (used in the new efi UDP codebase) */ } efi; }; diff -uprN a/efi/udp.c b/efi/udp.c --- a/efi/udp.c 2014-10-06 10:27:44.000000000 -0600 +++ b/efi/udp.c 2016-02-28 08:41:29.867226806 -0700 @@ -1,5 +1,6 @@ /* - * Copyright 2013-2014 Intel Corporation - All Rights Reserved + * Serva (c) 2010-2016 Patrick Masotta - All Rights Reserved + * */ #include <string.h> @@ -8,50 +9,189 @@ #include "net.h" #include "fs/pxe/pxe.h" + +#define TICKS_PER_SECOND 10000000 +#define TICKS_PER_MS 10000 + +#define UDP_TIME_TO_GETMAP 5 * TICKS_PER_SECOND +#define UDP_TIME_TX_TIMEOUT 1 * TICKS_PER_SECOND + 500 * TICKS_PER_MS +#define UDP_TIME_RX_TIMEOUT 1 * TICKS_PER_SECOND + 500 * TICKS_PER_MS + + +/// +/// Type defined as RX. +/// This data structure wraps receive udp parameters. +/// +typedef struct { + void* buf; + uint16_t* buf_len; + uint32_t* src_ip; + uint16_t* src_port; +}RX; + +/// +/// Type defined as UDP_IO. +/// This data structure wraps the UDP instance and configuration. +/// +typedef struct { + uint16_t known_TID; + struct efi_binding* b; + EFI_UDP4* Protocol_Udp4; + EFI_UDP4_CONFIG_DATA Config_Udp4; + EFI_UDP4_COMPLETION_TOKEN* Token; + EFI_EVENT Timeout_Timer; + EFI_EVENT CB_OK_Event; + RX rx; +}UDP_IO; + + +#define EFI_IP4_EQUAL(Ip1, Ip2) (CompareMem ((Ip1), (Ip2), sizeof (EFI_IPv4_ADDRESS)) == 0) +EFI_IPv4_ADDRESS mZeroIp4Addr = {{0, 0, 0, 0}}; +static BOOLEAN volatile UseDefaultSetting = TRUE; + extern EFI_GUID Udp4ServiceBindingProtocol, Udp4Protocol; -/* - * This UDP binding is configured to operate in promiscuous mode. It is - * only used for reading packets. It has no associated state unlike - * socket->net.efi.binding, which has a remote IP address and port - * number. - */ -static struct efi_binding *udp_reader; + + + +/** + Poll the UDP to get the IP4 default address, which may be retrieved + by DHCP. + + The default time out value is 5 seconds. If IP has retrieved the default address, + the UDP is reconfigured. + + + @param udp_io The UDP_IO instance + @param udata The UDP configure data to reconfigure the UDP_IO + + @retval TRUE The default address is retrieved and UDP is reconfigured. + @retval FALSE Some error occured. + +**/ +BOOLEAN +efi_udp_get_mapping (UDP_IO* udp_io, EFI_UDP4_CONFIG_DATA* udata) +{ + EFI_STATUS status; + EFI_UDP4* udp; + EFI_IP4_MODE_DATA Ip4Mode; + +// ASSERT (UseDefaultSetting); + + udp = udp_io->Protocol_Udp4; + + status = uefi_call_wrapper( BS->SetTimer, 3, + udp_io->Timeout_Timer, + TimerRelative, + UDP_TIME_TO_GETMAP + ); + + if (EFI_ERROR (status)) + return FALSE; + + while (EFI_ERROR ( uefi_call_wrapper(BS->CheckEvent, 1, udp_io->Timeout_Timer) )) + { + udp->Poll(udp); + + if (!EFI_ERROR(udp->GetModeData(udp, NULL, &Ip4Mode, NULL, NULL)) && + Ip4Mode.IsConfigured) + { + udp->Configure(udp, NULL); + return (BOOLEAN) (udp->Configure(udp, udata) == EFI_SUCCESS); + } + } + + return FALSE; +} + + /** - * Try to configure this UDP socket + * Try to configure this UDP_IO * - * @param:udp, the EFI_UDP4 socket to configure - * @param:udata, the EFI_UDP4_CONFIG_DATA to use - * @param:f, the name of the function as a wide string. + * @param:udp_io, The UDP_IO containing the EFI_UDP4 socket to configure + * and the EFI_UDP4_CONFIG_DATA to use. + * @param:f, The name of the invoking function as a wide string. * * @out: status as EFI_STATUS */ - -EFI_STATUS core_udp_configure(EFI_UDP4 *udp, EFI_UDP4_CONFIG_DATA *udata, - short unsigned int *f) +EFI_STATUS efi_udp_configure(UDP_IO *udp_io, short unsigned int *f) { - EFI_STATUS status; - int unmapped = 1; - jiffies_t start, last, cur; - - last = start = jiffies(); - while (unmapped){ - status = uefi_call_wrapper(udp->Configure, 2, udp, udata); - if (status != EFI_NO_MAPPING) - unmapped = 0; - else { - cur = jiffies(); - if ( (cur - last) >= EFI_NOMAP_PRINT_DELAY ) { - last = cur; - Print(L"%s: stalling on configure with no mapping\n", f); - } else if ( (cur - start) > EFI_NOMAP_PRINT_DELAY * EFI_NOMAP_PRINT_COUNT) { - Print(L"%s: aborting on no mapping\n", f); - unmapped = 0; - } - } - } - return status; + + EFI_STATUS status; + EFI_UDP4* udp = udp_io->Protocol_Udp4; + EFI_UDP4_CONFIG_DATA* udata = &udp_io->Config_Udp4; + + + status = uefi_call_wrapper(udp->Configure, 2, udp, NULL); + if (EFI_ERROR (status)) + { + return status; + } + + + status= uefi_call_wrapper(udp->Configure, 2, udp, udata); + if( status == EFI_SUCCESS ) + { + EFI_STATUS status; + + status = uefi_call_wrapper(udp->GetModeData, 5, udp, + udata, NULL, NULL, NULL); + + if(status == EFI_SUCCESS ) + return EFI_SUCCESS; + else + return -1; + } + + else + if ( status == EFI_NO_MAPPING && + UseDefaultSetting && + efi_udp_get_mapping (udp_io, udata) && + EFI_SUCCESS == uefi_call_wrapper(udp->GetModeData, 5, udp, + udata, NULL, NULL, NULL) + ) + return EFI_SUCCESS; + else + if( + UseDefaultSetting && + !EFI_IP4_EQUAL (&mZeroIp4Addr, &IPInfo.gateway) && + !EFI_IP4_EQUAL (&mZeroIp4Addr, &IPInfo.myip) && + !EFI_IP4_EQUAL (&mZeroIp4Addr, &IPInfo.netmask) + ) + { // udp->Configure() and efi_udp_get_mapping() failed lets try a manual config + EFI_STATUS status; + + UseDefaultSetting=FALSE; + udata->UseDefaultAddress = FALSE; + memcpy(&udata->StationAddress , &IPInfo.myip, sizeof(IPInfo.myip)); + memcpy(&udata->SubnetMask, &IPInfo.netmask, sizeof(IPInfo.netmask)); + + status = uefi_call_wrapper(udp->Routes , 5, + udp, + FALSE, + &mZeroIp4Addr, + &mZeroIp4Addr, + (EFI_IPv4_ADDRESS *)&IPInfo.gateway + ); + if (EFI_ERROR (status)) + { + uefi_call_wrapper(udp->Configure, 2, udp, NULL); + return -1; + } + + if( EFI_ERROR (uefi_call_wrapper(udp->Configure, 2, udp, NULL)) || + EFI_ERROR (uefi_call_wrapper(udp->Configure, 2, udp, udata)) + ) + return -1; + else + return EFI_SUCCESS; + + } + + else + return -1; + } /** @@ -63,55 +203,76 @@ EFI_STATUS core_udp_configure(EFI_UDP4 * */ int core_udp_open(struct pxe_pvt_inode *socket) { - EFI_UDP4_CONFIG_DATA udata; - struct efi_binding *b; - EFI_STATUS status; - EFI_UDP4 *udp; - + EFI_STATUS status; + struct efi_binding* b; + EFI_UDP4* udp; + UDP_IO* udp_io; + (void)socket; - udp_reader = efi_create_binding(&Udp4ServiceBindingProtocol, &Udp4Protocol); - if (!udp_reader) - return -1; - - b = efi_create_binding(&Udp4ServiceBindingProtocol, &Udp4Protocol); - if (!b) - goto bail; - - udp = (EFI_UDP4 *)udp_reader->this; - - memset(&udata, 0, sizeof(udata)); - - status = core_udp_configure(udp, &udata, L"core_udp_open"); - if (status != EFI_SUCCESS) - goto bail; - - socket->net.efi.binding = b; - - /* - * Save the random local port number that the UDPv4 Protocol - * Driver picked for us. The TFTP protocol uses the local port - * number as the TID. - */ - status = uefi_call_wrapper(udp->GetModeData, 5, udp, - &udata, NULL, NULL, NULL); - if (status != EFI_SUCCESS) - Print(L"Failed to get UDP mode data: %d\n", status); - else - socket->net.efi.localport = udata.StationPort; + + b = efi_create_binding(&Udp4ServiceBindingProtocol, &Udp4Protocol); + if(!b) + return -1; + + udp_io=zalloc(sizeof(UDP_IO)); + if(!udp_io) + goto bail; + + udp_io->b = b; + + udp = (EFI_UDP4 *)b->this; + udp_io->Protocol_Udp4 = udp; + + socket->net.efi.context = udp_io; + + // + // Create the timer used to time out transmit, receive, and get map events + // + status = uefi_call_wrapper(BS->CreateEvent, 5, + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &udp_io->Timeout_Timer + ); + if (EFI_ERROR (status)) + goto bail; + + // + // Create the event to signal when the send/receive callback function ends + // correctly. + // + status = uefi_call_wrapper(BS->CreateEvent, 5, + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &udp_io->CB_OK_Event + ); + if (EFI_ERROR (status)) + goto bail; return 0; bail: if (b) - efi_destroy_binding(b, &Udp4ServiceBindingProtocol); + efi_destroy_binding(b, &Udp4ServiceBindingProtocol); - efi_destroy_binding(udp_reader, &Udp4ServiceBindingProtocol); - udp_reader = NULL; + if(udp_io && udp_io->Timeout_Timer) + uefi_call_wrapper(BS->CloseEvent, 1, udp_io->Timeout_Timer); + + if(udp_io && udp_io->CB_OK_Event) + uefi_call_wrapper(BS->CloseEvent, 1, udp_io->CB_OK_Event); + + + if(udp_io) + free(udp_io); return -1; } + /** * Close a socket * @@ -119,299 +280,394 @@ bail: */ void core_udp_close(struct pxe_pvt_inode *socket) { - efi_destroy_binding(udp_reader, &Udp4ServiceBindingProtocol); - udp_reader = NULL; - if (!socket->net.efi.binding) - return; - - efi_destroy_binding(socket->net.efi.binding, &Udp4ServiceBindingProtocol); - socket->net.efi.binding = NULL; + UDP_IO* udp_io; + udp_io = (UDP_IO*)socket->net.efi.context; + + + if (!udp_io->b) + return; + + efi_destroy_binding(udp_io->b, &Udp4ServiceBindingProtocol); + udp_io->b = NULL; + + if(udp_io->Timeout_Timer) + uefi_call_wrapper(BS->CloseEvent, 1, udp_io->Timeout_Timer); + + if(udp_io->CB_OK_Event) + uefi_call_wrapper(BS->CloseEvent, 1, udp_io->CB_OK_Event); + + if(socket->net.efi.context) + free(socket->net.efi.context); + socket->net.efi.context=NULL; + + } /** * Establish a connection on an open socket * - * @param:socket, the open socket - * @param:ip, the ip address - * @param:port, the port number, host-byte order + * @param:socket, the open socket + * @param:ip, the source ip address + * @param:port, the source port number, host-byte order */ -void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip, - uint16_t port) +void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t src_ip, + uint16_t src_port) { - EFI_UDP4_CONFIG_DATA udata; - EFI_STATUS status; - EFI_UDP4 *udp; - - udp = (EFI_UDP4 *)socket->net.efi.binding->this; - memset(&udata, 0, sizeof(udata)); - - /* Re-use the existing local port number */ - udata.StationPort = socket->net.efi.localport; - - udata.UseDefaultAddress = TRUE; - memcpy(&udata.RemoteAddress, &ip, sizeof(ip)); - udata.RemotePort = port; - udata.AcceptPromiscuous = TRUE; - udata.TimeToLive = 64; - - status = core_udp_configure(udp, &udata, L"core_udp_connect"); - if (status != EFI_SUCCESS) { - Print(L"Failed to configure UDP: %d\n", status); - return; - } + EFI_STATUS status; + UDP_IO* udp_io; + + udp_io = (UDP_IO*)socket->net.efi.context; + + if ( src_port != udp_io->Config_Udp4.RemotePort ) + { + udp_io->Config_Udp4.RemotePort = src_port; + + status = efi_udp_configure(udp_io, L"core_udp_connect"); + if (EFI_ERROR (status)) + { + Print(L"Failed to configure UDP: %d\n", status); + return; + } + } + } /** * Tear down a connection on an open socket * - * @param:socket, the open socket + * @param:socket, the open socket */ void core_udp_disconnect(struct pxe_pvt_inode *socket) { - EFI_STATUS status; - EFI_UDP4 *udp; - - udp = (EFI_UDP4 *)socket->net.efi.binding->this; - - /* Reset */ - status = uefi_call_wrapper(udp->Configure, 2, udp, NULL); - if (status != EFI_SUCCESS) - Print(L"Failed to reset UDP: %d\n", status); + + return; + } -static int volatile cb_status = -1; -static EFIAPI void udp4_cb(EFI_EVENT event, void *context) -{ - (void)event; - - EFI_UDP4_COMPLETION_TOKEN *token = context; - if (token->Status == EFI_SUCCESS) - cb_status = 0; - else - cb_status = 1; +/** + * + * Send callback function + * + */ +VOID +EFIAPI +UdpIoOnDgramSent ( + IN EFI_EVENT event, + IN VOID* context + ) +{ + UDP_IO* udp_io; + EFI_UDP4_COMPLETION_TOKEN* token; + + udp_io = (UDP_IO*) context; + if( udp_io && + (token = udp_io->Token) && + token->Status == EFI_SUCCESS + ) + uefi_call_wrapper(BS->SignalEvent, 1, udp_io->CB_OK_Event); } + /** - * Read data from the network stack + * Send a UDP packet (blocking call). * - * @param:socket, the open socket - * @param:buf, location of buffer to store data - * @param:buf_len, size of buffer - - * @out: src_ip, ip address of the data source - * @out: src_port, port number of the data source, host-byte order + * @param:socket, the open socket + * @param:data, data buffer to send + * @param:len, size of data bufer */ -int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len, - uint32_t *src_ip, uint16_t *src_port) + +void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len) { - EFI_UDP4_COMPLETION_TOKEN token; - EFI_UDP4_FRAGMENT_DATA *frag; - EFI_UDP4_RECEIVE_DATA *rxdata; - struct efi_binding *b; EFI_STATUS status; - EFI_UDP4 *udp; - size_t size; - int rv = -1; - jiffies_t start; - - (void)socket; - - b = udp_reader; - udp = (EFI_UDP4 *)b->this; - memset(&token, 0, sizeof(token)); - - status = efi_setup_event(&token.Event, (EFI_EVENT_NOTIFY)udp4_cb, - &token); - if (status != EFI_SUCCESS) - return -1; - - status = uefi_call_wrapper(udp->Receive, 2, udp, &token); - if (status != EFI_SUCCESS) - goto bail; - - start = jiffies(); - while (cb_status == -1) { - /* 15ms receive timeout... */ - if (jiffies() - start >= 15) { - if (jiffies() - start >= 30) - dprintf("Failed to cancel UDP\n"); - - uefi_call_wrapper(udp->Cancel, 2, udp, &token); - dprintf("core_udp_recv: timed out\n"); - } + UDP_IO* udp_io; + EFI_UDP4* udp; + EFI_UDP4_COMPLETION_TOKEN* token=NULL; + EFI_UDP4_TRANSMIT_DATA* txdata=NULL; + EFI_UDP4_FRAGMENT_DATA* frag; - uefi_call_wrapper(udp->Poll, 1, udp); - } + udp_io = (UDP_IO*)socket->net.efi.context; + udp = udp_io->Protocol_Udp4; - if (cb_status == 0) - rv = 0; - /* Reset */ - cb_status = -1; - - if (rv) - goto bail; - - rxdata = token.Packet.RxData; - frag = &rxdata->FragmentTable[0]; + token = zalloc(sizeof(EFI_UDP4_COMPLETION_TOKEN)); + if (!token) + goto bail; - size = min(frag->FragmentLength, *buf_len); - memcpy(buf, frag->FragmentBuffer, size); - *buf_len = size; + txdata = zalloc(sizeof(EFI_UDP4_TRANSMIT_DATA)); + if (!txdata) + goto bail; - memcpy(src_port, &rxdata->UdpSession.SourcePort, sizeof(*src_port)); - memcpy(src_ip, &rxdata->UdpSession.SourceAddress, sizeof(*src_ip)); + status = efi_setup_event(&token->Event, (EFI_EVENT_NOTIFY)UdpIoOnDgramSent, + udp_io); + if (EFI_ERROR (status)) + goto bail; - uefi_call_wrapper(BS->SignalEvent, 1, rxdata->RecycleSignal); -bail: - uefi_call_wrapper(BS->CloseEvent, 1, token.Event); - return rv; -} + udp_io->Token = token; -/** - * Send a UDP packet. - * - * @param:socket, the open socket - * @param:data, data buffer to send - * @param:len, size of data bufer - */ -void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len) -{ - EFI_UDP4_COMPLETION_TOKEN *token; - EFI_UDP4_TRANSMIT_DATA *txdata; - EFI_UDP4_FRAGMENT_DATA *frag; - struct efi_binding *b = socket->net.efi.binding; - EFI_STATUS status; - EFI_UDP4 *udp = (EFI_UDP4 *)b->this; - - token = zalloc(sizeof(*token)); - if (!token) - return; - - txdata = zalloc(sizeof(*txdata)); - if (!txdata) { - free(token); - return; - } - - status = efi_setup_event(&token->Event, (EFI_EVENT_NOTIFY)udp4_cb, - token); - if (status != EFI_SUCCESS) - goto bail; - - txdata->DataLength = len; - txdata->FragmentCount = 1; + txdata->DataLength = len; + txdata->FragmentCount = 1; + frag = &txdata->FragmentTable[0]; - frag->FragmentLength = len; frag->FragmentBuffer = (void *)data; token->Packet.TxData = txdata; - + + status = uefi_call_wrapper(BS->SetTimer, 3, + udp_io->Timeout_Timer, + TimerRelative, + UDP_TIME_TX_TIMEOUT + ); + if (EFI_ERROR (status)) + goto bail; + + uefi_call_wrapper(BS->CheckEvent, 1, udp_io->CB_OK_Event); status = uefi_call_wrapper(udp->Transmit, 2, udp, token); - if (status != EFI_SUCCESS) - goto close; + if (EFI_ERROR (status)) + { + goto close; + } - while (cb_status == -1) - uefi_call_wrapper(udp->Poll, 1, udp); + + while (1) + { + uefi_call_wrapper(udp->Poll, 1, udp); + + if(!EFI_ERROR ( uefi_call_wrapper(BS->CheckEvent, 1, udp_io->CB_OK_Event) )) + { + goto close; //TX OK + } + + if(!EFI_ERROR ( uefi_call_wrapper(BS->CheckEvent, 1, udp_io->Timeout_Timer) )) + { + dprintf("core_udp_send: timed out\n"); + goto close; //TX timeout + } + } - /* Reset */ - cb_status = -1; close: uefi_call_wrapper(BS->CloseEvent, 1, token->Event); bail: - free(txdata); - free(token); + if(txdata) + free(txdata); + + if(token) + free(token); + + udp_io->Token = NULL; } + + /** * Send a UDP packet to a destination * - * @param:socket, the open socket - * @param:data, data buffer to send - * @param:len, size of data bufer - * @param:ip, the ip address - * @param:port, the port number, host-byte order + * @param:socket, the open socket + * @param:data, data buffer to send + * @param:len, size of data bufer + * @param:ip, the remote ip address + * @param:port, the remote port number, host-byte order */ void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data, - size_t len, uint32_t ip, uint16_t port) + size_t len, uint32_t remote_ip, uint16_t remote_port) { - EFI_UDP4_COMPLETION_TOKEN *token; - EFI_UDP4_TRANSMIT_DATA *txdata; - EFI_UDP4_FRAGMENT_DATA *frag; - EFI_UDP4_CONFIG_DATA udata; - EFI_STATUS status; - struct efi_binding *b; - EFI_UDP4 *udp; + EFI_STATUS status; + UDP_IO* udp_io; - (void)socket; - b = efi_create_binding(&Udp4ServiceBindingProtocol, &Udp4Protocol); - if (!b) - return; + udp_io = (UDP_IO*)socket->net.efi.context; + + if(!udp_io->known_TID) + udp_io->known_TID=remote_port; + + udp_io->Config_Udp4.AcceptBroadcast = FALSE; + udp_io->Config_Udp4.AcceptPromiscuous = FALSE; + udp_io->Config_Udp4.AcceptAnyPort = FALSE; + udp_io->Config_Udp4.AllowDuplicatePort = FALSE; + udp_io->Config_Udp4.TypeOfService = 0; + udp_io->Config_Udp4.TimeToLive = 64; + udp_io->Config_Udp4.DoNotFragment = FALSE; + udp_io->Config_Udp4.ReceiveTimeout = 0; + udp_io->Config_Udp4.TransmitTimeout = 0; + + + if (UseDefaultSetting) + { + udp_io->Config_Udp4.UseDefaultAddress = TRUE; + } + else + { + udp_io->Config_Udp4.UseDefaultAddress = FALSE; + memcpy(&udp_io->Config_Udp4.StationAddress , &IPInfo.myip, sizeof(IPInfo.myip)); + memcpy(&udp_io->Config_Udp4.SubnetMask, &IPInfo.netmask, sizeof(IPInfo.netmask)); + } + + //udp_io->Config_Udp4.StationPort = 0; //Reuse or initially assigned by FW + + memcpy(&udp_io->Config_Udp4.RemoteAddress, &remote_ip, sizeof(remote_ip)); + udp_io->Config_Udp4.RemotePort = remote_port; + + + status = efi_udp_configure(udp_io, L"core_udp_sendto"); + if (EFI_ERROR (status)) + return; + + core_udp_send(socket, data, len); - udp = (EFI_UDP4 *)b->this; +} - token = zalloc(sizeof(*token)); - if (!token) - goto out; + + +/** + * + * Receive callback function + * + */ +VOID +EFIAPI +UdpIoOnDgramRecvd ( + IN EFI_EVENT event, + IN VOID* context + ) +{ + UDP_IO* udp_io; + EFI_UDP4_COMPLETION_TOKEN* token; + EFI_UDP4_FRAGMENT_DATA* frag; + EFI_UDP4_RECEIVE_DATA* rxdata; + + size_t size; + + udp_io = (UDP_IO*) context; + + if( udp_io && + (token = udp_io->Token) && + token->Status == EFI_SUCCESS + ) + { + rxdata = token->Packet.RxData; + frag = &rxdata->FragmentTable[0]; + + size = min(frag->FragmentLength, *(udp_io->rx.buf_len)); + memcpy(udp_io->rx.buf, frag->FragmentBuffer, size); + *(udp_io->rx.buf_len) = size; + + memcpy(udp_io->rx.src_port, &rxdata->UdpSession.SourcePort, sizeof(*udp_io->rx.src_port)); + memcpy(udp_io->rx.src_ip, &rxdata->UdpSession.SourceAddress, sizeof(*udp_io->rx.src_ip)); + + uefi_call_wrapper(BS->SignalEvent, 1, rxdata->RecycleSignal); + + uefi_call_wrapper(BS->SignalEvent, 1, udp_io->CB_OK_Event); + + } + +} - txdata = zalloc(sizeof(*txdata)); - if (!txdata) - goto bail; - - memset(&udata, 0, sizeof(udata)); - - /* Re-use the existing local port number */ - udata.StationPort = socket->net.efi.localport; - - udata.UseDefaultAddress = TRUE; - memcpy(&udata.RemoteAddress, &ip, sizeof(ip)); - udata.RemotePort = port; - udata.AcceptPromiscuous = TRUE; - udata.TimeToLive = 64; - - status = core_udp_configure(udp, &udata, L"core_udp_sendto"); - if (status != EFI_SUCCESS) - goto bail; - - status = efi_setup_event(&token->Event, (EFI_EVENT_NOTIFY)udp4_cb, - token); - if (status != EFI_SUCCESS) - goto bail; - txdata->DataLength = len; - txdata->FragmentCount = 1; - frag = &txdata->FragmentTable[0]; +/** + * Read data from the network stack (blocking call) + * + * @param:socket, the open socket + * @param:buf, location of buffer to store data + * @param:buf_len, size of buffer - frag->FragmentLength = len; - frag->FragmentBuffer = (void *)data; + * @out:src_ip, ip address of the data source + * @out:src_port, port number of the data source, host-byte order + */ + +int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len, + uint32_t *src_ip, uint16_t *src_port) +{ + EFI_STATUS status; + UDP_IO* udp_io; + EFI_UDP4* udp; + EFI_UDP4_COMPLETION_TOKEN* token; + int rv = -1; - token->Packet.TxData = txdata; - status = uefi_call_wrapper(udp->Transmit, 2, udp, token); - if (status != EFI_SUCCESS) - goto close; + udp_io = (UDP_IO*)socket->net.efi.context; + udp = udp_io->Protocol_Udp4; + + token = zalloc(sizeof(EFI_UDP4_COMPLETION_TOKEN)); + + if (!token) + return -1; - while (cb_status == -1) - uefi_call_wrapper(udp->Poll, 1, udp); - /* Reset */ - cb_status = -1; + status = efi_setup_event(&token->Event, (EFI_EVENT_NOTIFY)UdpIoOnDgramRecvd, + udp_io); + if (EFI_ERROR (status)) + goto bail; + + + udp_io->Token = token; + + udp_io->rx.buf = buf; + udp_io->rx.buf_len = buf_len; + udp_io->rx.src_ip = src_ip; + udp_io->rx.src_port = src_port; + + status = uefi_call_wrapper( BS->SetTimer, 3, + udp_io->Timeout_Timer, + TimerRelative, + UDP_TIME_RX_TIMEOUT + ); + if (EFI_ERROR (status)) + goto bail; + + if( udp_io->Config_Udp4.RemotePort == udp_io->known_TID ) + { + udp_io->Config_Udp4.RemotePort=0; + status = efi_udp_configure(udp_io, L"core_udp_recv"); + if (EFI_ERROR (status)) + goto bail; + } + + uefi_call_wrapper(BS->CheckEvent, 1, udp_io->CB_OK_Event); + + status = uefi_call_wrapper(udp->Receive, 2, udp, token); + if (EFI_ERROR (status)) + goto bail; + + while (1) + { + uefi_call_wrapper(udp->Poll, 1, udp); + + + if(!EFI_ERROR ( uefi_call_wrapper(BS->CheckEvent, 1, udp_io->CB_OK_Event) )) + { + rv = 0; + goto close; //RX OK + } + + if( ( EFI_SUCCESS == uefi_call_wrapper(BS->CheckEvent, 1, udp_io->Timeout_Timer)) ) + { + uefi_call_wrapper(udp->Cancel, 2, udp, token); + dprintf("core_udp_recv: timed out\n"); + rv = -1; + goto bail; //RX timeout + } + + } -close: - uefi_call_wrapper(BS->CloseEvent, 1, token->Event); +close: + bail: - free(txdata); - free(token); -out: - efi_destroy_binding(b, &Udp4ServiceBindingProtocol); + uefi_call_wrapper(BS->CloseEvent, 1, token->Event); + + if(token) + free(token); + + udp_io->Token=NULL; + + return rv; } + + -------------- next part -------------- A non-text attachment was scrubbed... Name: UEFI UDP compare-.png Type: image/png Size: 70861 bytes Desc: not available URL: <http://www.zytor.com/pipermail/syslinux/attachments/20160228/a7d90d8d/attachment-0001.png> -------------- next part -------------- A non-text attachment was scrubbed... Name: efi_udp.patch Type: application/octet-stream Size: 24996 bytes Desc: not available URL: <http://www.zytor.com/pipermail/syslinux/attachments/20160228/a7d90d8d/attachment-0001.obj>
Patrick Masotta via Syslinux <syslinux at zytor.com> writes:> There's a picture attached comparing performance between the old and > new udp.c code.Impressive! -- Regards, Feri.
On Sun, Feb 28, 2016 at 04:26:07PM +0000, Patrick Masotta via Syslinux wrote:> > > I have re-implemented /efi/udp.c> Signed-off-by: Patrick Masotta <masottaus at yahoo.com> > > diff -uprN a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h > --- a/core/fs/pxe/pxe.h 2014-10-06 10:27:44.000000000 -0600 > +++ b/core/fs/pxe/pxe.h 2016-02-28 08:44:47.127996962 -0700 > @@ -130,6 +130,7 @@ union net_private { > struct net_private_efi { > struct efi_binding *binding; /* EFI binding for protocol */ > uint16_t localport; /* Local port number (0=not in use) */ > + void* context; /* Holds the UDP_IO Instance (used in the new efi UDP codebase) */ > } efi; > }; > > diff -uprN a/efi/udp.c b/efi/udp.c > --- a/efi/udp.c 2014-10-06 10:27:44.000000000 -0600 > +++ b/efi/udp.c 2016-02-28 08:41:29.867226806 -0700 > @@ -1,5 +1,6 @@ > /* > - * Copyright 2013-2014 Intel Corporation - All Rights Reserved > + * Serva (c) 2010-2016 Patrick Masotta - All Rights Reserved > + * > */ > > #include <string.h> > @@ -8,50 +9,189 @@ > #include "net.h" > #include "fs/pxe/pxe.h" > > + > +#define TICKS_PER_SECOND 10000000 > +#define TICKS_PER_MS 10000 > + > +#define UDP_TIME_TO_GETMAP 5 * TICKS_PER_SECOND > +#define UDP_TIME_TX_TIMEOUT 1 * TICKS_PER_SECOND + 500 * TICKS_PER_MS > +#define UDP_TIME_RX_TIMEOUT 1 * TICKS_PER_SECOND + 500 * TICKS_PER_MS<snip/>> > /** > - * Try to configure this UDP socket > + * Try to configure this UDP_IO > * > - * @param:udp, the EFI_UDP4 socket to configure > - * @param:udata, the EFI_UDP4_CONFIG_DATA to use > - * @param:f, the name of the function as a wide string. > + * @param:udp_io, The UDP_IO containing the EFI_UDP4 socket to configure > + * and the EFI_UDP4_CONFIG_DATA to use. > + * @param:f, The name of the invoking function as a wide string. > * > * @out: status as EFI_STATUS > */ > - > -EFI_STATUS core_udp_configure(EFI_UDP4 *udp, EFI_UDP4_CONFIG_DATA *udata, > - short unsigned int *f) > +EFI_STATUS efi_udp_configure(UDP_IO *udp_io, short unsigned int *f) > { > } > > /** > * Establish a connection on an open socket > * > - * @param:socket, the open socket > - * @param:ip, the ip address > - * @param:port, the port number, host-byte order > + * @param:socket, the open socketWhite space change> + * @param:ip, the source ip addressWhite space change, plus 'source '> + * @param:port, the source port number, host-byte orderWhite space change, plus 'source '> */ > -void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip, > - uint16_t port) > +void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t src_ip, > + uint16_t src_port)Changed 'ip' and 'port' in 'src_ip' and 'src_port'. However: 'src_ip' and 'src_port' are not in } + * @param:ip, the source ip address } + * @param:port, the source port number, host-byte order <snip/>> -static EFIAPI void udp4_cb(EFI_EVENT event, void *context) > +VOID > +EFIAPI > +UdpIoOnDgramSent ( > + IN EFI_EVENT event, > + IN VOID* context > + )Such coding style change did me really stop removing this unified patch. Groeten Geert Stappers -- Leven en laten leven ------------- volgend deel ------------ Een niet-tekst bijlage is gescrubt... Naam: signature.asc Type: application/pgp-signature Grootte: 836 bytes Omschrijving: Digital signature URL : <http://www.zytor.com/pipermail/syslinux/attachments/20160228/0593b013/attachment.sig>
On Sun, Feb 28, 2016 at 11:26 AM, Patrick Masotta via Syslinux <syslinux at zytor.com> wrote:> b) "UEFI: Failed to load ldlinux.e64/ldlinux.e32" > http://www.syslinux.org/archives/2015-October/024341.html > This report has led to Gene's patch: > > https://github.com/geneC/syslinux/commit/9e0926bb338deb5c634ccb4ee29eb4577158cfdc > it was reported working but I think "it cannot work" if it has these lines > > + memcpy(&udata.StationAddress, &IPInfo.myip, sizeof(IPInfo.myip)); > + memcpy(&udata.StationAddress, &IPInfo.netmask, sizeof(IPInfo.netmask)); > > the StationAddress gets overwritten by a netmask...Thanks for noticing. I've corrected this and I'm reviewing the patch itself. -- -Gene
Possibly Parallel Threads
- [PATCH 0/1] UEFI UDP/TFTP
- [PATCH 2/5] ntfs: remove unused variable and have ntfssect use char API calls
- [PATCH] Updated udp.c to use real client ip and subnetmask values if on local subnet
- [PATCH 2/4] efi/udp: Add retry disabling UseDefaultAddress in core_udp_connect and core_udp_sendto
- [PATCH 1/4] efi/udp: core_udp_connect should use SubnetMask not StationAddress for netmask