1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cerrno>
17 #include <cstdlib>
18 #include <cstdio>
19 #include <cstdint>
20 #include <fcntl.h>
21 #include <iostream>
22 #include <string>
23 #include <sys/stat.h>
24 #include <unistd.h>
25
26 #include "begetctl.h"
27 #include "fs_manager/fs_manager.h"
28 #include "shell.h"
29 #include "shell_utils.h"
30 #include "init_param.h"
31
32 constexpr int MAX_LOGO_SIZE = 1024 * 2038;
33 constexpr int PARTITION_INFO_POS = 1144;
34 constexpr int PARTITION_INFO_MAX_LENGTH = 256;
35 constexpr int BLOCK_SZIE_1 = 512;
36 constexpr uint64_t LOGO_MAGIC = 0XABCABCAB;
37
38 #define MISC_DEVICE_NODE "/dev/block/by-name/misc"
39
ClearLogo(int fd)40 static void ClearLogo(int fd)
41 {
42 if (fd < 0) {
43 return;
44 }
45 char buffer[8] = {0}; // logo magic number + logo size is 8
46 int addrOffset = (PARTITION_INFO_POS + PARTITION_INFO_MAX_LENGTH + BLOCK_SZIE_1 - 1) / BLOCK_SZIE_1;
47 if (lseek(fd, addrOffset * BLOCK_SZIE_1, SEEK_SET) < 0) {
48 std::cout << "Failed to clean file\n";
49 return;
50 }
51 if (write(fd, &buffer, sizeof(buffer)) != sizeof(buffer)) {
52 std::cout << "clean misc failed\n";
53 return;
54 }
55 }
56
WriteLogoContent(int fd,const std::string & logoPath,uint32_t size)57 static void WriteLogoContent(int fd, const std::string &logoPath, uint32_t size)
58 {
59 if (size == 0 || size > MAX_LOGO_SIZE) {
60 BSH_LOGE("logo size is invalid!");
61 return;
62 }
63 FILE *rgbFile = fopen(logoPath.c_str(), "rb");
64 if (rgbFile == nullptr) {
65 std::cout << "cannot find pic file\n";
66 return;
67 }
68 char *buffer = reinterpret_cast<char *>(calloc(1, size));
69 if (buffer == nullptr) {
70 (void)fclose(rgbFile);
71 return;
72 }
73 (void)fread(buffer, 1, size, rgbFile);
74 if (ferror(rgbFile)) {
75 (void)fclose(rgbFile);
76 free(buffer);
77 return;
78 }
79 ssize_t ret = write(fd, buffer, size);
80 if (ret == -1 || ret != size) {
81 (void)fclose(rgbFile);
82 free(buffer);
83 return;
84 }
85 free(buffer);
86 (void)fclose(rgbFile);
87 }
88
WriteLogo(int fd,const std::string & logoPath)89 static int WriteLogo(int fd, const std::string &logoPath)
90 {
91 int addrOffset = (PARTITION_INFO_POS + PARTITION_INFO_MAX_LENGTH + BLOCK_SZIE_1 - 1) / BLOCK_SZIE_1;
92 if (lseek(fd, addrOffset * BLOCK_SZIE_1, SEEK_SET) < 0) {
93 BSH_LOGI("Failed lseek logoPath %s errno %d ", logoPath.c_str(), errno);
94 return -1;
95 }
96
97 uint32_t magic = 0;
98 if (read(fd, &magic, sizeof(uint32_t)) != sizeof(uint32_t)) {
99 BSH_LOGI("Failed magic logoPath %s errno %d ", logoPath.c_str(), errno);
100 return -1;
101 }
102 #ifndef STARTUP_INIT_TEST
103 if (magic == LOGO_MAGIC) {
104 BSH_LOGI("Get matched magic number, logo already written\n");
105 return 0;
106 }
107 #endif
108 struct stat st {};
109 magic = LOGO_MAGIC;
110 lseek(fd, addrOffset * BLOCK_SZIE_1, SEEK_SET);
111 if (write(fd, &magic, sizeof(magic)) != sizeof(magic)) {
112 BSH_LOGI("Write magic number failed %d", errno);
113 return -1;
114 }
115
116 if (stat(logoPath.c_str(), &st) < 0) {
117 if (errno == ENOENT) {
118 BSH_LOGI("%s is not exist", logoPath.c_str());
119 } else {
120 BSH_LOGI("Failed to get %s stat", logoPath.c_str());
121 }
122 ClearLogo(fd);
123 return -1;
124 }
125
126 if (st.st_size <= 0 || st.st_size > MAX_LOGO_SIZE) {
127 BSH_LOGE("Invalid logo file with size ");
128 ClearLogo(fd);
129 return -1;
130 }
131
132 uint32_t logoSize = static_cast<uint32_t>(st.st_size);
133 if (write(fd, &logoSize, sizeof(logoSize)) != sizeof(logoSize)) {
134 BSH_LOGE("Write logo size failed ");
135 ClearLogo(fd);
136 return -1;
137 }
138
139 WriteLogoContent(fd, logoPath, logoSize);
140 return 0;
141 }
142
WriteLogoToMisc(const std::string & logoPath)143 static void WriteLogoToMisc(const std::string &logoPath)
144 {
145 if (logoPath.empty()) {
146 std::cout << "logo path is empty\n";
147 return;
148 }
149 int fd = open(MISC_DEVICE_NODE, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
150 if (fd < 0) {
151 BSH_LOGI("Failed to writeLogoToMisc errno %d ", errno);
152 return;
153 }
154
155 if (WriteLogo(fd, logoPath) < 0) {
156 BSH_LOGI("Failed WriteLogo errno %d ", errno);
157 }
158 close(fd);
159 int addrOffset = (PARTITION_INFO_POS + PARTITION_INFO_MAX_LENGTH + BLOCK_SZIE_1 - 1) / BLOCK_SZIE_1;
160 int fd1 = open(MISC_DEVICE_NODE, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
161 if (fd1 < 0) {
162 return;
163 }
164 if (lseek(fd1, addrOffset * BLOCK_SZIE_1, SEEK_SET) < 0) {
165 BSH_LOGI("Failed lseek errno %d ", errno);
166 close(fd1);
167 return;
168 }
169
170 uint32_t magic = 0;
171 uint32_t size = 0;
172 if (read(fd1, &magic, sizeof(uint32_t)) != sizeof(uint32_t)) {
173 BSH_LOGI("Failed read errno %d ", errno);
174 close(fd1);
175 return;
176 }
177 if (read(fd1, &size, sizeof(uint32_t)) != sizeof(uint32_t)) {
178 BSH_LOGI("Failed read migic errno %d ", errno);
179 close(fd1);
180 return;
181 }
182
183 close(fd1);
184 }
185
main_cmd(BShellHandle shell,int argc,char ** argv)186 static int main_cmd(BShellHandle shell, int argc, char **argv)
187 {
188 if (argc >= 2 && strcmp(const_cast<char *>("--write_logo"), argv[0]) == 0) { // 2 min arg
189 WriteLogoToMisc(argv[1]);
190 } else {
191 char *helpArgs[] = {const_cast<char *>("misc_daemon"), nullptr};
192 BShellCmdHelp(shell, 1, helpArgs);
193 }
194 return 0;
195 }
196
MODULE_CONSTRUCTOR(void)197 MODULE_CONSTRUCTOR(void)
198 {
199 const CmdInfo infos[] = {
200 {
201 const_cast<char *>("misc_daemon"), main_cmd, const_cast<char *>("write start logo"),
202 const_cast<char *>("misc_daemon --write_logo xxx.rgb"), const_cast<char *>("misc_daemon --write_logo")
203 }
204 };
205 for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) {
206 BShellEnvRegisterCmd(GetShellHandle(), &infos[i]);
207 }
208 }
209