pull/187/merge
Joel Stanley 2 years ago committed by GitHub
commit 5d008f2f20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

9
.gitignore vendored

@ -7,6 +7,7 @@
microwatt.json
microwatt.svf
*_tb
*.swp
main_ram.bin
tests/*/*.bin
tests/*/*.hex
@ -15,3 +16,11 @@ TAGS
litedram/build/*
liteeth/build/*
obj_dir/*
tags
scripts/mw_debug/mw_debug
loader/loader.bin
loader/loader.hex
loader/loader.elf
loader/powerpc.lds
*.swn
*.swo

@ -0,0 +1,64 @@
ARCH = $(shell uname -m)
ifneq ("$(ARCH)", "ppc64")
ifneq ("$(ARCH)", "ppc64le")
CROSS_COMPILE ?= powerpc64le-linux-gnu-
endif
endif

PYTHON3 ?= python3
MW_DEBUG ?= mw_debug
BRAM_ADDRESS ?= 0x80000000

# Use make V=1 for a verbose build.
ifndef V
Q_CC= @echo ' [CC] ' $@;
Q_LINK= @echo ' [LINK] ' $@;
Q_OBJCOPY=@echo ' [OBJCOPY] ' $@;
Q_PYTHON= @echo ' [PYTHON] ' $@;
endif

CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy

CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple \
-mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector \
-mstrict-align -ffreestanding -nostdinc -flto \
-Ilibc/include/ -I../include -isystem $(shell $(CC) -print-file-name=include) \
-D__USE_LIBC
ASFLAGS = $(CFLAGS)
LDFLAGS = -T powerpc.lds -static -nostdlib -Wl,--gc-sections -Wl,--build-id=none

LIBC_SRC := libc/src/isdigit.c libc/src/memcmp.c libc/src/strcat.c \
libc/src/strncasecmp.c libc/src/strtok.c libc/src/vsnprintf.c \
libc/src/isprint.c libc/src/memcpy.c libc/src/strchr.c libc/src/strncmp.c \
libc/src/strtol.c libc/src/isspace.c libc/src/memmove.c libc/src/strcmp.c \
libc/src/strncpy.c libc/src/strtoul.c libc/src/isxdigit.c libc/src/memset.c \
libc/src/strcpy.c libc/src/strrchr.c libc/src/tolower.c libc/src/memchr.c \
libc/src/strcasecmp.c libc/src/strlen.c libc/src/strstr.c libc/src/toupper.c
LIBC_OBJ := $(LIBC_SRC:.c=.o)

COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.S = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c

all: loader.hex

load: loader.bin
$(MW_DEBUG) -b jtag load $^ $(BRAM_ADDRESS)

%.lds : %.lds.S
$(Q_CC)$(CC) -I../include -P -E $< -o $@

loader.elf: loader.o head.o ../lib/console.o $(LIBC_OBJ) | powerpc.lds
$(Q_LINK)$(CC) $(LDFLAGS) -o $@ $^
@size $@

loader.bin: loader.elf
$(Q_OBJCOPY)$(OBJCOPY) -O binary $^ $@

loader.hex: loader.bin
$(Q_PYTHON)$(PYTHON3) ../scripts/bin2hex.py $^ > $@

.PHONY:
clean:
@rm -f *.o $(LIBC_OBJ) ../lib/console.o loader.elf loader.bin loader.hex powerpc.lds

@ -0,0 +1,38 @@
/* Copyright 2020 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <microwatt_soc.h>

#define STACK_TOP (BRAM_BASE + 0x3000)

/* Load an immediate 64-bit value into a register */
#define LOAD_IMM64(r, e) \
lis r,(e)@highest; \
ori r,r,(e)@higher; \
rldicr r,r, 32, 31; \
oris r,r, (e)@h; \
ori r,r, (e)@l;

.section ".head","ax"

.global start
start:
/* setup stack */
LOAD_IMM64(%r1, STACK_TOP - 0x100)
LOAD_IMM64(%r12, main)
mtctr %r12,
bctrl
b .

