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