建立工程,成功创建两个虚拟串口
This commit is contained in:
174
source/OpenAMP/libmetal/lib/system/linux/init.c
Normal file
174
source/OpenAMP/libmetal/lib/system/linux/init.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file linux/init.c
|
||||
* @brief Linux libmetal initialization.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
struct metal_state _metal;
|
||||
|
||||
extern int metal_linux_irq_init();
|
||||
extern void metal_linux_irq_shutdown();
|
||||
|
||||
/** Sort function for page size array. */
|
||||
static int metal_pagesize_compare(const void *_a, const void *_b)
|
||||
{
|
||||
const struct metal_page_size *a = _a, *b = _b;
|
||||
long diff = a->page_size - b->page_size;
|
||||
return metal_sign(diff);
|
||||
}
|
||||
|
||||
static int metal_add_page_size(const char *path, int shift, int mmap_flags)
|
||||
{
|
||||
int index = _metal.num_page_sizes;
|
||||
unsigned long size = 1UL << shift;
|
||||
|
||||
if (index >= MAX_PAGE_SIZES) {
|
||||
metal_log(METAL_LOG_WARNING, "skipped page size %ld - overflow\n",
|
||||
size);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
if (!path || shift <= 0) {
|
||||
metal_log(METAL_LOG_WARNING, "skipped page size %ld - invalid args\n",
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
_metal.page_sizes[index].page_shift = shift;
|
||||
_metal.page_sizes[index].page_size = size;
|
||||
_metal.page_sizes[index].mmap_flags = mmap_flags;
|
||||
strncpy(_metal.page_sizes[index].path, path, PATH_MAX);
|
||||
_metal.num_page_sizes ++;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "added page size %ld @%s\n", size, path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int metal_init_page_sizes(void)
|
||||
{
|
||||
const int max_sizes = MAX_PAGE_SIZES - 1;
|
||||
long sizes[max_sizes];
|
||||
|
||||
/* Determine system page size. */
|
||||
sizes[0] = getpagesize();
|
||||
if (sizes[0] <= 0) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to get page size\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
_metal.page_size = sizes[0];
|
||||
_metal.page_shift = metal_log2(sizes[0]);
|
||||
metal_add_page_size(_metal.tmp_path, _metal.page_shift, 0);
|
||||
|
||||
#ifdef HAVE_HUGETLBFS_H
|
||||
#ifndef MAP_HUGE_SHIFT
|
||||
/* System does not support multiple huge page sizes. */
|
||||
sizes[0] = gethugepagesize();
|
||||
if (sizes[0] > 0) {
|
||||
metal_add_page_size(hugetlbfs_find_path(),
|
||||
metal_log2(sizes[0]),
|
||||
MAP_HUGETLB);
|
||||
}
|
||||
#else
|
||||
if (gethugepagesize() >= 0) {
|
||||
int i, count;
|
||||
|
||||
/* System supports multiple huge page sizes. */
|
||||
count = gethugepagesizes(sizes, max_sizes);
|
||||
for (i = 0; i < count; i++) {
|
||||
int shift = metal_log2(sizes[i]);
|
||||
if ((shift & MAP_HUGE_MASK) != shift)
|
||||
continue;
|
||||
metal_add_page_size(
|
||||
hugetlbfs_find_path_for_size(sizes[i]),
|
||||
shift, (MAP_HUGETLB |
|
||||
(shift << MAP_HUGE_SHIFT)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Finally sort the resulting array by size. */
|
||||
qsort(_metal.page_sizes, _metal.num_page_sizes,
|
||||
sizeof(struct metal_page_size), metal_pagesize_compare);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_sys_init(const struct metal_init_params *params)
|
||||
{
|
||||
static char sysfs_path[SYSFS_PATH_MAX];
|
||||
const char *tmp_path;
|
||||
unsigned int seed;
|
||||
FILE* urandom;
|
||||
int result;
|
||||
|
||||
/* Determine sysfs mount point. */
|
||||
result = sysfs_get_mnt_path(sysfs_path, sizeof(sysfs_path));
|
||||
if (result) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to get sysfs path (%s)\n",
|
||||
strerror(-result));
|
||||
return result;
|
||||
}
|
||||
_metal.sysfs_path = sysfs_path;
|
||||
|
||||
/* Find the temporary directory location. */
|
||||
tmp_path = getenv("TMPDIR");
|
||||
if (!tmp_path)
|
||||
tmp_path = "/tmp";
|
||||
_metal.tmp_path = tmp_path;
|
||||
|
||||
/* Initialize the pseudo-random number generator. */
|
||||
urandom = fopen("/dev/urandom", "r");
|
||||
if (!urandom) {
|
||||
metal_log(METAL_LOG_ERROR, "failed to open /dev/urandom (%s)\n",
|
||||
strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
if (fread(&seed, 1, sizeof(seed), urandom) <= 0) {
|
||||
metal_log(METAL_LOG_DEBUG, "Failed fread /dev/urandom\n");
|
||||
}
|
||||
fclose(urandom);
|
||||
srand(seed);
|
||||
|
||||
result = metal_init_page_sizes();
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
result = metal_linux_bus_init();
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
result = open("/proc/self/pagemap", O_RDONLY | O_CLOEXEC);
|
||||
if (result < 0) {
|
||||
metal_log(METAL_LOG_DEBUG, "Failed pagemap open - %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
_metal.pagemap_fd = result;
|
||||
|
||||
metal_unused(params);
|
||||
|
||||
/* Initialize IRQ handling */
|
||||
metal_linux_irq_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_sys_finish(void)
|
||||
{
|
||||
|
||||
/* Shutdown IRQ handling */
|
||||
metal_linux_irq_shutdown();
|
||||
metal_linux_bus_finish();
|
||||
close(_metal.pagemap_fd);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user