@ -0,0 +1,29 @@
/******************************************************************************
* Copyright (c) 2004, 2008, 2012 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _ASSERT_H
#define _ASSERT_H

#define assert(cond) \
do { if (!(cond)) { \
assert_fail(__FILE__ \
":" stringify(__LINE__) \
":" stringify(cond)); } \
} while(0)

void __attribute__((noreturn)) assert_fail(const char *msg);

#define stringify(expr) stringify_1(expr)
/* Double-indirection required to stringify expansions */
#define stringify_1(expr) #expr

#endif

@ -0,0 +1,54 @@
/* Copyright 2013-2014 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __COMPILER_H
#define __COMPILER_H

#ifndef __ASSEMBLY__

#include <stddef.h>

/* Macros for various compiler bits and pieces */
#define __packed __attribute__((packed))
#define __align(x) __attribute__((__aligned__(x)))
#define __unused __attribute__((unused))
#define __used __attribute__((used))
#define __section(x) __attribute__((__section__(x)))
#define __noreturn __attribute__((noreturn))
/* not __const as this has a different meaning (const) */
#define __attrconst __attribute__((const))
#define __warn_unused_result __attribute__((warn_unused_result))
#define __noinline __attribute__((noinline))

#if 0 /* Provided by gcc stddef.h */
#define offsetof(type,m) __builtin_offsetof(type,m)
#endif

#define __nomcount __attribute__((no_instrument_function))

/* Compiler barrier */
static inline void barrier(void)
{
// asm volatile("" : : : "memory");
}

#endif /* __ASSEMBLY__ */

/* Stringification macro */
#define __tostr(x) #x
#define tostr(x) __tostr(x)

#endif /* __COMPILER_H */

@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _CTYPE_H
#define _CTYPE_H

#include <compiler.h>

int __attrconst isdigit(int c);
int __attrconst isxdigit(int c);
int __attrconst isprint(int c);
int __attrconst isspace(int c);

int __attrconst tolower(int c);
int __attrconst toupper(int c);

#endif

@ -0,0 +1,36 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _ERRNO_H
#define _ERRNO_H

extern int errno;

/*
* Error number definitions
*/
#define EPERM 1 /* not permitted */
#define ENOENT 2 /* file or directory not found */
#define EIO 5 /* input/output error */
#define EBADF 9 /* Bad file number */
#define ENOMEM 12 /* not enough space */
#define EACCES 13 /* permission denied */
#define EFAULT 14 /* bad address */
#define EBUSY 16 /* resource busy */
#define EEXIST 17 /* file already exists */
#define ENODEV 19 /* device not found */
#define EINVAL 22 /* invalid argument */
#define EDOM 33 /* math argument out of domain of func */
#define ERANGE 34 /* math result not representable */
#define ENOSYS 38 /* Function not implemented */

#endif

@ -0,0 +1,32 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _LIMITS_H
#define _LIMITS_H

#define UCHAR_MAX 255
#define SCHAR_MAX 127
#define SCHAR_MIN (-128)

#define USHRT_MAX 65535
#define SHRT_MAX 32767
#define SHRT_MIN (-32768)

#define UINT_MAX (4294967295U)
#define INT_MAX 2147483647
#define INT_MIN (-2147483648)

#define ULONG_MAX ((unsigned long)-1L)
#define LONG_MAX (ULONG_MAX/2)
#define LONG_MIN ((-LONG_MAX)-1)

#endif

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _STDINT_H
#define _STDINT_H

typedef unsigned char uint8_t;
typedef signed char int8_t;

typedef unsigned short uint16_t;
typedef signed short int16_t;

typedef unsigned int uint32_t;
typedef signed int int32_t;

typedef unsigned long long uint64_t;
typedef signed long long int64_t;

typedef unsigned long int uintptr_t;

#endif

@ -0,0 +1,35 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _STDIO_H
#define _STDIO_H

#include <stdarg.h>
#include "stddef.h"

#define EOF (-1)

int _printf(const char *format, ...) __attribute__((format (printf, 1, 2)));

#ifndef pr_fmt
#define pr_fmt(fmt) fmt
#endif

#define printf(f, ...) do { _printf(pr_fmt(f), ##__VA_ARGS__); } while(0)

int snprintf(char *str, size_t size, const char *format, ...) __attribute__((format (printf, 3, 4)));
int vsnprintf(char *str, size_t size, const char *format, va_list);

