/*----------------------------------------------------------------------------*/ WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) { P_BSS_INFO_T prBssInfo; P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; UINT_16 u2StatusCode = STATUS_CODE_RESERVED; BOOLEAN fgReplyAssocResp = FALSE; ASSERT(prAdapter); do { /* 4 <1> Check if we have the STA_RECORD_T for incoming Assoc Req */ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); /* We should have the corresponding Sta Record. */ if ((!prStaRec) || (!prStaRec->fgIsInUse)) { /* Not to reply association response with failure code due to lack of STA_REC */ break; } if (!IS_CLIENT_STA(prStaRec)) break; if (prStaRec->ucStaState == STA_STATE_3) { /* Do Reassocation */ } else if ((prStaRec->ucStaState == STA_STATE_2) && (prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2)) { /* Normal case */ } else { DBGLOG(AAA, WARN, ("Previous AuthAssocState (%d) != SEND_AUTH2.\n", prStaRec->eAuthAssocState)); /* Maybe Auth Response TX fail, but actually it success. */ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); } /* update RCPI */ ASSERT(prSwRfb->prRxStatusGroup3); prStaRec->ucRCPI = (UINT_8) HAL_RX_STATUS_GET_RCPI(prSwRfb->prRxStatusGroup3); /* 4 <2> Check P2P network conditions */ #if CFG_ENABLE_WIFI_DIRECT if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); if (prBssInfo->fgIsNetActive) { /* 4 <2.1> Validate Assoc Req Frame and get Status Code */ /* Check if for this BSSID */ if (WLAN_STATUS_SUCCESS == assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { /* 4 <2.2> Validate Assoc Req Frame for Network Specific Conditions */ fgReplyAssocResp = p2pFuncValidateAssocReq(prAdapter, prSwRfb, (PUINT_16) & u2StatusCode); } else { fgReplyAssocResp = TRUE; } break; } } } #endif /* CFG_ENABLE_WIFI_DIRECT */ /* 4 <3> Check BOW network conditions */ #if CFG_ENABLE_BT_OVER_WIFI if (IS_STA_BOW_TYPE(prStaRec)) { prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); if ((prBssInfo->fgIsNetActive) && (OP_MODE_BOW == prBssInfo->eCurrentOPMode)) { /* 4 <3.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ /* Check if for this BSSID */ if (WLAN_STATUS_SUCCESS == assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { /* 4 <3.2> Validate Auth Frame for Network Specific Conditions */ fgReplyAssocResp = bowValidateAssocReq(prAdapter, prSwRfb, &u2StatusCode); } else { fgReplyAssocResp = TRUE; } /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ break; } } } #endif /* CFG_ENABLE_BT_OVER_WIFI */ return WLAN_STATUS_SUCCESS; /* To release the SW_RFB_T */ } while (FALSE); /* 4 <4> Update STA_RECORD_T and reply Assoc Resp Frame */ if (fgReplyAssocResp) { UINT_16 u2IELength; PUINT_8 pucIE; if ((((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))-> u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_REASSOC_REQ) { u2IELength = prSwRfb->u2PacketLen - (UINT_16) OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]); pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; } else { u2IELength = prSwRfb->u2PacketLen - (UINT_16) OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]); pucIE = ((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; } rlmProcessAssocReq(prAdapter, prSwRfb, pucIE, u2IELength); /* 4 <4.1> Assign Association ID */ if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { #if CFG_ENABLE_WIFI_DIRECT if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex); if (p2pRoleFsmRunEventAAAComplete(prAdapter, prStaRec, prBssInfo) == WLAN_STATUS_SUCCESS) { prStaRec->u2AssocId = bssAssignAssocID(prStaRec); /* prStaRec->eAuthAssocState = AA_STATE_IDLE; */ /* NOTE(Kevin): for TX done */ prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ } else { /* Client List FULL. */ u2StatusCode = STATUS_CODE_REQ_DECLINED; prStaRec->u2AssocId = 0; /* Invalid Assocation ID */ /* If(Re)association fail,remove sta record and use class error to handle sta*/ prStaRec->eAuthAssocState = AA_STATE_IDLE; /* NOTE(Kevin): Better to change state here, not at TX Done */ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); } } #endif #if CFG_ENABLE_BT_OVER_WIFI if ((IS_STA_BOW_TYPE(prStaRec))) { /* if (bowRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { */ prStaRec->u2AssocId = bssAssignAssocID(prStaRec); prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; /* NOTE(Kevin): for TX done */ /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ } #endif } else { prStaRec->u2AssocId = 0; /* Invalid Assocation ID */ /* If (Re)association fail, remove sta record and use class error to handle sta */ prStaRec->eAuthAssocState = AA_STATE_IDLE; /* NOTE(Kevin): Better to change state here, not at TX Done */ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); } /* Update the record join time. */ GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); /* Update Station Record - Status/Reason Code */ prStaRec->u2StatusCode = u2StatusCode; /* NOTE: Ignore the return status for AAA */ /* 4 <4.2> Reply Assoc Resp */ assocSendReAssocRespFrame(prAdapter, prStaRec); } return WLAN_STATUS_SUCCESS; } /* end of aaaFsmRunEventRxAssoc() */
static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) { UINT_8 ip[4] = { 0 }; UINT_32 u4NumIPv4 = 0; //#ifdef CONFIG_IPV6 #if 0 UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack UINT_32 u4NumIPv6 = 0; #endif struct in_ifaddr *ifa = (struct in_ifaddr *) ptr; struct net_device *prDev = ifa->ifa_dev->dev; UINT_32 i; P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; P_GLUE_INFO_T prGlueInfo = NULL; if (prDev == NULL) { DBGLOG(REQ, INFO, ("netdev_event: device is empty.\n")); return NOTIFY_DONE; } if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { DBGLOG(REQ, INFO, ("netdev_event: xxx\n")); return NOTIFY_DONE; } prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); if (prGlueInfo == NULL) { DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n")); return NOTIFY_DONE; } ASSERT(prGlueInfo); // <3> get the IPv4 address if(!prDev || !(prDev->ip_ptr)||\ !((struct in_device *)(prDev->ip_ptr))->ifa_list||\ !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){ DBGLOG(REQ, INFO, ("ip is not avaliable.\n")); return NOTIFY_DONE; } kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); DBGLOG(REQ, INFO, ("ip is %d.%d.%d.%d\n", ip[0],ip[1],ip[2],ip[3])); // todo: traverse between list to find whole sets of IPv4 addresses if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) { u4NumIPv4++; } if (fgIsUnderEarlierSuspend == false) { #if defined(MTK_WLAN_ARP_OFFLOAD) if(NETDEV_UP == notification && PARAM_MEDIA_STATE_CONNECTED == prGlueInfo->eParamMediaStateIndicated){ PARAM_CUSTOM_SW_CTRL_STRUC_T SwCtrlInfo; UINT_32 u4SetInfoLen; WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; SwCtrlInfo.u4Id = 0x90110000; SwCtrlInfo.u4Data = 1; rStatus = kalIoctl(prGlueInfo, wlanoidSetSwCtrlWrite, (PVOID)&SwCtrlInfo, sizeof(SwCtrlInfo), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); if (rStatus != WLAN_STATUS_SUCCESS) { DBGLOG(REQ, INFO, ("ARP OFFLOAD fail 0x%lx\n", rStatus)); } return NOTIFY_DONE; }else { #endif DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated)); return NOTIFY_DONE; #if defined(MTK_WLAN_ARP_OFFLOAD) } #endif } //#ifdef CONFIG_IPV6 #if 0 if(!prDev || !(prDev->ip6_ptr)||\ !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\ !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){ printk(KERN_INFO "ipv6 is not avaliable.\n"); return NOTIFY_DONE; } kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", ip6[0],ip6[1],ip6[2],ip6[3], ip6[4],ip6[5],ip6[6],ip6[7], ip6[8],ip6[9],ip6[10],ip6[11], ip6[12],ip6[13],ip6[14],ip6[15] ); // todo: traverse between list to find whole sets of IPv6 addresses if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) { //u4NumIPv6++; } #endif // here we can compare the dev with other network's netdev to // set the proper arp filter // // IMPORTANT: please make sure if the context can sleep, if the context can't sleep // we should schedule a kernel thread to do this for us // <7> set up the ARP filter { WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; UINT_32 u4SetInfoLen = 0; UINT_8 aucBuf[32] = {0}; UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)aucBuf; P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; //#ifdef CONFIG_IPV6 #if 0 prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6; #else prParamNetAddrList->u4AddressCount = u4NumIPv4; #endif prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; for (i = 0; i < u4NumIPv4; i++) { prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;; prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;; #if 0 kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip)); u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); #else prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress; kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); #endif } //#ifdef CONFIG_IPV6 #if 0 for (i = 0; i < u4NumIPv6; i++) { prParamNetAddr->u2AddressLength = 6;; prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;; kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6)); u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); } #endif ASSERT(u4Len <= sizeof(aucBuf)); DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList)); rStatus = kalIoctl(prGlueInfo, wlanoidSetNetworkAddress, (PVOID)prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); if (rStatus != WLAN_STATUS_SUCCESS) { DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus)); } } return NOTIFY_DONE; }
EFI_HANDLE mBootLogoHandle = NULL; BOOLEAN mIsLogoValid = FALSE; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *mLogoBltBuffer = NULL; UINTN mLogoDestX = 0; UINTN mLogoDestY = 0; UINTN mLogoWidth = 0; UINTN mLogoHeight = 0; BMP_IMAGE_HEADER mBmpImageHeaderTemplate = { 'B', // CharB 'M', // CharM 0, // Size will be updated at runtime {0, 0}, // Reserved sizeof (BMP_IMAGE_HEADER), // ImageOffset sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize), // HeaderSize 0, // PixelWidth will be updated at runtime 0, // PixelHeight will be updated at runtime 1, // Planes 24, // BitPerPixel 0, // CompressionType 0, // ImageSize will be updated at runtime 0, // XPixelsPerMeter 0, // YPixelsPerMeter 0, // NumberOfColors 0 // ImportantColors }; BOOLEAN mAcpiBgrtInstalled = FALSE; BOOLEAN mAcpiBgrtStatusChanged = FALSE; BOOLEAN mAcpiBgrtBufferChanged = FALSE;
EFI_STATUS CreateTimeBasedPayload ( IN OUT UINTN *DataSize, IN OUT UINT8 **Data ) { EFI_STATUS Status; UINT8 *NewData; UINT8 *Payload; UINTN PayloadSize; EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; UINTN DescriptorSize; EFI_TIME Time; EFI_GUID efi_cert_type = EFI_CERT_TYPE_PKCS7_GUID; if (Data == NULL || DataSize == NULL) { return EFI_INVALID_PARAMETER; } // // In Setup mode or Custom mode, the variable does not need to be signed but the // parameters to the SetVariable() call still need to be prepared as authenticated // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate // data in it. // Payload = *Data; PayloadSize = *DataSize; DescriptorSize = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); if (NewData == NULL) { return EFI_OUT_OF_RESOURCES; } if ((Payload != NULL) && (PayloadSize != 0)) { CopyMem (NewData + DescriptorSize, Payload, PayloadSize); } DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); ZeroMem (&Time, sizeof (EFI_TIME)); Status = RT->GetTime(&Time, NULL); if (EFI_ERROR (Status)) { FreePool(NewData); return Status; } Time.Pad1 = 0; Time.Nanosecond = 0; Time.TimeZone = 0; Time.Daylight = 0; Time.Pad2 = 0; CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); DescriptorData->AuthInfo.Hdr.wRevision = 0x0200; DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; DescriptorData->AuthInfo.CertType = efi_cert_type; /* we're expecting an EFI signature list, so don't free the input since * it might not be in a pool */ #if 0 if (Payload != NULL) { FreePool(Payload); } #endif *DataSize = DescriptorSize + PayloadSize; *Data = NewData; return EFI_SUCCESS; }
// EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = { { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP } // { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP }, // { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP }, // { EXCEPT_ARM_DATA_ABORT, GDB_SIGEMT }, // { EXCEPT_ARM_RESERVED, GDB_SIGILL } }; // Shut up some annoying RVCT warnings #ifdef __CC_ARM #pragma diag_suppress 1296 #endif UINTN gRegisterOffsets[] = { OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR), OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC),
static void wlanP2PEarlySuspend(void) { struct net_device *prDev = NULL; P_GLUE_INFO_T prGlueInfo = NULL; UINT_8 ip[4] = { 0 }; UINT_32 u4NumIPv4 = 0; #ifdef CONFIG_IPV6 UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ UINT_32 u4NumIPv6 = 0; #endif UINT_32 i; P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; printk(KERN_INFO "*********p2pEarlySuspend************\n"); if (!wlanExportGlueInfo(&prGlueInfo)) { printk(KERN_INFO "*********p2pEarlySuspend ignored************\n"); return; } ASSERT(prGlueInfo); /* <1> Sanity check and acquire the net_device */ prDev = prGlueInfo->prP2PInfo->prDevHandler; ASSERT(prDev); /* <3> get the IPv4 address */ if (!prDev || !(prDev->ip_ptr) || !((struct in_device *)(prDev->ip_ptr))->ifa_list || !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { printk(KERN_INFO "ip is not avaliable.\n"); return; } /* <4> copy the IPv4 address */ kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); printk(KERN_INFO "ip is %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); /* todo: traverse between list to find whole sets of IPv4 addresses */ if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) { u4NumIPv4++; } #ifdef CONFIG_IPV6 /* <5> get the IPv6 address */ if (!prDev || !(prDev->ip6_ptr) || !((struct in_device *)(prDev->ip6_ptr))->ifa_list || !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { printk(KERN_INFO "ipv6 is not avaliable.\n"); return; } /* <6> copy the IPv6 address */ kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); printk(KERN_INFO "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", ip6[0], ip6[1], ip6[2], ip6[3], ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15] ); /* todo: traverse between list to find whole sets of IPv6 addresses */ if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) { } #endif /* <7> set up the ARP filter */ { WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; UINT_32 u4SetInfoLen = 0; /* UINT_8 aucBuf[32] = {0}; */ UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; /* aucBuf; */ P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6; prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; for (i = 0; i < u4NumIPv4; i++) { prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; #if 0 kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + sizeof(ip)); u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); #else prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); /* prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); // TODO: frog. The pointer is not right. */ prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + (UINT_32) (prParamNetAddr-> u2AddressLength + OFFSET_OF (PARAM_NETWORK_ADDRESS, aucAddress))); u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP); #endif } #ifdef CONFIG_IPV6 for (i = 0; i < u4NumIPv6; i++) { prParamNetAddr->u2AddressLength = 6; prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); /* prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6)); */ prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + (UINT_32) (prParamNetAddr-> u2AddressLength + OFFSET_OF (PARAM_NETWORK_ADDRESS, aucAddress))); u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); } #endif ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); rStatus = kalIoctl(prGlueInfo, wlanoidSetP2pSetNetworkAddress, (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); if (rStatus != WLAN_STATUS_SUCCESS) { printk(KERN_INFO DRV_NAME "set HW pattern filter fail 0x%lx\n", rStatus); } } }
/** Communicates with a registered handler. This function provides a service to send and receive messages from a registered UEFI service. This function is part of the SMM Communication Protocol that may be called in physical mode prior to SetVirtualAddressMap() and in virtual mode after SetVirtualAddressMap(). @param[in] This The EFI_SMM_COMMUNICATION_PROTOCOL instance. @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM. @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data being returned. Zero if the handler does not wish to reply with any data. @retval EFI_SUCCESS The message was successfully posted. @retval EFI_INVALID_PARAMETER The CommBuffer was NULL. **/ EFI_STATUS EFIAPI SmmCommunicationCommunicate ( IN CONST EFI_SMM_COMMUNICATION_PROTOCOL *This, IN OUT VOID *CommBuffer, IN OUT UINTN *CommSize ) { EFI_STATUS Status; EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader; BOOLEAN OldInSmm; // // Check parameters // if ((CommBuffer == NULL) || (CommSize == NULL)) { return EFI_INVALID_PARAMETER; } // // CommSize must hold HeaderGuid and MessageLength // if (*CommSize < OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) { return EFI_INVALID_PARAMETER; } // // If not already in SMM, then generate a Software SMI // if (!gSmmCorePrivate->InSmm && gSmmCorePrivate->SmmEntryPointRegistered) { // // Put arguments for Software SMI in gSmmCorePrivate // gSmmCorePrivate->CommunicationBuffer = CommBuffer; gSmmCorePrivate->BufferSize = *CommSize; // // Generate Software SMI // Status = mSmmControl2->Trigger (mSmmControl2, NULL, NULL, FALSE, 0); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } // // Return status from software SMI // *CommSize = gSmmCorePrivate->BufferSize; return gSmmCorePrivate->ReturnStatus; } // // If we are in SMM, then the execution mode must be physical, which means that // OS established virtual addresses can not be used. If SetVirtualAddressMap() // has been called, then a direct invocation of the Software SMI is not // not allowed so return EFI_INVALID_PARAMETER. // if (EfiGoneVirtual()) { return EFI_INVALID_PARAMETER; } // // If we are not in SMM, don't allow call SmiManage() directly when SMRAM is closed or locked. // if ((!gSmmCorePrivate->InSmm) && (!mSmmAccess->OpenState || mSmmAccess->LockState)) { return EFI_INVALID_PARAMETER; } // // Save current InSmm state and set InSmm state to TRUE // OldInSmm = gSmmCorePrivate->InSmm; gSmmCorePrivate->InSmm = TRUE; // // Already in SMM and before SetVirtualAddressMap(), so call SmiManage() directly. // CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommBuffer; *CommSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data); Status = gSmmCorePrivate->Smst->SmiManage ( &CommunicateHeader->HeaderGuid, NULL, CommunicateHeader->Data, CommSize ); // // Update CommunicationBuffer, BufferSize and ReturnStatus // Communicate service finished, reset the pointer to CommBuffer to NULL // *CommSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data); // // Restore original InSmm state // gSmmCorePrivate->InSmm = OldInSmm; return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND; }
/** Extract the displayed formset for given HII handle and class guid. @param Handle The HII handle. @param SetupClassGuid The class guid specifies which form set will be displayed. @param SkipCount Skip some formsets which has processed before. @param FormSetTitle Formset title string. @param FormSetHelp Formset help string. @param FormSetGuid Formset Guid. @retval TRUE The formset for given HII handle will be displayed. @return FALSE The formset for given HII handle will not be displayed. **/ BOOLEAN ExtractDisplayedHiiFormFromHiiHandle ( IN EFI_HII_HANDLE Handle, IN EFI_GUID *SetupClassGuid, IN UINTN SkipCount, OUT EFI_STRING_ID *FormSetTitle, OUT EFI_STRING_ID *FormSetHelp, OUT EFI_GUID *FormSetGuid ) { EFI_STATUS Status; UINTN BufferSize; EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; UINT8 *Package; UINT8 *OpCodeData; UINT32 Offset; UINT32 Offset2; UINT32 PackageListLength; EFI_HII_PACKAGE_HEADER PackageHeader; EFI_GUID *ClassGuid; UINT8 ClassGuidNum; BOOLEAN FoundAndSkip; ASSERT (Handle != NULL); ASSERT (SetupClassGuid != NULL && FormSetTitle != NULL && FormSetHelp != NULL && FormSetGuid != NULL); *FormSetTitle = 0; *FormSetHelp = 0; ClassGuidNum = 0; ClassGuid = NULL; FoundAndSkip = FALSE; // // Get HII PackageList // BufferSize = 0; HiiPackageList = NULL; Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); // // Handle is a invalid handle. Check if Handle is corrupted. // ASSERT (Status != EFI_NOT_FOUND); // // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. // ASSERT (Status == EFI_BUFFER_TOO_SMALL); HiiPackageList = AllocatePool (BufferSize); ASSERT (HiiPackageList != NULL); Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); if (EFI_ERROR (Status)) { return FALSE; } // // Get Form package from this HII package List // Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); while (Offset < PackageListLength) { Package = ((UINT8 *) HiiPackageList) + Offset; CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); Offset += PackageHeader.Length; if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { // // Search FormSet Opcode in this Form Package // Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); while (Offset2 < PackageHeader.Length) { OpCodeData = Package + Offset2; Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) { // // Find FormSet OpCode // ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3); ClassGuid = (EFI_GUID *) (VOID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET)); while (ClassGuidNum-- > 0) { if (CompareGuid (SetupClassGuid, ClassGuid)) { // // Check whether need to skip the formset. // if (SkipCount != 0) { SkipCount--; FoundAndSkip = TRUE; break; } CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); CopyGuid (FormSetGuid, (CONST EFI_GUID *)(&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)); FreePool (HiiPackageList); return TRUE; } ClassGuid ++; } if (FoundAndSkip) { break; } } else if (CompareGuid (SetupClassGuid, &gEfiHiiPlatformSetupFormsetGuid)) { // // Check whether need to skip the formset. // if (SkipCount != 0) { SkipCount--; break; } CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); CopyGuid (FormSetGuid, (CONST EFI_GUID *)(&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)); FreePool (HiiPackageList); return TRUE; } } } } } FreePool (HiiPackageList); return FALSE; }
CopyMem (&Mode->PermanentAddress, &Private->MacAddress, sizeof (EFI_MAC_ADDRESS)); // // Since the fake SNP is based on a real NIC, to avoid conflict with the host NIC // network stack, we use a different MAC address. // So just change the last byte of the MAC address for the real NIC. // Mode->CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++; return EFI_SUCCESS; } static struct bpf_insn mFilterInstructionTemplate[] = { // Load 4 bytes from the destination MAC address. BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])), // Compare to first 4 bytes of fake MAC address. BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x12345678, 0, 3 ), // Load remaining 2 bytes from the destination MAC address. BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( ETHERNET_HEADER, DstAddr[4])), // Compare to remaining 2 bytes of fake MAC address. BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x9ABC, 5, 0 ), // Load 4 bytes from the destination MAC address. BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])), // Compare to first 4 bytes of broadcast MAC address. BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0xFFFFFFFF, 0, 2),
&pSocket->pTxPacketListHead, &pSocket->pTxPacketListTail, &pPort->pTxActive, &pPort->pTxFree ); DBG_EXIT ( ); } /** Interface between the socket layer and the network specific code that supports SOCK_DGRAM sockets over UDPv4. **/ CONST ESL_PROTOCOL_API cEslUdp6Api = { "UDPv6", IPPROTO_UDP, OFFSET_OF ( ESL_PORT, Context.Udp6.ConfigData ), OFFSET_OF ( ESL_LAYER, pUdp6List ), sizeof ( struct sockaddr_in6 ), sizeof ( struct sockaddr_in6 ), AF_INET6, sizeof (((ESL_PACKET *)0 )->Op.Udp6Rx ), sizeof (((ESL_PACKET *)0 )->Op.Udp6Rx ), OFFSET_OF ( ESL_IO_MGMT, Token.Udp6Rx.Packet.RxData ), FALSE, EADDRINUSE, NULL, // Accept NULL, // ConnectPoll NULL, // ConnectStart EslUdp6SocketIsConfigured, EslUdp6LocalAddressGet, EslUdp6LocalAddressSet,
/** Initializes the FV Header and Variable Store Header to support variable operations. @param[in] Ptr - Location to initialize the headers **/ VOID InitializeFvAndVariableStoreHeaders ( IN VOID *Ptr ) { // // Templates for standard (non-authenticated) variable FV header // STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndVarTemplate = { { // EFI_FIRMWARE_VOLUME_HEADER FvHdr; // UINT8 ZeroVector[16]; { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // EFI_GUID FileSystemGuid; EFI_SYSTEM_NV_DATA_FV_GUID, // UINT64 FvLength; EMU_FVB_SIZE, // UINT32 Signature; EFI_FVH_SIGNATURE, // EFI_FVB_ATTRIBUTES_2 Attributes; 0x4feff, // UINT16 HeaderLength; EMU_FV_HEADER_LENGTH, // UINT16 Checksum; 0, // UINT16 ExtHeaderOffset; 0, // UINT8 Reserved[1]; {0}, // UINT8 Revision; EFI_FVH_REVISION, // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]; { { 2, // UINT32 NumBlocks; EMU_FVB_BLOCK_SIZE // UINT32 Length; } } }, // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap; { 0, 0 }, // End of block map { // VARIABLE_STORE_HEADER VarHdr; // EFI_GUID Signature; EFI_VARIABLE_GUID, // UINT32 Size; ( FixedPcdGet32 (PcdVariableStoreSize) - OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr) ), // UINT8 Format; VARIABLE_STORE_FORMATTED, // UINT8 State; VARIABLE_STORE_HEALTHY, // UINT16 Reserved; 0, // UINT32 Reserved1; 0 } }; // // Templates for authenticated variable FV header // STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndAuthenticatedVarTemplate = { { // EFI_FIRMWARE_VOLUME_HEADER FvHdr; // UINT8 ZeroVector[16]; { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // EFI_GUID FileSystemGuid; EFI_SYSTEM_NV_DATA_FV_GUID, // UINT64 FvLength; EMU_FVB_SIZE, // UINT32 Signature; EFI_FVH_SIGNATURE, // EFI_FVB_ATTRIBUTES_2 Attributes; 0x4feff, // UINT16 HeaderLength; EMU_FV_HEADER_LENGTH, // UINT16 Checksum; 0, // UINT16 ExtHeaderOffset; 0, // UINT8 Reserved[1]; {0}, // UINT8 Revision; EFI_FVH_REVISION, // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]; { { 2, // UINT32 NumBlocks; EMU_FVB_BLOCK_SIZE // UINT32 Length; } } }, // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap; { 0, 0 }, // End of block map { // VARIABLE_STORE_HEADER VarHdr; // EFI_GUID Signature; // need authenticated variables for secure boot EFI_AUTHENTICATED_VARIABLE_GUID, // UINT32 Size; ( FixedPcdGet32 (PcdVariableStoreSize) - OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr) ), // UINT8 Format; VARIABLE_STORE_FORMATTED, // UINT8 State; VARIABLE_STORE_HEALTHY, // UINT16 Reserved; 0, // UINT32 Reserved1; 0 } }; EFI_FIRMWARE_VOLUME_HEADER *Fv; // // Copy the template structure into the location // if (FeaturePcdGet (PcdSecureBootEnable) == FALSE) { CopyMem (Ptr, (VOID*)&FvAndVarTemplate, sizeof (FvAndVarTemplate)); } else { CopyMem (Ptr, (VOID*)&FvAndAuthenticatedVarTemplate, sizeof (FvAndAuthenticatedVarTemplate)); } // // Update the checksum for the FV header // Fv = (EFI_FIRMWARE_VOLUME_HEADER*) Ptr; Fv->Checksum = CalculateCheckSum16 (Ptr, Fv->HeaderLength); }
/** Get all configurations from a detected usb device. @param PeiServices Describes the list of possible PEI Services. @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance. @retval EFI_SUCCESS The new detected usb device is configured successfully. @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource. @retval Others Other failure occurs. **/ EFI_STATUS PeiUsbGetAllConfiguration ( IN EFI_PEI_SERVICES **PeiServices, IN PEI_USB_DEVICE *PeiUsbDevice ) { EFI_STATUS Status; EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc; PEI_USB_IO_PPI *UsbIoPpi; UINT16 ConfigDescLength; UINT8 *Ptr; UINTN SkipBytes; UINTN LengthLeft; UINTN InterfaceIndex; UINTN Index; UINTN NumOfEndpoint; UsbIoPpi = &PeiUsbDevice->UsbIoPpi; // // First get its 4-byte configuration descriptor // Status = PeiUsbGetDescriptor ( PeiServices, UsbIoPpi, (USB_DT_CONFIG << 8), // Value 0, // Index 4, // Length PeiUsbDevice->ConfigurationData ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n")); return Status; } MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL); ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData; ConfigDescLength = ConfigDesc->TotalLength; // // Reject if TotalLength even cannot cover itself. // if (ConfigDescLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (ConfigDesc->TotalLength)) { return EFI_DEVICE_ERROR; } // // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData. // if (ConfigDescLength > sizeof (PeiUsbDevice->ConfigurationData)) { return EFI_DEVICE_ERROR; } // // Then we get the total descriptors for this configuration // Status = PeiUsbGetDescriptor ( PeiServices, UsbIoPpi, (USB_DT_CONFIG << 8), 0, ConfigDescLength, PeiUsbDevice->ConfigurationData ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n")); return Status; } // // Parse this configuration descriptor // First get the current config descriptor; // Status = GetExpectedDescriptor ( PeiUsbDevice->ConfigurationData, ConfigDescLength, USB_DT_CONFIG, (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR), &SkipBytes ); if (EFI_ERROR (Status)) { return Status; } Ptr = PeiUsbDevice->ConfigurationData + SkipBytes; PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr; Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR); LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR); for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) { // // Get the interface descriptor // Status = GetExpectedDescriptor ( Ptr, LengthLeft, USB_DT_INTERFACE, (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR), &SkipBytes ); if (EFI_ERROR (Status)) { return Status; } Ptr += SkipBytes; if (InterfaceIndex == 0) { PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr; } PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr; Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR); LengthLeft -= SkipBytes; LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR); // // Parse all the endpoint descriptor within this interface // NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints; ASSERT (NumOfEndpoint <= MAX_ENDPOINT); for (Index = 0; Index < NumOfEndpoint; Index++) { // // Get the endpoint descriptor // Status = GetExpectedDescriptor ( Ptr, LengthLeft, USB_DT_ENDPOINT, (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR), &SkipBytes ); if (EFI_ERROR (Status)) { return Status; } Ptr += SkipBytes; if (InterfaceIndex == 0) { PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr; } PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr; Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR); LengthLeft -= SkipBytes; LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR); } } return EFI_SUCCESS; }
static char * convert_ccsid(LIBSSH2_SESSION *session, libssh2_string_cache **cache, unsigned short outccsid, unsigned short inccsid, const char *instring, ssize_t inlen, size_t *outlen) { char *inp; char *outp; size_t olen; size_t ilen; size_t buflen; size_t curlen; ssize_t termsize; int i; char *dst; libssh2_string_cache *outstring; QtqCode_T incode; QtqCode_T outcode; iconv_t cd; if (!instring) { if (outlen) *outlen = 0; return NULL; } if (outlen) *outlen = -1; if (!session || !cache) return NULL; /* Get terminator size. */ termsize = terminator_size(outccsid); if (termsize < 0) return NULL; /* Prepare conversion parameters. */ memset((void *) &incode, 0, sizeof incode); memset((void *) &outcode, 0, sizeof outcode); incode.CCSID = inccsid; outcode.CCSID = outccsid; curlen = OFFSET_OF(libssh2_string_cache, string); inp = (char *) instring; ilen = inlen; buflen = inlen + curlen; if (inlen < 0) { incode.length_option = 1; buflen = STRING_GRANULE; ilen = 0; } /* Allocate output string buffer and open conversion descriptor. */ dst = LIBSSH2_ALLOC(session, buflen + termsize); if (!dst) return NULL; cd = QtqIconvOpen(&outcode, &incode); if (cd.return_value == -1) { LIBSSH2_FREE(session, (char *) dst); return NULL; } /* Convert string. */ for (;;) { outp = dst + curlen; olen = buflen - curlen; i = iconv(cd, &inp, &ilen, &outp, &olen); if (inlen < 0 && olen == buflen - curlen) { /* Special case: converted 0-length (sub)strings do not store the terminator. */ if (termsize) { memset(outp, 0, termsize); olen -= termsize; } } curlen = buflen - olen; if (i >= 0 || errno != E2BIG) break; /* Must expand buffer. */ buflen += STRING_GRANULE; outp = LIBSSH2_REALLOC(session, dst, buflen + termsize); if (!outp) break; dst = outp; } iconv_close(cd); /* Check for error. */ if (i < 0 || !outp) { LIBSSH2_FREE(session, dst); return NULL; } /* Process terminator. */ if (inlen < 0) curlen -= termsize; else if (termsize) memset(dst + curlen, 0, termsize); /* Shorten buffer if possible. */ if (curlen < buflen) dst = LIBSSH2_REALLOC(session, dst, curlen + termsize); /* Link to cache. */ outstring = (libssh2_string_cache *) dst; outstring->next = *cache; *cache = outstring; /* Return length if required. */ if (outlen) *outlen = curlen - OFFSET_OF(libssh2_string_cache, string); return outstring->string; }