示例#1
0
/**
 *
 * Write Data to RSA RAM at a given offset
 *
 * @param	InstancePtr is a pointer to the XSecure_Aes instance.
 * @param	WrData is pointer to the data to be written to RSA RAM
 * @param	RamOffset is the offset for the data to be written in RSA RAM
 *
 * @return	None
 *
 * @note	None
 *
 ******************************************************************************/
static void XSecure_RsaWriteMem(XSecure_Rsa *InstancePtr, u32* WrData,
							u8 RamOffset)
{
	/* Assert validates the input arguments */
	Xil_AssertVoid(InstancePtr != NULL);

	u32 Index = 0U;
	u32 DataOffset = 0U;
	u32 TmpIndex = 0U;
	u32 Data = 0U;

	/** Each of this loop will write 192 bits of data*/
	for (DataOffset = 0U; DataOffset < 22U; DataOffset++)
	{
		for (Index = 0U; Index < 6U; Index++)
		{
			TmpIndex = (DataOffset*6) + Index;
			/**
			* Exponent size is only 4 bytes
			* and rest of the data needs to be 0
			*/
			if(XSECURE_CSU_RSA_RAM_EXPO == RamOffset)
			{
				if(0U == TmpIndex )
				{
					Data = Xil_Htonl(*WrData);
				}
				else
				{
					Data = 0x0U;
				}
			}
			else
			{
				if(TmpIndex >=128U)
				{
					Data = 0x0U;
				}
				else
				{
				/**
				* The RSA data in Image is in Big Endian.
				* So reverse it before putting in RSA memory,
				* becasue RSA h/w expects it in Little endian.
				*/

				Data = Xil_Htonl(WrData[127U - TmpIndex]);
				}
			}
			XSecure_WriteReg(InstancePtr->BaseAddress,
			(XSECURE_CSU_RSA_WR_DATA_0_OFFSET + (Index * 4)),
							Data);
		}
		XSecure_WriteReg(InstancePtr->BaseAddress,
				XSECURE_CSU_RSA_WR_ADDR_OFFSET,
				((RamOffset * 22) + DataOffset));
	}
}
示例#2
0
static void XSecure_RsaMod32Inverse(XSecure_Rsa *InstancePtr)
{
	/* Assert validates the input arguments */
	Xil_AssertVoid(InstancePtr != NULL);

	/* Calculate the MINV */
	u8 Count = 0U;
	u32 *ModPtr = (u32 *)(InstancePtr->Mod);
	u32 ModVal = Xil_Htonl(ModPtr[127]);
	u32 Inv = 2U - ModVal;

	for (Count = 0U; Count < 4U; ++Count)
	{
		Inv = (Inv * (2U - ( ModVal * Inv ) ) );
	}

	Inv = -Inv;

	/* Put the value in MINV registers */
	XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_RSA_MINV0_OFFSET,
						(Inv & 0xFF ));
	XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_RSA_MINV1_OFFSET,
						((Inv >> 8) & 0xFF ));
	XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_RSA_MINV2_OFFSET,
						((Inv >> 16) & 0xFF ));
	XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_RSA_MINV3_OFFSET,
						((Inv >> 24) & 0xFF ));
}
/******************************************************************************
*
* This function calculates the next block size and updates the required
* parameters.
*
* @param	PartitionParams is a pointer to XFsblPs_PlPartition
* @param	ChunkAdrs is a pointer to the data location
* @param	ChunkSize is the remaining chunk size
*
* @return
* 		Error code on failure
* 		XFSBL_SUCESS on success
*
* @note		None
*
******************************************************************************/
static u32 XFsbl_DecrptSetUpNextBlk(XFsblPs_PlPartition *PartitionParams,
		UINTPTR ChunkAdrs, u32 ChunkSize)
{
	u32 Status = XFSBL_SUCCESS;
	u32 SssAes;
	u32 SssCfg;

	/* Length of next block */
	PartitionParams->PlEncrypt.NextBlkLen =
			Xil_Htonl(XSecure_ReadReg(
			PartitionParams->PlEncrypt.SecureAes->BaseAddress,
				XSECURE_CSU_AES_IV_3_OFFSET)) * 4;
	PartitionParams->PlEncrypt.SecureAes->Iv =
		(u32 *)(PartitionParams->PlEncrypt.SecureAes->BaseAddress +
			(UINTPTR)XSECURE_CSU_AES_IV_0_OFFSET);

	/* Configure the SSS for AES. */
	SssAes = XSecure_SssInputAes(XSECURE_CSU_SSS_SRC_SRC_DMA);
	SssCfg = SssAes | XSecure_SssInputPcap(XSECURE_CSU_SSS_SRC_AES);
	XSecure_SssSetup(SssCfg);

	/* Start the message. */
	XSecure_WriteReg(PartitionParams->PlEncrypt.SecureAes->BaseAddress,
				XSECURE_CSU_AES_START_MSG_OFFSET,
				XSECURE_CSU_AES_START_MSG);

	/* Transfer IV of the next block */
	XFsbl_DmaPlCopy(PartitionParams->PlEncrypt.SecureAes->CsuDmaPtr,
			(UINTPTR)PartitionParams->PlEncrypt.SecureAes->Iv,
					XSECURE_SECURE_GCM_TAG_SIZE/4, 0);

	PartitionParams->PlEncrypt.SecureAes->SizeofData =
				PartitionParams->PlEncrypt.NextBlkLen;

	XSecure_WriteReg(PartitionParams->PlEncrypt.SecureAes->BaseAddress,
					XSECURE_CSU_AES_KUP_WR_OFFSET, 0x0);


	return Status;

}
示例#4
0
/**
 *
 * Read back the resulting data from RSA RAM
 *
 * @param	InstancePtr is a pointer to the XSecure_Rsa instance.
 * @param	RdData is the pointer to location where the decrypted data will
 * 			be written
 *
 * @return	None
 *
 * @note	None
 *
 ******************************************************************************/
