FreeCalypso > hg > freecalypso-tools
comparison loadtools/flamdsec.c @ 977:511e2b85c115
fc-loadtool: implement flash lock-state command
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 01 Dec 2023 07:51:01 +0000 |
parents | |
children | c5133c3c11b1 |
comparison
equal
deleted
inserted
replaced
976:ff4ce8d5ece4 | 977:511e2b85c115 |
---|---|
1 /* | |
2 * This module is a place to implement commands that are specific to | |
3 * security features (OTP, sector locking) of AMD-style flash chips. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <stdio.h> | |
8 #include <stdint.h> | |
9 #include <stdlib.h> | |
10 #include "flash.h" | |
11 | |
12 extern struct flash_bank_info flash_bank_info[2]; | |
13 | |
14 static | |
15 issue_read_id(base_addr) | |
16 uint32_t base_addr; | |
17 { | |
18 if (do_w16(base_addr + 0xAAA, 0xAA)) { | |
19 bad_w16: fprintf(stderr, | |
20 "unexpected response to w16 in read ID cmd sequence - aborting\n"); | |
21 return(-1); | |
22 } | |
23 if (do_w16(base_addr + 0x554, 0x55)) | |
24 goto bad_w16; | |
25 if (do_w16(base_addr + 0xAAA, 0x90)) | |
26 goto bad_w16; | |
27 return(0); | |
28 } | |
29 | |
30 static | |
31 issue_reset_cmd(base_addr) | |
32 uint32_t base_addr; | |
33 { | |
34 if (do_w16(base_addr + 0xAAA, 0xF0)) { | |
35 fprintf(stderr, | |
36 "unexpected response to w16 when resetting flash to read mode!\n"); | |
37 return(-1); | |
38 } | |
39 return(0); | |
40 } | |
41 | |
42 static | |
43 read_mode_lock_word(base_addr, word_offset, retp) | |
44 uint32_t base_addr, word_offset; | |
45 uint16_t *retp; | |
46 { | |
47 if (do_w16(base_addr + 0xAAA, 0xAA)) { | |
48 bad_w16: fprintf(stderr, | |
49 "unexpected response to w16 in mode lock query sequence - aborting\n"); | |
50 return(-1); | |
51 } | |
52 if (do_w16(base_addr + 0x554, 0x55)) | |
53 goto bad_w16; | |
54 if (do_w16(base_addr + 0xAAA, 0x60)) | |
55 goto bad_w16; | |
56 if (do_w16(base_addr + word_offset, 0x48)) | |
57 goto bad_w16; | |
58 if (do_r16(base_addr + word_offset, retp) < 0) | |
59 return(-1); | |
60 return(0); | |
61 } | |
62 | |
63 static | |
64 pln_special_mode_entry(base_addr, mode_opc) | |
65 uint32_t base_addr; | |
66 uint16_t mode_opc; | |
67 { | |
68 if (do_w16(base_addr + 0xAAA, 0xAA)) { | |
69 bad_w16: fprintf(stderr, | |
70 "unexpected response to w16 in PL-N special mode entry sequence - aborting\n"); | |
71 return(-1); | |
72 } | |
73 if (do_w16(base_addr + 0x554, 0x55)) | |
74 goto bad_w16; | |
75 if (do_w16(base_addr + 0xAAA, mode_opc)) | |
76 goto bad_w16; | |
77 return(0); | |
78 } | |
79 | |
80 static | |
81 pln_special_mode_exit(base_addr) | |
82 uint32_t base_addr; | |
83 { | |
84 if (do_w16(base_addr, 0x90)) { | |
85 bad_w16: fprintf(stderr, | |
86 "unexpected response to w16 in PL-N special mode exit sequence - aborting\n"); | |
87 return(-1); | |
88 } | |
89 if (do_w16(base_addr, 0x00)) | |
90 goto bad_w16; | |
91 return(0); | |
92 } | |
93 | |
94 flashcmd_lock_state(argc, argv, bank) | |
95 char **argv; | |
96 { | |
97 struct flash_bank_info *bi; | |
98 struct amd_lock_info *li; | |
99 struct lock_group_desc *grp; | |
100 uint32_t offset, part_addr; | |
101 uint16_t word; | |
102 unsigned ng, nb; | |
103 | |
104 if (argc > 2) { | |
105 fprintf(stderr, "error: too many arguments\n"); | |
106 return(-1); | |
107 } | |
108 if (flash_detect(bank, 0) < 0) | |
109 return(-1); | |
110 bi = flash_bank_info + bank; | |
111 li = bi->amd_lock; | |
112 if (!li) { | |
113 fprintf(stderr, | |
114 "Operation not supported for this flash chip type\n"); | |
115 return(-1); | |
116 } | |
117 offset = 0; | |
118 for (ng = 0; ng < li->ngroups; ng++) { | |
119 grp = li->groups + ng; | |
120 if (grp->part_begin) { | |
121 part_addr = bi->base_addr + offset; | |
122 if (issue_read_id(part_addr) < 0) | |
123 return(-1); | |
124 } | |
125 if (offset == 0 && li->have_status_word_3) { | |
126 if (do_r16(bi->base_addr + 6, &word) < 0) | |
127 return(-1); | |
128 printf("Global status word 3: %04X\n", word); | |
129 } | |
130 if (offset == 0 && li->have_status_word_7) { | |
131 if (do_r16(bi->base_addr + 0xE, &word) < 0) | |
132 return(-1); | |
133 printf("Global status word 7: %04X\n", word); | |
134 } | |
135 for (nb = 0; nb < grp->nblocks; nb++) { | |
136 if (do_r16(bi->base_addr + offset + 4, &word) < 0) | |
137 return(-1); | |
138 printf("Sector%s at 0x%X: %s\n", | |
139 grp->is_group ? " group" : "", offset, | |
140 (word & 1) ? "locked" : "unlocked"); | |
141 offset += grp->block_size; | |
142 } | |
143 if (grp->part_end) { | |
144 if (issue_reset_cmd(part_addr) < 0) | |
145 return(-1); | |
146 } | |
147 } | |
148 if (li->have_mode_lock_bits) { | |
149 if (read_mode_lock_word(bi->base_addr, 0x14, &word) < 0) | |
150 return(-1); | |
151 printf("Password Protection Mode lock: %04X\n", word); | |
152 if (issue_reset_cmd(bi->base_addr) < 0) | |
153 return(-1); | |
154 if (read_mode_lock_word(bi->base_addr, 0x24, &word) < 0) | |
155 return(-1); | |
156 printf("Persistent Protection Mode lock: %04X\n", word); | |
157 if (issue_reset_cmd(bi->base_addr) < 0) | |
158 return(-1); | |
159 } | |
160 if (li->have_pln_lock_reg) { | |
161 if (pln_special_mode_entry(bi->base_addr, 0x40) < 0) | |
162 return(-1); | |
163 if (do_r16(bi->base_addr, &word) < 0) | |
164 return(-1); | |
165 printf("PL-N Lock Register: %04X\n", word); | |
166 if (pln_special_mode_exit(bi->base_addr) < 0) | |
167 return(-1); | |
168 } | |
169 return(0); | |
170 } |