blob: b435afefd70650c6e99ee3c102856ee7edaa90fa [file] [log] [blame]
Caleb Connollyb55c0f82023-12-07 00:13:07 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Common initialisation for Qualcomm Snapdragon boards.
4 *
5 * Copyright (c) 2023 Linaro Ltd.
6 * Author: Caleb Connolly <caleb.connolly@linaro.org>
7 */
8
9#define LOG_DEBUG
10
11#include <dm/device.h>
12#include <efi.h>
13#include <efi_loader.h>
14#include <malloc.h>
15#include <scsi.h>
16#include <part.h>
17
18#include "qcom-priv.h"
19
20struct efi_fw_image fw_images[] = {
21 {
22 .image_type_id = QUALCOMM_UBOOT_BOOT_IMAGE_GUID,
23 .fw_name = u"QUALCOMM-UBOOT",
24 .image_index = 1,
25 },
26};
27
28struct efi_capsule_update_info update_info = {
29 /* Filled in by configure_dfu_string() */
30 .dfu_string = NULL,
31 .num_images = ARRAY_SIZE(fw_images),
32 .images = fw_images,
33};
34
35/**
36 * out_len includes the trailing null space
37 */
38static int get_cmdline_option(const char *cmdline, const char *key, char *out, int out_len)
39{
40 const char *p, *p_end;
41 int len;
42
43 p = strstr(cmdline, key);
44 if (!p)
45 return -ENOENT;
46
47 p += strlen(key);
48 p_end = strstr(p, " ");
49 if (!p_end)
50 return -ENOENT;
51
52 len = p_end - p;
53 if (len > out_len)
54 len = out_len;
55
56 strncpy(out, p, len);
57 out[len] = '\0';
58
59 return 0;
60}
61
62/* The bootargs are populated by the previous stage bootloader */
63static const char *get_cmdline(void)
64{
65 ofnode node;
66 static const char *cmdline = NULL;
67
68 if (cmdline)
69 return cmdline;
70
71 node = ofnode_path("/chosen");
72 if (!ofnode_valid(node))
73 return NULL;
74
75 cmdline = ofnode_read_string(node, "bootargs");
76
77 return cmdline;
78}
79
80static int find_boot_partition(const char *partname, struct blk_desc *blk_dev, struct disk_partition *info)
81{
82 int ret;
83 int partnum;
84
85 for (partnum = 1;; partnum++) {
86 ret = part_get_info(blk_dev, partnum, info);
87 if (ret) {
88 return ret;
89 }
90 if (!strncmp(info->name, partname, 6)) {
91 return partnum;
92 }
93 }
94
95 return 0;
96}
97
Caleb Connollye5baf282024-02-23 11:39:26 +000098void qcom_set_serialno(void)
99{
100 const char *cmdline = get_cmdline();
101 char serial[32];
102
103 if (!cmdline) {
104 debug("Failed to get bootargs\n");
105 return;
106 }
107
108 get_cmdline_option(cmdline, "androidboot.serialno=", serial, sizeof(serial));
109 if (serial[0] != '\0') {
110 env_set("serial#", serial);
111 }
112}
113
Caleb Connollyb55c0f82023-12-07 00:13:07 +0000114/**
115 * qcom_configure_capsule_updates() - Configure the DFU string for capsule updates
116 *
117 * U-Boot is flashed to the boot partition on Qualcomm boards. In most cases there
118 * are two boot partitions, boot_a and boot_b. As we don't currently support doing
119 * full A/B updates, we only support updating the currently active boot partition.
120 *
121 * So we need to find the current slot suffix and the associated boot partition.
122 * The slot suffix is most easily accessed via the bootargs which are populated by
123 * the previous stage bootloader (ABL). However in the future we will likely want to
124 * read them directly from the GPT vendor attribute bits.
125 *
126 * For now only SCSI is supported.
127 */
128void qcom_configure_capsule_updates(void)
129{
130 struct blk_desc *desc;
131 struct disk_partition info;
132 int ret, partnum = -1, devnum;
133 char *dfu_string;
134 const char *cmdline;
135 char partname[7] = "boot";
136
137#ifdef CONFIG_DM_SCSI
138 /* Scan for SCSI devices */
139 ret = scsi_scan(false);
140 if (ret) {
141 debug("Failed to scan SCSI devices: %d\n", ret);
142 return;
143 }
144#else
145 debug("Qualcomm UEFI CapsuleUpdates requires SCSI support\n");
146 return;
147#endif
148
149 cmdline = get_cmdline();
150 if (!cmdline) {
151 debug("Failed to get bootargs\n");
152 return;
153 }
154
155 /* Some boards might only have one boot partition, so this is optional */
156 ret = get_cmdline_option(cmdline, "androidboot.slot_suffix=", &partname[4], 3);
157 if (ret < 0)
158 debug("Failed to get slot suffix from bootargs (board might be A-only?)\n");
159
160 for(devnum = 0;; devnum++) {
161 ret = blk_get_desc(UCLASS_SCSI, devnum, &desc);
162 if (ret == -ENODEV)
163 break;
164 else if (ret)
165 continue;
166 if (desc->part_type != PART_TYPE_UNKNOWN) {
167 partnum = find_boot_partition(partname, desc, &info);
168 if (partnum >= 0)
169 break;
170 }
171 }
172 if (partnum < 0) {
173 debug("Failed to find boot partition\n");
174 return;
175 }
176
177 dfu_string = malloc(32);
178
179 snprintf(dfu_string, 32, "scsi %d=u-boot-bin part %d", devnum, partnum);
180 printf("DFU string: %s\n", dfu_string);
181
182 update_info.dfu_string = dfu_string;
183}