1 /** 2 * Functions for generating psuedo-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-sections.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 psuedo-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 memset(section + 13, 0, 3); 56 57 //Copy in the sections/context structures, free resources. 58 UINT8* cur_pos = section + 40; 59 for (int i=0; i<error_structure_num; i++) 60 { 61 memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE); 62 free(error_structures[i]); 63 cur_pos += ARM_ERROR_INFO_SIZE; 64 } 65 for (int i=0; i<context_structure_num; i++) 66 { 67 memcpy(cur_pos, context_structures[i], context_structure_lengths[i]); 68 free(context_structures[i]); 69 cur_pos += context_structure_lengths[i]; 70 } 71 72 //Set return values and exit. 73 *location = section; 74 return total_len; 75 } 76 77 //Generates a single pseudo-random ARM error info structure. Must be later freed. 78 void* generate_arm_error_info() 79 { 80 UINT8* error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE); 81 82 //Version (zero for revision of table referenced), length. 83 *error_info = 0; 84 *(error_info + 1) = ARM_ERROR_INFO_SIZE; 85 86 //Type of error. 87 UINT8 error_type = rand() % 4; 88 *(error_info + 4) = error_type; 89 90 //Make sure reserved bits are zero according with the type. 91 UINT64* error_subinfo = (UINT64*)(error_info + 8); 92 switch (error_type) 93 { 94 //Cache/TLB 95 case 0: 96 case 1: 97 *error_subinfo &= 0xFFFFFFF; 98 break; 99 100 //Bus 101 case 2: 102 *error_subinfo &= 0xFFFFFFFFFFF; 103 break; 104 105 //Microarch/other. 106 default: 107 break; 108 } 109 110 return error_info; 111 } 112 113 //Generates a single pseudo-random ARM context info structure. Must be later freed. 114 size_t generate_arm_context_info(void** location) 115 { 116 //Initial length is 8 bytes. Add extra based on type. 117 UINT16 reg_type = rand() % 9; 118 UINT32 reg_size = 0; 119 120 //Set register size. 121 switch (reg_type) 122 { 123 //AARCH32 GPR, AARCH32 EL2 124 case 0: 125 case 2: 126 reg_size = 64; 127 break; 128 129 //AARCH32 EL1 130 case 1: 131 reg_size = 96; 132 break; 133 134 //AARCH32 EL3 135 case 3: 136 reg_size = 8; 137 break; 138 139 //AARCH64 GPR 140 case 4: 141 reg_size = 256; 142 break; 143 144 //AARCH64 EL1 145 case 5: 146 reg_size = 136; 147 break; 148 149 //AARCH64 EL2 150 case 6: 151 reg_size = 120; 152 break; 153 154 //AARCH64 EL3 155 case 7: 156 reg_size = 80; 157 break; 158 159 //Misc. single register. 160 case 8: 161 reg_size = 10; 162 break; 163 } 164 165 //Create context structure randomly. 166 int total_size = 8 + reg_size; 167 UINT16* context_info = (UINT16*)generate_random_bytes(total_size); 168 169 //Set header information. 170 *(context_info + 1) = reg_type; 171 *((UINT32*)(context_info + 2)) = reg_size; 172 173 //Set return values and exit. 174 *location = context_info; 175 return total_size; 176 }