1  /*
2   * Copyright (c) 2018-2019, 2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4   *
5   * Permission to use, copy, modify, and/or distribute this software for
6   * any purpose with or without fee is hereby granted, provided that the
7   * above copyright notice and this permission notice appear in all
8   * copies.
9   *
10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11   * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12   * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13   * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17   * PERFORMANCE OF THIS SOFTWARE.
18   */
19  
20  #include <linux/firmware.h>
21  #include "qdf_file.h"
22  #include "qdf_mem.h"
23  #include "qdf_module.h"
24  #include "qdf_status.h"
25  #include "qdf_trace.h"
26  #include "qdf_types.h"
27  
28  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
29  static inline
qdf_firmware_request_nowarn(const struct firmware ** fw,const char * name,struct device * device)30  int qdf_firmware_request_nowarn(const struct firmware **fw,
31  				const char *name,
32  				struct device *device)
33  {
34  	return firmware_request_nowarn(fw, name, device);
35  }
36  #else
37  static inline
qdf_firmware_request_nowarn(const struct firmware ** fw,const char * name,struct device * device)38  int qdf_firmware_request_nowarn(const struct firmware **fw,
39  				const char *name,
40  				struct device *device)
41  {
42  	return request_firmware(fw, name, device);
43  }
44  #endif
45  
46  
qdf_file_read(const char * path,char ** out_buf)47  QDF_STATUS qdf_file_read(const char *path, char **out_buf)
48  {
49  	int errno;
50  	const struct firmware *fw;
51  	char *buf;
52  
53  	*out_buf = NULL;
54  
55  	errno = qdf_firmware_request_nowarn(&fw, path, NULL);
56  	if (errno) {
57  		qdf_err("Failed to read file %s", path);
58  		return QDF_STATUS_E_FAILURE;
59  	}
60  
61  	/* qdf_mem_malloc zeros new memory; +1 size ensures null-termination */
62  	buf = qdf_mem_malloc(fw->size + 1);
63  	if (!buf) {
64  		release_firmware(fw);
65  		return QDF_STATUS_E_NOMEM;
66  	}
67  
68  	qdf_mem_copy(buf, fw->data, fw->size);
69  	release_firmware(fw);
70  	*out_buf = buf;
71  
72  	return QDF_STATUS_SUCCESS;
73  }
74  qdf_export_symbol(qdf_file_read);
75  
qdf_file_buf_free(char * file_buf)76  void qdf_file_buf_free(char *file_buf)
77  {
78  	QDF_BUG(file_buf);
79  	if (!file_buf)
80  		return;
81  
82  	qdf_mem_free(file_buf);
83  }
84  qdf_export_symbol(qdf_file_buf_free);
85  
86  #ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI
qdf_module_param_file_read(const char * path,char ** out_buf)87  QDF_STATUS qdf_module_param_file_read(const char *path, char **out_buf)
88  {
89  	int errno;
90  	const struct firmware *fw;
91  	char *buf;
92  
93  	*out_buf = NULL;
94  	errno = qdf_firmware_request_nowarn(&fw, path, NULL);
95  	if (errno) {
96  		qdf_err("Failed to read file %s", path);
97  		return QDF_STATUS_E_FAILURE;
98  	}
99  
100  	/* qdf_untracked_mem_malloc zeros new memory; +1 size
101  	 * ensures null-termination
102  	 */
103  	buf = qdf_untracked_mem_malloc(fw->size + 1);
104  	if (!buf) {
105  		release_firmware(fw);
106  		return QDF_STATUS_E_NOMEM;
107  	}
108  
109  	qdf_mem_copy(buf, fw->data, fw->size);
110  	release_firmware(fw);
111  	*out_buf = buf;
112  
113  	return QDF_STATUS_SUCCESS;
114  }
115  
qdf_module_param_file_free(char * file_buf)116  void qdf_module_param_file_free(char *file_buf)
117  {
118  	QDF_BUG(file_buf);
119  	if (!file_buf)
120  		return;
121  
122  	qdf_untracked_mem_free(file_buf);
123  }
124  #endif
125  
qdf_file_read_bytes(const char * path,char ** out_buf,unsigned int * out_buff_size)126  QDF_STATUS qdf_file_read_bytes(const char *path, char **out_buf,
127  			       unsigned int *out_buff_size)
128  {
129  	int errno;
130  	const struct firmware *fw;
131  	char *buf;
132  
133  	*out_buf = NULL;
134  
135  	errno = qdf_firmware_request_nowarn(&fw, path, NULL);
136  	if (errno) {
137  		qdf_err("Failed to read file %s", path);
138  		return QDF_STATUS_E_FAILURE;
139  	}
140  
141  	buf = qdf_mem_malloc(fw->size);
142  	if (!buf) {
143  		release_firmware(fw);
144  		return QDF_STATUS_E_NOMEM;
145  	}
146  
147  	qdf_mem_copy(buf, fw->data, fw->size);
148  	*out_buff_size = fw->size;
149  	*out_buf = buf;
150  	release_firmware(fw);
151  
152  	return QDF_STATUS_SUCCESS;
153  }
154  
155  qdf_export_symbol(qdf_file_read_bytes);
156