1 /**
2  * Functions for generating pseudo-random CXL protocol error sections.
3  *
4  * Author: Lawrence.Tang@arm.com
5  **/
6 
7 #include <stdlib.h>
8 #include "../../edk/BaseTypes.h"
9 #include "../gen-utils.h"
10 #include "gen-section.h"
11 
12 //Generates a single pseudo-random CXL protocol error section, saving the resulting address to the given
13 //location. Returns the size of the newly created section.
14 size_t generate_section_cxl_protocol(void** location)
15 {
16     //Create a random length for the CXL DVSEC and CXL error log.
17     //The logs attached here do not necessarily conform to the specification, and are simply random.
18     int dvsec_len = rand() % 64;
19     int error_log_len = rand() % 64;
20 
21     //Create random bytes.
22     int size = 116 + dvsec_len + error_log_len;
23     UINT8* bytes = generate_random_bytes(size);
24 
25     //Set CXL agent type.
26     int cxl_agent_type = rand() % 2;
27     *(bytes + 8) = cxl_agent_type;
28 
29     //Set reserved areas to zero.
30     UINT64* validation = (UINT64*)bytes;
31     *validation &= 0b111111; //Validation bits 6-63.
32     for (int i=0; i<7; i++)
33         *(bytes + 9 + i) = 0; //Reserved bytes 9-15.
34 
35     //We only reserve bytes if it's a CXL 1.1 device, and not a host downstream port.
36     if (cxl_agent_type == 0)
37     {
38         for (int i=0; i<3; i++)
39             *(bytes + 21 + i) = 0; //CXL agent address bytes 5-7.
40     }
41 
42     *(bytes + 34) &= ~0b111; //Device ID byte 10 bits 0-2.
43     UINT32* reserved = (UINT32*)(bytes + 36);
44     *reserved = 0; //Device ID bytes 12-15.
45     reserved = (UINT32*)(bytes + 112);
46     *reserved = 0; //Reserved bytes 112-115.
47 
48     //If the device is a host downstream port, serial/capability structure is invalid.
49     if (cxl_agent_type != 0)
50     {
51         for (int i=0; i<68; i++)
52             *(bytes + 40 + i) = 0; //Device serial & capability structure.
53     }
54 
55     //Set expected values.
56     UINT16* dvsec_length_field = (UINT16*)(bytes + 108);
57     UINT16* error_log_len_field = (UINT16*)(bytes + 110);
58     *dvsec_length_field = dvsec_len;
59     *error_log_len_field = error_log_len;
60 
61     //Set return values, exit.
62     *location = bytes;
63     return size;
64 }