├── CMakeLists.txt ├── bios.h └── fd44cpr.c /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(fd44cpr) 2 | SET(FD44CPR_SOURCES fd44cpr.c) 3 | SET(FD44CPR_HEADERS bios.h) 4 | ADD_EXECUTABLE(fd44cpr ${FD44CPR_SOURCES} ${FD44CPR_HEADERS}) -------------------------------------------------------------------------------- /bios.h: -------------------------------------------------------------------------------- 1 | #ifndef BIOS_H 2 | #define BIOS_H 3 | 4 | #include 5 | 6 | /* AMI Aptio extended capsule header */ 7 | typedef struct _APTIO_CAPSULE_HEADER { 8 | uint8_t CapsuleGuid[16]; 9 | uint32_t HeaderSize; 10 | uint32_t Flags; 11 | uint32_t CapsuleImageSize; 12 | uint16_t RomImageOffset; /* offset in bytes from the beginning of the capsule header to the start of 13 | the capsule volume */ 14 | } APTIO_CAPSULE_HEADER; 15 | 16 | const uint8_t APTIO_CAPSULE_GUID[] = { 0x8B, 0xA6, 0x3C, 0x4A, 0x23, 0x77, 0xFB, 0x48, 0x80, 0x3D, 0x57, 17 | 0x8C, 0xC1, 0xFE, 0xC4, 0x4D}; 18 | 19 | /* BOOTEFI */ 20 | const uint8_t BOOTEFI_HEADER[] = {'$','B','O','O','T','E','F','I','$'}; 21 | #define BOOTEFI_MOTHERBOARD_NAME_OFFSET 14 22 | #define BOOTEFI_MOTHERBOARD_NAME_LENGTH 60 23 | 24 | /* GbE */ 25 | const uint8_t GBE_HEADER[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x10}; 26 | #define GBE_MAC_OFFSET (-16) 27 | #define GBE_MAC_LENGTH 6 28 | static const uint8_t GBE_MAC_STUB[] = {0x88, 0x88, 0x88, 0x88, 0x87, 0x88}; 29 | 30 | /* SLIC */ 31 | const uint8_t EFI_VOLUME_HEADER[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xE5, 0x8C, 0x8C, 0x3D, 0x8A, 33 | 0x1C, 0x4F, 0x99, 0x35, 0x89, 0x61, 0x85, 0xC3, 0x2D, 0xD3 }; 34 | const uint8_t DUMMY_MSOA_MODULE_HEADER[] = {0x70, 0x8C, 0x49, 0xDE, 0xDA, 0x1E, 0x6B, 0x46, 0xAB, 0xCF, 0xDD, 0x3A, 35 | 0xBC, 0x3D, 0x24, 0xB4}; 36 | const uint8_t MSOA_MODULE_HEADER[] = {0xB9, 0x2A, 0x90, 0xA1, 0x94, 0x53, 0xF2, 0x45, 0x85, 0x7A, 0x12, 37 | 0x82, 0x42, 0x13, 0xEE, 0xFB}; 38 | const uint8_t SLIC_PUBKEY_HEADER[] = {0xFB, 0xEB, 0xFF, 0xCD, 0xDC, 0x17, 0xBC, 0x46, 0x9B, 0x75, 0x59, 39 | 0xB8, 0x61, 0x92, 0x09, 0x13}; 40 | const uint8_t SLIC_PUBKEY_PART1[] = {0x78, 0x02, 0x02, 0x40, 0x6E, 0x01, 0x00, 0xF8, 0x56, 0x01, 0x00, 41 | 0x19}; 42 | #define SLIC_PUBKEY_LENGTH 366 43 | const uint8_t SLIC_MARKER_HEADER[] = {0x58, 0x44, 0x63, 0x15, 0xA4, 0xE8, 0x6D, 0x43, 0xAC, 0x2F, 0x57, 44 | 0xE3, 0x3E, 0x53, 0x4C, 0xCF}; 45 | const uint8_t SLIC_MARKER_PART1[] = {0x75, 0x4E, 0x02, 0x40, 0x38, 0x00, 0x00, 0xF8, 0x20, 0x00, 0x00, 46 | 0x19}; 47 | #define SLIC_MARKER_LENGTH 56 48 | #define MODULE_DATA_CHECKSUM_OFFSET 17 49 | #define MODULE_DATA_CHECKSUM_START 24 50 | 51 | /* FD44 */ 52 | const uint8_t FD44_MODULE_HEADER[] = {0x0B, 0x82, 0x44, 0xFD, 0xAB, 0xF1, 0xC0, 0x41, 0xAE, 0x4E, 0x0C, 53 | 0x55, 0x55, 0x6E, 0xB9, 0xBD}; 54 | #define FD44_MODULE_HEADER_BSA_OFFSET 28 55 | const uint8_t FD44_MODULE_HEADER_BSA[] = {'B', 'S', 'A', '_'}; 56 | #define FD44_MODULE_HEADER_LENGTH 36 57 | #define FD44_MODULE_SIZE_OFFSET 20 58 | 59 | /* ASUSBKP */ 60 | const uint8_t ASUSBKP_HEADER[] = {'A','S','U','S','B','K','P','$'}; 61 | const uint8_t ASUSBKP_PUBKEY_HEADER[] = {'S','2','L','P','R', 0x01, 0x00, 0x00}; 62 | const uint8_t ASUSBKP_MARKER_HEADER[] = {'K','E','Y','S', 0x1C, 0x00, 0x00, 0x00}; 63 | 64 | #endif /* BIOS_H */ 65 | -------------------------------------------------------------------------------- /fd44cpr.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "bios.h" 8 | 9 | /* Return codes */ 10 | #define ERR_OK 0 11 | #define ERR_EMPTY_FD44_MODULE 1 12 | #define ERR_ARGS 2 13 | #define ERR_INPUT_FILE 3 14 | #define ERR_OUTPUT_FILE 4 15 | #define ERR_MEMORY 5 16 | #define ERR_NO_FD44_MODULE 6 17 | #define ERR_DIFFERENT_BOARD 7 18 | #define ERR_NO_GBE 8 19 | #define ERR_NO_SLIC 9 20 | 21 | /* Implementation of GNU memmem function using Boyer-Moore-Horspool algorithm 22 | * Returns pointer to the beginning of found pattern of NULL if not found */ 23 | uint8_t* find_pattern(uint8_t* begin, uint8_t* end, const uint8_t* pattern, uint32_t plen) 24 | { 25 | uint32_t scan = 0; 26 | uint32_t bad_char_skip[256]; 27 | uint32_t last; 28 | uint32_t slen; 29 | 30 | if (plen == 0 || !begin || !pattern || !end || end <= begin) 31 | return NULL; 32 | 33 | slen = end - begin; 34 | 35 | for (scan = 0; scan <= 255; scan++) 36 | bad_char_skip[scan] = plen; 37 | 38 | last = plen - 1; 39 | 40 | for (scan = 0; scan < last; scan++) 41 | bad_char_skip[pattern[scan]] = last - scan; 42 | 43 | while (slen >= plen) 44 | { 45 | for (scan = last; begin[scan] == pattern[scan]; scan--) 46 | if (scan == 0) 47 | return begin; 48 | 49 | slen -= bad_char_skip[begin[last]]; 50 | begin += bad_char_skip[begin[last]]; 51 | } 52 | 53 | return NULL; 54 | } 55 | 56 | /* Finds free space between begin and end to insert new module. 57 | * Returns aligned pointer to empty space or NULL if it can't be found. */ 58 | uint8_t* find_free_space(uint8_t* begin, uint8_t* end, uint32_t space_length) 59 | { 60 | uint8_t* current; 61 | uint32_t size; 62 | uint32_t allignment; 63 | 64 | current = end; 65 | 66 | // Skipping 0xFF bytes from end 67 | while (*current-- == 0xFF); 68 | current++; 69 | 70 | // Error if begin passed, all bytes are 0xFF, which is incorrect 71 | if (current < begin) 72 | return NULL; 73 | 74 | // Alligning pounter to 8 75 | size = current - begin; 76 | if (size % 8) 77 | allignment = 8 - size % 8; 78 | else 79 | allignment = 0; 80 | 81 | if (size + allignment < space_length) 82 | return NULL; 83 | 84 | return current + allignment; 85 | } 86 | 87 | /* Calculates 2's complement 8-bit checksum of data from data[0] to data[length-1] and stores it to *checksum 88 | * Returns 1 on success and 0 on failure */ 89 | int calculate_checksum(uint8_t* data, uint32_t length, uint8_t* checksum) 90 | { 91 | uint8_t counter; 92 | 93 | if (!data || !length || !checksum) 94 | return 0; 95 | counter = 0; 96 | while (length--) 97 | counter += data[length]; 98 | *checksum = ~counter + 1; 99 | return 1; 100 | } 101 | 102 | /* Converts SIZE field of MODULE_HEADER (3 bytes in reversed order) to uint32_t. 103 | * Returns 1 on success or 0 on error */ 104 | int size2int(uint8_t* module_size, uint32_t* size) 105 | { 106 | if (!module_size || !size) 107 | return 0; 108 | 109 | *size = (module_size[2] << 16) + 110 | (module_size[1] << 8) + 111 | module_size[0]; 112 | return 1; 113 | } 114 | 115 | /* Entry point */ 116 | int main(int argc, char* argv[]) 117 | { 118 | FILE* file; /* file pointer to work with input and output files */ 119 | char* inputfile; /* path to input file*/ 120 | char* outputfile; /* path to output file */ 121 | uint8_t* buffer; /* buffer to read input and output file */ 122 | uint8_t* end; /* pointer to the end of buffer */ 123 | uint32_t filesize; /* size of opened file */ 124 | uint32_t read; /* read bytes counter */ 125 | uint8_t* bootefi; /* BOOTEFI header */ 126 | uint8_t* capsuleHeader; /* Capsule header */ 127 | int8_t hasCapsuleHeader; /* flag that output file has capsule header */ 128 | uint16_t headerSize; /* size of capsule header */ 129 | int8_t hasGbe; /* flag that input file has GbE region */ 130 | int8_t hasSLIC; /* flag that input file has SLIC pubkey and marker */ 131 | int8_t isModuleEmpty = 0; /* flag that FD44 module is empty in input file */ 132 | int8_t defaultOptions; /* flag that program is ran with default options */ 133 | int8_t copyModule; /* flag that FD44 module copying is requested */ 134 | int8_t copyGbe; /* flag that GbE MAC copying is requested */ 135 | int8_t copySLIC; /* flag that SLIC copying is requested */ 136 | int8_t skipMotherboardNameCheck; /* flag that motherboard name in output file doesn't need to be checked */ 137 | uint8_t motherboardName[BOOTEFI_MOTHERBOARD_NAME_LENGTH]; /* motherboard name storage */ 138 | uint8_t gbeMac[GBE_MAC_LENGTH]; /* GbE MAC storage */ 139 | uint8_t slicPubkey[SLIC_PUBKEY_LENGTH /* SLIC----*/ 140 | - sizeof(SLIC_PUBKEY_HEADER) /* pubkey--*/ 141 | - sizeof(SLIC_PUBKEY_PART1)]; /* storage */ 142 | uint8_t slicMarker[SLIC_MARKER_LENGTH /* SLIC----*/ 143 | - sizeof(SLIC_MARKER_HEADER) /* marker--*/ 144 | - sizeof(SLIC_MARKER_PART1)]; /* storage */ 145 | uint8_t* fd44Module = 0; /* FD44 module storage, will be allocated later */ 146 | uint32_t fd44ModuleSize; /* size of FD44 module */ 147 | 148 | 149 | if (argc < 3 || (argv[1][0] == '-' && argc < 4)) 150 | { 151 | printf("FD44Copier v0.7.0\nThis program copies GbE MAC address, FD44 module data,\n"\ 152 | "SLIC pubkey and marker from one BIOS image file to another.\n\n" 153 | "Usage: FD44Copier <-OPTIONS> INFILE OUTFILE\n\n" 154 | "Options: m - copy module data.\n" 155 | " g - copy GbE MAC address.\n" 156 | " s - copy SLIC pubkey and marker.\n" 157 | " n - do not check that both BIOS files are for same motherboard.\n" 158 | " - copy all available data and check for same motherboard in both BIOS files.\n\n"); 159 | return ERR_ARGS; 160 | } 161 | 162 | /* Checking for options presence and setting options */ 163 | if (argv[1][0] == '-') 164 | { 165 | /* Setting supplied options */ 166 | copyModule = (strchr(argv[1], 'm') != NULL); 167 | copyGbe = (strchr(argv[1], 'g') != NULL); 168 | copySLIC = (strchr(argv[1], 's') != NULL); 169 | skipMotherboardNameCheck = 170 | (strchr(argv[1], 'n') != NULL); 171 | defaultOptions = 0; 172 | inputfile = argv[2]; 173 | outputfile = argv[3]; 174 | } 175 | else 176 | { 177 | /* Setting default options */ 178 | defaultOptions = 1; 179 | copyModule = 1; 180 | copyGbe = 1; 181 | copySLIC = 1; 182 | skipMotherboardNameCheck = 0; 183 | inputfile = argv[1]; 184 | outputfile = argv[2]; 185 | } 186 | 187 | /* Opening input file */ 188 | file = fopen(inputfile, "rb"); 189 | if (!file) 190 | { 191 | perror("Can't open input file.\n"); 192 | return ERR_INPUT_FILE; 193 | } 194 | 195 | /* Determining file size */ 196 | fseek(file, 0, SEEK_END); 197 | filesize = ftell(file); 198 | fseek(file, 0, SEEK_SET); 199 | 200 | /* Allocating memory for buffer */ 201 | buffer = (uint8_t*)malloc(filesize); 202 | if (!buffer) 203 | { 204 | printf("Can't allocate memory for input file.\n"); 205 | return ERR_MEMORY; 206 | } 207 | end = buffer + filesize; 208 | 209 | /* Reading whole file to buffer */ 210 | read = fread((void*)buffer, sizeof(char), filesize, file); 211 | if (read != filesize) 212 | { 213 | perror("Can't read input file.\n"); 214 | return ERR_INPUT_FILE; 215 | } 216 | 217 | /* Searching for bootefi signature */ 218 | bootefi = find_pattern(buffer, end, BOOTEFI_HEADER, sizeof(BOOTEFI_HEADER)); 219 | if (!bootefi) 220 | { 221 | printf("ASUS BIOS file signature not found in input file.\n"); 222 | return ERR_INPUT_FILE; 223 | } 224 | 225 | /* Storing motherboard name */ 226 | if (!skipMotherboardNameCheck && !memcpy(motherboardName, bootefi + BOOTEFI_MOTHERBOARD_NAME_OFFSET, sizeof(motherboardName))) 227 | { 228 | printf("Memcpy failed.\nMotherboard name can't be stored.\n"); 229 | return ERR_MEMORY; 230 | } 231 | 232 | /* Searching for GbE and storing MAC address if it is found */ 233 | if (copyGbe) 234 | { 235 | uint8_t* gbe = find_pattern(buffer, end, GBE_HEADER, sizeof(GBE_HEADER)); 236 | hasGbe = 0; 237 | if (gbe) 238 | { 239 | hasGbe = 1; 240 | /* Checking if first GbE is a stub */ 241 | if (!memcmp(gbe + GBE_MAC_OFFSET, GBE_MAC_STUB, sizeof(GBE_MAC_STUB))) 242 | { 243 | uint8_t* gbe2; 244 | gbe2 = find_pattern(gbe + sizeof(GBE_HEADER), end, GBE_HEADER, sizeof(GBE_HEADER)); 245 | /* Checking if second GbE is not a stub */ 246 | if(gbe2 && memcmp(gbe2 + GBE_MAC_OFFSET, GBE_MAC_STUB, sizeof(GBE_MAC_STUB))) 247 | gbe = gbe2; 248 | } 249 | 250 | if (!memcpy(gbeMac, gbe + GBE_MAC_OFFSET, GBE_MAC_LENGTH)) 251 | { 252 | printf("Memcpy failed.\nGbE MAC can't be copied.\n"); 253 | return ERR_MEMORY; 254 | } 255 | } 256 | 257 | if (!defaultOptions && !hasGbe) 258 | { 259 | printf("GbE region not found in input file, but required by -g option.\n"); 260 | return ERR_NO_GBE; 261 | } 262 | } 263 | 264 | /* Searching for SLIC pubkey and marker and storing them if found*/ 265 | if (copySLIC) 266 | { 267 | uint8_t* slic_pubkey = find_pattern(buffer, end, SLIC_PUBKEY_HEADER, sizeof(SLIC_PUBKEY_HEADER)); 268 | uint8_t* slic_marker = find_pattern(buffer, end, SLIC_MARKER_HEADER, sizeof(SLIC_MARKER_HEADER)); 269 | hasSLIC = 0; 270 | if (slic_pubkey && slic_marker) 271 | { 272 | slic_pubkey += sizeof(SLIC_PUBKEY_HEADER) + sizeof(SLIC_PUBKEY_PART1); 273 | slic_marker += sizeof(SLIC_MARKER_HEADER) + sizeof(SLIC_MARKER_PART1); 274 | if (!memcpy(slicPubkey, slic_pubkey, sizeof(slicPubkey))) 275 | { 276 | printf("Memcpy failed.\nSLIC pubkey can't be copied.\n"); 277 | return ERR_MEMORY; 278 | } 279 | if (!memcpy(slicMarker, slic_marker, sizeof(slicMarker))) 280 | { 281 | printf("Memcpy failed.\nSLIC marker can't be copied.\n"); 282 | return ERR_MEMORY; 283 | } 284 | hasSLIC = 1; 285 | } 286 | else /* If SLIC headers not found, searching for SLIC pubkey and marker in ASUSBKP module */ 287 | { 288 | uint8_t* asusbkp = find_pattern(buffer, end, ASUSBKP_HEADER, sizeof(ASUSBKP_HEADER)); 289 | if (asusbkp) 290 | { 291 | slic_pubkey = find_pattern(asusbkp, end, ASUSBKP_PUBKEY_HEADER, sizeof(ASUSBKP_PUBKEY_HEADER)); 292 | slic_marker = find_pattern(asusbkp, end, ASUSBKP_MARKER_HEADER, sizeof(ASUSBKP_MARKER_HEADER)); 293 | if (slic_pubkey && slic_marker) 294 | { 295 | slic_pubkey += sizeof(ASUSBKP_PUBKEY_HEADER); 296 | slic_marker += sizeof(ASUSBKP_MARKER_HEADER); 297 | if (!memcpy(slicPubkey, slic_pubkey, sizeof(slicPubkey))) 298 | { 299 | printf("Memcpy failed\nSLIC pubkey can't be copied.\n"); 300 | return ERR_MEMORY; 301 | } 302 | if (!memcpy(slicMarker, slic_marker, sizeof(slicMarker))) 303 | { 304 | printf("Memcpy failed\nSLIC marker can't be copied.\n"); 305 | return ERR_MEMORY; 306 | } 307 | hasSLIC = 1; 308 | } 309 | } 310 | } 311 | 312 | if (!defaultOptions && !hasSLIC) 313 | { 314 | printf("SLIC pubkey and marker not found in input file, but required by -s option.\n"); 315 | return ERR_NO_SLIC; 316 | } 317 | } 318 | 319 | /* Searching for FD44 module header */ 320 | if (copyModule) 321 | { 322 | uint8_t* module = 0; 323 | uint8_t* fd44 = find_pattern(buffer, end, FD44_MODULE_HEADER, sizeof(FD44_MODULE_HEADER)); 324 | isModuleEmpty = 1; 325 | if (!fd44) 326 | { 327 | printf("FD44 module not found in input file.\n"); 328 | return ERR_NO_FD44_MODULE; 329 | } 330 | 331 | /* Looking for non-empty module */ 332 | while(isModuleEmpty && fd44) 333 | { 334 | 335 | /* Getting module size */ 336 | size2int(fd44 + FD44_MODULE_SIZE_OFFSET, &fd44ModuleSize); 337 | 338 | /* Checking that module has BSA signature */ 339 | if (!memcmp(fd44 + FD44_MODULE_HEADER_BSA_OFFSET, FD44_MODULE_HEADER_BSA, sizeof(FD44_MODULE_HEADER_BSA))) 340 | { 341 | uint32_t pos; 342 | /* Looking for non-FF byte starting from the beginning of data */ 343 | module = fd44 + FD44_MODULE_HEADER_LENGTH; 344 | for (pos = 0; pos < fd44ModuleSize - FD44_MODULE_HEADER_LENGTH; pos++) 345 | { 346 | /* If found - this module is not empty */ 347 | if (module[pos] != 0xFF) 348 | { 349 | isModuleEmpty = 0; 350 | break; 351 | } 352 | } 353 | } 354 | 355 | /* Finding next module */ 356 | fd44 = find_pattern(fd44 + FD44_MODULE_HEADER_LENGTH, end, FD44_MODULE_HEADER, sizeof(FD44_MODULE_HEADER)); 357 | } 358 | 359 | /* Checking if all modules are empty */ 360 | if (isModuleEmpty) 361 | { 362 | printf("FD44 modules are empty in input file. Data restoration required.\nUse FD44Editor to restore your data.\n"); 363 | } 364 | else /* Storing module contents */ 365 | { 366 | /* No need to store module header */ 367 | fd44ModuleSize -= FD44_MODULE_HEADER_LENGTH; 368 | 369 | /* No need to store FF bytes */ 370 | while (module[--fd44ModuleSize] == 0xFF) 371 | ; 372 | fd44ModuleSize++; 373 | 374 | /* Allocating memory for module storage */ 375 | fd44Module = (uint8_t*)malloc(fd44ModuleSize); 376 | if (!fd44Module) 377 | { 378 | printf("Can't allocate memory for FD44 module.\nFD44 module can't be copied.\n"); 379 | return ERR_MEMORY; 380 | } 381 | 382 | /* Storing module contents */ 383 | if (!memcpy(fd44Module, module, fd44ModuleSize)) 384 | { 385 | printf("Memcpy failed.\nFD44 module can't be copied.\n"); 386 | return ERR_MEMORY; 387 | } 388 | } 389 | } 390 | 391 | /* Closing input file */ 392 | free(buffer); 393 | fclose(file); 394 | 395 | /* Opening output file */ 396 | file = fopen(outputfile, "r+b"); 397 | if (!file) 398 | { 399 | perror("Can't open output file.\n"); 400 | return ERR_OUTPUT_FILE; 401 | } 402 | 403 | /* Determining file size */ 404 | fseek(file, 0, SEEK_END); 405 | filesize = ftell(file); 406 | fseek(file, 0, SEEK_SET); 407 | 408 | /* Allocating memory for buffer */ 409 | buffer = (uint8_t*)malloc(filesize); 410 | if (!buffer) 411 | { 412 | printf("Can't allocate memory for output file.\n"); 413 | return ERR_MEMORY; 414 | } 415 | 416 | /* Reading whole file to buffer */ 417 | read = fread((void*)buffer, sizeof(char), filesize, file); 418 | if (read != filesize) 419 | { 420 | perror("Can't read output file.\n"); 421 | return ERR_OUTPUT_FILE; 422 | } 423 | 424 | /* Searching for capsule file signature, if found - remove capsule file header */ 425 | hasCapsuleHeader = 0; 426 | capsuleHeader = find_pattern(buffer, buffer + sizeof(APTIO_CAPSULE_GUID), APTIO_CAPSULE_GUID, sizeof(APTIO_CAPSULE_GUID)); 427 | if (capsuleHeader) 428 | { 429 | APTIO_CAPSULE_HEADER *header = (APTIO_CAPSULE_HEADER*)buffer; 430 | hasCapsuleHeader = 1; 431 | headerSize = header->RomImageOffset; 432 | buffer += headerSize; 433 | filesize -= headerSize; 434 | } 435 | end = buffer + filesize; 436 | 437 | /* Searching for bootefi signature */ 438 | bootefi = find_pattern(buffer, end, BOOTEFI_HEADER, sizeof(BOOTEFI_HEADER)); 439 | if (!bootefi) 440 | { 441 | printf("ASUS BIOS file signature not found in output file.\n"); 442 | return ERR_OUTPUT_FILE; 443 | } 444 | 445 | /* Checking motherboard name */ 446 | if (!skipMotherboardNameCheck && memcmp(motherboardName, bootefi + BOOTEFI_MOTHERBOARD_NAME_OFFSET, strlen((const char*)motherboardName))) 447 | { 448 | printf("Motherboard name in output file differs from motherboard name in input file.\n"); 449 | return ERR_DIFFERENT_BOARD; 450 | } 451 | 452 | /* If input file had GbE block, searching for it in output file and replacing it */ 453 | if (copyGbe && hasGbe) 454 | { 455 | /* First GbE block */ 456 | uint8_t* gbe = find_pattern(buffer, end, GBE_HEADER, sizeof(GBE_HEADER)); 457 | if (!gbe) 458 | { 459 | printf("GbE region not found in output file.\n"); 460 | return ERR_NO_GBE; 461 | } 462 | if (!memcpy(gbe + GBE_MAC_OFFSET, gbeMac, sizeof(gbeMac))) 463 | { 464 | printf("Memcpy failed.\nGbE MAC can't be copied.\n"); 465 | return ERR_MEMORY; 466 | } 467 | 468 | /* Second GbE block */ 469 | gbe = find_pattern(gbe + sizeof(GBE_HEADER), end, GBE_HEADER, sizeof(GBE_HEADER)); 470 | 471 | if (gbe && !memcpy(gbe + GBE_MAC_OFFSET, gbeMac, sizeof(gbeMac))) 472 | { 473 | printf("Memcpy failed.\nGbE MAC can't be copied.\n"); 474 | return ERR_MEMORY; 475 | } 476 | 477 | printf("GbE MAC address copied.\n"); 478 | } 479 | 480 | /* Searching for EFI volume containing MSOA module and add SLIC pubkey and marker modules if found */ 481 | if (copySLIC && hasSLIC) 482 | { 483 | uint8_t* efi_volume_begin; 484 | uint8_t* efi_volume_end; 485 | uint8_t* msoa_module; 486 | uint8_t* pubkey_module; 487 | uint8_t* marker_module; 488 | uint8_t data_checksum; 489 | 490 | do 491 | { 492 | /* Searching for existing SLIC modules */ 493 | pubkey_module = find_pattern(buffer, end, SLIC_PUBKEY_HEADER, sizeof(SLIC_PUBKEY_HEADER)); 494 | marker_module = find_pattern(buffer, end, SLIC_MARKER_HEADER, sizeof(SLIC_MARKER_HEADER)); 495 | if (pubkey_module || marker_module) 496 | { 497 | printf("SLIC pubkey or marker found in output file.\nSLIC table copy is not needed.\n"); 498 | break; 499 | } 500 | 501 | /* Searching for second EFI Volume to instert SLIC */ 502 | efi_volume_begin = find_pattern(buffer, end, EFI_VOLUME_HEADER, sizeof(EFI_VOLUME_HEADER)); 503 | if (!efi_volume_begin) 504 | { 505 | printf("First EFI volume not found in output file. The file is possibly corrupted. SLIC table can't be inserted."); 506 | break; 507 | } 508 | efi_volume_end = efi_volume_begin + *(uint32_t*)(efi_volume_begin + sizeof(EFI_VOLUME_HEADER)); 509 | efi_volume_begin = find_pattern(efi_volume_end, end, EFI_VOLUME_HEADER, sizeof(EFI_VOLUME_HEADER)); 510 | if (!efi_volume_begin) 511 | { 512 | printf("Second EFI volume not found in output file. The file is possibly corrupted. SLIC table can't be inserted."); 513 | break; 514 | } 515 | efi_volume_end = efi_volume_begin + *(uint32_t*)(efi_volume_begin + sizeof(EFI_VOLUME_HEADER)) - 16; 516 | 517 | /* Searching for DummyMSOA or MSOA module */ 518 | msoa_module = find_pattern(efi_volume_begin, efi_volume_end, DUMMY_MSOA_MODULE_HEADER, sizeof(DUMMY_MSOA_MODULE_HEADER)); 519 | if (!msoa_module) 520 | { 521 | msoa_module = find_pattern(efi_volume_begin, efi_volume_end, MSOA_MODULE_HEADER, sizeof(MSOA_MODULE_HEADER)); 522 | if (!msoa_module) 523 | { 524 | printf("DummyMSOA and MSOA module not found in first EFI volume.\nSLIC table can't be copied.\n"); 525 | break; 526 | } 527 | } 528 | 529 | /* Searching for free space at the end of EFI volume with MSOA module to insert pubkey module */ 530 | pubkey_module = find_free_space(efi_volume_begin, efi_volume_end, SLIC_PUBKEY_LENGTH + SLIC_MARKER_LENGTH); 531 | if (!pubkey_module) 532 | { 533 | printf("Not enough free space to insert SLIC modules.\nSLIC table can't be copied.\n"); 534 | break; 535 | } 536 | 537 | /* Writing pubkey header */ 538 | if (!memcpy(pubkey_module, SLIC_PUBKEY_HEADER, sizeof(SLIC_PUBKEY_HEADER))) 539 | { 540 | printf("Memcpy failed.\nSLIC table can't be copied.\n"); 541 | return ERR_MEMORY; 542 | } 543 | /* Writing pubkey first part */ 544 | if (!memcpy(pubkey_module + sizeof(SLIC_PUBKEY_HEADER), SLIC_PUBKEY_PART1, sizeof(SLIC_PUBKEY_PART1))) 545 | { 546 | printf("Memcpy failed.\nSLIC table can't be copied.\n"); 547 | return ERR_MEMORY; 548 | } 549 | /* Writing pubkey */ 550 | if (!memcpy(pubkey_module + sizeof(SLIC_PUBKEY_HEADER) + sizeof(SLIC_PUBKEY_PART1), slicPubkey, sizeof(slicPubkey))) 551 | { 552 | printf("Memcpy failed.\nSLIC table can't be copied.\n"); 553 | return ERR_MEMORY; 554 | } 555 | /* Calculating pubkey module data checksum */ 556 | if (!calculate_checksum(pubkey_module + MODULE_DATA_CHECKSUM_START, SLIC_PUBKEY_LENGTH - MODULE_DATA_CHECKSUM_START, &data_checksum)) 557 | { 558 | printf("Pubkey module checksum calculation failed.\nSLIC table can't be copied.\n"); 559 | return ERR_MEMORY; 560 | } 561 | /* Writing pubkey module data checksum */ 562 | pubkey_module[MODULE_DATA_CHECKSUM_OFFSET] = data_checksum; 563 | 564 | /* Searching for free space to insert marker module */ 565 | marker_module = find_free_space(pubkey_module, efi_volume_end, SLIC_MARKER_LENGTH); 566 | if (!marker_module) 567 | { 568 | printf("Not enough free space to insert marker module.\nSLIC table can't be copied.\n"); 569 | return ERR_MEMORY; 570 | } 571 | 572 | /* Writing marker header*/ 573 | if (!memcpy(marker_module, SLIC_MARKER_HEADER, sizeof(SLIC_MARKER_HEADER))) 574 | { 575 | printf("Memcpy failed.\nSLIC table can't be copied.\n"); 576 | return ERR_MEMORY; 577 | } 578 | /* Writing marker first part*/ 579 | if (!memcpy(marker_module + sizeof(SLIC_MARKER_HEADER), SLIC_MARKER_PART1, sizeof(SLIC_MARKER_PART1))) 580 | { 581 | printf("Memcpy failed.\nSLIC table can't be copied.\n"); 582 | return ERR_MEMORY; 583 | } 584 | /* Writing marker */ 585 | if (!memcpy(marker_module + sizeof(SLIC_MARKER_HEADER) + sizeof(SLIC_MARKER_PART1), slicMarker, sizeof(slicMarker))) 586 | { 587 | printf("Memcpy failed.\nSLIC table can't be copied.\n"); 588 | return ERR_MEMORY; 589 | } 590 | /* Calculating pubkey module data checksum */ 591 | if (!calculate_checksum(marker_module + MODULE_DATA_CHECKSUM_START, SLIC_MARKER_LENGTH - MODULE_DATA_CHECKSUM_START, &data_checksum)) 592 | { 593 | printf("Marker module checksum calculation failed.\nSLIC table can't be copied.\n"); 594 | return ERR_MEMORY; 595 | } 596 | /* Writing marker module data checksum */ 597 | marker_module[MODULE_DATA_CHECKSUM_OFFSET] = data_checksum; 598 | 599 | printf("SLIC pubkey and marker copied.\n"); 600 | } while (0); /* Used for break */ 601 | } 602 | 603 | /* Searching for module header */ 604 | if (copyModule) 605 | { 606 | char isCopied; 607 | uint32_t currentModuleSize; 608 | uint8_t* module; 609 | uint8_t* fd44 = find_pattern(buffer, end, FD44_MODULE_HEADER, sizeof(FD44_MODULE_HEADER)); 610 | if (!fd44) 611 | { 612 | printf("FD44 module not found in output file.\n"); 613 | return ERR_NO_FD44_MODULE; 614 | } 615 | 616 | if (!isModuleEmpty) 617 | { 618 | /* Copying data to all BSA_ modules */ 619 | isCopied = 0; 620 | while (fd44) 621 | { 622 | /* Getting module size */ 623 | size2int(fd44 + FD44_MODULE_SIZE_OFFSET, ¤tModuleSize); 624 | if (!memcmp(fd44 + FD44_MODULE_HEADER_BSA_OFFSET, FD44_MODULE_HEADER_BSA, sizeof(FD44_MODULE_HEADER_BSA))) 625 | { 626 | module = fd44 + FD44_MODULE_HEADER_LENGTH; 627 | /* Checking that there is enough space in module to insert data */ 628 | if (currentModuleSize - FD44_MODULE_HEADER_LENGTH < fd44ModuleSize) 629 | { 630 | printf("FD44 module at %08X is too small.\n", module - buffer); 631 | fd44 = find_pattern(fd44 + currentModuleSize, end, FD44_MODULE_HEADER, sizeof(FD44_MODULE_HEADER)); 632 | break; 633 | } 634 | /* Copying module data*/ 635 | if (!memcpy(module, fd44Module, fd44ModuleSize)) 636 | { 637 | printf("Memcpy failed.\nFD44 module can't be copied.\n"); 638 | return ERR_MEMORY; 639 | } 640 | isCopied = 1; 641 | } 642 | 643 | fd44 = find_pattern(fd44 + currentModuleSize, end, FD44_MODULE_HEADER, sizeof(FD44_MODULE_HEADER)); 644 | } 645 | 646 | /* Checking if there is at least one non-empty module after copying */ 647 | if(isCopied) 648 | printf("FD44 module copied.\n"); 649 | else 650 | { 651 | printf("FD44 module can't be copied.\n"); 652 | return ERR_NO_FD44_MODULE; 653 | } 654 | } 655 | } 656 | 657 | /* Reopening file to resize it */ 658 | fclose(file); 659 | file = fopen(outputfile, "wb"); 660 | 661 | /* Writing buffer to output file */ 662 | read = fwrite(buffer, sizeof(char), filesize, file); 663 | if (read != filesize) 664 | { 665 | perror("Can't write output file.\n"); 666 | return ERR_OUTPUT_FILE; 667 | } 668 | 669 | /* Cleaning */ 670 | if (hasCapsuleHeader) 671 | { 672 | printf("Capsule file header removed.\n"); 673 | buffer -= headerSize; 674 | } 675 | free(buffer); 676 | if (copyModule && !isModuleEmpty) 677 | free(fd44Module); 678 | fclose(file); 679 | 680 | if (isModuleEmpty) 681 | return ERR_EMPTY_FD44_MODULE; 682 | 683 | return ERR_OK; 684 | } 685 | --------------------------------------------------------------------------------