int putchar(int ch);
int puts(const char *str);

#endif

@ -0,0 +1,25 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _STDLIB_H
#define _STDLIB_H

#include "stddef.h"

#define RAND_MAX 32767

int atoi(const char *str);
long atol(const char *str);
unsigned long int strtoul(const char *nptr, char **endptr, int base);
long int strtol(const char *nptr, char **endptr, int base);

#endif

@ -0,0 +1,45 @@
/******************************************************************************
* Copyright (c) 2004, 2016 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _STRING_H
#define _STRING_H

#include "stddef.h"

char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
char *strcat(char *dest, const char *src);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
int strcasecmp(const char *s1, const char *s2);
int strncasecmp(const char *s1, const char *s2, size_t n);
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
size_t strlen(const char *s);
size_t strnlen(const char *s, size_t n);
char *strstr(const char *hay, const char *needle);
char *strtok(char *src, const char *pattern);
char *strdup(const char *src);

void *memset(void *s, int c, size_t n);
void *memchr(const void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
void *memcpy_from_ci(void *destpp, const void *srcpp, size_t len);
void *memmove(void *dest, const void *src, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);

static inline int ffs(unsigned long val)
{
return __builtin_ffs(val);
}

#endif

@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _UNISTD_H
#define _UNISTD_H

#include <stddef.h>

typedef long ssize_t;

extern int open(const char *name, int flags);
extern int close(int fd);
extern ssize_t read(int fd, void *buf, size_t count);
extern ssize_t write(int fd, const void *buf, size_t count);
extern ssize_t lseek(int fd, long offset, int whence);

#endif

@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst isdigit(int ch)
{
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return 1;
default:
return 0;
}
}

@ -0,0 +1,19 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst isprint(int ch)
{
return (ch >= 32 && ch < 127);
}

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst isspace(int ch)
{
switch (ch) {
case ' ':
case '\f':
case '\n':
case '\r':
case '\t':
case '\v':
return 1;
default:
return 0;
}
}

@ -0,0 +1,22 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst isxdigit(int ch)
{
return (
(ch >= '0' && ch <= '9') |
(ch >= 'A' && ch <= 'F') |
(ch >= 'a' && ch <= 'f') );
}

@ -0,0 +1,28 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

void *memchr(const void *ptr, int c, size_t n);
void *memchr(const void *ptr, int c, size_t n)
{
unsigned char ch = (unsigned char)c;
const unsigned char *p = ptr;

while (n-- > 0) {
if (*p == ch)
return (void *)p;
p += 1;
}

return NULL;
}

@ -0,0 +1,29 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

int memcmp(const void *ptr1, const void *ptr2, size_t n);
int memcmp(const void *ptr1, const void *ptr2, size_t n)
{
const unsigned char *p1 = ptr1;
const unsigned char *p2 = ptr2;

while (n-- > 0) {
if (*p1 != *p2)
return (*p1 - *p2);
p1 += 1;
p2 += 1;
}

return 0;
}

@ -0,0 +1,36 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>
#include <stdint.h>

void *memcpy(void *dest, const void *src, size_t n);
void *memcpy(void *dest, const void *src, size_t n)
{
void *ret = dest;

while (n >= 8) {
*(uint64_t *)dest = *(uint64_t *)src;
dest += 8;
src += 8;
n -= 8;
}

while (n > 0) {
*(uint8_t *)dest = *(uint8_t *)src;
dest += 1;
src += 1;
n -= 1;
}

return ret;
}

@ -0,0 +1,36 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n)
{
/* Do the buffers overlap in a bad way? */
if (src < dest && src + n >= dest) {
char *cdest;
const char *csrc;
int i;

/* Copy from end to start */
cdest = dest + n - 1;
csrc = src + n - 1;
for (i = 0; i < n; i++) {
*cdest-- = *csrc--;
}
return dest;
} else {
/* Normal copy is possible */
return memcpy(dest, src, n);
}
}

@ -0,0 +1,40 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#define CACHE_LINE_SIZE 128

#include <stddef.h>

