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