4 * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
30 #define NVM_TYPE_CALIB 0
31 #define NVM_TYPE_STATIC 1
32 #define NVM_TYPE_DYNAMIC 2
33 #define NVM_FILE_TYPE_POS 36
35 /* NVM Payload information */
36 #define NVM_PAYLOAD_OFFSET_0 48
37 #define NVM_PAYLOAD_LENGTH_0 52
38 #define NVM_PAYLOAD_OFFSET_1 64
39 #define NVM_PAYLOAD_LENGTH_1 68
40 #define NVM_DATA_LEN_POS 80
42 /* Image Path information */
43 #define MODEM_IMAGE_PATH "/boot/modem.bin"
44 #define NVM_DIR_PATH "/csa/nv"
45 #define NV_FILE_PATH NVM_DIR_PATH "/nvdata.bin"
47 /* NV offsets and size */
48 #define MODEM_NV_OFFSET 0xA00000
49 #define MAX_NVDATA_SIZE 0x200000
50 #define NVM_CALIB_OFFSET 0x80000
51 #define NVM_STATIC_OFFSET 0x100000
53 struct nvm_payload_info {
54 unsigned long m_offset_0;
55 unsigned long m_length_0;
56 unsigned long m_offset_1;
57 unsigned long m_length_1;
60 static nvm_error __nvm_file_write(int nvm_type, const char *update_buf, int update_len, int offset)
63 nvm_error ret_val = NVM_NO_ERR;
66 char err_str[256] = {0, };
70 if (NULL == update_buf) {
71 err("Buffer is invalid!!!");
77 msg(" [NVM File] calib.nvm");
78 offset = offset + NVM_CALIB_OFFSET;
82 msg(" [NVM File] static.nvm");
83 offset = offset + NVM_STATIC_OFFSET;
86 case NVM_TYPE_DYNAMIC:
87 msg(" [NVM File] dynamic.nvm");
91 err("[NVM File] Wrong NVM file type: [%d]", nvm_type);
95 /* Open NVM file for Write operation */
96 nv_fd = open(NV_FILE_PATH, O_RDWR);
98 strerror_r(errno, err_str, 255);
99 err("[OPEN] Failed: [%s]", err_str);
103 /* Seek the offset */
104 ret = lseek(nv_fd, (long)offset, SEEK_SET);
106 strerror_r(errno, err_str, 255);
107 err("[SEEK] Failed: [%s]", err_str);
108 ret_val = NVM_RES_LEN_ERR;
110 dbg("Buffer: [0x%x] length: [%d]", update_buf, update_len);
112 /* Write the buffer to file */
113 ret = write(nv_fd, update_buf, update_len);
115 dbg("[WRITE] Successfully updated NVM data");
116 } else if (ret == 0) {
117 strerror_r(errno, err_str, 255);
118 dbg("[WRITE] Nothing is written: [%s]", err_str);
120 strerror_r(errno, err_str, 255);
121 err("[WRITE] Failed: [%s]", err_str);
122 ret_val = NVM_MEM_FULL_ERR;
132 static nvm_error __nvm_write_payload_1(int nvm_type,
133 const char *p_bin_buff, struct nvm_payload_info *nvm1)
135 const char *p_buf_ptr = p_bin_buff;
138 return __nvm_file_write(nvm_type,
139 (p_buf_ptr + NVM_DATA_LEN_POS + nvm1->m_length_0),
144 static nvm_error __nvm_write_payload_0(int nvm_type,
145 const char *p_bin_buff, struct nvm_payload_info *nvm)
150 ret_val = __nvm_file_write(nvm_type,
151 (p_bin_buff + NVM_DATA_LEN_POS),
154 if (NVM_NO_ERR == ret_val) {
155 /* The payload_0 has been done, so calls this method to write payload_1 to file */
156 ret_val = __nvm_write_payload_1(nvm_type, p_bin_buff, nvm);
158 err("Failed to write to NV data file!!!");
164 int nvm_sum_4_bytes(const char *pos)
167 sum = sum | (*(pos+3)) << 24;
168 sum = sum | (*(pos+2)) << 16;
169 sum = sum | (*(pos+1)) << 8;
174 nvm_error nvm_process_nv_update(const char *data)
176 struct nvm_payload_info nvm_info;
181 memset(&nvm_info, 0x0, sizeof(struct nvm_payload_info));
183 /* Determine lengths from the little-endian 4 bytes */
184 nvm_info.m_length_0 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_LENGTH_0]);
185 nvm_info.m_offset_0 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_OFFSET_0]);
186 nvm_info.m_length_1 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_LENGTH_1]);
187 nvm_info.m_offset_1 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_OFFSET_1]);
188 dbg("Offsets - 0th: [%d] 1st: [%d]", nvm_info.m_offset_0, nvm_info.m_offset_1);
190 nvm_type = *(data + NVM_FILE_TYPE_POS);
191 if ((NVM_TYPE_CALIB <= nvm_type)
192 && (NVM_TYPE_DYNAMIC >= nvm_type)) {
193 dbg("NVM type: [%d]", nvm_type);
195 /* Write NVM data to file */
196 ret_val = __nvm_write_payload_0(nvm_type, data, &nvm_info);
198 err("Wrong NVM file type: [%d]", nvm_type);
199 ret_val = NVM_RES_ERR;
205 gboolean nvm_create_nvm_data()
210 char err_str[256] = {0, };
212 gboolean ret_val = FALSE;
215 /* Open modem binary */
216 modem_fd = open(MODEM_IMAGE_PATH, O_RDONLY | O_NDELAY);
218 strerror_r(errno, err_str, 255);
219 err("[OPEN] Failed for (%s): [%s]", MODEM_IMAGE_PATH, err_str);
223 /* Create NV data folder if it doesn't exist */
224 if (mkdir(NVM_DIR_PATH, 0755) < 0) {
225 if (errno != EEXIST) {
226 strerror_r(errno, err_str, 255);
227 err("mkdir() failed: [%s]", err_str);
229 /* Close 'modem_fd' */
232 } else if (open(NV_FILE_PATH, O_EXCL) > 0) {
233 /* NV data file already exists */
234 dbg("File exists: [%s]", NV_FILE_PATH);
236 /* Close 'modem_fd' */
240 dbg("File does't exsits... need to create!!!");
244 /* Change directory permissions */
245 if (chmod(NVM_DIR_PATH, 0755) < 0) {
246 strerror_r(errno, err_str, 255);
247 err("chmod() failed: [%s]", err_str);
249 /* Close 'modem_fd' */
254 /* Open NV data file for different file operations */
255 nv_fd = open(NV_FILE_PATH, O_RDWR | O_CREAT | O_SYNC, S_IRWXU);
257 strerror_r(errno, err_str, 255);
258 err("[OPEN] Failed for (%s): %s", NV_FILE_PATH, err_str);
260 /* Close 'modem_fd' */
265 dbg("Setting the file descriptor offset to NV data in modem.bin");
267 /* Seek pre-defined offset in modem binary */
268 if (lseek(modem_fd, MODEM_NV_OFFSET, SEEK_SET) < 0) {
269 strerror_r(errno, err_str, 255);
270 err("[SEEK] Failed: [%s]", err_str);
274 /* Allocate memory */
275 buffer = g_try_malloc0(MAX_NVDATA_SIZE);
276 if (NULL == buffer) {
277 err("Failed to allocate memory");
281 /* Read NV data from modem binary */
282 if (read(modem_fd, buffer, MAX_NVDATA_SIZE) < 0) {
283 strerror_r(errno, err_str, 255);
284 err("[READ] Failed: [%s]", err_str);
288 /* Write the data read from modem binary to nvdata */
289 if (write(nv_fd, buffer, MAX_NVDATA_SIZE) < 0) {
290 strerror_r(errno, err_str, 255);
291 err("[WRITE} Failed: [%s]", err_str);
298 if (ret_val == FALSE) {
299 err("nvdata (%s) creation Failed!!!", NV_FILE_PATH);
301 dbg("nvdata (%s) created Success", NV_FILE_PATH);