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.
32 #define NVM_TYPE_CALIB 0
33 #define NVM_TYPE_STATIC 1
34 #define NVM_TYPE_DYNAMIC 2
35 #define NVM_FILE_TYPE_POS 36
37 /* NVM Payload information */
38 #define NVM_PAYLOAD_OFFSET_0 48
39 #define NVM_PAYLOAD_LENGTH_0 52
40 #define NVM_PAYLOAD_OFFSET_1 64
41 #define NVM_PAYLOAD_LENGTH_1 68
42 #define NVM_DATA_LEN_POS 80
44 /* Image Path information */
45 #define MODEM_IMAGE_PATH "/boot/modem.bin"
46 #define NVM_DIR_PATH "/csa/nv"
47 #define NV_FILE_PATH NVM_DIR_PATH "/nvdata.bin"
49 /* NV offsets and size */
50 #define MODEM_NV_OFFSET 0xA00000
51 #define MAX_NVDATA_SIZE 0x200000
52 #define NVM_CALIB_OFFSET 0x80000
53 #define NVM_STATIC_OFFSET 0x100000
55 struct nvm_payload_info {
56 unsigned long m_offset_0;
57 unsigned long m_length_0;
58 unsigned long m_offset_1;
59 unsigned long m_length_1;
62 static nvm_error __nvm_file_write(int nvm_type, const char *update_buf, int update_len, int offset)
65 nvm_error ret_val = NVM_NO_ERR;
68 char err_str[256] = {0, };
72 if (NULL == update_buf) {
73 err("Buffer is invalid!!!");
79 msg(" [NVM File] calib.nvm");
80 offset = offset + NVM_CALIB_OFFSET;
84 msg(" [NVM File] static.nvm");
85 offset = offset + NVM_STATIC_OFFSET;
88 case NVM_TYPE_DYNAMIC:
89 msg(" [NVM File] dynamic.nvm");
93 err("[NVM File] Wrong NVM file type: [%d]", nvm_type);
97 /* Open NVM file for Write operation */
98 nv_fd = open(NV_FILE_PATH, O_RDWR);
100 strerror_r(errno, err_str, 255);
101 err("[OPEN] Failed: [%s]", err_str);
105 /* Seek the offset */
106 ret = lseek(nv_fd, (long)offset, SEEK_SET);
108 strerror_r(errno, err_str, 255);
109 err("[SEEK] Failed: [%s]", err_str);
110 ret_val = NVM_RES_LEN_ERR;
112 dbg("Buffer: [0x%x] length: [%d]", update_buf, update_len);
114 /* Write the buffer to file */
115 ret = write(nv_fd, update_buf, update_len);
117 dbg("[WRITE] Successfully updated NVM data");
118 } else if (ret == 0) {
119 strerror_r(errno, err_str, 255);
120 dbg("[WRITE] Nothing is written: [%s]", err_str);
122 strerror_r(errno, err_str, 255);
123 err("[WRITE] Failed: [%s]", err_str);
124 ret_val = NVM_MEM_FULL_ERR;
134 static nvm_error __nvm_write_payload_1(int nvm_type,
135 const char *p_bin_buff, struct nvm_payload_info *nvm1)
137 const char *p_buf_ptr = p_bin_buff;
140 return __nvm_file_write(nvm_type,
141 (p_buf_ptr + NVM_DATA_LEN_POS + nvm1->m_length_0),
146 static nvm_error __nvm_write_payload_0(int nvm_type,
147 const char *p_bin_buff, struct nvm_payload_info *nvm)
152 ret_val = __nvm_file_write(nvm_type,
153 (p_bin_buff + NVM_DATA_LEN_POS),
156 if (NVM_NO_ERR == ret_val) {
157 /* The payload_0 has been done, so calls this method to write payload_1 to file */
158 ret_val = __nvm_write_payload_1(nvm_type, p_bin_buff, nvm);
160 err("Failed to write to NV data file!!!");
166 int nvm_sum_4_bytes(const char *pos)
169 sum = sum | (*(pos+3)) << 24;
170 sum = sum | (*(pos+2)) << 16;
171 sum = sum | (*(pos+1)) << 8;
176 nvm_error nvm_process_nv_update(const char *data)
178 struct nvm_payload_info nvm_info;
183 memset(&nvm_info, 0x0, sizeof(struct nvm_payload_info));
185 /* Determine lengths from the little-endian 4 bytes */
186 nvm_info.m_length_0 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_LENGTH_0]);
187 nvm_info.m_offset_0 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_OFFSET_0]);
188 nvm_info.m_length_1 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_LENGTH_1]);
189 nvm_info.m_offset_1 = nvm_sum_4_bytes(&data[NVM_PAYLOAD_OFFSET_1]);
190 dbg("Offsets - 0th: [%d] 1st: [%d]", nvm_info.m_offset_0, nvm_info.m_offset_1);
192 nvm_type = *(data + NVM_FILE_TYPE_POS);
193 if ((NVM_TYPE_CALIB <= nvm_type)
194 && (NVM_TYPE_DYNAMIC >= nvm_type)) {
195 dbg("NVM type: [%d]", nvm_type);
197 /* Write NVM data to file */
198 ret_val = __nvm_write_payload_0(nvm_type, data, &nvm_info);
200 err("Wrong NVM file type: [%d]", nvm_type);
201 ret_val = NVM_RES_ERR;
207 gboolean nvm_create_nvm_data()
212 char err_str[256] = {0, };
214 gboolean ret_val = FALSE;
217 /* Open modem binary */
218 modem_fd = open(MODEM_IMAGE_PATH, O_RDONLY | O_NDELAY);
220 strerror_r(errno, err_str, 255);
221 err("[OPEN] Failed for (%s): [%s]", MODEM_IMAGE_PATH, err_str);
225 /* Create NV data folder if it doesn't exist */
226 if (mkdir(NVM_DIR_PATH, 0755) < 0) {
227 if (errno != EEXIST) {
228 strerror_r(errno, err_str, 255);
229 err("mkdir() failed: [%s]", err_str);
231 /* Close 'modem_fd' */
234 } else if (open(NV_FILE_PATH, O_EXCL) > 0) {
235 /* NV data file already exists */
236 dbg("File exists: [%s]", NV_FILE_PATH);
238 /* Close 'modem_fd' */
242 dbg("File does't exsits... need to create!!!");
246 /* Change directory permissions */
247 if (chmod(NVM_DIR_PATH, 0755) < 0) {
248 strerror_r(errno, err_str, 255);
249 err("chmod() failed: [%s]", err_str);
251 /* Close 'modem_fd' */
256 /* Open NV data file for different file operations */
257 nv_fd = open(NV_FILE_PATH, O_RDWR | O_CREAT | O_SYNC, S_IRWXU);
259 strerror_r(errno, err_str, 255);
260 err("[OPEN] Failed for (%s): %s", NV_FILE_PATH, err_str);
262 /* Close 'modem_fd' */
267 dbg("Setting the file descriptor offset to NV data in modem.bin");
269 /* Seek pre-defined offset in modem binary */
270 if (lseek(modem_fd, MODEM_NV_OFFSET, SEEK_SET) < 0) {
271 strerror_r(errno, err_str, 255);
272 err("[SEEK] Failed: [%s]", err_str);
276 /* Allocate memory */
277 buffer = g_try_malloc0(MAX_NVDATA_SIZE);
278 if (NULL == buffer) {
279 err("Failed to allocate memory");
283 /* Read NV data from modem binary */
284 if (read(modem_fd, buffer, MAX_NVDATA_SIZE) < 0) {
285 strerror_r(errno, err_str, 255);
286 err("[READ] Failed: [%s]", err_str);
290 /* Write the data read from modem binary to nvdata */
291 if (write(nv_fd, buffer, MAX_NVDATA_SIZE) < 0) {
292 strerror_r(errno, err_str, 255);
293 err("[WRITE} Failed: [%s]", err_str);
300 if (ret_val == FALSE) {
301 err("nvdata (%s) creation Failed!!!", NV_FILE_PATH);
303 dbg("nvdata (%s) created Success", NV_FILE_PATH);