arm-trusted-firmware/lib/semihosting/semihosting.c
Antonio Nino Diaz 09d40e0e08 Sanitise includes across codebase
Enforce full include path for includes. Deprecate old paths.

The following folders inside include/lib have been left unchanged:

- include/lib/cpus/${ARCH}
- include/lib/el3_runtime/${ARCH}

The reason for this change is that having a global namespace for
includes isn't a good idea. It defeats one of the advantages of having
folders and it introduces problems that are sometimes subtle (because
you may not know the header you are actually including if there are two
of them).

For example, this patch had to be created because two headers were
called the same way: e0ea0928d5 ("Fix gpio includes of mt8173 platform
to avoid collision."). More recently, this patch has had similar
problems: 46f9b2c3a2 ("drivers: add tzc380 support").

This problem was introduced in commit 4ecca33988 ("Move include and
source files to logical locations"). At that time, there weren't too
many headers so it wasn't a real issue. However, time has shown that
this creates problems.

Platforms that want to preserve the way they include headers may add the
removed paths to PLAT_INCLUDES, but this is discouraged.

Change-Id: I39dc53ed98f9e297a5966e723d1936d6ccf2fc8f
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2019-01-04 10:43:17 +00:00

218 lines
4.6 KiB
C

/*
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <lib/semihosting.h>
#ifndef SEMIHOSTING_SUPPORTED
#define SEMIHOSTING_SUPPORTED 1
#endif
long semihosting_call(unsigned long operation,
void *system_block_address);
typedef struct {
const char *file_name;
unsigned long mode;
size_t name_length;
} smh_file_open_block_t;
typedef struct {
long handle;
uintptr_t buffer;
size_t length;
} smh_file_read_write_block_t;
typedef struct {
long handle;
ssize_t location;
} smh_file_seek_block_t;
typedef struct {
char *command_line;
size_t command_length;
} smh_system_block_t;
long semihosting_connection_supported(void)
{
return SEMIHOSTING_SUPPORTED;
}
long semihosting_file_open(const char *file_name, size_t mode)
{
smh_file_open_block_t open_block;
open_block.file_name = file_name;
open_block.mode = mode;
open_block.name_length = strlen(file_name);
return semihosting_call(SEMIHOSTING_SYS_OPEN,
(void *) &open_block);
}
long semihosting_file_seek(long file_handle, ssize_t offset)
{
smh_file_seek_block_t seek_block;
long result;
seek_block.handle = file_handle;
seek_block.location = offset;
result = semihosting_call(SEMIHOSTING_SYS_SEEK,
(void *) &seek_block);
if (result)
result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0);
return result;
}
long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer)
{
smh_file_read_write_block_t read_block;
long result = -EINVAL;
if ((length == NULL) || (buffer == (uintptr_t)NULL))
return result;
read_block.handle = file_handle;
read_block.buffer = buffer;
read_block.length = *length;
result = semihosting_call(SEMIHOSTING_SYS_READ,
(void *) &read_block);
if (result == *length) {
return -EINVAL;
} else if (result < *length) {
*length -= result;
return 0;
} else
return result;
}
long semihosting_file_write(long file_handle,
size_t *length,
const uintptr_t buffer)
{
smh_file_read_write_block_t write_block;
long result = -EINVAL;
if ((length == NULL) || (buffer == (uintptr_t)NULL))
return -EINVAL;
write_block.handle = file_handle;
write_block.buffer = (uintptr_t)buffer; /* cast away const */
write_block.length = *length;
result = semihosting_call(SEMIHOSTING_SYS_WRITE,
(void *) &write_block);
*length = result;
return (result == 0) ? 0 : -EINVAL;
}
long semihosting_file_close(long file_handle)
{
return semihosting_call(SEMIHOSTING_SYS_CLOSE,
(void *) &file_handle);
}
long semihosting_file_length(long file_handle)
{
return semihosting_call(SEMIHOSTING_SYS_FLEN,
(void *) &file_handle);
}
char semihosting_read_char(void)
{
return semihosting_call(SEMIHOSTING_SYS_READC, NULL);
}
void semihosting_write_char(char character)
{
semihosting_call(SEMIHOSTING_SYS_WRITEC, (void *) &character);
}
void semihosting_write_string(char *string)
{
semihosting_call(SEMIHOSTING_SYS_WRITE0, (void *) string);
}
long semihosting_system(char *command_line)
{
smh_system_block_t system_block;
system_block.command_line = command_line;
system_block.command_length = strlen(command_line);
return semihosting_call(SEMIHOSTING_SYS_SYSTEM,
(void *) &system_block);
}
long semihosting_get_flen(const char *file_name)
{
long file_handle;
size_t length;
assert(semihosting_connection_supported());
file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB);
if (file_handle == -1)
return file_handle;
/* Find the length of the file */
length = semihosting_file_length(file_handle);
return semihosting_file_close(file_handle) ? -1 : length;
}
long semihosting_download_file(const char *file_name,
size_t buf_size,
uintptr_t buf)
{
long ret = -EINVAL;
size_t length;
long file_handle;
/* Null pointer check */
if (!buf)
return ret;
assert(semihosting_connection_supported());
file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB);
if (file_handle == -1)
return ret;
/* Find the actual length of the file */
length = semihosting_file_length(file_handle);
if (length == -1)
goto semihosting_fail;
/* Signal error if we do not have enough space for the file */
if (length > buf_size)
goto semihosting_fail;
/*
* A successful read will return 0 in which case we pass back
* the actual number of bytes read. Else we pass a negative
* value indicating an error.
*/
ret = semihosting_file_read(file_handle, &length, buf);
if (ret)
goto semihosting_fail;
else
ret = length;
semihosting_fail:
semihosting_file_close(file_handle);
return ret;
}