xref: /rk3399_rockchip-uboot/lib/libxbc/libxbc.c (revision f93178ae1e66403ffee11e75d56a89659c32e108)
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