1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "osal_firmware.h"
32 #include <limits.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include "fs/file.h"
36 #include "hdf_log.h"
37 #include "osal_mem.h"
38
39 #define HDF_LOG_TAG osal_fw
40 #define HDF_FW_BLOCK_SIZE 64
41
42 struct OsalFwDesc {
43 int32_t fd;
44 uint8_t *buff;
45 uint32_t offset;
46 bool openFlag;
47 };
48
OsalRequestFirmware(struct OsalFirmware * fwPara,const char * fwName,void * device)49 int32_t OsalRequestFirmware(struct OsalFirmware *fwPara, const char *fwName, void *device)
50 {
51 struct OsalFwDesc *fw = NULL;
52 uint8_t *base = NULL;
53 struct stat fwStat;
54 char path[PATH_MAX + 1] = {0};
55 int32_t fd = -1;
56
57 (void)device;
58 if (fwPara == NULL || fwName == NULL) {
59 HDF_LOGE("%s invalid param", __func__);
60 return HDF_ERR_INVALID_PARAM;
61 }
62
63 fwPara->fwSize = 0;
64 fwPara->para = NULL;
65
66 if (realpath(fwName, path) == NULL) {
67 HDF_LOGE("%s file name is invalid\n", __func__);
68 return HDF_FAILURE;
69 }
70
71 fd = open(path, O_RDONLY, S_IREAD);
72 if (fd == -1) {
73 HDF_LOGE("%s open file fail %d", __func__, errno);
74 return HDF_FAILURE;
75 }
76
77 if (fstat(fd, &fwStat) == -1) {
78 HDF_LOGE("%s fstat file fail %d", __func__, errno);
79 close(fd);
80 return HDF_FAILURE;
81 }
82
83 base = (uint8_t *)OsalMemCalloc(sizeof(*fw) + HDF_FW_BLOCK_SIZE);
84 if (base == NULL) {
85 HDF_LOGE("%s malloc fail", __func__);
86 close(fd);
87 return HDF_ERR_MALLOC_FAIL;
88 }
89
90 fw = (struct OsalFwDesc *)base;
91 fw->fd = fd;
92 fwPara->fwSize = (uint32_t)fwStat.st_size;
93
94 fw->openFlag = true;
95 fw->buff = base + sizeof(*fw);
96 fw->offset = 0;
97
98 fwPara->para = (void *)fw;
99
100 return HDF_SUCCESS;
101 }
102
OsalSeekFirmware(struct OsalFirmware * fwPara,uint32_t offset)103 int32_t OsalSeekFirmware(struct OsalFirmware *fwPara, uint32_t offset)
104 {
105 struct OsalFwDesc *fw = NULL;
106
107 if (fwPara == NULL || offset >= fwPara->fwSize || fwPara->para == NULL) {
108 HDF_LOGE("%s invalid param", __func__);
109 return HDF_ERR_INVALID_PARAM;
110 }
111
112 fw = (struct OsalFwDesc *)fwPara->para;
113 fw->offset = offset;
114
115 return HDF_SUCCESS;
116 }
117
OsalReadFirmware(struct OsalFirmware * fwPara,struct OsalFwBlock * block)118 int32_t OsalReadFirmware(struct OsalFirmware *fwPara, struct OsalFwBlock *block)
119 {
120 uint32_t readOffset;
121 uint32_t readSize;
122 struct OsalFwDesc *fw = NULL;
123
124 if (fwPara == NULL || fwPara->para == NULL || block == NULL) {
125 HDF_LOGE("%s invalid param", __func__);
126 return HDF_ERR_INVALID_PARAM;
127 }
128
129 fw = (struct OsalFwDesc *)fwPara->para;
130 if (fw->openFlag == false) {
131 HDF_LOGE("%s file do not open", __func__);
132 return HDF_ERR_INVALID_PARAM;
133 }
134
135 block->data = fw->buff;
136 block->endFlag = false;
137 block->dataSize = HDF_FW_BLOCK_SIZE;
138
139 if (fw->offset >= fwPara->fwSize) {
140 HDF_LOGE("%s file offset invalid %d %d", __func__, fw->offset, fwPara->fwSize);
141 return HDF_ERR_INVALID_PARAM;
142 }
143
144 if (fw->offset + block->dataSize >= fwPara->fwSize) {
145 block->dataSize = fwPara->fwSize - fw->offset;
146 block->endFlag = true;
147 }
148
149 if (fw->fd == -1) {
150 HDF_LOGE("%s invalid file id", __func__);
151 return HDF_ERR_INVALID_PARAM;
152 }
153
154 readOffset = (uint32_t)lseek(fw->fd, fw->offset, SEEK_SET);
155 if (readOffset != fw->offset) {
156 HDF_LOGE("%s seek offset fail %d %d", __func__, readOffset, fw->offset);
157 return HDF_FAILURE;
158 }
159 readSize = (uint32_t)read(fw->fd, block->data, block->dataSize);
160 if (readSize != block->dataSize) {
161 HDF_LOGE("%s read file fail %d %d", __func__, readSize, block->dataSize);
162 return HDF_FAILURE;
163 }
164
165 block->curOffset = fw->offset;
166 fw->offset += block->dataSize;
167
168 return HDF_SUCCESS;
169 }
170
OsalReleaseFirmware(struct OsalFirmware * fwPara)171 int32_t OsalReleaseFirmware(struct OsalFirmware *fwPara)
172 {
173 struct OsalFwDesc *fw = NULL;
174
175 if (fwPara == NULL || fwPara->para == NULL) {
176 HDF_LOGE("%s invalid param", __func__);
177 return HDF_ERR_INVALID_PARAM;
178 }
179
180 fw = (struct OsalFwDesc *)fwPara->para;
181 if (fw->fd == -1) {
182 HDF_LOGE("%s invalid file id", __func__);
183 return HDF_ERR_INVALID_PARAM;
184 }
185
186 if (close(fw->fd) != 0) {
187 HDF_LOGE("%s close fail %d", __func__, errno);
188 return HDF_FAILURE;
189 }
190 OsalMemFree(fwPara->para);
191 fwPara->para = NULL;
192
193 return HDF_SUCCESS;
194 }
195
196