void *memset(void *dest, int c, size_t size);
void *memset(void *dest, int c, size_t size)
{
unsigned char *d = (unsigned char *)dest;
unsigned long big_c = 0;

if (c) {
big_c = c;
big_c |= (big_c << 8) | big_c;
big_c |= (big_c << 16) | big_c;
big_c |= (big_c << 32) | big_c;
}
while (size >= 8 && c == 0) {
*((unsigned long *)d) = big_c;
d+=8;
size-=8;
}

while (size-- > 0) {
*d++ = (unsigned char)c;
}

return dest;
}

@ -0,0 +1,27 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <ctype.h>

int strcasecmp(const char *s1, const char *s2);
int strcasecmp(const char *s1, const char *s2)
{
while (*s1 != 0 && *s2 != 0) {
if (toupper(*s1) != toupper(*s2))
break;
++s1;
++s2;
}

return *s1 - *s2;
}

@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

size_t strlen(const char *s);
char *strcpy(char *dst, const char *src);
char *strcat(char *dst, const char *src);
char *strcat(char *dst, const char *src)
{
size_t p;

p = strlen(dst);
strcpy(&dst[p], src);

return dst;
}

@ -0,0 +1,28 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

char *strchr(const char *s, int c);
char *strchr(const char *s, int c)
{
char cb = c;

while (*s != 0) {
if (*s == cb) {
return (char *)s;
}
s += 1;
}

return NULL;
}

@ -0,0 +1,25 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

int strcmp(const char *s1, const char *s2);
int strcmp(const char *s1, const char *s2)
{
while (*s1 != 0 && *s2 != 0) {
if (*s1 != *s2)
break;
s1 += 1;
s2 += 1;
}

return *s1 - *s2;
}

@ -0,0 +1,23 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

char *strcpy(char *dst, const char *src);
char *strcpy(char *dst, const char *src)
{
char *ptr = dst;

do {
*ptr++ = *src;
} while (*src++ != 0);

return dst;
}

@ -0,0 +1,40 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

size_t strlen(const char *s);
size_t strlen(const char *s)
{
size_t len = 0;

while (*s != 0) {
len += 1;
s += 1;
}

return len;
}

size_t strnlen(const char *s, size_t n);
size_t strnlen(const char *s, size_t n)
{
size_t len = 0;

while (*s != 0 && n) {
len += 1;
s += 1;
n--;
}

return len;
}

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <ctype.h>

int strncasecmp(const char *s1, const char *s2, size_t n);
int strncasecmp(const char *s1, const char *s2, size_t n)
{
if (n < 1)
return 0;

while (*s1 != 0 && *s2 != 0 && --n > 0) {
if (toupper(*s1) != toupper(*s2))
break;
++s1;
++s2;
}

return toupper(*s1) - toupper(*s2);
}

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

int strncmp(const char *s1, const char *s2, size_t n);
int strncmp(const char *s1, const char *s2, size_t n)
{
if (n < 1)
return 0;

while (*s1 != 0 && *s2 != 0 && --n > 0) {
if (*s1 != *s2)
break;
s1 += 1;
s2 += 1;
}

return *s1 - *s2;
}

@ -0,0 +1,33 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

char *strncpy(char *dst, const char *src, size_t n);
char *strncpy(char *dst, const char *src, size_t n)
{
char *ret = dst;

/* Copy string */
while (*src != 0 && n > 0) {
*dst++ = *src++;
n -= 1;
}

/* strncpy always clears the rest of destination string... */
while (n > 0) {
*dst++ = 0;
n -= 1;
}

return ret;
}

