mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-02-05 01:57:52 +01:00
Provide a crc32 function (will be needed later). Do some minor naming and coding cleanups Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de> Link: https://github.com/openwrt/openwrt/pull/19832 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
139 lines
2.7 KiB
C
139 lines
2.7 KiB
C
/*
|
|
* rt-loader memory functions
|
|
* (c) 2025 Markus Stockhausen
|
|
*
|
|
* This is a small function collection to get some rudimentary memory management working when
|
|
* running bare metal. None of these functions is optimized but works well for current needs.
|
|
*/
|
|
|
|
#include "board.h"
|
|
#include "globals.h"
|
|
#include "memory.h"
|
|
#include "nanoprintf.h"
|
|
|
|
#define CACHE_OP(op, addr) \
|
|
__asm__ __volatile__( \
|
|
" .set push \n" \
|
|
" .set noreorder \n" \
|
|
" .set mips3\n\t \n" \
|
|
" cache %0, %1 \n" \
|
|
" .set pop \n" \
|
|
: \
|
|
: "i" (op), "R" (*(unsigned char *)(addr)))
|
|
|
|
void flush_cache(void *start_addr, size_t count)
|
|
{
|
|
/*
|
|
* MIPS cores may have different cache lines. Most common are 16 and 32 bytes. Avoid
|
|
* detection routines or multiple implementations and take the lowest known value that
|
|
* will fit fine for cores with longer cache lines
|
|
*/
|
|
|
|
unsigned long lsize = 16;
|
|
unsigned long addr = (unsigned long)start_addr & ~(lsize - 1);
|
|
unsigned long aend = ((unsigned long)start_addr + count - 1) & ~(lsize - 1);
|
|
|
|
while (1) {
|
|
CACHE_OP(CACHE_HIT_INVALIDATE_I, addr);
|
|
CACHE_OP(CACHE_HIT_WRITEBACK_INV_D, addr);
|
|
if (addr == aend)
|
|
break;
|
|
addr += lsize;
|
|
}
|
|
}
|
|
|
|
void free(void *ptr)
|
|
{
|
|
/* this is only one shot allocation */
|
|
}
|
|
|
|
int memcmp(const void *s1, const void *s2, size_t count)
|
|
{
|
|
volatile char *p1 = (volatile char *)s1;
|
|
volatile char *p2 = (volatile char *)s2;
|
|
|
|
while (count--) {
|
|
if (*p1 != *p2)
|
|
return (int)(*p1) - (int)(*p2);
|
|
|
|
p1++;
|
|
p2++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *memmove(void *dst, const void *src, size_t count)
|
|
{
|
|
volatile char *d = (volatile char *)dst;
|
|
volatile char *s = (volatile char *)src;
|
|
|
|
if (d < s) {
|
|
while (count--)
|
|
*d++ = *s++;
|
|
} else if (d > s) {
|
|
d += count;
|
|
s += count;
|
|
while (count--)
|
|
*--d = *--s;
|
|
}
|
|
|
|
return dst;
|
|
}
|
|
|
|
void *memcpy(void *dst, const void *src, size_t count)
|
|
{
|
|
memmove(dst, src, count);
|
|
}
|
|
|
|
void *memset(void *dst, int c, size_t count)
|
|
{
|
|
volatile char *d = (volatile char *)dst;
|
|
|
|
while (count--)
|
|
*d++ = c;
|
|
|
|
return (void *)d;
|
|
}
|
|
|
|
void *malloc(size_t count)
|
|
{
|
|
void *start;
|
|
|
|
start = (void *)(((unsigned int)_heap_addr + MEMORY_ALIGNMENT - 1) & ~(MEMORY_ALIGNMENT - 1));
|
|
if ((start + count) > _heap_addr_max) {
|
|
printf("malloc(%d) failed. Only %dkB of %dkB heap left.\n",
|
|
count, (_heap_addr_max - start) >> 10, HEAP_SIZE >> 10);
|
|
board_panic();
|
|
}
|
|
|
|
_heap_addr += count;
|
|
|
|
return start;
|
|
}
|
|
|
|
size_t strlen(const char *s)
|
|
{
|
|
size_t len = 0;
|
|
|
|
while (s[len]) len++;
|
|
|
|
return len;
|
|
}
|
|
|
|
unsigned int crc32(void *m, size_t count)
|
|
{
|
|
unsigned int crc = 0xffffffff;
|
|
unsigned char *data = m;
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
crc ^= data[i];
|
|
for (int j = 0; j < 8; j++)
|
|
if (crc & 1)
|
|
crc = (crc >> 1) ^ 0xEDB88320;
|
|
else
|
|
crc >>= 1;
|
|
}
|
|
|
|
return ~crc;
|
|
}
|