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