blob: cdcb5c53c2076241e6b3937bc01f03f962c454df [file] [log] [blame]
hailfingerf8993012010-12-05 16:33:59 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2008 coresystems GmbH
5 * Copyright (C) 2010 Carl-Daniel Hailfinger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
hailfingerf8993012010-12-05 16:33:59 +000016 */
17
18#include "flash.h"
Stuart Langley6f7f4472020-03-26 16:29:52 +110019#include "chipdrivers.h"
hailfingerf8993012010-12-05 16:33:59 +000020
Souvik Ghoshd75cd672016-06-17 14:21:39 -070021static int unlock_w39_fwh_block(struct flashctx *flash, unsigned int offset)
hailfingerf8993012010-12-05 16:33:59 +000022{
23 chipaddr wrprotect = flash->virtual_registers + offset + 2;
24 uint8_t locking;
25
Souvik Ghoshd75cd672016-06-17 14:21:39 -070026 locking = chip_readb(flash, wrprotect);
hailfingerf8993012010-12-05 16:33:59 +000027 /* Read or write lock present? */
28 if (locking & ((1 << 2) | (1 << 0))) {
29 /* Lockdown active? */
30 if (locking & (1 << 1)) {
stefanctdfd58832011-07-25 20:38:52 +000031 msg_cerr("Can't unlock block at 0x%08x!\n", offset);
hailfingerf8993012010-12-05 16:33:59 +000032 return -1;
33 } else {
stefanctdfd58832011-07-25 20:38:52 +000034 msg_cdbg("Unlocking block at 0x%08x\n", offset);
Souvik Ghoshd75cd672016-06-17 14:21:39 -070035 chip_writeb(flash, 0, wrprotect);
hailfingerf8993012010-12-05 16:33:59 +000036 }
37 }
38
39 return 0;
40}
41
Souvik Ghoshd75cd672016-06-17 14:21:39 -070042static uint8_t w39_idmode_readb(struct flashctx *flash, unsigned int offset)
hailfingerf8993012010-12-05 16:33:59 +000043{
44 chipaddr bios = flash->virtual_memory;
45 uint8_t val;
46
47 /* Product Identification Entry */
Souvik Ghoshd75cd672016-06-17 14:21:39 -070048 chip_writeb(flash, 0xAA, bios + 0x5555);
49 chip_writeb(flash, 0x55, bios + 0x2AAA);
50 chip_writeb(flash, 0x90, bios + 0x5555);
hailfingerf8993012010-12-05 16:33:59 +000051 programmer_delay(10);
52
53 /* Read something, maybe hardware lock bits */
Souvik Ghoshd75cd672016-06-17 14:21:39 -070054 val = chip_readb(flash, bios + offset);
hailfingerf8993012010-12-05 16:33:59 +000055
56 /* Product Identification Exit */
Souvik Ghoshd75cd672016-06-17 14:21:39 -070057 chip_writeb(flash, 0xAA, bios + 0x5555);
58 chip_writeb(flash, 0x55, bios + 0x2AAA);
59 chip_writeb(flash, 0xF0, bios + 0x5555);
hailfingerf8993012010-12-05 16:33:59 +000060 programmer_delay(10);
61
62 return val;
63}
64
65static int printlock_w39_tblwp(uint8_t lock)
66{
67 msg_cdbg("Hardware bootblock locking (#TBL) is %sactive.\n",
68 (lock & (1 << 2)) ? "" : "not ");
69 msg_cdbg("Hardware remaining chip locking (#WP) is %sactive..\n",
70 (lock & (1 << 3)) ? "" : "not ");
71 if (lock & ((1 << 2) | (1 << 3)))
72 return -1;
73
74 return 0;
75}
76
77static int printlock_w39_bootblock_64k16k(uint8_t lock)
78{
79 msg_cdbg("Software 64 kB bootblock locking is %sactive.\n",
80 (lock & (1 << 0)) ? "" : "not ");
81 msg_cdbg("Software 16 kB bootblock locking is %sactive.\n",
82 (lock & (1 << 1)) ? "" : "not ");
83 if (lock & ((1 << 1) | (1 << 0)))
84 return -1;
85
86 return 0;
87}
88
Souvik Ghoshd75cd672016-06-17 14:21:39 -070089static int printlock_w39_common(struct flashctx *flash, unsigned int offset)
hailfingerf8993012010-12-05 16:33:59 +000090{
91 uint8_t lock;
92
93 lock = w39_idmode_readb(flash, offset);
94 msg_cdbg("Lockout bits:\n");
95 return printlock_w39_tblwp(lock);
96}
97
Souvik Ghoshd75cd672016-06-17 14:21:39 -070098static int unlock_w39_fwh(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +000099{
Patrick Georgif3fa2992017-02-02 16:24:44 +0100100 unsigned int i, total_size = flash->chip->total_size * 1024;
Stuart Langley6f7f4472020-03-26 16:29:52 +1100101
hailfingerf8993012010-12-05 16:33:59 +0000102 /* Unlock the complete chip */
Patrick Georgif3fa2992017-02-02 16:24:44 +0100103 for (i = 0; i < total_size; i += flash->chip->page_size)
hailfingerf8993012010-12-05 16:33:59 +0000104 if (unlock_w39_fwh_block(flash, i))
105 return -1;
106
107 return 0;
108}
109
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700110int printlock_w39l040(struct flashctx *flash)
mkarcherb8f55a62011-03-06 17:58:05 +0000111{
112 uint8_t lock;
113 int ret;
114
115 lock = w39_idmode_readb(flash, 0x00002);
116 msg_cdbg("Bottom boot block:\n");
117 ret = printlock_w39_bootblock_64k16k(lock);
118
119 lock = w39_idmode_readb(flash, 0x7fff2);
120 msg_cdbg("Top boot block:\n");
121 ret |= printlock_w39_bootblock_64k16k(lock);
122
123 return ret;
124}
125
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700126int printlock_w39v040a(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000127{
128 uint8_t lock;
129 int ret = 0;
130
131 /* The W39V040A datasheet contradicts itself on the lock register
132 * location: 0x00002 and 0x7fff2 are both mentioned. Pick the one
133 * which is similar to the other chips of the same family.
134 */
135 lock = w39_idmode_readb(flash, 0x7fff2);
136 msg_cdbg("Lockout bits:\n");
137
138 ret = printlock_w39_tblwp(lock);
139 ret |= printlock_w39_bootblock_64k16k(lock);
140
141 return ret;
142}
143
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700144int printlock_w39v040b(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000145{
146 return printlock_w39_common(flash, 0x7fff2);
147}
148
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700149int printlock_w39v040c(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000150{
151 /* Typo in the datasheet? The other chips use 0x7fff2. */
152 return printlock_w39_common(flash, 0xfff2);
153}
154
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700155int printlock_w39v040fa(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000156{
157 int ret = 0;
158
159 ret = printlock_w39v040a(flash);
Stuart Langley6f7f4472020-03-26 16:29:52 +1100160 ret |= printlock_regspace2_uniform_64k(flash);
hailfingerf8993012010-12-05 16:33:59 +0000161
162 return ret;
163}
164
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700165int printlock_w39v040fb(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000166{
167 int ret = 0;
168
169 ret = printlock_w39v040b(flash);
Stuart Langley6f7f4472020-03-26 16:29:52 +1100170 ret |= printlock_regspace2_uniform_64k(flash);
hailfingerf8993012010-12-05 16:33:59 +0000171
172 return ret;
173}
174
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700175int printlock_w39v040fc(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000176{
177 int ret = 0;
178
179 /* W39V040C and W39V040FC use different WP/TBL offsets. */
180 ret = printlock_w39_common(flash, 0x7fff2);
Stuart Langley6f7f4472020-03-26 16:29:52 +1100181 ret |= printlock_regspace2_uniform_64k(flash);
hailfingerf8993012010-12-05 16:33:59 +0000182
183 return ret;
184}
185
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700186int printlock_w39v080a(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000187{
188 return printlock_w39_common(flash, 0xffff2);
189}
190
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700191int printlock_w39v080fa(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000192{
193 int ret = 0;
194
195 ret = printlock_w39v080a(flash);
Stuart Langley6f7f4472020-03-26 16:29:52 +1100196 ret |= printlock_regspace2_uniform_64k(flash);
hailfingerf8993012010-12-05 16:33:59 +0000197
198 return ret;
199}
200
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700201int printlock_w39v080fa_dual(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000202{
203 msg_cinfo("Block locking for W39V080FA in dual mode is "
204 "undocumented.\n");
205 /* Better safe than sorry. */
206 return -1;
207}
208
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700209int unlock_w39v040fb(struct flashctx *flash)
mkarcher64dbd922010-12-26 23:55:12 +0000210{
211 if (unlock_w39_fwh(flash))
212 return -1;
213 if (printlock_w39_common(flash, 0x7fff2))
214 return -1;
215
216 return 0;
217}
218
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700219int unlock_w39v080fa(struct flashctx *flash)
hailfingerf8993012010-12-05 16:33:59 +0000220{
221 if (unlock_w39_fwh(flash))
222 return -1;
223 if (printlock_w39_common(flash, 0xffff2))
224 return -1;
225
226 return 0;
227}
Alan Greenebbee922019-09-02 11:36:59 +1000228
229int printlock_at49f(struct flashctx *flash)
230{
231 uint8_t lock = w39_idmode_readb(flash, 0x00002);
232 msg_cdbg("Hardware bootblock lockout is %sactive.\n",
233 (lock & 0x01) ? "" : "not ");
234 return 0;
235}