@ -0,0 +1,28 @@
/******************************************************************************
* Copyright (c) 2004, 2008, 2019 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

char *strrchr(const char *s, int c);
char *strrchr(const char *s, int c)
{
char *last = NULL;
char cb = c;

while (*s != 0) {
if (*s == cb)
last = (char *)s;
s += 1;
}

return last;
}

@ -0,0 +1,39 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

size_t strlen(const char *s);
int strncmp(const char *s1, const char *s2, size_t n);
char *strstr(const char *hay, const char *needle);
char *strstr(const char *hay, const char *needle)
{
char *pos;
size_t hlen, nlen;

if (hay == NULL || needle == NULL)
return NULL;
hlen = strlen(hay);
nlen = strlen(needle);
if (nlen < 1)
return (char *)hay;

for (pos = (char *)hay; pos < hay + hlen; pos++) {
if (strncmp(pos, needle, nlen) == 0) {
return pos;
}
}

return NULL;
}

@ -0,0 +1,48 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

char *strtok(char *src, const char *pattern);
char *strtok(char *src, const char *pattern)
{
static char *nxtTok;
char *retVal = NULL;

if (!src) {
src = nxtTok;
if (!src)
return retVal;
}

while (*src) {
const char *pp = pattern;
while (*pp) {
if (*pp == *src) {
break;
}
pp++;
}
if (!*pp) {
if (!retVal)
retVal = src;
else if (!src[-1])
break;
} else
*src = '\0';
src++;
}

nxtTok = src;

return retVal;
}

@ -0,0 +1,113 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stdlib.h>

long int strtol(const char *S, char **PTR,int BASE)
{
long rval = 0;
short int negative = 0;
short int digit;
// *PTR is S, unless PTR is NULL, in which case i override it with my own ptr
char* ptr;
if (PTR == NULL)
{
//override
PTR = &ptr;
}
// i use PTR to advance through the string
*PTR = (char *) S;
//check if BASE is ok
if ((BASE < 0) || BASE > 36)
{
return 0;
}
// ignore white space at beginning of S
while ((**PTR == ' ')
|| (**PTR == '\t')
|| (**PTR == '\n')
|| (**PTR == '\r')
)
{
(*PTR)++;
}
// check if S starts with "-" in which case the return value is negative
if (**PTR == '-')
{
negative = 1;
(*PTR)++;
}
// if BASE is 0... determine the base from the first chars...
if (BASE == 0)
{
// if S starts with "0x", BASE = 16, else 10
if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
{
BASE = 16;
}
else
{
BASE = 10;
}
}
if (BASE == 16)
{
// S may start with "0x"
if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
{
(*PTR)++;
(*PTR)++;
}
}
//until end of string
while (**PTR)
{
if (((**PTR) >= '0') && ((**PTR) <= '9'))
{
//digit (0..9)
digit = **PTR - '0';
}
else if (((**PTR) >= 'a') && ((**PTR) <='z'))
{
//alphanumeric digit lowercase(a (10) .. z (35) )
digit = (**PTR - 'a') + 10;
}
else if (((**PTR) >= 'A') && ((**PTR) <='Z'))
{
//alphanumeric digit uppercase(a (10) .. z (35) )
digit = (**PTR - 'A') + 10;
}
else
{
//end of parseable number reached...
break;
}
if (digit < BASE)
{
rval = (rval * BASE) + digit;
}
else
{
//digit found, but its too big for current base
//end of parseable number reached...
break;
}
//next...
(*PTR)++;
}
if (negative)
{
return rval * -1;
}
//else
return rval;
}

@ -0,0 +1,103 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stdlib.h>

unsigned long int strtoul(const char *S, char **PTR,int BASE)
{
unsigned long rval = 0;
short int digit;
// *PTR is S, unless PTR is NULL, in which case i override it with my own ptr
char* ptr;
if (PTR == NULL)
{
//override
PTR = &ptr;
}
// i use PTR to advance through the string
*PTR = (char *) S;
//check if BASE is ok
if ((BASE < 0) || BASE > 36)
{
return 0;
}
// ignore white space at beginning of S
while ((**PTR == ' ')
|| (**PTR == '\t')
|| (**PTR == '\n')
|| (**PTR == '\r')
)
{
(*PTR)++;
}
// if BASE is 0... determine the base from the first chars...
if (BASE == 0)
{
// if S starts with "0x", BASE = 16, else 10
if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
{
BASE = 16;
}
else
{
BASE = 10;
}
}
if (BASE == 16)
{
// S may start with "0x"
if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
{
(*PTR)++;
(*PTR)++;
}
}
//until end of string
while (**PTR)
{
if (((**PTR) >= '0') && ((**PTR) <='9'))
{
//digit (0..9)
digit = **PTR - '0';
}
else if (((**PTR) >= 'a') && ((**PTR) <='z'))
{
//alphanumeric digit lowercase(a (10) .. z (35) )
digit = (**PTR - 'a') + 10;
}
else if (((**PTR) >= 'A') && ((**PTR) <='Z'))
{
//alphanumeric digit uppercase(a (10) .. z (35) )
digit = (**PTR - 'A') + 10;
}
else
{
//end of parseable number reached...
break;
}
if (digit < BASE)
{
rval = (rval * BASE) + digit;
}
else
{
//digit found, but its too big for current base
//end of parseable number reached...
break;
}
//next...
(*PTR)++;
}
//done
return rval;
}

@ -0,0 +1,19 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst tolower(int c)
{
return (((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a' ) : c);
}

@ -0,0 +1,21 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include "ctype.h"

int __attrconst toupper (int cha)
{
if((cha >= 'a') && (cha <= 'z'))
return(cha - 'a' + 'A');
return(cha);
}

@ -0,0 +1,304 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stdbool.h>
#include <compiler.h>
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include <stdarg.h>

static const unsigned long long convert[] = {
0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF,
0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
};

static int
print_str_fill(char **buffer, size_t bufsize, char *sizec,
const char *str, char c)
{
size_t i, sizei, len;
char *bstart = *buffer;

sizei = strtoul(sizec, NULL, 10);
len = strlen(str);
if (sizei > len) {
for (i = 0;
(i < (sizei - len)) && ((*buffer - bstart) < bufsize);
i++) {
**buffer = c;
*buffer += 1;
}
}
return 1;
}

static int
print_str(char **buffer, size_t bufsize, const char *str)
{
char *bstart = *buffer;
size_t i;

for (i = 0; (i < strlen(str)) && ((*buffer - bstart) < bufsize); i++) {
**buffer = str[i];
*buffer += 1;
}
return 1;
}

static unsigned int __attrconst
print_intlen(unsigned long value, unsigned short int base)
{
int i = 0;

while (value > 0) {
if (base == 16)
value >>= 4;
else
value /= base;
i++;
}
if (i == 0)
i = 1;
return i;
}

static int
print_itoa(char **buffer, size_t bufsize, unsigned long value,
unsigned short base, bool upper)
{
const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
char c;
int i, len;

if(base <= 2 || base > 16)
return 0;

len = i = print_intlen(value, base);

/* Don't print to buffer if bufsize is not enough. */
if (len > bufsize)
return 0;

