static int cfm_flash_get_next_manifest()

in core/manifest/cfm/cfm_flash.c [1271:1405]


static int cfm_flash_get_next_manifest (const struct cfm *cfm, uint32_t component_id,
	int manifest_type, struct cfm_manifest *allowable_manifest, bool first)
{
	const struct cfm_flash *cfm_flash = (const struct cfm_flash*) cfm;

	union {
		struct cfm_allowable_pfm_element allowable_pfm_element;
		struct cfm_allowable_id_element allowable_id_element;
	} buffer;
	struct cfm_allowable_pfm_element *allowable_pfm_element_ptr = &buffer.allowable_pfm_element;
	struct cfm_allowable_id_element *allowable_id_element_ptr = &buffer.allowable_id_element;
	struct cfm_allowable_id *allowable_id_ptr;
	size_t allowable_pfm_element_len = sizeof (struct cfm_allowable_pfm_element);
	size_t ids_len;
	size_t offset;
	uint8_t *element_entry_ptr;
	int num_allowable_id;
	int i_allowable_id;
	int status;

	if ((cfm == NULL) || (allowable_manifest == NULL)) {
		return CFM_INVALID_ARGUMENT;
	}

	element_entry_ptr = (uint8_t*) &allowable_manifest->context;

	if (first) {
		*element_entry_ptr = 0;
	}
	else {
		cfm_flash_free_manifest (cfm, allowable_manifest);
	}

	allowable_manifest->check_count = 0;
	allowable_manifest->check = NULL;
	allowable_manifest->platform_id = NULL;

	// All allowable manifest elements have the same format, so use allowable PFM element containers
	status = cfm_flash_get_next_element (cfm_flash, component_id,
		(uint8_t**) &allowable_pfm_element_ptr, &allowable_pfm_element_len, element_entry_ptr,
		manifest_type);
	if (ROT_IS_ERROR (status)) {
		return status;
	}

	allowable_manifest->manifest_index = allowable_pfm_element_ptr->port_id;

	allowable_pfm_element_ptr->manifest.platform_id[
		allowable_pfm_element_ptr->manifest.platform_id_len] = '\0';
	allowable_manifest->platform_id =
		strdup ((char*) allowable_pfm_element_ptr->manifest.platform_id);
	if (allowable_manifest->platform_id == NULL) {
		return CFM_NO_MEMORY;
	}

	status = manifest_flash_get_child_elements_info (&cfm_flash->base_flash,
		cfm_flash->base_flash.hash, *element_entry_ptr, manifest_type, CFM_COMPONENT_DEVICE,
		CFM_ALLOWABLE_ID, NULL, &num_allowable_id, NULL);
	if (status != 0) {
		goto free_manifest;
	}

	allowable_manifest->check_count = num_allowable_id;
	allowable_manifest->check = platform_calloc (allowable_manifest->check_count,
		sizeof (struct cfm_allowable_id));
	if (allowable_manifest->check == NULL) {
		status = CFM_NO_MEMORY;
		goto free_manifest;
	}

	for (i_allowable_id = 0; i_allowable_id < num_allowable_id; ++i_allowable_id) {
		// Read Allowable ID element
		status = manifest_flash_read_element_data (&cfm_flash->base_flash,
			cfm_flash->base_flash.hash, CFM_ALLOWABLE_ID, *element_entry_ptr, manifest_type, 0,
			NULL, NULL, NULL, (uint8_t**) &allowable_id_element_ptr,
			sizeof (struct cfm_allowable_id_element));
		if (ROT_IS_ERROR (status)) {
			if (status == MANIFEST_CHILD_NOT_FOUND) {
				status = CFM_ENTRY_NOT_FOUND;
			}

			goto free_manifest;
		}

		if (status < (int) (sizeof (struct cfm_allowable_id_element))) {
			status = CFM_MALFORMED_ALLOWABLE_ID_ENTRY;

			goto free_manifest;
		}

		allowable_id_ptr = &allowable_manifest->check[i_allowable_id];
		allowable_id_ptr->check = (enum cfm_check) allowable_id_element_ptr->check.check;
		allowable_id_ptr->id_count = allowable_id_element_ptr->num_id;

		offset = sizeof (struct cfm_allowable_id_element);

		ids_len = allowable_id_ptr->id_count * sizeof (uint32_t);

		allowable_id_ptr->allowable_id = platform_malloc (ids_len);
		if (allowable_id_ptr->allowable_id == NULL) {
			status = CFM_NO_MEMORY;
			goto free_manifest;
		}

		// Read each ID
		status = manifest_flash_read_element_data (&cfm_flash->base_flash,
			cfm_flash->base_flash.hash, CFM_ALLOWABLE_ID, *element_entry_ptr, manifest_type, offset,
			element_entry_ptr, NULL, NULL, (uint8_t**) &allowable_id_ptr->allowable_id, ids_len);
		if (ROT_IS_ERROR (status)) {
			goto free_manifest;
		}

		if (status < (int) (ids_len)) {
			status = CFM_MALFORMED_ALLOWABLE_ID_ENTRY;

			goto free_manifest;
		}

		if (allowable_id_element_ptr->check.endianness == CFM_MULTIBYTE_BIG_ENDIAN) {
			for (uint8_t i_id = 0; i_id < allowable_id_ptr->id_count; i_id++) {
				*((uint32_t*) &allowable_id_ptr->allowable_id[i_id]) =
					SWAP_BYTES_UINT32 (allowable_id_ptr->allowable_id[i_id]);
			}
		}

		*element_entry_ptr = *element_entry_ptr + 1;
	}

	return 0;

free_manifest:
	cfm_flash_free_manifest (cfm, allowable_manifest);

	return status;
}