| /* | |
| * Copyright (C) 2021 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include "libxbc.h" | |
| #define BOOTCONFIG_MAGIC "#BOOTCONFIG\n" | |
| #define BOOTCONFIG_MAGIC_SIZE 12 | |
| #define BOOTCONFIG_SIZE_SIZE 4 | |
| #define BOOTCONFIG_CHECKSUM_SIZE 4 | |
| #define BOOTCONFIG_TRAILER_SIZE BOOTCONFIG_MAGIC_SIZE + \ | |
| BOOTCONFIG_SIZE_SIZE + \ | |
| BOOTCONFIG_CHECKSUM_SIZE | |
| /* | |
| * Simple checksum for a buffer. | |
| * | |
| * @param addr pointer to the start of the buffer. | |
| * @param size size of the buffer in bytes. | |
| * @return check sum result. | |
| */ | |
| static uint32_t checksum(const unsigned char* const buffer, uint32_t size) { | |
| uint32_t sum = 0; | |
| for (uint32_t i = 0; i < size; i++) { | |
| sum += buffer[i]; | |
| } | |
| return sum; | |
| } | |
| /* | |
| * Check if the bootconfig trailer is present within the bootconfig section. | |
| * | |
| * @param bootconfig_end_addr address of the end of the bootconfig section. If | |
| * the trailer is present, it will be directly preceding this address. | |
| * @return true if the trailer is present, false if not. | |
| */ | |
| static bool isTrailerPresent(uint64_t bootconfig_end_addr) { | |
| return !strncmp((char*)(bootconfig_end_addr - BOOTCONFIG_MAGIC_SIZE), | |
| BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); | |
| } | |
| /* | |
| * Add a string of boot config parameters to memory appended by the trailer. | |
| */ | |
| int32_t addBootConfigParameters(const char* params, uint32_t params_size, | |
| uint64_t bootconfig_start_addr, uint32_t bootconfig_size) { | |
| if (!params || !bootconfig_start_addr) { | |
| return -1; | |
| } | |
| if (params_size == 0) { | |
| return 0; | |
| } | |
| int32_t applied_bytes = 0; | |
| int32_t new_size = 0; | |
| uint64_t end = bootconfig_start_addr + bootconfig_size; | |
| if (isTrailerPresent(end)) { | |
| end -= BOOTCONFIG_TRAILER_SIZE; | |
| applied_bytes -= BOOTCONFIG_TRAILER_SIZE; | |
| memcpy(&new_size, (void *)end, BOOTCONFIG_SIZE_SIZE); | |
| } else { | |
| new_size = bootconfig_size; | |
| } | |
| // params | |
| memcpy((void*)end, params, params_size); | |
| applied_bytes += params_size; | |
| applied_bytes += addBootConfigTrailer(bootconfig_start_addr, | |
| bootconfig_size + applied_bytes); | |
| return applied_bytes; | |
| } | |
| /* | |
| * Add boot config trailer. | |
| */ | |
| int32_t addBootConfigTrailer(uint64_t bootconfig_start_addr, | |
| uint32_t bootconfig_size) { | |
| if (!bootconfig_start_addr) { | |
| return -1; | |
| } | |
| if (bootconfig_size == 0) { | |
| return 0; | |
| } | |
| uint64_t end = bootconfig_start_addr + bootconfig_size; | |
| if (isTrailerPresent(end)) { | |
| // no need to overwrite the current trailers | |
| return 0; | |
| } | |
| // size | |
| memcpy((void *)(end), &bootconfig_size, BOOTCONFIG_SIZE_SIZE); | |
| // checksum | |
| uint32_t sum = | |
| checksum((unsigned char*)bootconfig_start_addr, bootconfig_size); | |
| memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE), &sum, | |
| BOOTCONFIG_CHECKSUM_SIZE); | |
| // magic | |
| memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE + BOOTCONFIG_CHECKSUM_SIZE), | |
| BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); | |
| return BOOTCONFIG_TRAILER_SIZE; | |
| } |