diff --git a/src/include/ipxe/efi/Protocol/AppleNetBoot.h b/src/include/ipxe/efi/Protocol/AppleNetBoot.h new file mode 100644 index 000000000..144beff1c --- /dev/null +++ b/src/include/ipxe/efi/Protocol/AppleNetBoot.h @@ -0,0 +1,46 @@ +#ifndef __EFI_APPLE_NET_BOOT_PROTOCOL_H__ +#define __EFI_APPLE_NET_BOOT_PROTOCOL_H__ + +/** @file + * + * Apple Net Boot Protocol + * + */ + +FILE_LICENCE ( BSD3 ); + +#define EFI_APPLE_NET_BOOT_PROTOCOL_GUID \ + { 0x78ee99fb, 0x6a5e, 0x4186, \ + { 0x97, 0xde, 0xcd, 0x0a, 0xba, 0x34, 0x5a, 0x74 } } + +typedef struct _EFI_APPLE_NET_BOOT_PROTOCOL EFI_APPLE_NET_BOOT_PROTOCOL; + +/** + Get a DHCP packet obtained by the firmware during NetBoot. + + @param This A pointer to the APPLE_NET_BOOT_PROTOCOL instance. + @param BufferSize A pointer to the size of the buffer in bytes. + @param DataBuffer The memory buffer to copy the packet to. If it is + NULL, then the size of the packet is returned + in BufferSize. + @retval EFI_SUCCESS The packet was copied. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the + current packet. BufferSize has been + updated with the size needed to + complete the request. +**/ +typedef +EFI_STATUS +(EFIAPI *GET_DHCP_RESPONSE) ( + IN EFI_APPLE_NET_BOOT_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *DataBuffer + ); + +struct _EFI_APPLE_NET_BOOT_PROTOCOL +{ + GET_DHCP_RESPONSE GetDhcpResponse; + GET_DHCP_RESPONSE GetBsdpResponse; +}; + +#endif /*__EFI_APPLE_NET_BOOT_PROTOCOL_H__ */ diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index 390d4e6e6..db9943a42 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -154,6 +154,7 @@ struct efi_config_table { #define EEFI( efirc ) EPLATFORM ( EINFO_EPLATFORM, efirc ) extern EFI_GUID efi_absolute_pointer_protocol_guid; +extern EFI_GUID efi_apple_net_boot_protocol_guid; extern EFI_GUID efi_arp_protocol_guid; extern EFI_GUID efi_arp_service_binding_protocol_guid; extern EFI_GUID efi_block_io_protocol_guid; diff --git a/src/interface/efi/efi_debug.c b/src/interface/efi/efi_debug.c index 84160d643..19531fdc1 100644 --- a/src/interface/efi/efi_debug.c +++ b/src/interface/efi/efi_debug.c @@ -71,6 +71,8 @@ struct efi_well_known_guid { static struct efi_well_known_guid efi_well_known_guids[] = { { &efi_absolute_pointer_protocol_guid, "AbsolutePointer" }, + { &efi_apple_net_boot_protocol_guid, + "AppleNetBoot" }, { &efi_arp_protocol_guid, "Arp" }, { &efi_arp_service_binding_protocol_guid, diff --git a/src/interface/efi/efi_guid.c b/src/interface/efi/efi_guid.c index 39da5efe0..62ee5a517 100644 --- a/src/interface/efi/efi_guid.c +++ b/src/interface/efi/efi_guid.c @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include +#include #include #include #include @@ -84,6 +85,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); EFI_GUID efi_absolute_pointer_protocol_guid = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID; +/** Apple NetBoot protocol GUID */ +EFI_GUID efi_apple_net_boot_protocol_guid + = EFI_APPLE_NET_BOOT_PROTOCOL_GUID; + /** ARP protocol GUID */ EFI_GUID efi_arp_protocol_guid = EFI_ARP_PROTOCOL_GUID; diff --git a/src/interface/efi/efi_pxe.c b/src/interface/efi/efi_pxe.c index 1847e3fd1..a1f81df59 100644 --- a/src/interface/efi/efi_pxe.c +++ b/src/interface/efi/efi_pxe.c @@ -42,6 +42,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include #include @@ -80,6 +81,8 @@ struct efi_pxe { EFI_PXE_BASE_CODE_PROTOCOL base; /** PXE base code mode */ EFI_PXE_BASE_CODE_MODE mode; + /** Apple NetBoot protocol */ + EFI_APPLE_NET_BOOT_PROTOCOL apple; /** TCP/IP network-layer protocol */ struct tcpip_net_protocol *tcpip; @@ -1498,6 +1501,83 @@ static EFI_PXE_BASE_CODE_PROTOCOL efi_pxe_base_code_protocol = { .SetPackets = efi_pxe_set_packets, }; +/****************************************************************************** + * + * Apple NetBoot protocol + * + ****************************************************************************** + */ + +/** + * Get DHCP/BSDP response + * + * @v packet Packet + * @v len Length of data buffer + * @v data Data buffer + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_apple_get_response ( EFI_PXE_BASE_CODE_PACKET *packet, UINTN *len, + VOID *data ) { + + /* Check length */ + if ( *len < sizeof ( *packet ) ) { + *len = sizeof ( *packet ); + return EFI_BUFFER_TOO_SMALL; + } + + /* Copy packet */ + memcpy ( data, packet, sizeof ( *packet ) ); + *len = sizeof ( *packet ); + + return EFI_SUCCESS; +} + +/** + * Get DHCP response + * + * @v apple Apple NetBoot protocol + * @v len Length of data buffer + * @v data Data buffer + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_apple_get_dhcp_response ( EFI_APPLE_NET_BOOT_PROTOCOL *apple, + UINTN *len, VOID *data ) { + struct efi_pxe *pxe = container_of ( apple, struct efi_pxe, apple ); + + return efi_apple_get_response ( &pxe->mode.DhcpAck, len, data ); +} + +/** + * Get BSDP response + * + * @v apple Apple NetBoot protocol + * @v len Length of data buffer + * @v data Data buffer + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_apple_get_bsdp_response ( EFI_APPLE_NET_BOOT_PROTOCOL *apple, + UINTN *len, VOID *data ) { + struct efi_pxe *pxe = container_of ( apple, struct efi_pxe, apple ); + + return efi_apple_get_response ( &pxe->mode.PxeReply, len, data ); +} + +/** Apple NetBoot protocol */ +static EFI_APPLE_NET_BOOT_PROTOCOL efi_apple_net_boot_protocol = { + .GetDhcpResponse = efi_apple_get_dhcp_response, + .GetBsdpResponse = efi_apple_get_bsdp_response, +}; + +/****************************************************************************** + * + * Installer + * + ****************************************************************************** + */ + /** * Install PXE base code protocol * @@ -1526,6 +1606,8 @@ int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev ) { pxe->handle = handle; memcpy ( &pxe->base, &efi_pxe_base_code_protocol, sizeof ( pxe->base )); pxe->base.Mode = &pxe->mode; + memcpy ( &pxe->apple, &efi_apple_net_boot_protocol, + sizeof ( pxe->apple ) ); pxe->buf.op = &efi_pxe_buf_operations; intf_init ( &pxe->tftp, &efi_pxe_tftp_desc, &pxe->refcnt ); intf_init ( &pxe->udp, &efi_pxe_udp_desc, &pxe->refcnt ); @@ -1545,7 +1627,9 @@ int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev ) { /* Install PXE base code protocol */ if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( - &handle, &efi_pxe_base_code_protocol_guid, &pxe->base, + &handle, + &efi_pxe_base_code_protocol_guid, &pxe->base, + &efi_apple_net_boot_protocol_guid, &pxe->apple, NULL ) ) != 0 ) { rc = -EEFI ( efirc ); DBGC ( pxe, "PXE %s could not install base code protocol: %s\n", @@ -1560,7 +1644,9 @@ int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev ) { return 0; bs->UninstallMultipleProtocolInterfaces ( - handle, &efi_pxe_base_code_protocol_guid, &pxe->base, + handle, + &efi_pxe_base_code_protocol_guid, &pxe->base, + &efi_apple_net_boot_protocol_guid, &pxe->apple, NULL ); err_install_protocol: ref_put ( &pxe->refcnt ); @@ -1590,7 +1676,9 @@ void efi_pxe_uninstall ( EFI_HANDLE handle ) { /* Uninstall PXE base code protocol */ bs->UninstallMultipleProtocolInterfaces ( - handle, &efi_pxe_base_code_protocol_guid, &pxe->base, + handle, + &efi_pxe_base_code_protocol_guid, &pxe->base, + &efi_apple_net_boot_protocol_guid, &pxe->apple, NULL ); /* Remove from list and drop list's reference */