1 /** 2 * Functions for generating pseudo-random CPER ARM processor sections. 3 * 4 * Author: Lawrence.Tang@arm.com 5 **/ 6 7 #include <stdlib.h> 8 #include <string.h> 9 #include "../../edk/BaseTypes.h" 10 #include "../gen-utils.h" 11 #include "gen-section.h" 12 #define ARM_ERROR_INFO_SIZE 32 13 14 void* generate_arm_error_info(); 15 size_t generate_arm_context_info(void** location); 16 17 //Generates a single pseudo-random ARM processor section, saving the resulting address to the given 18 //location. Returns the size of the newly created section. 19 size_t generate_section_arm(void** location) 20 { 21 //Set up for generation of error/context structures. 22 UINT16 error_structure_num = rand() % 4 + 1; //Must be at least 1. 23 UINT16 context_structure_num = rand() % 3; 24 void* error_structures[error_structure_num]; 25 void* context_structures[context_structure_num]; 26 size_t context_structure_lengths[context_structure_num]; 27 28 //Generate the structures. 29 for (int i=0; i<error_structure_num; i++) 30 error_structures[i] = generate_arm_error_info(); 31 for (int i=0; i<context_structure_num; i++) 32 context_structure_lengths[i] = generate_arm_context_info(context_structures + i); 33 34 //Determine a random amount of vendor specific info. 35 int vendor_info_len = rand() % 16; 36 37 //Create the section as a whole. 38 size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE); 39 for (int i=0; i<context_structure_num; i++) 40 total_len += context_structure_lengths[i]; 41 total_len += vendor_info_len; 42 UINT8* section = generate_random_bytes(total_len); 43 44 //Set header information. 45 UINT16* info_nums = (UINT16*)(section + 4); 46 *info_nums = error_structure_num; 47 *(info_nums + 1) = context_structure_num; 48 UINT32* section_length = (UINT32*)(section + 8); 49 *section_length = total_len; 50 51 //Error affinity. 52 *(section + 12) = rand() % 4; 53 54 //Reserved zero bytes. 55 UINT64* validation = (UINT64*)section; 56 *validation &= 0b111; 57 UINT32* running_state = (UINT32*)(section + 32); 58 *running_state &= 0b1; 59 memset(section + 13, 0, 3); 60 61 //Copy in the sections/context structures, free resources. 62 UINT8* cur_pos = section + 40; 63 for (int i=0; i<error_structure_num; i++) 64 { 65 memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE); 66 free(error_structures[i]); 67 cur_pos += ARM_ERROR_INFO_SIZE; 68 } 69 for (int i=0; i<context_structure_num; i++) 70 { 71 memcpy(cur_pos, context_structures[i], context_structure_lengths[i]); 72 free(context_structures[i]); 73 cur_pos += context_structure_lengths[i]; 74 } 75 76 //Set return values and exit. 77 *location = section; 78 return total_len; 79 } 80 81 //Generates a single pseudo-random ARM error info structure. Must be later freed. 82 void* generate_arm_error_info() 83 { 84 UINT8* error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE); 85 86 //Version (zero for revision of table referenced), length. 87 *error_info = 0; 88 *(error_info + 1) = ARM_ERROR_INFO_SIZE; 89 90 //Type of error. 91 UINT8 error_type = rand() % 4; 92 *(error_info + 4) = error_type; 93 94 //Reserved bits for error information. 95 UINT16* validation = (UINT16*)(error_info + 2); 96 *validation &= 0x1F; 97 98 //Make sure reserved bits are zero according with the type. 99 UINT64* error_subinfo = (UINT64*)(error_info + 8); 100 switch (error_type) 101 { 102 //Cache/TLB 103 case 0: 104 case 1: 105 *error_subinfo &= 0xFFFFFFF; 106 break; 107 108 //Bus 109 case 2: 110 *error_subinfo &= 0xFFFFFFFFFFF; 111 break; 112 113 //Microarch/other. 114 default: 115 break; 116 } 117 118 return error_info; 119 } 120 121 //Generates a single pseudo-random ARM context info structure. Must be later freed. 122 size_t generate_arm_context_info(void** location) 123 { 124 //Initial length is 8 bytes. Add extra based on type. 125 UINT16 reg_type = rand() % 9; 126 UINT32 reg_size = 0; 127 128 //Set register size. 129 switch (reg_type) 130 { 131 //AARCH32 GPR, AARCH32 EL2 132 case 0: 133 case 2: 134 reg_size = 64; 135 break; 136 137 //AARCH32 EL1 138 case 1: 139 reg_size = 96; 140 break; 141 142 //AARCH32 EL3 143 case 3: 144 reg_size = 8; 145 break; 146 147 //AARCH64 GPR 148 case 4: 149 reg_size = 256; 150 break; 151 152 //AARCH64 EL1 153 case 5: 154 reg_size = 136; 155 break; 156 157 //AARCH64 EL2 158 case 6: 159 reg_size = 120; 160 break; 161 162 //AARCH64 EL3 163 case 7: 164 reg_size = 80; 165 break; 166 167 //Misc. single register. 168 case 8: 169 reg_size = 10; 170 break; 171 } 172 173 //Create context structure randomly. 174 int total_size = 8 + reg_size; 175 UINT16* context_info = (UINT16*)generate_random_bytes(total_size); 176 177 //Set header information. 178 *(context_info + 1) = reg_type; 179 *((UINT32*)(context_info + 2)) = reg_size; 180 181 //Set return values and exit. 182 *location = context_info; 183 return total_size; 184 }