1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 * Description: diag memory read and write
15 * This file should be changed only infrequently and with great care.
16 */
17
18 #include "diag_cmd_mem_read_write.h"
19 #include "securec.h"
20 #include "diag_cmd_mem_read_write_st.h"
21 #include "soc_diag_cmd_id.h"
22 #include "errcode.h"
23
24 #define REPORT_DATA_PER_SIZE 64
25
26 typedef struct {
27 mem_read_ind_head_t head;
28 uint8_t data[REPORT_DATA_PER_SIZE];
29 } mem_read_ind_common_t;
30
diag_cmd_permit_read(uintptr_t start_addr,uintptr_t end_addr)31 __attribute__((weak)) bool diag_cmd_permit_read(uintptr_t start_addr, uintptr_t end_addr)
32 {
33 unused(start_addr);
34 unused(end_addr);
35 return true;
36 }
37
diag_cmd_permit_write(uintptr_t start_addr,uintptr_t end_addr)38 __attribute__((weak)) bool diag_cmd_permit_write(uintptr_t start_addr, uintptr_t end_addr)
39 {
40 unused(start_addr);
41 unused(end_addr);
42 return true;
43 }
44
diag_cmd_mem32(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)45 errcode_t diag_cmd_mem32(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size, diag_option_t *option)
46 {
47 unused(cmd_param_size);
48 mem_read_cmd_t cmd;
49 mem_read32_ind_t ind;
50 uint32_t num = 0;
51 (void)memcpy_s(&cmd, sizeof(mem_read_cmd_t), cmd_param, sizeof(mem_read_cmd_t));
52 (void)memset_s(&ind, sizeof(mem_read32_ind_t), 0, sizeof(mem_read32_ind_t));
53 uintptr_t end_addr = cmd.start_addr + (cmd.cnt * sizeof(uint32_t));
54 if (diag_cmd_permit_read(cmd.start_addr, end_addr) == false) {
55 return ERRCODE_FAIL;
56 }
57
58 ind.head.start_addr = cmd.start_addr;
59 while (ind.head.start_addr < end_addr) {
60 ind.head.start_addr = ind.head.start_addr + num * sizeof(uint32_t);
61 ind.head.size = uapi_min(end_addr - ind.head.start_addr, REPORT_DATA_PER_SIZE);
62 num = ind.head.size / (uint32_t)sizeof(uint32_t);
63 for (uint32_t c = 0; c < num; c++) {
64 uintptr_t addr = ind.head.start_addr + (c * sizeof(uint32_t));
65 uapi_reg_read32(addr, ind.data[c]);
66 }
67 (void)uapi_diag_report_packet(cmd_id, option, (uint8_t *)&ind,
68 (uint16_t)sizeof(mem_read_ind_head_t) + (uint16_t)ind.head.size, true);
69 }
70 return ERRCODE_SUCC;
71 }
72
diag_cmd_mem16(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)73 errcode_t diag_cmd_mem16(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size, diag_option_t *option)
74 {
75 mem_read_cmd_t cmd;
76 mem_read16_ind_t ind;
77 uint32_t num = 0;
78 (void)memcpy_s(&cmd, sizeof(mem_read_cmd_t), cmd_param, sizeof(mem_read_cmd_t));
79 (void)memset_s(&ind, sizeof(mem_read16_ind_t), 0, sizeof(mem_read16_ind_t));
80 uintptr_t end_addr = cmd.start_addr + (cmd.cnt * sizeof(uint16_t));
81 if (diag_cmd_permit_read(cmd.start_addr, end_addr) == false) {
82 return ERRCODE_FAIL;
83 }
84 unused(cmd_param_size);
85 ind.head.start_addr = cmd.start_addr;
86 while (ind.head.start_addr < end_addr) {
87 ind.head.start_addr = ind.head.start_addr + num * sizeof(uint16_t);
88 ind.head.size = uapi_min(end_addr - ind.head.start_addr, REPORT_DATA_PER_SIZE);
89 num = ind.head.size / (uint32_t)sizeof(uint16_t);
90 for (uint32_t c = 0; c < num; c++) {
91 uintptr_t addr = ind.head.start_addr + (c * sizeof(uint16_t));
92 uapi_reg_read16(addr, ind.data[c]);
93 }
94 (void)uapi_diag_report_packet(cmd_id, option, (uint8_t *)&ind,
95 (uint16_t)sizeof(mem_read_ind_head_t) + (uint16_t)ind.head.size, true);
96 }
97 return ERRCODE_SUCC;
98 }
99
diag_cmd_mem8(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)100 errcode_t diag_cmd_mem8(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size, diag_option_t *option)
101 {
102 mem_read_cmd_t cmd;
103 mem_read8_ind_t ind;
104 uint32_t num = 0;
105 (void)memcpy_s(&cmd, sizeof(mem_read_cmd_t), cmd_param, sizeof(mem_read_cmd_t));
106 (void)memset_s(&ind, sizeof(mem_read8_ind_t), 0, sizeof(mem_read8_ind_t));
107 uintptr_t end_addr = cmd.start_addr + (cmd.cnt * sizeof(uint8_t));
108 if (diag_cmd_permit_read(cmd.start_addr, end_addr) == false) {
109 return ERRCODE_FAIL;
110 }
111 unused(cmd_param_size);
112 ind.head.start_addr = cmd.start_addr;
113 while (ind.head.start_addr < end_addr) {
114 ind.head.start_addr = ind.head.start_addr + num * sizeof(uint8_t);
115 ind.head.size = uapi_min(end_addr - ind.head.start_addr, REPORT_DATA_PER_SIZE);
116 num = ind.head.size / (uint32_t)sizeof(uint8_t);
117 for (uint32_t c = 0; c < num; c++) {
118 uintptr_t addr = ind.head.start_addr + (c * sizeof(uint8_t));
119 uapi_reg_read8(addr, ind.data[c]);
120 }
121 (void)uapi_diag_report_packet(cmd_id, option, (uint8_t *)&ind,
122 (uint16_t)sizeof(mem_read_ind_head_t) + (uint16_t)ind.head.size, true);
123 }
124 return ERRCODE_SUCC;
125 }
126
diag_cmd_w1(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)127 errcode_t diag_cmd_w1(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size, diag_option_t *option)
128 {
129 mem_write_cmd_t cmd;
130 mem_write_ind_t ind;
131 unused(cmd_param_size);
132
133 (void)memcpy_s(&cmd, sizeof(mem_write_cmd_t), cmd_param, sizeof(mem_read_cmd_t));
134 uapi_reg_write8(cmd.start_addr, (uint8_t)cmd.val);
135
136 ind.ret = ERRCODE_SUCC;
137 uapi_diag_report_packet(cmd_id, option, (uint8_t *)&ind, (uint16_t)sizeof(mem_write_ind_t), true);
138 return ERRCODE_SUCC;
139 }
140
diag_cmd_w2(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)141 errcode_t diag_cmd_w2(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size, diag_option_t *option)
142 {
143 mem_write_cmd_t cmd;
144 mem_write_ind_t ind;
145 unused(cmd_param_size);
146
147 (void)memcpy_s(&cmd, sizeof(mem_write_cmd_t), cmd_param, sizeof(mem_write_cmd_t));
148 uapi_reg_write16(cmd.start_addr, (uint16_t)cmd.val);
149
150 ind.ret = ERRCODE_SUCC;
151 uapi_diag_report_packet(cmd_id, option, (uint8_t *)&ind, (uint16_t)sizeof(mem_write_ind_t), true);
152 return ERRCODE_SUCC;
153 }
154
diag_cmd_w4(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)155 errcode_t diag_cmd_w4(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size, diag_option_t *option)
156 {
157 mem_write_cmd_t cmd;
158 mem_write_ind_t ind;
159 unused(cmd_param_size);
160
161 (void)memcpy_s(&cmd, sizeof(mem_write_cmd_t), cmd_param, sizeof(mem_write_cmd_t));
162 uapi_reg_write32(cmd.start_addr, cmd.val);
163
164 ind.ret = ERRCODE_SUCC;
165 uapi_diag_report_packet(cmd_id, option, (uint8_t *)&ind, (uint16_t)sizeof(mem_write_ind_t), true);
166 return ERRCODE_SUCC;
167 }
168
diag_cmd_mem_operate(uint16_t cmd_id,void * cmd_param,uint16_t cmd_param_size,diag_option_t * option)169 errcode_t diag_cmd_mem_operate(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size, diag_option_t *option)
170 {
171 switch (cmd_id) {
172 case DIAG_CMD_MEM_MEM32:
173 return diag_cmd_mem32(cmd_id, cmd_param, cmd_param_size, option);
174 case DIAG_CMD_MEM_MEM16:
175 return diag_cmd_mem16(cmd_id, cmd_param, cmd_param_size, option);
176 case DIAG_CMD_MEM_MEM8:
177 return diag_cmd_mem8(cmd_id, cmd_param, cmd_param_size, option);
178 case DIAG_CMD_MEM_W1:
179 return diag_cmd_w1(cmd_id, cmd_param, cmd_param_size, option);
180 case DIAG_CMD_MEM_W2:
181 return diag_cmd_w2(cmd_id, cmd_param, cmd_param_size, option);
182 case DIAG_CMD_MEM_W4:
183 return diag_cmd_w4(cmd_id, cmd_param, cmd_param_size, option);
184 default:
185 return ERRCODE_NOT_SUPPORT;
186 }
187 }
188