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