static void XSecure_RsaGetData(XSecure_Rsa *InstancePtr, u32 *RdData)
{
	/* Assert validates the input arguments */
	Xil_AssertVoid(InstancePtr != NULL);

	u32 Index = 0U;
	u32 DataOffset = 0U;
	s32 TmpIndex = 0;

	/* Each of this loop will write 192 bits of data */
	for (DataOffset = 0U; DataOffset < 22U; DataOffset++)
	{
		XSecure_WriteReg(InstancePtr->BaseAddress,
				XSECURE_CSU_RSA_RD_ADDR_OFFSET,
				(XSECURE_CSU_RSA_RAM_RES_Y * 22) + DataOffset);

		Index = (DataOffset == 0U) ? 2: 0;
		for (; Index < 6; Index++)
		{
			TmpIndex = 129 - ((DataOffset*6) + Index);
			if(TmpIndex < 0)
			{
				break;
			}
			/*
			 * The Signature digest is compared in Big endian.
			 * So because RSA h/w results in Little endian,
			 * reverse it after reading it from RSA memory,
			 */
			RdData[TmpIndex] = Xil_Htonl(XSecure_ReadReg(
						InstancePtr->BaseAddress,
			(XSECURE_CSU_RSA_RD_DATA_0_OFFSET+ (Index * 4))));
		}
	}

}
/**
* Node Commands
*
* This function is part of the callback system for the Ethernet transport
* and will be executed when a valid node commands is recevied.
*
* @param    Command Header         - WARPNet Command Header
*           Command Arguments      - WARPNet Command Arguments
*           Response Header        - WARPNet Response Header
*           Response Arguments     - WARPNet Response Arguments
*           Packet Source          - Ethernet Packet Source
*           Ethernet Device Number - Indicates which Ethernet device packet came from
*
* @return	None.
*
* @note		See on-line documentation for more information about the ethernet
*           packet structure for WARPNet:  www.warpproject.org
*
******************************************************************************/
int node_processCmd(const wn_cmdHdr* cmdHdr,const void* cmdArgs, wn_respHdr* respHdr,void* respArgs, void* pktSrc, unsigned int eth_dev_num){
	//IMPORTANT ENDIAN NOTES:
	// -cmdHdr is safe to access directly (pre-swapped if needed)
	// -cmdArgs is *not* pre-swapped, since the framework doesn't know what it is
	// -respHdr will be swapped by the framework; user code should fill it normally
	// -respArgs will *not* be swapped by the framework, since only user code knows what it is
	//    Any data added to respArgs by the code below must be endian-safe (swapped on AXI hardware)

	int           status     = 0;
	const u32   * cmdArgs32  = cmdArgs;
	u32         * respArgs32 = respArgs;

	unsigned int  respIndex  = 0;
	unsigned int  respSent   = NO_RESP_SENT;
    unsigned int  max_words  = 320;                // Max number of u32 words that can be sent in the packet (~1400 bytes)
                                                   //   If we need more, then we will need to rework this to send multiple response packets

    unsigned int  temp, i;

    // Variables for functions
    u32           id;
    u32           flags;
	u32           start_address;
	u32           curr_address;
	u32           next_address;
	u32           size;
	u32           evt_log_size;
	u32           transfer_size;
	u32           bytes_per_pkt;
	u32           num_bytes;
	u32           num_pkts;

	u32           interval;


	unsigned int  cmdID;
    
	cmdID = WN_CMD_TO_CMDID(cmdHdr->cmd);
    
	respHdr->cmd     = cmdHdr->cmd;
	respHdr->length  = 0;
	respHdr->numArgs = 0;

#ifdef _DEBUG_
	xil_printf("In node_processCmd():  ID = %d \n", cmdID);
#endif

	switch(cmdID){

	    //---------------------------------------------------------------------
        case WARPNET_TYPE:
        	// Return the WARPNet Type
            respArgs32[respIndex++] = Xil_Htonl( node_info.type );    
        
			respHdr->length += (respIndex * sizeof(respArgs32));
			respHdr->numArgs = respIndex;
        break;
        
    
	    //---------------------------------------------------------------------
		case NODE_INFO:
			// Return the info about the WLAN_EXP_NODE
            
            // Send node parameters
            temp = node_get_parameters( &respArgs32[respIndex], max_words, TRANSMIT_OVER_NETWORK);
            respIndex += temp;
            max_words -= temp;
            if ( max_words <= 0 ) { xil_printf("No more space left in NODE_INFO packet \n"); };
            
            // Send transport parameters
            temp = transport_get_parameters( eth_dev_num, &respArgs32[respIndex], max_words, TRANSMIT_OVER_NETWORK);
            respIndex += temp;
            max_words -= temp;
            if ( max_words <= 0 ) { xil_printf("No more space left in NODE_INFO packet \n"); };

#ifdef _DEBUG_
            xil_printf("NODE INFO: \n");
            for ( i = 0; i < respIndex; i++ ) {
            	xil_printf("   [%2d] = 0x%8x \n", i, respArgs32[i]);
            }
            xil_printf("END NODE INFO \n");
#endif

            // --------------------------------
            // Future parameters go here
            // --------------------------------
                        
            // Finalize response
			respHdr->length += (respIndex * sizeof(respArgs32));
			respHdr->numArgs = respIndex;
		break;
        

	    //---------------------------------------------------------------------
		case NODE_IDENTIFY:
			// Return Null Response
			//   The WLAN_EXP_NODE currently does not have access to LEDs

            xil_printf("  Node: %d    IP Address: %d.%d.%d.%d \n", node_info.node, node_info.ip_addr[0], node_info.ip_addr[1],node_info.ip_addr[2],node_info.ip_addr[3]);

            // --------------------------------
            // TODO:  Add in visual identifiers for the node
            // --------------------------------
        break;


	    //---------------------------------------------------------------------
		case NODE_CONFIG_SETUP:
            // NODE_CONFIG_SETUP Packet Format:
            //   - Note:  All u32 parameters in cmdArgs32 are byte swapped so use Xil_Ntohl()
            //
            //   - cmdArgs32[0] - Serial Number
            //   - cmdArgs32[1] - Node ID
            //   - cmdArgs32[2] - IP Address
            //   - cmdArgs32[3] - Unicast Port
            //   - cmdArgs32[4] - Broadcast Port
            // 
            if ( node_info.node == 0xFFFF ) {
                // Only update the parameters if the serial numbers match
                if ( node_info.serial_number ==  Xil_Ntohl(cmdArgs32[0]) ) {

                    xil_printf("  Reconfiguring ETH %c \n", wn_conv_eth_dev_num(eth_dev_num) );

                	node_info.node = Xil_Ntohl(cmdArgs32[1]) & 0xFFFF;

                    xil_printf("  New Node ID       : %d \n", node_info.node);
                    
                    // Grab New IP Address
                    node_info.ip_addr[0]     = (Xil_Ntohl(cmdArgs32[2]) >> 24) & 0xFF;
                    node_info.ip_addr[1]     = (Xil_Ntohl(cmdArgs32[2]) >> 16) & 0xFF;
                    node_info.ip_addr[2]     = (Xil_Ntohl(cmdArgs32[2]) >>  8) & 0xFF;
                    node_info.ip_addr[3]     = (Xil_Ntohl(cmdArgs32[2])      ) & 0xFF;
                    
                    // Grab new ports
                    node_info.unicast_port   = Xil_Ntohl(cmdArgs32[3]);
                    node_info.broadcast_port = Xil_Ntohl(cmdArgs32[4]);

                    xil_printf("  New IP Address    : %d.%d.%d.%d \n", node_info.ip_addr[0], node_info.ip_addr[1],node_info.ip_addr[2],node_info.ip_addr[3]);
                    xil_printf("  New Unicast Port  : %d \n", node_info.unicast_port);
                    xil_printf("  New Broadcast Port: %d \n", node_info.broadcast_port);

                    transport_set_hw_info( eth_dev_num, node_info.ip_addr, node_info.hw_addr);

                    status = transport_config_sockets(eth_dev_num, node_info.unicast_port, node_info.broadcast_port);

                    if(status != 0) {
        				xil_printf("Error binding transport...\n");
        			}
                } else {
                    xil_printf("NODE_IP_SETUP Packet with Serial Number %d ignored.  My serial number is %d \n", Xil_Ntohl(cmdArgs32[0]), node_info.serial_number);
                }
            }
/**
 * This function validates the partition
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number in the image to be loaded
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *
 *****************************************************************************/
static u32 XFsbl_PartitionValidation(XFsblPs * FsblInstancePtr,
						u32 PartitionNum)
{
	u32 Status=XFSBL_SUCCESS;
	u32 ChecksumType=0U;
	s32 IsEncryptionEnabled=FALSE;
	s32 IsAuthenticationEnabled=FALSE;
	u32 DestinationDevice=0U;
	u32 DestinationCpu=0U;
	u32 ExecState=0U;
	u32 CpuNo=0U;
	XFsblPs_PartitionHeader * PartitionHeader;
#if defined(XFSBL_RSA)
	u32 HashLen=0U;
#endif
#if defined(XFSBL_AES)
	u32 ImageOffset = 0U;
	u32 FsblIv[XIH_BH_IV_LENGTH / 4U];
	u32 UnencryptedLength = 0;
	u32 IvLocation;
#endif
#if defined(XFSBL_RSA) || defined(XFSBL_AES)
	u32 Length=0U;
#endif
#if defined(XFSBL_RSA) || defined(XFSBL_AES) || defined(XFSBL_BS)
	PTRSIZE LoadAddress=0U;
#endif
#if defined(XFSBL_BS)
	u32 BitstreamWordSize = 0;
#endif

	/**
	 * Update the variables
	 */
	PartitionHeader =
	    &FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];
	ChecksumType = XFsbl_GetChecksumType(PartitionHeader);

	/**
	 * Check the encryption status
	 */
	if (XFsbl_IsEncrypted(PartitionHeader) ==
			XIH_PH_ATTRB_ENCRYPTION )
	{
		IsEncryptionEnabled = TRUE;

#ifdef XFSBL_AES
		/* Copy the Iv from Flash into local memory */
		IvLocation = ImageOffset + XIH_BH_IV_OFFSET;

		Status = FsblInstancePtr->DeviceOps.DeviceCopy(IvLocation,
				(PTRSIZE) FsblIv, XIH_BH_IV_LENGTH);

		if (Status != XFSBL_SUCCESS) {
			XFsbl_Printf(DEBUG_GENERAL,
					"XFSBL_ERROR_DECRYPTION_IV_COPY_FAIL \r\n");
			Status = XFSBL_ERROR_DECRYPTION_IV_COPY_FAIL;
			goto END;
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_AES_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_AES_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * check the authentication status
	 */
	if (XFsbl_IsRsaSignaturePresent(PartitionHeader) ==
			XIH_PH_ATTRB_RSA_SIGNATURE )
	{
		IsAuthenticationEnabled = TRUE;
	}
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);
	DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader);


	/**
         * Get the execution state
         */
        ExecState = XFsbl_GetA53ExecState(PartitionHeader);

	/**
	 * if destination cpu is not present, it means it is for same cpu
	 */
	if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE)
	{
		DestinationCpu = FsblInstancePtr->ProcessorID;
	}


	/**
	 * Checksum Validation
	 */
	if (ChecksumType == XIH_PH_ATTRB_CHECKSUM_MD5)
	{
		/**
		 * Do the checksum validation
		 */
	}

#if defined(XFSBL_RSA) || defined(XFSBL_AES)
	if ((IsAuthenticationEnabled == TRUE) || (IsEncryptionEnabled == TRUE))
	{
		LoadAddress = PartitionHeader->DestinationLoadAddress;
		Length = PartitionHeader->TotalDataWordLength * 4U;
		Status = XFsbl_GetLoadAddress(DestinationCpu,
				&LoadAddress, Length);
		if (XFSBL_SUCCESS != Status)
		{
			goto END;
		}
	}
#endif

#ifdef XFSBL_BS
	if ((DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL) &&
			(LoadAddress == 0U))
	{
		LoadAddress = XFSBL_DDR_TEMP_ADDRESS;
	}
#endif

	/**
	 * Authentication Check
	 */
	if (IsAuthenticationEnabled == TRUE)
	{
		XFsbl_Printf(DEBUG_INFO,"Authentication Enabled\r\n");
#ifdef XFSBL_RSA
		/**
		 * Get the Sha type to be used from
		 * boot header attributes
		 */
		if ((FsblInstancePtr->BootHdrAttributes &
			XIH_BH_IMAGE_ATTRB_SHA2_MASK) ==
			XIH_BH_IMAGE_ATTRB_SHA2_MASK)
		{
			HashLen = XFSBL_HASH_TYPE_SHA2;
		} else {
			HashLen = XFSBL_HASH_TYPE_SHA3;
		}

		/**
		 * cache disbale can be removed
		 */
		Xil_DCacheDisable();

		/**
		 * Do the authentication validation
		 */
		Status = XFsbl_Authentication(FsblInstancePtr, LoadAddress, Length,
			(LoadAddress + Length) - XFSBL_AUTH_CERT_MIN_SIZE,
			HashLen);

		if (Status != XFSBL_SUCCESS)
                {
                        goto END;
                }
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_RSA_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_RSA_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * Decrypt image through CSU DMA
	 */
	if (IsEncryptionEnabled == TRUE) {
		XFsbl_Printf(DEBUG_INFO, "Decryption Enabled\r\n");
#ifdef XFSBL_AES

		/* AES expects IV in big endian form */
		FsblIv[0] = Xil_Htonl(FsblIv[0]);
		FsblIv[1] = Xil_Htonl(FsblIv[1]);
		FsblIv[2] = Xil_Htonl(FsblIv[2]);

		/* Initialize the Aes Instance so that it's ready to use */
		XSecure_AesInitialize(&SecureAes, &CsuDma,
		 XSECURE_CSU_AES_KEY_SRC_DEV, FsblIv, NULL);

		XFsbl_Printf(DEBUG_INFO, " Aes initialized \r\n");

		UnencryptedLength = PartitionHeader->UnEncryptedDataWordLength * 4U;


		if (DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PL) {
			Status = XSecure_AesDecrypt(&SecureAes, (u8 *) LoadAddress,
					(u8 *) LoadAddress, UnencryptedLength);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_DECRYPTION_FAIL;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_DECRYPTION_FAIL\r\n");
				goto END;
			} else {
				XFsbl_Printf(DEBUG_GENERAL, "Decryption Successful\r\n");
			}
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_AES_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_AES_NOT_ENABLED;
		goto END;
#endif
	}

#ifdef XFSBL_BS
	/**
	 * for PL image use CSU DMA to route to PL
	 */
	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
		/**
		 * Fsbl hook before bit stream download
		 */
		Status = XFsbl_HookBeforeBSDownload();
		if (Status != XFSBL_SUCCESS)
		{
			Status = XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD;
			XFsbl_Printf(DEBUG_GENERAL,
			 "XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD\r\n");
			goto END;
		}

		XFsbl_Printf(DEBUG_GENERAL, "Bitstream download to start now\r\n");

		Status = XFsbl_PcapInit();
		if (Status != XFSBL_SUCCESS) {
			goto END;
		}

		if (IsEncryptionEnabled == TRUE) {
#ifdef XFSBL_AES
			/*
			 * The secure bitstream would be sent through CSU DMA to AES
			 * and the decrypted bitstream is sent directly to PCAP
			 * by configuring SSS appropriately
			 */
			Status = XSecure_AesDecrypt(&SecureAes,
					(u8 *) XFSBL_DESTINATION_PCAP_ADDR,
					(u8 *) LoadAddress, UnencryptedLength);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_BITSTREAM_DECRYPTION_FAIL;
				XFsbl_Printf(DEBUG_GENERAL,
						"XFSBL_ERROR_BITSTREAM_DECRYPTION_FAIL\r\n");
				/* Reset PL */
				XFsbl_Out32(CSU_PCAP_PROG, 0x0);
				goto END;
			} else {
				XFsbl_Printf(DEBUG_GENERAL,
						"Bitstream decryption Successful\r\n");
			}
#endif
		}
		else {

			/* Use CSU DMA to load Bit stream to PL */
			BitstreamWordSize = PartitionHeader->UnEncryptedDataWordLength;

			Status = XFsbl_WriteToPcap(BitstreamWordSize, (u8 *) LoadAddress);
			if (Status != XFSBL_SUCCESS) {
				goto END;
			}
		}

		Status = XFsbl_PLWaitForDone();
		if (Status != XFSBL_SUCCESS) {
			goto END;
		}

		/**
		 * Fsbl hook after bit stream download
		 */
		Status = XFsbl_HookAfterBSDownload();
		if (Status != XFSBL_SUCCESS)
		{
			Status = XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD;
			XFsbl_Printf(DEBUG_GENERAL,
			 "XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD\r\n");
			goto END;
		}
	}
