blob: 04e38811dc452c04730dc20e4934fd2a5e2d0352 [file] [log] [blame]
Nikolai Artemievc9feb1b2021-10-21 01:35:13 +11001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright 2021 Google LLC
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include "writeprotect.h"
18#include "chipdrivers.h"
19
20/*
21 * Protection range calculation that works with many common SPI flash chips.
22 */
23void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *bits, size_t chip_len)
24{
25 /* Interpret BP bits as an integer */
26 size_t i;
27 size_t bp = 0;
28 size_t bp_max = 0;
29
30 for (i = 0; i < bits->bp_bit_count; i++) {
31 bp |= bits->bp[i] << i;
32 bp_max |= 1 << i;
33 }
34
35 if (bp == 0) {
36 /* Special case: all BP bits are 0 => no write protection */
37 *len = 0;
38 } else if (bp == bp_max) {
39 /* Special case: all BP bits are 1 => full write protection */
40 *len = chip_len;
41 } else {
42 /*
43 * Usual case: the BP bits encode a coefficient in the form
44 * `coeff = 2 ** (bp - 1)`.
45 *
46 * The range's length is given by multiplying the coefficient
47 * by a base unit, usually a 4K sector or a 64K block.
48 */
49
50 size_t coeff = 1 << (bp - 1);
51 size_t max_coeff = 1 << (bp_max - 2);
52
53 size_t sector_len = 4 * KiB;
54 size_t default_block_len = 64 * KiB;
55
56 if (bits->sec_bit_present && bits->sec == 1) {
57 /*
58 * SEC=1, protect 4K sectors. Flash chips clamp the
59 * protection length at 32K, probably to avoid overlap
60 * with the SEC=0 case.
61 */
62 *len = min(sector_len * coeff, default_block_len / 2);
63 } else {
64 /*
65 * SEC=0 or is not present, protect blocks.
66 *
67 * With very large chips, the 'block' size can be
68 * larger than 64K. This occurs when a larger block
69 * size is needed so that half the chip can be
70 * protected by the maximum possible coefficient.
71 */
72 size_t min_block_len = chip_len / 2 / max_coeff;
73 size_t block_len = max(min_block_len, default_block_len);
74
75 *len = min(block_len * coeff, chip_len);
76 }
77 }
78
79 /* Apply TB bit */
80 bool protect_top = bits->tb_bit_present ? (bits->tb == 0) : 1;
81
82 /* Apply CMP bit */
83 if (bits->cmp_bit_present && bits->cmp == 1) {
84 *len = chip_len - *len;
85 protect_top = !protect_top;
86 }
87
88 /* Calculate start address, ensuring that empty ranges start at 0 */
89 if (protect_top && *len > 0)
90 *start = chip_len - *len;
91 else
92 *start = 0;
93}