Esempio n. 1
0
/**
*
* This function validates the partition header.
*
* @param	Header Partition header pointer
*
* @return
*		- XST_FAILURE if bad header.
* 		- XST_SUCCESS if successful.
*
* @note		None
*
*******************************************************************************/
u32 ValidateHeader(PartHeader *Header)
{
	struct HeaderArray *Hap;

    Hap = (struct HeaderArray *)Header;

	/*
	 * If there are no partitions to load, fail
	 */
	if (IsEmptyHeader(Hap) == XST_SUCCESS) {
		fsbl_printf(DEBUG_GENERAL, "IMAGE_HAS_NO_PARTITIONS\r\n");
	    return XST_FAILURE;
	}

	/*
	 * Validate partition header checksum
	 */
	if (ValidatePartitionHeaderChecksum(Hap) != XST_SUCCESS) {
		fsbl_printf(DEBUG_GENERAL, "PARTITION_HEADER_CORRUPTION\r\n");
		return XST_FAILURE;
	}

    /*
     * Validate partition data size
     */
	if (Header->ImageWordLen > MAXIMUM_IMAGE_WORD_LEN) {
		fsbl_printf(DEBUG_GENERAL, "INVALID_PARTITION_LENGTH\r\n");
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
Esempio n. 2
0
/**
*
* This function validates the partition header.
*
* @param	Partition header pointer
*
* @return
*		- MOVE_IMAGE_FAIL if bad header.
* 		- XST_SUCCESS if successful.
*
* @note		None
*
*******************************************************************************/
u32 ValidateHeader(struct PartHeader *Header)
{
	struct HeaderArray *Hap;
	u32 ImageLength;
	u32 PartitionLength;

	Hap = (struct HeaderArray *)Header;

	/* If there are no partitions to load, fail */
	if (IsLastPartition(Hap) ||
		IsEmptyHeader(Hap)) {
		fsbl_printf(DEBUG_GENERAL,"IMAGE_HAS_NO_PARTITIONS\r\n");
		OutputStatus(IMAGE_HAS_NO_PARTITIONS);
		return MOVE_IMAGE_FAIL;
	}

	/* Validate Checksum of partition header */
	if (PartitionHeaderChecksum(Hap) == XST_FAILURE) {
		fsbl_printf(DEBUG_GENERAL,"PARTITION_HEADER_CORRUPTION\r\n");
		OutputStatus(PARTITION_HEADER_CORRUPTION);
		return MOVE_IMAGE_FAIL;
	}

	ImageLength = Header->ImageWordLen;
	PartitionLength = Header->PartitionWordLen;

	if (ImageLength > MAXIMUM_IMAGE_WORD_LEN) {
		fsbl_printf(DEBUG_GENERAL,"INVALID_PARTITION_LENGTH\r\n");
		OutputStatus(INVALID_PARTITION_LENGTH);
		return MOVE_IMAGE_FAIL;
	}

	/* For current tool implementation, partition header is not
	 * encrypted. If the tool will encrypt the partition header,
	 * the following should be overwritten after header decryption
	 */
	if (ImageLength == 0) {
		/* if it is an empty partition, it is OK */
		if (PartitionLength != 0) {
			fsbl_printf(DEBUG_INFO,"PartitionImageMove:"
			"0 Image Length, "
			"non-zero partition Length\r\n");
			fsbl_printf(DEBUG_GENERAL,"INVALID_PARTITION_HEADER\r\n");
			OutputStatus(INVALID_PARTITION_HEADER);
			return MOVE_IMAGE_FAIL;
		}
	}

	return XST_SUCCESS;
} /* end of ValidateHeader */
Esempio n. 3
0
/**
*
* This function reads the data at the provided FLASH address and expects
* the partition header structure to be present. If the header is not
* present (blank FLASH) or does not match expected values, MOVE_IMAGE_FAIL
* is returned.
*
* There are four cases in partition handling:
*
* 1. If attribute indicates this is a bitstream partition, FPGA is programmed,
*	and if this is the last partition, FSBL hangs with WDT kicking
* 2. If Image word Length != data word length, the partition is encrypted
*	partition. The partition is decrypted into DDR
* 3. Other cases, partition is moved from flash to DDR through copying or DMA
* 4. If partition data word length is 0, the partition is to be skipped. Note
*	that partition header cannot be encrypted for this to work
*
* Except case 1, the reboot status register is updated to reflect the next
* partition.
*
* @param	ImageAddress is the start of the image
* @param	PartitionNum is the index of the partition to process
*
* @return
*		- MOVE_IMAGE_FAIL (0xFFFFFFFF) if image load failed
*		- Address to begin executing at if successful
*
* @note
*
****************************************************************************/
u32 PartitionMove(u32 ImageAddress, int PartitionNum)
{
	u32 SourceAddr;
	u32 LoadAddr;
	u32 ExecAddr;
	u32 ImageLength;
	u32 DataLength;
	u32 SectionCount;
	u32 PartitionStart;
	u32 PartitionLength;
	u32 NextPartitionAddr;
	int NextPartition;
	u32 Status;
	u32 Attribute;

	 /* Flag to determine if image is encrypted or not */
	u32 IsEncrypted = 0;
	struct HeaderArray *Hap;
	struct PartHeader Header;
	/* Execution Address */
	ExecAddr = MOVE_IMAGE_FAIL;

	/* Default is not to skip partition execution */
	SkipPartition = 0;

	fsbl_printf(DEBUG_INFO,"image move with partition number %d\r\n",
			PartitionNum);

	PartitionStart = GoToPartition(ImageAddress, PartitionNum);

	GetHeader(PartitionStart, &Header);

	fsbl_printf(DEBUG_INFO,"Header dump:\n\r");
	DumpHeader(&Header);

	Hap = (struct HeaderArray *)&Header;
	Status = ValidateHeader(&Header);

	if(Status != XST_SUCCESS) {
		return Status;
	}

	ImageLength = Header.ImageWordLen;
	DataLength = Header.DataWordLen;
	PartitionLength = Header.PartitionWordLen;
	LoadAddr = Header.LoadAddr;
	ExecAddr = Header.ExecAddr;
	SourceAddr = Header.PartitionStart;
	Attribute = Header.PartitionAttr;
	SectionCount = Header.SectionCount;

	/* The offset in header is word offset */
	SourceAddr = SourceAddr << WORD_LENGTH_SHIFT;

	/* Consider image offset */
	SourceAddr += ImageAddress;

	fsbl_printf(DEBUG_INFO,"Partition Start %08x, "
						"Partition Length %08x\r\n",
						PartitionStart, PartitionLength);

	fsbl_printf(DEBUG_INFO,"Source addr %08x, Load addr %08x, "
						"Exec addr %08x\r\n",
						SourceAddr, LoadAddr, ExecAddr);

	/*
	 * If encrypted partition header, will get wrong next partition
	 * address. Next run will fail and invoke FSBL fallback.
	 * WARNING: Cannot handle skipping over encrypted partition header
	 */
	if (DataLength == 0) {
		fsbl_printf(DEBUG_INFO,"PartitionImageMove: skip partition. "
			"If encrypted partition, will fail\r\n");

		SkipPartition = 1;
		goto update_status_reg;
	}

	if (Attribute == ATTRIBUTE_PL_IMAGE_MASK) {

		/* FSBL user hook call before bitstream download. */
		Status = FsblHookBeforeBitstreamDload();

		if (Status != XST_SUCCESS) {
			/* Error Handling here */
			fsbl_printf(DEBUG_GENERAL,"FSBL_BEFORE_BSTREAM_HOOK_FAILED\r\n");
			OutputStatus(FSBL_BEFORE_BSTREAM_HOOK_FAIL);
			FsblFallback();
		}

		/* Check if encrypted or non encrypted */
		/* If the ImageLength not equal to DataLength, encrypted */
		if (ImageLength != DataLength) {
			IsEncrypted = 1;
			fsbl_printf(DEBUG_INFO,"Encrypted partition \r \n");
		}

		fsbl_printf(DEBUG_INFO,"Source addr %x, load addr %x, "
				"exec addr %x\r\n", SourceAddr, LoadAddr, ExecAddr);

		fsbl_printf(DEBUG_GENERAL,"Bitstream Download Start \r\n");

		if (IsEncrypted) {
			/* Bitstream NAND/SD encrypted */
			if (((FlashReadBaseAddress & 0xFF000000) == XPS_NAND_BASEADDR) ||
				(FlashReadBaseAddress == XPS_SDIO0_BASEADDR)) {
				fsbl_printf(DEBUG_INFO,"Bitstream NAND/SD encrypted \r\n");
				Status = WritePcapXferData(
						(u32 *)(SourceAddr),
						(u32 *)XDCFG_DMA_INVALID_ADDRESS,
						(ImageLength), 0, XDCFG_SECURE_PCAP_WRITE);
			} else {
			/* Bitstream QSPI/NOR Encrypted */
				fsbl_printf(DEBUG_INFO,"Bit stream QSPI/NOR encrypted \r\n");
				Status = WritePcapXferData(
		 					(u32 *)(FlashReadBaseAddress + SourceAddr),
							(u32 *)XDCFG_DMA_INVALID_ADDRESS,
							(ImageLength), 0, XDCFG_SECURE_PCAP_WRITE);
			}

		} else {
				/* Bitstream NAND/SD Unencrypted */
				if (((FlashReadBaseAddress & 0xFF000000) == XPS_NAND_BASEADDR) ||
						(FlashReadBaseAddress == XPS_SDIO0_BASEADDR)) {
					fsbl_printf(DEBUG_INFO,"Bit stream NAND/SD Unencrypted \r\n");
					Status = WritePcapXferData(
							(u32 *)(SourceAddr),
							(u32 *)XDCFG_DMA_INVALID_ADDRESS,
							(ImageLength), 0, XDCFG_NON_SECURE_PCAP_WRITE);
				} else {
					/* Bitstream QSPI/NOR - unencrypted */
					fsbl_printf(DEBUG_INFO,"Bitstream QSPI/NOR Unencrypted \r\n");
					Status = WritePcapXferData(
						(u32 *)(FlashReadBaseAddress + SourceAddr),
						(u32 *)XDCFG_DMA_INVALID_ADDRESS,
						(ImageLength), 0, XDCFG_NON_SECURE_PCAP_WRITE);
				}
		}

		if (Status != XST_SUCCESS) {
			fsbl_printf(DEBUG_GENERAL,"BITSTREAM_DOWNLOAD_FAIL");
			OutputStatus(BITSTREAM_DOWNLOAD_FAIL);
			return MOVE_IMAGE_FAIL;
		} else {
			fsbl_printf(DEBUG_GENERAL,"Bitstream download successful!\r\n");
		}

		/* FSBL user hook call after bitstream download. */
		Status = FsblHookAfterBitstreamDload();

		if (Status != XST_SUCCESS) {
			fsbl_printf(DEBUG_GENERAL,"FSBL_AFTER_BSTREAM_HOOK_FAIL");
			/* Error Handling here */
			OutputStatus(FSBL_AFTER_BSTREAM_HOOK_FAIL);
			FsblFallback();
		}
		/* We will skip soft reset and start loading the next partition */
		SkipPartition = 1;

		/* Go to the next partition */
		goto update_status_reg;

	} /* End of bitstream */
	/* Process all the partitions of application */

	while(SectionCount-- > 0) {

	/* If image length not equal to data length, encrypted */
	if (ImageLength != DataLength) {
		IsEncrypted = 1;
		fsbl_printf(DEBUG_INFO,"Application encrypted\n\r");
		/* NAND and SD do not support encrypted partitions */
		 if (((FlashReadBaseAddress & 0xFF000000) == XPS_NAND_BASEADDR) ||
			 (FlashReadBaseAddress == XPS_SDIO0_BASEADDR)) {

			 fsbl_printf(DEBUG_INFO,"Images on NAND or SD	encrypted\r\n");
			 Status = WritePcapXferData(
						(u32 *)SourceAddr,
						(u32 *)LoadAddr, ImageLength,
						 DataLength, XDCFG_SECURE_PCAP_WRITE);

		} else {
			 Status = WritePcapXferData(
					 	 (u32 *)(FlashReadBaseAddress + SourceAddr),
					 	 (u32 *)LoadAddr, ImageLength,
					 	 DataLength, XDCFG_SECURE_PCAP_WRITE);

		}
		 
		if (Status != XST_SUCCESS) {
			fsbl_printf(DEBUG_GENERAL,"DECRYPTION_FAIL \r\n");
			OutputStatus(DECRYPTION_FAIL);
			return MOVE_IMAGE_FAIL;
		 }
		 
		fsbl_printf(DEBUG_INFO,"Transfer is completed \r\n");
		if (SectionCount != 0) {
			fsbl_printf(DEBUG_INFO,"load_next_partition\n\r");
			goto load_next_partition;
		}

		goto update_status_reg;
	}	else {/*End of if ImageLength != DataLength */

		fsbl_printf(DEBUG_INFO,"Start transfer data into DDR\n\r");

		/* Copy the flash contents to DDR */

		MoveImage(SourceAddr, LoadAddr, (DataLength << WORD_LENGTH_SHIFT));

	}

load_next_partition:

	//JM detect cpu1 boot vector as last partiton and finish up
    if (LoadAddr == 0xFFFFFFF0) {
		goto update_status_reg;
	}

	PartitionNum += 1;

	/* Read the next partition */
	fsbl_printf(DEBUG_INFO,"Get next partition header\n\r");

	NextPartitionAddr = GoToPartition(ImageAddress, PartitionNum);
	GetHeader(NextPartitionAddr, &Header);

	fsbl_printf(DEBUG_INFO,"Next partition header dump\r\n");
	DumpHeader(&Header);

	Status = ValidateHeader(&Header);
	if(Status != XST_SUCCESS) {
		fsbl_printf(DEBUG_INFO,"Validation of Header failed\r\n");
		return Status;
	}

	/* Don't re-initialize ExecAddr & SectionCount */
	ImageLength = Header.ImageWordLen;
	DataLength = Header.DataWordLen;
	PartitionLength = Header.PartitionWordLen;
	LoadAddr = Header.LoadAddr;
	SourceAddr = Header.PartitionStart;
	//JM reinit SectionCount if this is a new sub-partition
	if (SectionCount == 0) {
		SectionCount = Header.SectionCount;
}

	/* The offset in header is word offset */
	SourceAddr = SourceAddr << WORD_LENGTH_SHIFT;

	/* Consider image offset */
	SourceAddr += ImageAddress;

	fsbl_printf(DEBUG_INFO,"Partition Start %08x, Partition Length %08x\r\n",
						PartitionStart, PartitionLength);

	fsbl_printf(DEBUG_INFO,"Source addr %08x, Load addr %08x, Exec addr %08x\r\n",
						SourceAddr, LoadAddr, ExecAddr);

	} /* End of while Section count > 0 */


update_status_reg:

	NextPartition = PartitionNum + 1;

	fsbl_printf(DEBUG_INFO,"Get next partition header\n\r");

	NextPartitionAddr = GoToPartition(ImageAddress, PartitionNum + 1);
	GetHeader(NextPartitionAddr, &Header);
	Hap = (struct HeaderArray *)&Header;

	fsbl_printf(DEBUG_INFO,"Next Header dump:\n\r");
	DumpHeader(&Header);

	/* If it is the last partition, then we will keep on running this one */
	if (IsLastPartition(Hap)) {
		fsbl_printf(DEBUG_INFO,"There are no more partitions to load\r\n");
		NextPartition = PartitionNum;
		/*
		 * Fix for CR #663277
		 * Review : Since we donot support OCM remap,
		 * any elf whose execution address is 0x0
		 * We will do a JTAG exit 
		 */
 
		if (ExecAddr == 0) {
			fsbl_printf(DEBUG_INFO,"No Execution Address JTAG handoff \r\n");
			/* Stop the Watchdog before JTAG handoff */
#ifdef	XPAR_XWDTPS_0_BASEADDR
			XWdtPs_Stop(&Watchdog);
#endif
			ClearFSBLIn();
			FsblHandoffJtagExit();
		}

	} else if(IsEmptyHeader(Hap)) {
		fsbl_printf(DEBUG_GENERAL,"Empty partition header \r\n");
		OutputStatus(EMPTY_PARTITION_HEADER);
		return MOVE_IMAGE_FAIL;
	}


	Status = FsblSetNextPartition(NextPartition);
	if (Status != XST_SUCCESS) {
		fsbl_printf(DEBUG_INFO,"Next partition number %d is not valid\n",
							NextPartition);
		OutputStatus(TOO_MANY_PARTITIONS);
		return MOVE_IMAGE_FAIL;
	 }

	fsbl_printf(DEBUG_INFO,"end of partition move, reboot status reg %x, "
		 "Next partition %d\r\n", MoverIn32(REBOOT_STATUS_REG), NextPartition);

	/* Returning Execution Address */
	return ExecAddr;
} /* End of Partition Move */