do {
c = zeichen[value % base];
if (upper)
c = toupper(c);

(*buffer)[--i] = c;
value /= base;
} while(value);

*buffer += len;

return 1;
}



static int
print_fill(char **buffer, size_t bufsize, char *sizec, unsigned long size,
unsigned short int base, char c, int optlen)
{
int i, sizei, len;
char *bstart = *buffer;

sizei = strtoul(sizec, NULL, 10);
len = print_intlen(size, base) + optlen;
if (sizei > len) {
for (i = 0;
(i < (sizei - len)) && ((*buffer - bstart) < bufsize);
i++) {
**buffer = c;
*buffer += 1;
}
}

return 0;
}


static int
print_format(char **buffer, size_t bufsize, const char *format, void *var)
{
char *start;
unsigned int i = 0, length_mod = sizeof(int);
unsigned long value = 0;
unsigned long signBit;
char *form, sizec[32];
char sign = ' ';
bool upper = false;

form = (char *) format;
start = *buffer;

form++;
if(*form == '0' || *form == '.') {
sign = '0';
form++;
}

while ((*form != '\0') && ((*buffer - start) < bufsize)) {
switch(*form) {
case 'u':
case 'd':
case 'i':
sizec[i] = '\0';
value = (unsigned long) var;
signBit = 0x1ULL << (length_mod * 8 - 1);
if ((*form != 'u') && (signBit & value)) {
**buffer = '-';
*buffer += 1;
value = (-(unsigned long)value) & convert[length_mod];
}
print_fill(buffer, bufsize - (*buffer - start),
sizec, value, 10, sign, 0);
print_itoa(buffer, bufsize - (*buffer - start),
value, 10, upper);
break;
case 'X':
upper = true;
/* fallthrough */
case 'x':
sizec[i] = '\0';
value = (unsigned long) var & convert[length_mod];
print_fill(buffer, bufsize - (*buffer - start),
sizec, value, 16, sign, 0);
print_itoa(buffer, bufsize - (*buffer - start),
value, 16, upper);
break;
case 'O':
case 'o':
sizec[i] = '\0';
value = (long int) var & convert[length_mod];
print_fill(buffer, bufsize - (*buffer - start),
sizec, value, 8, sign, 0);
print_itoa(buffer, bufsize - (*buffer - start),
value, 8, upper);
break;
case 'p':
sizec[i] = '\0';
print_fill(buffer, bufsize - (*buffer - start),
sizec, (unsigned long) var, 16, ' ', 2);
print_str(buffer, bufsize - (*buffer - start),
"0x");
print_itoa(buffer, bufsize - (*buffer - start),
(unsigned long) var, 16, upper);
break;
case 'c':
sizec[i] = '\0';
print_fill(buffer, bufsize - (*buffer - start),
sizec, 1, 10, ' ', 0);
**buffer = (unsigned long) var;
*buffer += 1;
break;
case 's':
sizec[i] = '\0';
print_str_fill(buffer,
bufsize - (*buffer - start), sizec,
(char *) var, ' ');

print_str(buffer, bufsize - (*buffer - start),
(char *) var);
break;
case 'l':
form++;
if(*form == 'l') {
length_mod = sizeof(long long int);
} else {
form--;
length_mod = sizeof(long int);
}
break;
case 'h':
form++;
if(*form == 'h') {
length_mod = sizeof(signed char);
} else {
form--;
length_mod = sizeof(short int);
}
break;
case 'z':
length_mod = sizeof(size_t);
break;
default:
if(*form >= '0' && *form <= '9')
sizec[i++] = *form;
}
form++;
}

return (long int) (*buffer - start);
}


