1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include "wm_sasc.h"
19
20 extern void dumpBuffer(char *name, char* buffer, int len);
21
22 #define TEST_DEBUG_EN 1
23 #if TEST_DEBUG_EN
24 #define TEST_DEBUG(fmt, ...) printf("%s: "fmt, __func__, ##__VA_ARGS__)
25 #else
26 #define TEST_DEBUG(fmt, ...)
27 #endif
28
switch_to_ree(void)29 static void switch_to_ree(void)
30 {
31 csi_vic_disable_irq(SYS_TICK_IRQn);
32 __asm__ volatile(
33 "mtcr r14, cr<6, 3> \n"
34 "mfcr a3, psr\n"
35 "bclri a3, 30 \n" // Clear PSR.T
36 "mtcr a3, psr \n"
37 "psrset ee, ie \n" // Set EE & IE
38 "mfcr a3, psr\n"
39 "bseti a3, 9 \n" // Set MM
40 "mtcr a3, psr \n"
41 );
42 __asm__ volatile("mtcr %0, vbr" : : "r"(& (__Vectors)));
43 TEST_DEBUG("switched to ree\n");
44 }
45
get_block_from_addr(uint32_t base_addr)46 static SASC_Type* get_block_from_addr(uint32_t base_addr)
47 {
48 if (base_addr >= 0x8000000 && base_addr < 0x10000000) {
49 return SASC_FLASH;
50 } else if (base_addr < 0x20028000 && base_addr >= 0x20000000) {
51 return SASC_B1;
52 } else if (base_addr < 0x20048000 && base_addr >= 0x20028000) {
53 return SASC_B2;
54 }
55 return NULL;
56 }
57
wm_sasc_config_region(SASC_Type * block,uint32_t idx,uint32_t base_addr,sasc_region_size_e size,sasc_region_attr_t * attr,uint32_t enable)58 static void wm_sasc_config_region(SASC_Type *block, uint32_t idx, uint32_t base_addr, sasc_region_size_e size,
59 sasc_region_attr_t *attr, uint32_t enable)
60 {
61 base_addr &= 0x03FFFFFC;
62 block->REGION[idx] = size | (base_addr << 6);
63 // printf("region %d: 0x%x\n", idx, size | (base_addr << 6));
64 block->CAR = _R2_Pos(attr->car, idx) | (block->CAR & ~(_R2_Msk(idx)));
65 switch (attr->car) {
66 case SASC_UN_SE_USER:
67 block->AP0 = _R2_Pos(attr->ap, idx) | (block->AP0 & ~(_R2_Msk(idx)));
68 block->CD0 = _R2_Pos(attr->cd, idx) | (block->CD0 & ~(_R2_Msk(idx)));
69 break;
70 case SASC_UN_SE_SUPER:
71 block->AP1 = _R2_Pos(attr->ap, idx) | (block->AP1 & ~(_R2_Msk(idx)));
72 block->CD1 = _R2_Pos(attr->cd, idx) | (block->CD1 & ~(_R2_Msk(idx)));
73 break;
74 case SASC_SE_USER:
75 block->AP2 = _R2_Pos(attr->ap, idx) | (block->AP2 & ~(_R2_Msk(idx)));
76 block->CD2 = _R2_Pos(attr->cd, idx) | (block->CD2 & ~(_R2_Msk(idx)));
77 break;
78 default:
79 break;
80 }
81 block->CR = _R1_Pos(enable, idx) | (block->CR & ~(_R1_Msk(idx)));
82 }
83
wm_sasc_enable_region(SASC_Type * block,uint32_t idx)84 void wm_sasc_enable_region(SASC_Type *block, uint32_t idx)
85 {
86 block->CR = _R1_Pos(1, idx) | (block->CR & ~(_R1_Msk(idx)));
87 }
88
wm_sasc_disable_region(SASC_Type * block,uint32_t idx)89 void wm_sasc_disable_region(SASC_Type *block, uint32_t idx)
90 {
91 block->CR = (block->CR & ~(_R1_Msk(idx)));
92 }
93
set_region_protect(uint32_t base_addr,uint32_t idx,sasc_region_size_e size,sasc_region_attr_t * attr)94 void set_region_protect(uint32_t base_addr, uint32_t idx, sasc_region_size_e size, sasc_region_attr_t *attr)
95 {
96 SASC_Type* block = get_block_from_addr(base_addr);
97
98 TEST_DEBUG("base_addr %x idx %u size 0x%x ap %d cd %d car %d\n", \
99 base_addr, idx, size, attr->ap, attr->cd, attr->car);
100 if (base_addr >= 0x8000000 && base_addr < 0x10000000) {
101 base_addr &= 0x1FFFFFF;
102 } else if (base_addr < 0x20028000 && base_addr >= 0x20000000) {
103 base_addr &= 0x3FFFF;
104 } else if (base_addr < 0x20048000 && base_addr >= 0x20028000) {
105 base_addr &= 0x7FFFF;
106 }
107 wm_sasc_config_region(block, idx, base_addr, size, attr, 1);
108 }
109
110 /**
111 *******************************************************
112 * TEST CODE IS BELOW
113 *******************************************************
114 */
115
access_region(uint32_t base_addr,sasc_region_size_e size,sasc_region_attr_t * attr,int pos)116 void access_region(uint32_t base_addr, sasc_region_size_e size, sasc_region_attr_t *attr, int pos)
117 {
118 char dest[4] = {0xa5, 0xa5, 0xa5, 0xa5};
119 uint32_t s = 1 << (size - 3);
120 TEST_DEBUG("base_addr %x size 0x%x\n", base_addr, s);
121
122 switch (pos) {
123 case 0:
124 memcpy_s(dest, sizeof(dest), (char*)(base_addr + s), sizeof(dest));
125 TEST_DEBUG("Behind addr %x size 0x%lx can read\n", base_addr + s, (unsigned long)sizeof(dest));
126 TEST_DEBUG("start to read addr %x size 0x%lx\n", \
127 base_addr + s - (uint32_t)sizeof(dest), (unsigned long)sizeof(dest));
128 memcpy_s(dest, sizeof(dest), (char*)(base_addr + s - sizeof(dest)), sizeof(dest));
129 TEST_DEBUG("addr %x size 0x%lx can read\n", \
130 base_addr + s - (uint32_t)sizeof(dest), (unsigned long)sizeof(dest));
131 break;
132 case 1:
133 memcpy_s(dest, sizeof(dest), (char*)(base_addr - sizeof(dest)), sizeof(dest));
134 TEST_DEBUG("Front addr %x size 0x%lx can read\n", \
135 base_addr - (uint32_t)sizeof(dest), (unsigned long)sizeof(dest));
136 TEST_DEBUG("start to read addr %x size 0x%lx\n", base_addr, (unsigned long)sizeof(dest));
137 memcpy_s(dest, sizeof(dest), (char*)base_addr, sizeof(dest));
138 TEST_DEBUG("base_addr %x size 0x%lx can read\n", base_addr, (unsigned long)sizeof(dest));
139 break;
140 case 2:
141 memcpy_s((char*)(base_addr - sizeof(dest)), sizeof(base_addr -sizeof(dest)), dest, sizeof(dest));
142 TEST_DEBUG("Front addr %x size 0x%lx can write\n", \
143 base_addr - (uint32_t)sizeof(dest), (unsigned long)sizeof(dest));
144 TEST_DEBUG("start to write addr %x size 0x%lx\n", base_addr, (unsigned long)sizeof(dest));
145 memcpy_s((char*)base_addr, sizeof(base_addr), dest, sizeof(dest));
146 TEST_DEBUG("base_addr %x size 0x%lx can write\n", base_addr, (unsigned long)sizeof(dest));
147 break;
148 default:
149 memcpy_s((char*)(base_addr + s), sizeof(base_addr + s), dest, sizeof(dest));
150 TEST_DEBUG("Behind addr %x size 0x%lx can write\n", base_addr + s, (unsigned long)sizeof(dest));
151 TEST_DEBUG("start to write addr %x size 0x%lx\n", \
152 base_addr + s - (uint32_t)sizeof(dest), (unsigned long)sizeof(dest));
153 memcpy_s((char*)(base_addr + s - sizeof(dest)), sizeof(base_addr + s - sizeof(dest)), dest, sizeof(dest));
154 TEST_DEBUG("addr %x size 0x%lx can write\n", \
155 base_addr + s - (uint32_t)sizeof(dest), (unsigned long)sizeof(dest));
156 break;
157 }
158 dumpBuffer("dest", dest, sizeof(dest));
159 }
160
sasc_region_security_test(int num)161 int sasc_region_security_test(int num)
162 {
163 sasc_region_attr_t attr;
164 attr.ap = SASC_AP_DENYALL;
165 attr.cd = SASC_CD_DA_OF;
166 attr.car = SASC_SE_SUPER;
167 set_region_protect(0x08010000, 0, SASC_REGION_SIZE_64KB, &attr);
168 set_region_protect(0x20010000, 1, SASC_REGION_SIZE_16KB, &attr);
169 set_region_protect(0x20030000, 2, SASC_REGION_SIZE_32KB, &attr);
170
171 // SASC_B2->REGION[0] = SASC_REGION_SIZE_32KB | (0x8000 << 6);
172
173 switch_to_ree();
174
175 switch (num) {
176 case 0:
177 access_region(0x20010000, SASC_REGION_SIZE_16KB, &attr, 0);
178 break;
179 case 1:
180 access_region(0x20010000, SASC_REGION_SIZE_16KB, &attr, 1);
181 break;
182 case 2:
183 access_region(0x20010000, SASC_REGION_SIZE_16KB, &attr, 2);
184 break;
185 case 3:
186 access_region(0x20010000, SASC_REGION_SIZE_16KB, &attr, 3);
187 break;
188 case 4:
189 access_region(0x20030000, SASC_REGION_SIZE_32KB, &attr, 0);
190 break;
191 case 5:
192 access_region(0x20030000, SASC_REGION_SIZE_32KB, &attr, 1);
193 break;
194 case 6:
195 access_region(0x20030000, SASC_REGION_SIZE_32KB, &attr, 2);
196 break;
197 case 7:
198 access_region(0x20030000, SASC_REGION_SIZE_32KB, &attr, 3);
199 break;
200 case 8:
201 access_region(0x08010000, SASC_REGION_SIZE_64KB, &attr, 0);
202 break;
203 case 9:
204 access_region(0x08010000, SASC_REGION_SIZE_64KB, &attr, 1);
205 break;
206 default:
207 break;
208 }
209 return -1;
210 }
211
212