Blame view
common/fb_mmc.c
5.98 KB
c0aebb338
|
1 2 3 4 5 |
/* * Copyright 2014 Broadcom Corporation. * * SPDX-License-Identifier: GPL-2.0+ */ |
0ff7e585d
|
6 |
#include <config.h> |
c0aebb338
|
7 |
#include <common.h> |
2a981dc2c
|
8 |
#include <blk.h> |
3c8f98f5f
|
9 |
#include <fastboot.h> |
c0aebb338
|
10 |
#include <fb_mmc.h> |
3d4ef38de
|
11 |
#include <image-sparse.h> |
c0aebb338
|
12 |
#include <part.h> |
897923819
|
13 |
#include <mmc.h> |
5e0efc1bc
|
14 |
#include <div64.h> |
c0aebb338
|
15 |
|
6f6c86309
|
16 17 18 19 20 21 |
/* * FIXME: Ensure we always set these names via Kconfig once xxx_PARTITION is * migrated */ #ifndef CONFIG_FASTBOOT_GPT_NAME #define CONFIG_FASTBOOT_GPT_NAME "gpt" |
0ff7e585d
|
22 |
#endif |
b6dd69a4d
|
23 |
|
6f6c86309
|
24 |
#ifndef CONFIG_FASTBOOT_MBR_NAME |
b6dd69a4d
|
25 26 |
#define CONFIG_FASTBOOT_MBR_NAME "mbr" #endif |
a5d1e04a5
|
27 |
struct fb_mmc_sparse { |
4101f6879
|
28 |
struct blk_desc *dev_desc; |
a5d1e04a5
|
29 |
}; |
b6dd69a4d
|
30 |
static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc, |
8a41802f2
|
31 32 33 |
const char *name, disk_partition_t *info) { int ret; |
87b8530fe
|
34 |
ret = part_get_info_by_name(dev_desc, name, info); |
8a41802f2
|
35 36 37 38 39 40 41 42 43 44 |
if (ret) { /* strlen("fastboot_partition_alias_") + 32(part_name) + 1 */ char env_alias_name[25 + 32 + 1]; char *aliased_part_name; /* check for alias */ strcpy(env_alias_name, "fastboot_partition_alias_"); strncat(env_alias_name, name, 32); aliased_part_name = getenv(env_alias_name); if (aliased_part_name != NULL) |
87b8530fe
|
45 |
ret = part_get_info_by_name(dev_desc, |
8a41802f2
|
46 47 48 49 |
aliased_part_name, info); } return ret; } |
cc0f08cd3
|
50 51 |
static lbaint_t fb_mmc_sparse_write(struct sparse_storage *info, lbaint_t blk, lbaint_t blkcnt, const void *buffer) |
a5d1e04a5
|
52 |
{ |
cc0f08cd3
|
53 |
struct fb_mmc_sparse *sparse = info->priv; |
4101f6879
|
54 |
struct blk_desc *dev_desc = sparse->dev_desc; |
a5d1e04a5
|
55 |
|
cc0f08cd3
|
56 |
return blk_dwrite(dev_desc, blk, blkcnt, buffer); |
a5d1e04a5
|
57 |
} |
2c7240468
|
58 59 60 61 62 |
static lbaint_t fb_mmc_sparse_reserve(struct sparse_storage *info, lbaint_t blk, lbaint_t blkcnt) { return blkcnt; } |
4101f6879
|
63 |
static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info, |
c0aebb338
|
64 65 66 67 68 69 70 71 |
const char *part_name, void *buffer, unsigned int download_bytes) { lbaint_t blkcnt; lbaint_t blks; /* determine number of blocks to write */ blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1)); |
5e0efc1bc
|
72 |
blkcnt = lldiv(blkcnt, info->blksz); |
c0aebb338
|
73 74 75 76 |
if (blkcnt > info->size) { error("too large for partition: '%s' ", part_name); |
9bc34799c
|
77 |
fastboot_fail("too large for partition"); |
c0aebb338
|
78 79 80 81 82 |
return; } puts("Flashing Raw Image "); |
2a981dc2c
|
83 |
blks = blk_dwrite(dev_desc, info->start, blkcnt, buffer); |
c0aebb338
|
84 |
if (blks != blkcnt) { |
bcce53d04
|
85 86 |
error("failed writing to device %d ", dev_desc->devnum); |
9bc34799c
|
87 |
fastboot_fail("failed writing to device"); |
c0aebb338
|
88 89 90 91 92 93 |
return; } printf("........ wrote " LBAFU " bytes to '%s' ", blkcnt * info->blksz, part_name); |
9bc34799c
|
94 |
fastboot_okay(""); |
c0aebb338
|
95 |
} |
64ece8485
|
96 |
void fb_mmc_flash_write(const char *cmd, void *download_buffer, |
9bc34799c
|
97 |
unsigned int download_bytes) |
c0aebb338
|
98 |
{ |
4101f6879
|
99 |
struct blk_desc *dev_desc; |
c0aebb338
|
100 |
disk_partition_t info; |
db1d9e78e
|
101 |
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV); |
c0aebb338
|
102 103 104 |
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) { error("invalid mmc device "); |
9bc34799c
|
105 |
fastboot_fail("invalid mmc device"); |
c0aebb338
|
106 107 |
return; } |
bd42a9426
|
108 |
#if CONFIG_IS_ENABLED(EFI_PARTITION) |
0ff7e585d
|
109 110 111 112 113 114 115 116 |
if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) { printf("%s: updating MBR, Primary and Backup GPT(s) ", __func__); if (is_valid_gpt_buf(dev_desc, download_buffer)) { printf("%s: invalid GPT - refusing to write to flash ", __func__); |
9bc34799c
|
117 |
fastboot_fail("invalid GPT partition"); |
0ff7e585d
|
118 119 120 121 122 |
return; } if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) { printf("%s: writing GPT partitions failed ", __func__); |
b6dd69a4d
|
123 |
fastboot_fail("writing GPT partitions failed"); |
0ff7e585d
|
124 125 126 127 |
return; } printf("........ success "); |
9bc34799c
|
128 |
fastboot_okay(""); |
0ff7e585d
|
129 |
return; |
b6dd69a4d
|
130 131 |
} #endif |
b0cf73393
|
132 |
#if CONFIG_IS_ENABLED(DOS_PARTITION) |
b6dd69a4d
|
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
if (strcmp(cmd, CONFIG_FASTBOOT_MBR_NAME) == 0) { printf("%s: updating MBR ", __func__); if (is_valid_dos_buf(download_buffer)) { printf("%s: invalid MBR - refusing to write to flash ", __func__); fastboot_fail("invalid MBR partition"); return; } if (write_mbr_partition(dev_desc, download_buffer)) { printf("%s: writing MBR partition failed ", __func__); fastboot_fail("writing MBR partition failed"); return; } printf("........ success "); fastboot_okay(""); return; } #endif if (part_get_info_by_name_or_alias(dev_desc, cmd, &info)) { |
c0aebb338
|
157 158 |
error("cannot find partition: '%s' ", cmd); |
9bc34799c
|
159 |
fastboot_fail("cannot find partition"); |
c0aebb338
|
160 161 |
return; } |
a5d1e04a5
|
162 163 |
if (is_sparse_image(download_buffer)) { struct fb_mmc_sparse sparse_priv; |
cc0f08cd3
|
164 |
struct sparse_storage sparse; |
a5d1e04a5
|
165 166 |
sparse_priv.dev_desc = dev_desc; |
cc0f08cd3
|
167 |
sparse.blksz = info.blksz; |
a5d1e04a5
|
168 169 |
sparse.start = info.start; sparse.size = info.size; |
a5d1e04a5
|
170 |
sparse.write = fb_mmc_sparse_write; |
2c7240468
|
171 |
sparse.reserve = fb_mmc_sparse_reserve; |
a5d1e04a5
|
172 173 174 |
printf("Flashing sparse image at offset " LBAFU " ", |
cc0f08cd3
|
175 |
sparse.start); |
a5d1e04a5
|
176 |
|
cc0f08cd3
|
177 178 |
sparse.priv = &sparse_priv; write_sparse_image(&sparse, cmd, download_buffer, |
9bc34799c
|
179 |
download_bytes); |
a5d1e04a5
|
180 |
} else { |
e5bf9878e
|
181 182 |
write_raw_image(dev_desc, &info, cmd, download_buffer, download_bytes); |
a5d1e04a5
|
183 |
} |
c0aebb338
|
184 |
} |
897923819
|
185 |
|
9bc34799c
|
186 |
void fb_mmc_erase(const char *cmd) |
897923819
|
187 188 |
{ int ret; |
4101f6879
|
189 |
struct blk_desc *dev_desc; |
897923819
|
190 191 192 193 194 195 |
disk_partition_t info; lbaint_t blks, blks_start, blks_size, grp_size; struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV); if (mmc == NULL) { error("invalid mmc device"); |
9bc34799c
|
196 |
fastboot_fail("invalid mmc device"); |
897923819
|
197 198 |
return; } |
db1d9e78e
|
199 |
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV); |
897923819
|
200 201 |
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) { error("invalid mmc device"); |
9bc34799c
|
202 |
fastboot_fail("invalid mmc device"); |
897923819
|
203 204 |
return; } |
b6dd69a4d
|
205 |
ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info); |
897923819
|
206 207 |
if (ret) { error("cannot find partition: '%s'", cmd); |
9bc34799c
|
208 |
fastboot_fail("cannot find partition"); |
897923819
|
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
return; } /* Align blocks to erase group size to avoid erasing other partitions */ grp_size = mmc->erase_grp_size; blks_start = (info.start + grp_size - 1) & ~(grp_size - 1); if (info.size >= grp_size) blks_size = (info.size - (blks_start - info.start)) & (~(grp_size - 1)); else blks_size = 0; printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment ", blks_start, blks_start + blks_size); |
ec3cde1e8
|
224 |
blks = blk_derase(dev_desc, blks_start, blks_size); |
897923819
|
225 |
if (blks != blks_size) { |
bcce53d04
|
226 |
error("failed erasing from device %d", dev_desc->devnum); |
9bc34799c
|
227 |
fastboot_fail("failed erasing from device"); |
897923819
|
228 229 230 231 232 233 |
return; } printf("........ erased " LBAFU " bytes from '%s' ", blks_size * info.blksz, cmd); |
9bc34799c
|
234 |
fastboot_okay(""); |
897923819
|
235 |
} |