/*
* The vsnprintf function prints a formatted strings into a buffer.
* BUG: buffer size checking does not fully work yet
*/
int
vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
{
char *ptr, *bstart;

bstart = buffer;
ptr = (char *) format;

/*
* Return from here if size passed is zero, otherwise we would
* overrun buffer while setting NULL character at the end.
*/
if (!buffer || !bufsize)
return 0;

/* Leave one space for NULL character */
bufsize--;

while(*ptr != '\0' && (buffer - bstart) < bufsize)
{
if(*ptr == '%') {
char formstr[20];
int i=0;
do {
formstr[i] = *ptr;
ptr++;
i++;
} while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X'
|| *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%'
|| *ptr == 'O' || *ptr == 'o' ));
formstr[i++] = *ptr;
formstr[i] = '\0';
if(*ptr == '%') {
*buffer++ = '%';
} else {
print_format(&buffer,
bufsize - (buffer - bstart),
formstr, va_arg(arg, void *));
}
ptr++;
} else {

*buffer = *ptr;

buffer++;
ptr++;
}
}
*buffer = '\0';

return (buffer - bstart);
}

@ -0,0 +1,161 @@
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <stdbool.h>
#include "stdio.h"

#include "io.h"
#include "microwatt_soc.h"
#include "console.h"
#include "elf64.h"

#define DTB_ADDR 0x01000000UL
#define DTBIMAGE_ADDR 0x00500000UL

#ifdef DEBUG
#define debug(...) printf(__VA_ARGS__)
#else
#define debug(...) do {} while(0)
#endif

int _printf(const char *fmt, ...)
{
int count;
char buffer[128];
va_list ap;

va_start(ap, fmt);
count = vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
puts(buffer);
return count;
}

static inline void flush_cpu_icache(void)
{
__asm__ volatile ("icbi 0,0; isync" : : : "memory");
}

static void print_hex(unsigned long val)
{
int i, nibbles = sizeof(val)*2;
char buf[sizeof(val)*2+1];

for (i = nibbles-1; i >= 0; i--) {
buf[i] = (val & 0xf) + '0';
if (buf[i] > '9')
buf[i] += ('a'-'0'-10);
val >>= 4;
}
buf[nibbles] = '\0';
puts(buf);
}

static void fl_read(void *dst, uint32_t offset, uint32_t size)
{
memcpy(dst, (void *)(unsigned long)(SPI_FLASH_BASE + offset), size);
}