#endif

	/**
	 * Update the handoff details
	 */
	if ((DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PL) &&
			(DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PMU))
	{
		CpuNo = FsblInstancePtr->HandoffCpuNo;
		if (XFsbl_CheckHandoffCpu(FsblInstancePtr,
				DestinationCpu) == XFSBL_SUCCESS)
		{
			FsblInstancePtr->HandoffValues[CpuNo].CpuSettings =
					DestinationCpu | ExecState;
			FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress =
					PartitionHeader->DestinationExecutionAddress;
			FsblInstancePtr->HandoffCpuNo += 1U;
		}
	}

END:
	return Status;
}
示例#7
0
/**
 * Process Transport Commands
 *
 * This function is part of the Ethernet processing system and will process the
 * various transport related commands.
 *
 * @param   socket_index     - Index of the socket on which to send message
 * @param   from             - Pointer to socket address structure (struct sockaddr *) where command is from
 * @param   command          - Pointer to Command
 * @param   response         - Pointer to Response
 * @param   max_resp_len     - Maximum number of u32 words allowed in response
 *
 * @return  int              - Status of the command:
 *                                 NO_RESP_SENT - No response has been sent
 *                                 RESP_SENT    - A response has been sent
 *
 * @note    See on-line documentation for more information about the Ethernet
 *          packet structure:  www.warpproject.org
 *
 *****************************************************************************/
