blob: becd61a6b1523691942a1f3b4d242341de4ba067 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* 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.
*/
/* Syscall stubs for newlib on Kelvin */
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
int _close(int file) { return -1; }
int _fstat(int file, struct stat* st) { return 0; }
int _isatty(int file) {
errno = ENOTTY;
return 0;
}
int _lseek(int file, int ptr, int dir) { return 0; }
int _read(int file, char* ptr, int len) {
errno = EBADF;
return -1;
}
#ifndef LOG_MAX_SZ
#define LOG_MAX_SZ 256
#endif
// TODO(lundong): Handle stdout and stderr separately
int _write(int file, char* buf, int nbytes) {
static int _write_line_buffer_len = 0;
static char _write_line_buffer[LOG_MAX_SZ];
if (file != STDOUT_FILENO && file != STDERR_FILENO) {
errno = EBADF;
return -1;
}
if (nbytes <= 0) {
return 0;
}
if (buf == NULL) {
errno = EFAULT;
return -1;
}
int bytes_read = 0;
char c;
do {
int len = _write_line_buffer_len;
c = *(buf++);
bytes_read++;
_write_line_buffer[len++] = c;
if (len == LOG_MAX_SZ - 1 || c == '\n') {
_write_line_buffer[len] = '\0';
}
if ((_write_line_buffer[len] == '\0')) {
asm volatile("flog %0" : : "r"(_write_line_buffer));
len = 0;
}
_write_line_buffer_len = len;
} while (bytes_read < nbytes);
return bytes_read;
}
int _open(const char* path, int flags, ...) { return -1; }
void _exit(int status) {
asm volatile("ebreak");
while (1) {
}
}
int _kill(int pid, int sig) {
asm volatile("ebreak");
return -1;
}
int _getpid(void) {
asm volatile("ebreak");
return -1;
}
char* _heap_ptr; // Set to __heap_start__ in kelvin_start.S
// Based on newlib's nosys sbrk
void* _sbrk(int bytes) {
extern char __heap_end__;
char* prev_heap_end;
if ((bytes < 0) || (_heap_ptr + bytes > &__heap_end__)) {
errno = ENOMEM;
return (void*)-1;
}
prev_heap_end = _heap_ptr;
_heap_ptr += bytes;
return (void*)prev_heap_end;
}