4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Paresh Agarwal <paresh.agwl@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
33 #define NVM_TYPE_CALIB 0
34 #define NVM_TYPE_STATIC 1
35 #define NVM_TYPE_DYNAMIC 2
36 #define NVM_FILE_TYPE_POS 36
38 /* NVM Payload information */
39 #define NVM_PAYLOAD_OFFSET_0 48
40 #define NVM_PAYLOAD_LENGTH_0 52
41 #define NVM_PAYLOAD_OFFSET_1 64
42 #define NVM_PAYLOAD_LENGTH_1 68
43 #define NVM_DATA_LEN_POS 80
45 /* Image Path information */
46 #define MODEM_IMAGE_PATH "/opt/modem/modem.bin"
47 #define NVM_DIR_PATH "/csa/nv"
48 #define NV_FILE_PATH NVM_DIR_PATH"/nvdata.bin"
50 /* NV offsets and size */
51 #define MODEM_NV_OFFSET 0xA00000
52 #define MAX_NVDATA_SIZE 0x200000
53 #define NVM_CALIB_OFFSET 0x80000
54 #define NVM_STATIC_OFFSET 0x100000
56 struct nvm_payload_info {
57 unsigned long m_offset_0;
58 unsigned long m_length_0;
59 unsigned long m_offset_1;
60 unsigned long m_length_1;
63 static nvm_error __nvm_file_write(int nvm_type, const char *update_buf, int update_len, int offset)
66 nvm_error ret_val = NVM_NO_ERR;
69 char err_str[256] = {0, };
73 if (NULL == update_buf) {
74 err("Buffer is invalid!!!");
80 msg(" [NVM File] calib.nvm");
81 offset = offset + NVM_CALIB_OFFSET;
85 msg(" [NVM File] static.nvm");
86 offset = offset + NVM_STATIC_OFFSET;
89 case NVM_TYPE_DYNAMIC:
90 msg(" [NVM File] dynamic.nvm");
94 err("[NVM File] Wrong NVM file type: [%d]", nvm_type);
98 /* Open NVM file for Write operation */
99 nv_fd = open(NV_FILE_PATH, O_RDWR);
101 strerror_r(errno, err_str, 255);
102 err("[OPEN] Failed: [%s]", err_str);
106 /* Seek the offset */
107 ret = lseek(nv_fd, (long)offset, SEEK_SET);
109 strerror_r(errno, err_str, 255);
110 err("[SEEK] Failed: [%s]", err_str);
111 ret_val = NVM_RES_LEN_ERR;
113 dbg("Buffer: [0x%x] length: [%d]", update_buf, update_len);
115 /* Write the buffer to file */
116 ret = write(nv_fd, update_buf, update_len);
118 dbg("[WRITE] Successfully updated NVM data");
119 } else if (ret == 0) {
120 strerror_r(errno, err_str, 255);
121 dbg("[WRITE] Nothing is written: [%s]", err_str);
123 strerror_r(errno, err_str, 255);
124 err("[WRITE] Failed: [%s]", err_str);
125 ret_val = NVM_MEM_FULL_ERR;
135 static nvm_error __nvm_write_payload_1(int nvm_type,
136 const char *p_bin_buff, struct nvm_payload_info *nvm1)
138 const char *p_buf_ptr = p_bin_buff;
141 return __nvm_file_write(nvm_type,
142 (p_buf_ptr + NVM_DATA_LEN_POS + nvm1->m_length_0),
147 static nvm_error __nvm_write_payload_0(int nvm_type,
148 const char *p_bin_buff, struct nvm_payload_info *nvm)
153 ret_val = __nvm_file_write(nvm_type,
154 (p_bin_buff + NVM_DATA_LEN_POS),
157 if (NVM_NO_ERR == ret_val) {
158 /* The payload_0 has been done, so calls this method to write payload_1 to file */
159 ret_val = __nvm_write_payload_1(nvm_type, p_bin_buff, nvm);
161 err("Failed to write to NV data file!!!");
167 int nvm_sum_4_bytes(const char *pos)
170 sum = sum | (*(pos+3)) << 24;
171 sum = sum | (*(pos+2)) << 16;
172 sum = sum | (*(pos+1)) << 8;
177 nvm_error nvm_process_nv_update(const char *data)
179 struct nvm_payload_info nvm_info;
184 memset(&nvm_info, 0x0, sizeof(struct nvm_payload_info));
186 /* Determine lengths from the little-endian 4 bytes */
187 nvm_info.m_length_0 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_LENGTH_0]);
188 nvm_info.m_offset_0 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_OFFSET_0]);
189 nvm_info.m_length_1 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_LENGTH_1]);
190 nvm_info.m_offset_1 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_OFFSET_1]);
191 dbg("Offsets - 0th: [%d] 1st: [%d]", nvm_info.m_offset_0, nvm_info.m_offset_1);
193 nvm_type = *(data + NVM_FILE_TYPE_POS);
194 if ((NVM_TYPE_CALIB <= nvm_type)
195 && (NVM_TYPE_DYNAMIC >= nvm_type)) {
196 dbg("NVM type: [%d]", nvm_type);
198 /* Write NVM data to file */
199 ret_val = __nvm_write_payload_0(nvm_type, data, &nvm_info);
201 err("Wrong NVM file type: [%d]", nvm_type);
202 ret_val = NVM_RES_ERR;
208 gboolean nvm_create_nvm_data()
213 char err_str[256] = {0, };
215 gboolean ret_val = FALSE;
218 /* Open modem binary */
219 modem_fd = open(MODEM_IMAGE_PATH, O_RDONLY | O_NDELAY);
221 strerror_r(errno, err_str, 255);
222 err("[OPEN] Failed for (%s): [%s]", MODEM_IMAGE_PATH, err_str);
226 /* Create NV data folder if it doesn't exist */
227 if (mkdir(NVM_DIR_PATH, 0755) < 0) {
228 if (errno != EEXIST) {
229 strerror_r(errno, err_str, 255);
230 err("mkdir() failed: [%s]", err_str);
232 /* Close 'modem_fd' */
235 } else if ((nv_fd = open(NV_FILE_PATH, O_EXCL)) >= 0) {
236 /* NV data file already exists */
237 dbg("File exists: [%s]", NV_FILE_PATH);
239 /* Close 'modem_fd' */
244 dbg("File does't exsits... need to create!!!");
248 /* Change directory permissions */
249 if (chmod(NVM_DIR_PATH, 0755) < 0) {
250 strerror_r(errno, err_str, 255);
251 err("chmod() failed: [%s]", err_str);
253 /* Close 'modem_fd' */
258 /* Open NV data file for different file operations */
259 nv_fd = open(NV_FILE_PATH, O_RDWR | O_CREAT | O_SYNC, S_IRWXU);
261 strerror_r(errno, err_str, 255);
262 err("[OPEN] Failed for (%s): %s", NV_FILE_PATH, err_str);
264 /* Close 'modem_fd' */
269 dbg("Setting the file descriptor offset to NV data in modem.bin");
271 /* Seek pre-defined offset in modem binary */
272 if (lseek(modem_fd, MODEM_NV_OFFSET, SEEK_SET) < 0) {
273 strerror_r(errno, err_str, 255);
274 err("[SEEK] Failed: [%s]", err_str);
278 /* Allocate memory */
279 buffer = g_try_malloc0(MAX_NVDATA_SIZE);
280 if (NULL == buffer) {
281 err("Failed to allocate memory");
285 /* Read NV data from modem binary */
286 if (read(modem_fd, buffer, MAX_NVDATA_SIZE) < 0) {
287 strerror_r(errno, err_str, 255);
288 err("[READ] Failed: [%s]", err_str);
292 /* Write the data read from modem binary to nvdata */
293 if (write(nv_fd, buffer, MAX_NVDATA_SIZE) < 0) {
294 strerror_r(errno, err_str, 255);
295 err("[WRITE} Failed: [%s]", err_str);
302 if (ret_val == FALSE)
303 err("nvdata (%s) creation Failed!!!", NV_FILE_PATH);
305 dbg("nvdata (%s) created Success", NV_FILE_PATH);