int process_transport_cmd(int socket_index, void * from, cmd_resp * command, cmd_resp * response, u32 max_resp_len) {

    //
    // IMPORTANT ENDIAN NOTES:
    //     - command
    //         - header - Already endian swapped by the framework (safe to access directly)
    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the command)
    //     - response
    //         - header - Will be endian swapped by the framework (safe to write directly)
    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the response)
    //

    // Standard variables
    u32                 resp_sent      = NO_RESP_SENT;

    cmd_resp_hdr      * cmd_hdr        = command->header;
    u32               * cmd_args_32    = command->args;
    u32                 cmd_id         = CMD_TO_CMDID(cmd_hdr->cmd);

    cmd_resp_hdr      * resp_hdr       = response->header;
    u32               * resp_args_32   = response->args;
    u32                 resp_index     = 0;

    u32                 eth_dev_num    = socket_get_eth_dev_num(socket_index);


    // Set up the response header
    resp_hdr->cmd       = cmd_hdr->cmd;
    resp_hdr->length    = 0;
    resp_hdr->num_args  = 0;

    // Check Ethernet device number
    if (eth_dev_num == WARP_IP_UDP_INVALID_ETH_DEVICE) {
        wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Invalid socket index: %d\n", socket_index);
        return resp_sent;
    }

    // Process the command
    switch(cmd_id){

        //---------------------------------------------------------------------
        case CMDID_TRANSPORT_PING: {
            //
            // Nothing actually needs to be done when receiving the ping command. The framework is going
            // to respond regardless, which is all the host wants.
            //
        }
        break;

        //---------------------------------------------------------------------
        case CMDID_TRANSPORT_PAYLOAD_SIZE_TEST: {
            //
            // Due to packet fragmentation, it is not safe to just return the packet length.  We have seen
            // an issue where the host will send a 1514 byte fragment which results in a payload size of
            // 1472 and causes the transport to not behave correctly.  Therefore, we need to find the
            // last valid command argument and check that against the packet length.
            //
            u32              temp;
            u32              payload_index;
            u32              payload_size;
            u32              payload_num_words;
            u32              header_size;

            header_size        = (sizeof(transport_header) + sizeof(cmd_resp_hdr));                               // Transport / Command headers
            payload_index      = (((warp_ip_udp_buffer *)(command->buffer))->length - sizeof(cmd_resp_hdr)) / 4;  // Final index into command args (/4 truncates)

            // Check the value in the command args to make sure it matches the size_index
            payload_num_words  = Xil_Htonl(cmd_args_32[payload_index - 1]) + 1;     // NOTE:  Add 1 since the payload is zero indexed
            payload_size       = (payload_num_words * 4) + header_size;
            temp               = ((payload_index * 4) + header_size);

            // Update the max_pkt_words field
            if (payload_num_words > eth_devices[eth_dev_num].max_pkt_words) {
                eth_devices[eth_dev_num].max_pkt_words = payload_num_words;
            }

            if (payload_size != temp) {
                wlan_exp_printf(WLAN_EXP_PRINT_WARNING, print_type_transport, "Payload size mismatch.  Value in command args does not match index:  %d != %d\n", payload_size, temp);
            }

            resp_args_32[resp_index++] = Xil_Ntohl(payload_size);

            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
            resp_hdr->num_args = 1;
        }
        break;

        //---------------------------------------------------------------------
        case CMDID_TRANSPORT_NODE_GROUP_ID_ADD: {
            eth_devices[eth_dev_num].info.group_id = (eth_devices[eth_dev_num].info.group_id | Xil_Htonl(cmd_args_32[0]));
        }
        break;

        //---------------------------------------------------------------------
        case CMDID_TRANSPORT_NODE_GROUP_ID_CLEAR: {
            eth_devices[eth_dev_num].info.group_id = (eth_devices[eth_dev_num].info.group_id & ~Xil_Htonl(cmd_args_32[0]));
        }
        break;

        //---------------------------------------------------------------------
        default: {
            wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Unknown user command ID: %d\n", cmd_id);
        }
        break;
    }

    return resp_sent;
}
示例#8
0
int user_processCmd(const wl_cmdHdr* cmdHdr,const void* cmdArgs, wl_respHdr* respHdr, void* respArgs, void* pktSrc) {
    //IMPORTANT ENDIAN NOTES:
    // -cmdHdr is safe to access directly (pre-swapped if needed)
    // -cmdArgs is *not* pre-swapped, since the framework doesn't know what it is
    // -respHdr will be swapped by the framework; user code should fill it normally
    // -respArgs will *not* be swapped by the framework, since only user code knows what it is
    //    Any data added to respArgs by the code below must be endian-safe (swapped on AXI hardware)

    u32 cmdID;

    //Cast argument buffers into arrays for easy accessing
    const u32 *cmdArgs32 = cmdArgs;
    u32 *respArgs32 = respArgs;

    /* Example variables for processing user commands
    	const u32 *cmdArgs32 = cmdArgs;
    	u32 *respArgs32 = respArgs;

    	int respIndex = 0;

    	u32 arg0, arg1, result;
    */
    unsigned int respSent = NO_RESP_SENT;

    cmdID = WL_CMD_TO_CMDID(cmdHdr->cmd);

    respHdr->cmd = cmdHdr->cmd;
    respHdr->length = 0;
    respHdr->numArgs = 0;

#ifdef WARP_HW_VER_v3
    u32 stringBuffer32[10];
    u8 *stringBuffer8 = (u8*)stringBuffer32;
    int k;
    u32 readLength;
    u32 eepromAddrOffset;
#endif

    switch(cmdID) {

        /* Example user command
        	case SOME_CMD_ID:
        		arg0 = Xil_Ntohl(cmdArgs[0]);
        		arg1 = Xil_Ntohl(cmdArgs[1]);
        		result = do_something_with_args(arg0, arg1);

        		respArgs32[respIndex++] = Xil_Htonl(result);
        		respHdr->length += (respIndex * sizeof(respArgs32));
        		respHdr->numArgs = respIndex;
        	break;
        */
#ifdef WARP_HW_VER_v3
    case USER_EEPROM_WRITE_STRING:
        eepromAddrOffset = Xil_Ntohl(cmdArgs32[0]);

        for( k=0; k<((cmdHdr->length)/sizeof(u32)); k++ ) {
            stringBuffer32[k] = Xil_Ntohl(cmdArgs32[k+1]);
        }

        for( k=0; k<(cmdHdr->length); k++ ) {
            iic_eeprom_writeByte(EEPROM_BASEADDR,k+eepromAddrOffset,stringBuffer8[k]);
        }

        xil_printf("Wrote '%s' to EEPROM\n",stringBuffer8);
        break;
    case USER_EEPROM_READ_STRING:
        eepromAddrOffset = Xil_Ntohl(cmdArgs32[0]);
        readLength = Xil_Ntohl(cmdArgs32[1]);

        for( k=0; k<readLength; k++ ) {
            stringBuffer8[k] = iic_eeprom_readByte(EEPROM_BASEADDR,k+eepromAddrOffset);
        }

        xil_printf("Read '%s' from EEPROM\n",stringBuffer8);

        for( k=0; k<((readLength)/sizeof(u32)); k++ ) {
            respArgs32[k] = Xil_Htonl(stringBuffer32[k]);
        }
        respHdr->length += ((k) * sizeof(respArgs32));
        respHdr->numArgs = (k);

        break;
#endif

    default:
        xil_printf("Unknown user command ID: %d\n", cmdID);
        break;
    }
    return respSent;
}