blob: e45f4248758e5e580424acaea6aa6631d6095e83 [file] [log] [blame]
Yabin Cui8b309f62016-06-24 18:22:02 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _BOOTLOADER_MESSAGE_H
18#define _BOOTLOADER_MESSAGE_H
19
20#include <assert.h>
21#include <stddef.h>
22#include <stdint.h>
23
24// Spaces used by misc partition are as below:
25// 0 - 2K Bootloader Message
26// 2K - 16K Used by Vendor's bootloader (the 2K - 4K range may be optionally used
27// as bootloader_message_ab struct)
28// 16K - 64K Used by uncrypt and recovery to store wipe_package for A/B devices
29// Note that these offsets are admitted by bootloader,recovery and uncrypt, so they
30// are not configurable without changing all of them.
31static const size_t BOOTLOADER_MESSAGE_OFFSET_IN_MISC = 0;
32static const size_t WIPE_PACKAGE_OFFSET_IN_MISC = 16 * 1024;
33
34/* Bootloader Message (2-KiB)
35 *
36 * This structure describes the content of a block in flash
37 * that is used for recovery and the bootloader to talk to
38 * each other.
39 *
40 * The command field is updated by linux when it wants to
41 * reboot into recovery or to update radio or bootloader firmware.
42 * It is also updated by the bootloader when firmware update
43 * is complete (to boot into recovery for any final cleanup)
44 *
45 * The status field is written by the bootloader after the
46 * completion of an "update-radio" or "update-hboot" command.
47 *
48 * The recovery field is only written by linux and used
49 * for the system to send a message to recovery or the
50 * other way around.
51 *
52 * The stage field is written by packages which restart themselves
53 * multiple times, so that the UI can reflect which invocation of the
54 * package it is. If the value is of the format "#/#" (eg, "1/3"),
55 * the UI will add a simple indicator of that status.
56 *
57 * We used to have slot_suffix field for A/B boot control metadata in
58 * this struct, which gets unintentionally cleared by recovery or
59 * uncrypt. Move it into struct bootloader_message_ab to avoid the
60 * issue.
61 */
62struct bootloader_message {
63 char command[32];
64 char status[32];
65 char recovery[768];
66
67 // The 'recovery' field used to be 1024 bytes. It has only ever
68 // been used to store the recovery command line, so 768 bytes
69 // should be plenty. We carve off the last 256 bytes to store the
70 // stage string (for multistage packages) and possible future
71 // expansion.
72 char stage[32];
73
74 // The 'reserved' field used to be 224 bytes when it was initially
75 // carved off from the 1024-byte recovery field. Bump it up to
76 // 1184-byte so that the entire bootloader_message struct rounds up
77 // to 2048-byte.
78 char reserved[1184];
79};
80
81/**
82 * We must be cautious when changing the bootloader_message struct size,
83 * because A/B-specific fields may end up with different offsets.
84 */
85#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
86static_assert(sizeof(struct bootloader_message) == 2048,
87 "struct bootloader_message size changes, which may break A/B devices");
88#endif
89
90/**
91 * The A/B-specific bootloader message structure (4-KiB).
92 *
93 * We separate A/B boot control metadata from the regular bootloader
94 * message struct and keep it here. Everything that's A/B-specific
95 * stays after struct bootloader_message, which should be managed by
96 * the A/B-bootloader or boot control HAL.
97 *
98 * The slot_suffix field is used for A/B implementations where the
99 * bootloader does not set the androidboot.ro.boot.slot_suffix kernel
100 * commandline parameter. This is used by fs_mgr to mount /system and
101 * other partitions with the slotselect flag set in fstab. A/B
102 * implementations are free to use all 32 bytes and may store private
103 * data past the first NUL-byte in this field. It is encouraged, but
104 * not mandatory, to use 'struct bootloader_control' described below.
105 */
106struct bootloader_message_ab {
107 struct bootloader_message message;
108 char slot_suffix[32];
109
110 // Round up the entire struct to 4096-byte.
111 char reserved[2016];
112};
113
114/**
115 * Be cautious about the struct size change, in case we put anything post
116 * bootloader_message_ab struct (b/29159185).
117 */
118#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
119static_assert(sizeof(struct bootloader_message_ab) == 4096,
120 "struct bootloader_message_ab size changes");
121#endif
122
123#define BOOT_CTRL_MAGIC 0x42414342 /* Bootloader Control AB */
124#define BOOT_CTRL_VERSION 1
125
126struct slot_metadata {
127 // Slot priority with 15 meaning highest priority, 1 lowest
128 // priority and 0 the slot is unbootable.
129 uint8_t priority : 4;
130 // Number of times left attempting to boot this slot.
131 uint8_t tries_remaining : 3;
132 // 1 if this slot has booted successfully, 0 otherwise.
133 uint8_t successful_boot : 1;
134 // 1 if this slot is corrupted from a dm-verity corruption, 0
135 // otherwise.
136 uint8_t verity_corrupted : 1;
137 // Reserved for further use.
138 uint8_t reserved : 7;
139} __attribute__((packed));
140
141/* Bootloader Control AB
142 *
143 * This struct can be used to manage A/B metadata. It is designed to
144 * be put in the 'slot_suffix' field of the 'bootloader_message'
145 * structure described above. It is encouraged to use the
146 * 'bootloader_control' structure to store the A/B metadata, but not
147 * mandatory.
148 */
149struct bootloader_control {
150 // NUL terminated active slot suffix.
151 char slot_suffix[4];
152 // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
153 uint32_t magic;
154 // Version of struct being used (see BOOT_CTRL_VERSION).
155 uint8_t version;
156 // Number of slots being managed.
157 uint8_t nb_slot : 3;
158 // Number of times left attempting to boot recovery.
159 uint8_t recovery_tries_remaining : 3;
160 // Ensure 4-bytes alignment for slot_info field.
161 uint8_t reserved0[2];
162 // Per-slot information. Up to 4 slots.
163 struct slot_metadata slot_info[4];
164 // Reserved for further use.
165 uint8_t reserved1[8];
166 // CRC32 of all 28 bytes preceding this field (little endian
167 // format).
168 uint32_t crc32_le;
169} __attribute__((packed));
170
171#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
172static_assert(sizeof(struct bootloader_control) ==
173 sizeof(((struct bootloader_message_ab *)0)->slot_suffix),
174 "struct bootloader_control has wrong size");
175#endif
176#ifdef __cplusplus
177
178#include <string>
179#include <vector>
180
Tao Baobedf5fc2016-11-18 12:01:26 -0800181// Read bootloader message into boot. Error message will be set in err.
Yabin Cui8b309f62016-06-24 18:22:02 -0700182bool read_bootloader_message(bootloader_message* boot, std::string* err);
Tao Baobedf5fc2016-11-18 12:01:26 -0800183
184// Read bootloader message from the specified misc device into boot.
185bool read_bootloader_message_from(bootloader_message* boot, const std::string& misc_blk_device,
186 std::string* err);
187
188// Write bootloader message to BCB.
Yabin Cui8b309f62016-06-24 18:22:02 -0700189bool write_bootloader_message(const bootloader_message& boot, std::string* err);
Tao Baobedf5fc2016-11-18 12:01:26 -0800190
191// Write bootloader message to the specified BCB device.
192bool write_bootloader_message_to(const bootloader_message& boot,
193 const std::string& misc_blk_device, std::string* err);
194
195// Write bootloader message (boots into recovery with the options) to BCB.
Yabin Cui8b309f62016-06-24 18:22:02 -0700196bool write_bootloader_message(const std::vector<std::string>& options, std::string* err);
Tao Baobedf5fc2016-11-18 12:01:26 -0800197
198// Clear BCB.
Yabin Cui8b309f62016-06-24 18:22:02 -0700199bool clear_bootloader_message(std::string* err);
200
Vineela Tummalapallicba7fa82016-10-28 19:44:40 -0700201// Writes the reboot-bootloader reboot reason to the bootloader_message.
202bool write_reboot_bootloader(std::string* err);
203
Tao Baobedf5fc2016-11-18 12:01:26 -0800204// Read the wipe package from BCB (from offset WIPE_PACKAGE_OFFSET_IN_MISC).
Yabin Cui8b309f62016-06-24 18:22:02 -0700205bool read_wipe_package(std::string* package_data, size_t size, std::string* err);
Tao Baobedf5fc2016-11-18 12:01:26 -0800206
207// Write the wipe package into BCB (to offset WIPE_PACKAGE_OFFSET_IN_MISC).
Yabin Cui8b309f62016-06-24 18:22:02 -0700208bool write_wipe_package(const std::string& package_data, std::string* err);
209
210#else
211
212#include <stdbool.h>
213
214// C Interface.
215bool write_bootloader_message(const char* options);
Vineela Tummalapallicba7fa82016-10-28 19:44:40 -0700216bool write_reboot_bootloader(void);
Yabin Cui8b309f62016-06-24 18:22:02 -0700217
218#endif // ifdef __cplusplus
219
220#endif // _BOOTLOADER_MESSAGE_H