1de9707f9SLawrence Tang /**
2efe17e2cSLawrence Tang  * Functions for generating pseudo-random CPER PCI component error sections.
3de9707f9SLawrence Tang  *
4de9707f9SLawrence Tang  * Author: Lawrence.Tang@arm.com
5de9707f9SLawrence Tang  **/
6de9707f9SLawrence Tang 
7de9707f9SLawrence Tang #include <stdlib.h>
8de9707f9SLawrence Tang #include "../../edk/BaseTypes.h"
9de9707f9SLawrence Tang #include "../gen-utils.h"
108f977457SLawrence Tang #include "gen-section.h"
11de9707f9SLawrence Tang 
12efe17e2cSLawrence Tang //Generates a single pseudo-random PCI component error section, saving the resulting address to the given
13de9707f9SLawrence Tang //location. Returns the size of the newly created section.
generate_section_pci_dev(void ** location)14de9707f9SLawrence Tang size_t generate_section_pci_dev(void **location)
15de9707f9SLawrence Tang {
16de9707f9SLawrence Tang 	//Generate how many register pairs will be attached to this section.
17de9707f9SLawrence Tang 	UINT32 num_memory_pairs = rand() % 4;
18de9707f9SLawrence Tang 	UINT32 num_io_pairs = rand() % 4;
19de9707f9SLawrence Tang 	UINT32 num_registers = num_memory_pairs + num_io_pairs;
20de9707f9SLawrence Tang 
21de9707f9SLawrence Tang 	//Create random bytes.
22de9707f9SLawrence Tang 	int size = 40 + (num_registers * 16);
23de9707f9SLawrence Tang 	UINT8 *bytes = generate_random_bytes(size);
24de9707f9SLawrence Tang 
25de9707f9SLawrence Tang 	//Set reserved areas to zero.
26de9707f9SLawrence Tang 	UINT64 *validation = (UINT64 *)bytes;
27*f8fc7052SJohn Chung 	*validation &= 0x1F;	       //Validation 5-63
28*f8fc7052SJohn Chung 	for (int i = 0; i < 5; i++) {
29de9707f9SLawrence Tang 		*(bytes + 27 + i) = 0; //Bytes 11-15 of ID info.
30*f8fc7052SJohn Chung 	}
31d34f2b11SLawrence Tang 
32d34f2b11SLawrence Tang 	//Set expected values.
33d34f2b11SLawrence Tang 	UINT32 *memory_number_field = (UINT32 *)(bytes + 32);
34d34f2b11SLawrence Tang 	UINT32 *io_number_field = (UINT32 *)(bytes + 36);
35d34f2b11SLawrence Tang 	*memory_number_field = num_memory_pairs;
36d34f2b11SLawrence Tang 	*io_number_field = num_io_pairs;
37de9707f9SLawrence Tang 
38de9707f9SLawrence Tang 	//Fix error status.
39de9707f9SLawrence Tang 	create_valid_error_section(bytes + 8);
40de9707f9SLawrence Tang 
41de9707f9SLawrence Tang 	//Set return values, exit.
42de9707f9SLawrence Tang 	*location = bytes;
43de9707f9SLawrence Tang 	return size;
44de9707f9SLawrence Tang }
45