static unsigned long boot_flash(unsigned int offset)
{
Elf64_Ehdr ehdr;
Elf64_Phdr ph;
unsigned int i, poff, size, off;
void *addr;

fl_read(&ehdr, offset, sizeof(ehdr));
if (!IS_ELF(ehdr) || ehdr.e_ident[EI_CLASS] != ELFCLASS64) {
puts("Doesn't look like an elf64\n");
return -1UL;
}
if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB ||
ehdr.e_machine != EM_PPC64) {
puts("Not a ppc64le binary\n");
return -1UL;
}

poff = offset + ehdr.e_phoff;
for (i = 0; i < ehdr.e_phnum; i++) {
fl_read(&ph, poff, sizeof(ph));
if (ph.p_type != PT_LOAD)
continue;

/* XXX Add bound checking ! */
size = ph.p_filesz;
addr = (void *)ph.p_vaddr;
off = offset + ph.p_offset;
debug("Copy segment %d (0x%x bytes) to %p\n", i, size, addr);
fl_read(addr, off, size);
poff += ehdr.e_phentsize;
}

if (poff == offset + ehdr.e_phoff) {
puts("Did not find any loadable sections\n");
return -1UL;
}

debug("Found entry point: %x\n", ehdr.e_entry);

flush_cpu_icache();
return ehdr.e_entry;
}

int main(void)
{
unsigned long fl_off = 0;
potato_uart_init();
unsigned long payload, dtb;
void __attribute__((noreturn)) (*enter_kernel)(unsigned long fdt,
unsigned long entry,
unsigned long of);


puts("\nMicrowatt Loader ("__DATE__" "__TIME__"\n\n");

writeq(SYS_REG_CTRL_DRAM_AT_0, SYSCON_BASE + SYS_REG_CTRL);
flush_cpu_icache();

puts("Load binaries into SDRAM and select option to start:\n\n");
puts("vmlinux.bin and dtb:\n");
puts(" mw_debug -b jtag stop load vmlinux.bin load microwatt.dtb 0x1000000 start\n");
puts(" press 'l' to start'\n\n");

puts("dtbImage.microwatt:\n");
puts(" mw_debug -b jtag stop load dtbImage.microwatt 0x500000 start\n");
puts(" press 'w' to start'\n\n");

if (readq(SYSCON_BASE + SYS_REG_INFO) & SYS_REG_INFO_HAS_SPI_FLASH) {
unsigned long val = readq(SYSCON_BASE + SYS_REG_SPI_INFO);
fl_off = val & SYS_REG_SPI_INFO_FLASH_OFF_MASK;

puts("Flash:\n");
puts(" To boot a binary from flash, write it to "); print_hex(fl_off); puts("\n");
puts(" press 'f' to start'\n\n");
}

while (1) {
switch (getchar()) {
case 'l':
payload = 0;
dtb = DTB_ADDR;
goto load;
case 'w':
payload = DTBIMAGE_ADDR;
goto load;
case 'f':
payload = boot_flash(fl_off);
if (payload == -1UL)
continue;
goto load;
default:
continue;
}
}

load:
puts("Entering payload at "); print_hex(payload); puts("...\n");

enter_kernel = (void *)payload;

enter_kernel(dtb, 0, 0);
}

@ -0,0 +1,20 @@
#include <microwatt_soc.h>

#define BASE_ADDR BRAM_BASE

SECTIONS
{
. = BASE_ADDR;
.head : {
KEEP(*(.head))
}

.text : { *(.text*) *(.sfpr) *(.rodata*) }
.data : { *(.data*) }
.bss : { *(.bss*) }

/DISCARD/ : {
*(.note.*)
*(.comment)
}
}

@ -300,6 +300,21 @@ targets:
vivado: {part : xc7a35ticsg324-1L}
toplevel : toplevel

arty_a7-50:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram]
parameters :
- memory_size
- ram_init_file
- use_litedram=true
- disable_flatten_core
- no_bram
- spi_flash_offset=3145728
generate: [dram_arty]
tools:
vivado: {part : xc7a50ticsg324-1L}
toplevel : toplevel

arty_a7-100-nodram:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx, uart16550, xilinx_specific, litesdcard]

Loading…
Cancel
Save