1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "libxbc.h" 18 19 #define BOOTCONFIG_MAGIC "#BOOTCONFIG\n" 20 #define BOOTCONFIG_MAGIC_SIZE 12 21 #define BOOTCONFIG_SIZE_SIZE 4 22 #define BOOTCONFIG_CHECKSUM_SIZE 4 23 #define BOOTCONFIG_TRAILER_SIZE BOOTCONFIG_MAGIC_SIZE + \ 24 BOOTCONFIG_SIZE_SIZE + \ 25 BOOTCONFIG_CHECKSUM_SIZE 26 /* 27 * Simple checksum for a buffer. 28 * 29 * @param addr pointer to the start of the buffer. 30 * @param size size of the buffer in bytes. 31 * @return check sum result. 32 */ 33 static uint32_t checksum(const unsigned char* const buffer, uint32_t size) { 34 uint32_t sum = 0; 35 for (uint32_t i = 0; i < size; i++) { 36 sum += buffer[i]; 37 } 38 return sum; 39 } 40 41 /* 42 * Check if the bootconfig trailer is present within the bootconfig section. 43 * 44 * @param bootconfig_end_addr address of the end of the bootconfig section. If 45 * the trailer is present, it will be directly preceding this address. 46 * @return true if the trailer is present, false if not. 47 */ 48 static bool isTrailerPresent(uint64_t bootconfig_end_addr) { 49 return !strncmp((char*)(bootconfig_end_addr - BOOTCONFIG_MAGIC_SIZE), 50 BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); 51 } 52 53 /* 54 * Add a string of boot config parameters to memory appended by the trailer. 55 */ 56 int32_t addBootConfigParameters(char* params, uint32_t params_size, 57 uint64_t bootconfig_start_addr, uint32_t bootconfig_size) { 58 if (!params || !bootconfig_start_addr) { 59 return -1; 60 } 61 if (params_size == 0) { 62 return 0; 63 } 64 int32_t applied_bytes = 0; 65 int32_t new_size = 0; 66 uint64_t end = bootconfig_start_addr + bootconfig_size; 67 68 if (isTrailerPresent(end)) { 69 end -= BOOTCONFIG_TRAILER_SIZE; 70 applied_bytes -= BOOTCONFIG_TRAILER_SIZE; 71 memcpy(&new_size, (void *)end, BOOTCONFIG_SIZE_SIZE); 72 } else { 73 new_size = bootconfig_size; 74 } 75 76 // params 77 memcpy((void*)end, params, params_size); 78 79 applied_bytes += params_size; 80 applied_bytes += addBootConfigTrailer(bootconfig_start_addr, 81 bootconfig_size + applied_bytes); 82 83 return applied_bytes; 84 } 85 86 /* 87 * Add boot config trailer. 88 */ 89 int32_t addBootConfigTrailer(uint64_t bootconfig_start_addr, 90 uint32_t bootconfig_size) { 91 if (!bootconfig_start_addr) { 92 return -1; 93 } 94 if (bootconfig_size == 0) { 95 return 0; 96 } 97 uint64_t end = bootconfig_start_addr + bootconfig_size; 98 99 if (isTrailerPresent(end)) { 100 // no need to overwrite the current trailers 101 return 0; 102 } 103 104 // size 105 memcpy((void *)(end), &bootconfig_size, BOOTCONFIG_SIZE_SIZE); 106 107 // checksum 108 uint32_t sum = 109 checksum((unsigned char*)bootconfig_start_addr, bootconfig_size); 110 memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE), &sum, 111 BOOTCONFIG_CHECKSUM_SIZE); 112 113 // magic 114 memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE + BOOTCONFIG_CHECKSUM_SIZE), 115 BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); 116 117 return BOOTCONFIG_TRAILER_SIZE; 118 } 119