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