1/* 2 * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this list of 9 * conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 * of conditions and the following disclaimer in the documentation and/or other materials 13 * provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 16 * to endorse or promote products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "linux/kernel.h" 33#include "linux/module.h" 34#include "math.h" 35#include "limits.h" 36#include "sys/statfs.h" 37#include "los_sys_pri.h" 38#include "los_swtmr.h" 39#ifdef LOSCFG_KERNEL_DYNLOAD 40#include "los_ld_elflib.h" 41#endif 42#ifdef LOSCFG_NET_LWIP_SACK 43#include "lwip/sockets.h" 44#include "lwip/api.h" 45#include "lwip/netdb.h" 46#endif 47#include "linux/rbtree.h" 48#include "los_vm_common.h" 49#include "los_vm_zone.h" 50#include "los_vm_lock.h" 51 52 53#ifdef __LP64__ 54int dl_iterate_phdr(int (*callback)(void *info, size_t size, void *data), void *data) 55{ 56 PRINT_ERR("%s NOT SUPPORT\n", __FUNCTION__); 57 errno = ENOSYS; 58 return -1; 59} 60#endif 61 62void fs_show(const char *path) 63{ 64 INT32 ret; 65 struct statfs fss; 66 if (path == NULL) { 67 PRINTK("path is NULL\n"); 68 return; 69 } 70 ret = statfs(path, &fss); 71 PRINTK("Filesystem %s info: \n", path); 72 PRINTK("----------------------------------------\n"); 73 if (ret == ENOERR) { 74 PRINTK(" Total clusters: %u \n", fss.f_blocks); 75 PRINTK(" Cluster size: %u \n", fss.f_bsize); 76 PRINTK(" Free clusters: %u \n", fss.f_bfree); 77 } else { 78 ret = get_errno(); 79 PRINT_ERR("Get fsinfo failed: %d \n", ret); 80 } 81} 82 83#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1) - 1) 84 85unsigned long msecs_to_jiffies(const unsigned int m) 86{ 87 /* Negative value, means infinite timeout: */ 88 if ((INT32)m < 0) { 89 return (unsigned long)MAX_JIFFY_OFFSET; 90 } 91 92#if (HZ <= OS_SYS_MS_PER_SECOND) && !(OS_SYS_MS_PER_SECOND % HZ) 93 /* 94 * HZ is equal to or smaller than 1000, and 1000 is a nice 95 * round multiple of HZ, divide with the factor between them, 96 * but round upwards: 97 */ 98 return ((m + (OS_SYS_MS_PER_SECOND / HZ)) - 1) / (OS_SYS_MS_PER_SECOND / HZ); 99#else 100 PRINT_ERR("HZ: %d is not supported in %s\n", HZ, __FUNCTION__); 101 return ENOSUPP; 102#endif 103} 104 105UINT64 jiffies_to_tick(unsigned long j) 106{ 107 return j; 108} 109 110#define MAX_SCHEDULE_TIMEOUT UINT_MAX 111signed long schedule_timeout(signed long timeout) 112{ 113 UINT32 ret; 114 115 if (OS_INT_ACTIVE) { 116 PRINT_ERR("ERROR: OS_ERRNO_SWTMR_HWI_ACTIVE\n"); 117 return LOS_ERRNO_SWTMR_HWI_ACTIVE; 118 } 119 if (timeout < 0) { 120 PRINT_ERR("schedule_timeout: wrong timeout\n"); 121 return 0; 122 } 123#ifdef __LP64__ 124 if (timeout > MAX_SCHEDULE_TIMEOUT) { 125 timeout = LOS_WAIT_FOREVER; 126 } 127#endif 128 ret = LOS_TaskDelay(timeout); 129 if (ret == LOS_OK) { 130 return ret; 131 } else { 132 PRINT_ERR("ERROR: OS_ERRNO_SWTMR_NOT_STARTED\n"); 133 return LOS_ERRNO_SWTMR_NOT_STARTED; 134 } 135} 136 137UINT32 do_div_imp(UINT64 *n, UINT32 base) 138{ 139 UINT32 r; 140 141 if ((n == NULL) || (base == 0)) { 142 PRINT_ERR("%s invalid input param, n:%p, base %u\n", __FUNCTION__, n, base); 143 return 0; 144 } 145 146 r = *n % base; 147 *n = *n / base; 148 return r; 149} 150 151INT32 do_div_s64_imp(INT64 *n, INT32 base) 152{ 153 INT32 r; 154 155 if ((n == NULL) || (base == 0)) { 156 PRINT_ERR("%s invalid input param, n:%p, base:%u\n", __FUNCTION__, n, base); 157 return 0; 158 } 159 160 r = *n % base; 161 *n = *n / base; 162 return r; 163} 164 165char *basename(const char *path) 166{ 167 STATIC const CHAR empty[] = "."; 168 CHAR *first = (CHAR *)empty; 169 register CHAR *last = NULL; 170 171 if ((path != NULL) && *path) { 172 first = (CHAR *)path; 173 last = (CHAR *)path - 1; 174 175 do { 176 if ((*path != '/') && (path > ++last)) { 177 last = first = (CHAR *)path; 178 } 179 } while (*++path); 180 181 if (*first == '/') { 182 last = first; 183 } 184 last[1] = 0; 185 } 186 187 return first; 188} 189 190void *__dso_handle = NULL; 191 192/* Undo Linux compat changes. */ 193#undef RB_ROOT 194#define RB_ROOT(head) (head)->rbh_root 195 196int panic_cmp(struct rb_node *one, struct rb_node *two) 197{ 198 LOS_Panic("no cmp"); 199 return 0; 200} 201 202RB_GENERATE(linux_root, rb_node, __entry, panic_cmp); 203 204#define IS_PERIPH_ADDR(addr) \ 205 (((addr) >= U32_C(PERIPH_PMM_BASE)) && ((addr) <= U32_C(PERIPH_PMM_BASE) + U32_C(PERIPH_PMM_SIZE))) 206#define IS_MEMORY_ADDR(addr) \ 207 (((addr) >= U32_C(DDR_MEM_ADDR)) && ((addr) <= U32_C(DDR_MEM_ADDR) + U32_C(DDR_MEM_SIZE))) 208 209VOID *ioremap(PADDR_T paddr, unsigned long size) 210{ 211 if (IS_PERIPH_ADDR(paddr) && IS_PERIPH_ADDR(paddr + size)) { 212 return (VOID *)(UINTPTR)IO_DEVICE_ADDR(paddr); 213 } 214 215 VM_ERR("ioremap failed invalid addr or size %p %d", paddr, size); 216 return (VOID *)(UINTPTR)paddr; 217} 218 219VOID iounmap(VOID *vaddr) {} 220 221VOID *ioremap_nocache(PADDR_T paddr, unsigned long size) 222{ 223 if (IS_PERIPH_ADDR(paddr) && IS_PERIPH_ADDR(paddr + size)) { 224 return (VOID *)(UINTPTR)IO_UNCACHED_ADDR(paddr); 225 } 226 227 if (IS_MEMORY_ADDR(paddr) && IS_MEMORY_ADDR(paddr + size)) { 228 return (VOID *)(UINTPTR)MEM_UNCACHED_ADDR(paddr); 229 } 230 231 VM_ERR("ioremap_nocache failed invalid addr or size %p %d", paddr, size); 232 return (VOID *)(UINTPTR)paddr; 233} 234 235VOID *ioremap_cached(PADDR_T paddr, unsigned long size) 236{ 237 if (IS_PERIPH_ADDR(paddr) && IS_PERIPH_ADDR(paddr + size)) { 238 return (VOID *)(UINTPTR)IO_CACHED_ADDR(paddr); 239 } 240 241 if (IS_MEMORY_ADDR(paddr) && IS_MEMORY_ADDR(paddr + size)) { 242 return (VOID *)(UINTPTR)MEM_CACHED_ADDR(paddr); 243 } 244 245 VM_ERR("ioremap_cached failed invalid addr or size %p %d", paddr, size); 246 return (VOID *)(UINTPTR)paddr; 247} 248 249#ifdef LOSCFG_KERNEL_VM 250int remap_pfn_range(VADDR_T vaddr, unsigned long pfn, unsigned long size, unsigned long prot) 251{ 252 STATUS_T status = LOS_OK; 253 int ret; 254 LosVmMapRegion *region = NULL; 255 unsigned long vpos; 256 unsigned long end; 257 unsigned long paddr = pfn << PAGE_SHIFT; 258 LosVmSpace *space = LOS_SpaceGet(vaddr); 259 260 if (size == 0) { 261 VM_ERR("invalid map size %u", size); 262 return LOS_ERRNO_VM_INVALID_ARGS; 263 } 264 size = ROUNDUP(size, PAGE_SIZE); 265 266 if (!IS_PAGE_ALIGNED(vaddr) || pfn == 0) { 267 VM_ERR("invalid map map vaddr %x or pfn %x", vaddr, pfn); 268 return LOS_ERRNO_VM_INVALID_ARGS; 269 } 270 271 if (space == NULL) { 272 VM_ERR("aspace not exists"); 273 return LOS_ERRNO_VM_NOT_FOUND; 274 } 275 276 (VOID)LOS_MuxAcquire(&space->regionMux); 277 278 region = LOS_RegionFind(space, vaddr); 279 if (region == NULL) { 280 VM_ERR("region not exists"); 281 status = LOS_ERRNO_VM_NOT_FOUND; 282 goto OUT; 283 } 284 end = vaddr + size; 285 if (region->range.base + region->range.size < end) { 286 VM_ERR("out of range:base=%x size=%d vaddr=%x len=%u", 287 region->range.base, region->range.size, vaddr, size); 288 status = LOS_ERRNO_VM_INVALID_ARGS; 289 goto OUT; 290 } 291 292 /* check */ 293 for (vpos = vaddr; vpos < end; vpos += PAGE_SIZE) { 294 status = LOS_ArchMmuQuery(&space->archMmu, (VADDR_T)vpos, NULL, NULL); 295 if (status == LOS_OK) { 296 VM_ERR("remap_pfn_range, address mapping already exist"); 297 status = LOS_ERRNO_VM_INVALID_ARGS; 298 goto OUT; 299 } 300 } 301 302 /* map all */ 303 ret = LOS_ArchMmuMap(&space->archMmu, vaddr, paddr, size >> PAGE_SHIFT, prot); 304 if (ret <= 0) { 305 VM_ERR("ioremap LOS_ArchMmuMap failed err = %d", ret); 306 goto OUT; 307 } 308 309 status = LOS_OK; 310 311OUT: 312 (VOID)LOS_MuxRelease(&space->regionMux); 313 return status; 314} 315#endif 316