diff --git a/arch/Kconfig b/arch/Kconfig index 572b613e57..b7f4ca5a2c 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -468,6 +468,10 @@ config ARCH_HAVE_BOOTLOADER bool default n +config ARCH_HAVE_CPUINFO + bool + default n + config ARCH_FPU bool "FPU support" default y diff --git a/fs/procfs/Kconfig b/fs/procfs/Kconfig index a99acbf9e1..a07bc5ce44 100644 --- a/fs/procfs/Kconfig +++ b/fs/procfs/Kconfig @@ -38,6 +38,11 @@ config FS_PROCFS_EXCLUDE_BLOCKS system. This procfs file provides the text output for the NSH 'df' command. +config FS_PROCFS_EXCLUDE_CPUINFO + bool "Exclude cpuinfo procfs" + depends on ARCH_HAVE_CPUINFO + default DEFAULT_SMALL + config FS_PROCFS_EXCLUDE_CPULOAD bool "Exclude CPU load" depends on SCHED_CPULOAD diff --git a/fs/procfs/Make.defs b/fs/procfs/Make.defs index eb30d4ed94..57dbf97d06 100644 --- a/fs/procfs/Make.defs +++ b/fs/procfs/Make.defs @@ -21,10 +21,10 @@ ifeq ($(CONFIG_FS_PROCFS),y) # Files required for procfs file system support -CSRCS += fs_procfs.c fs_procfscpuload.c fs_procfscritmon.c -CSRCS += fs_procfsiobinfo.c fs_procfsmeminfo.c fs_procfsproc.c -CSRCS += fs_procfstcbinfo.c fs_procfsuptime.c fs_procfsutil.c -CSRCS += fs_procfsversion.c +CSRCS += fs_procfs.c fs_procfscpuinfo.c fs_procfscpuload.c +CSRCS += fs_procfscritmon.c fs_procfsiobinfo.c fs_procfsmeminfo.c +CSRCS += fs_procfsproc.c fs_procfstcbinfo.c fs_procfsuptime.c +CSRCS += fs_procfsutil.c fs_procfsversion.c # Include procfs build support diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index be3461472e..5065108904 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -52,6 +52,7 @@ * External Definitions ****************************************************************************/ +extern const struct procfs_operations g_cpuinfo_operations; extern const struct procfs_operations g_cpuload_operations; extern const struct procfs_operations g_critmon_operations; extern const struct procfs_operations g_iobinfo_operations; @@ -95,6 +96,10 @@ static const struct procfs_entry_s g_procfs_entries[] = { "[0-9]*", &g_proc_operations, PROCFS_DIR_TYPE }, #endif +#if defined(CONFIG_ARCH_HAVE_CPUINFO) && !defined(CONFIG_FS_PROCFS_EXCLUDE_CPUINFO) + { "cpuinfo", &g_cpuinfo_operations, PROCFS_FILE_TYPE }, +#endif + #if defined(CONFIG_SCHED_CPULOAD) && !defined(CONFIG_FS_PROCFS_EXCLUDE_CPULOAD) { "cpuload", &g_cpuload_operations, PROCFS_FILE_TYPE }, #endif diff --git a/fs/procfs/fs_procfscpuinfo.c b/fs/procfs/fs_procfscpuinfo.c new file mode 100644 index 0000000000..bf31d20210 --- /dev/null +++ b/fs/procfs/fs_procfscpuinfo.c @@ -0,0 +1,218 @@ +/**************************************************************************** + * fs/procfs/fs_procfscpuinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#if defined(CONFIG_ARCH_HAVE_CPUINFO) && !defined(CONFIG_FS_PROCFS_EXCLUDE_CPUINFO) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes one open "file" */ + +struct cpuinfo_file_s +{ + struct procfs_file_s base; /* Base open file structure */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* File system methods */ + +static int cpuinfo_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +static int cpuinfo_close(FAR struct file *filep); +static ssize_t cpuinfo_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static int cpuinfo_dup(FAR const struct file *oldp, + FAR struct file *newp); +static int cpuinfo_stat(FAR const char *relpath, FAR struct stat *buf); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct procfs_operations g_cpuinfo_operations = +{ + cpuinfo_open, /* open */ + cpuinfo_close, /* close */ + cpuinfo_read, /* read */ + NULL, /* write */ + cpuinfo_dup, /* dup */ + NULL, /* opendir */ + NULL, /* closedir */ + NULL, /* readdir */ + NULL, /* rewinddir */ + cpuinfo_stat /* stat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cpuinfo_open + ****************************************************************************/ + +static int cpuinfo_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + FAR struct cpuinfo_file_s *procfile; + + finfo("Open '%s'\n", relpath); + + /* Allocate a container to hold the file attributes */ + + procfile = kmm_zalloc(sizeof(struct cpuinfo_file_s)); + if (procfile == NULL) + { + ferr("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* Save the attributes as the open-specific state in filep->f_priv */ + + filep->f_priv = procfile; + return OK; +} + +/**************************************************************************** + * Name: cpuinfo_close + ****************************************************************************/ + +static int cpuinfo_close(FAR struct file *filep) +{ + FAR struct cpuinfo_file_s *procfile; + + /* Recover our private data from the struct file instance */ + + procfile = filep->f_priv; + DEBUGASSERT(procfile); + + /* Release the file attributes structure */ + + kmm_free(procfile); + filep->f_priv = NULL; + return OK; +} + +/**************************************************************************** + * Name: cpuinfo_read + ****************************************************************************/ + +static ssize_t cpuinfo_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + ssize_t copylen; + off_t offset; + + finfo("buffer=%p buflen=%zu\n", buffer, buflen); + + DEBUGASSERT(filep != NULL && buffer != NULL && buflen > 0); + offset = filep->f_pos; + + copylen = up_show_cpuinfo(buffer, buflen, offset); + if (copylen > 0) + { + filep->f_pos += copylen; + } + + return copylen; +} + +/**************************************************************************** + * Name: cpuinfo_dup + * + * Description: + * Duplicate open file data in the new file structure. + * + ****************************************************************************/ + +static int cpuinfo_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + FAR struct cpuinfo_file_s *oldattr; + FAR struct cpuinfo_file_s *newattr; + + finfo("Dup %p->%p\n", oldp, newp); + + /* Recover our private data from the old struct file instance */ + + oldattr = oldp->f_priv; + DEBUGASSERT(oldattr); + + /* Allocate a new container to hold the task and attribute selection */ + + newattr = kmm_malloc(sizeof(struct cpuinfo_file_s)); + if (newattr == NULL) + { + ferr("ERROR: Failed to allocate file attributes\n"); + return -ENOMEM; + } + + /* The copy the file attributes from the old attributes to the new */ + + memcpy(newattr, oldattr, sizeof(struct cpuinfo_file_s)); + + /* Save the new attributes in the new file structure */ + + newp->f_priv = newattr; + return OK; +} + +/**************************************************************************** + * Name: cpuinfo_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +static int cpuinfo_stat(FAR const char *relpath, FAR struct stat *buf) +{ + /* "cpuinfo" is the name for a read-only file */ + + memset(buf, 0, sizeof(struct stat)); + buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR; + return OK; +} +#endif /* !CONFIG_FS_PROCFS_EXCLUDE_CPUINFO */ diff --git a/fs/procfs/fs_procfsutil.c b/fs/procfs/fs_procfsutil.c index f093f74f99..1b3415849a 100644 --- a/fs/procfs/fs_procfsutil.c +++ b/fs/procfs/fs_procfsutil.c @@ -33,6 +33,16 @@ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_PROCFS) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Determines the size of an intermediate buffer in procfs_sprintf that must + * be large enough to handle the longest line generated by this logic. + */ + +#define LINEBUF_SIZE 128 + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -138,4 +148,66 @@ int procfs_snprintf(FAR char *buf, size_t size, return n < size - 1 ? n : size - 1; } +/**************************************************************************** + * Name: procfs_sprintf + * + * Description: + * This function used to continous format string and copy it to buffer. + * Every single string length must be smaller then LINEBUF_SIZE. + * + * Input Parameters: + * buf - The address of the user's receive buffer. + * size - The size (in bytes) of the user's receive buffer. + * offset - On input, when *offset is larger the 0 , this is the + * number of bytes to skip before returning data; If bytes + * were skipped, this *offset will be decremented. when it + * decrements to a negative value, -*offset is the number of + * data copied to buffer. + * + ****************************************************************************/ + +void procfs_sprintf(FAR char *buf, size_t size, FAR off_t *offset, + FAR const IPTR char *format, ...) +{ + char linebuf[LINEBUF_SIZE]; + size_t linesize; + size_t copysize; + va_list ap; + + va_start(ap, format); + linesize = vsnprintf(linebuf, LINEBUF_SIZE, format, ap); + va_end(ap); + + linesize = MIN(linesize, LINEBUF_SIZE - 1); + + if (*offset > 0) + { + if (linesize < *offset) + { + *offset -= linesize; + return; + } + else + { + copysize = MIN(linesize - *offset, size); + memcpy(buf, linebuf + *offset, copysize); + *offset = 0; + } + } + else + { + if (size + *offset > 0) + { + copysize = MIN(linesize, size + *offset); + memcpy(buf - *offset, linebuf, copysize); + } + else + { + copysize = 0; + } + } + + *offset -= copysize; +} + #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */ diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 52f5805191..462161c10b 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -2560,6 +2560,25 @@ unsigned long up_perf_gettime(void); unsigned long up_perf_getfreq(void); void up_perf_convert(unsigned long elapsed, FAR struct timespec *ts); +/**************************************************************************** + * Name: up_show_cpuinfo + * + * Description: + * This function will be called when reading /proc/cpufinfo. + * This function should be implemented by each arch to show its cpuinfo. + * + * Input Parameters: + * buf - The address of the user's receive buffer. + * buf_size - The size (in bytes) of the user's receive buffer. + * file_off - The /proc/cpuinfo file offset. + * + * Returned Value: + * The number of bytes actually transferred into the user's receive buffer. + * + ****************************************************************************/ + +ssize_t up_show_cpuinfo(FAR char *buf, size_t buf_size, off_t file_off); + /**************************************************************************** * Name: up_saveusercontext * diff --git a/include/nuttx/fs/procfs.h b/include/nuttx/fs/procfs.h index 5ff76262bf..04a64d69e9 100644 --- a/include/nuttx/fs/procfs.h +++ b/include/nuttx/fs/procfs.h @@ -222,6 +222,27 @@ size_t procfs_memcpy(FAR const char *src, size_t srclen, int procfs_snprintf(FAR char *buf, size_t size, FAR const IPTR char *format, ...) printf_like(3, 4); +/**************************************************************************** + * Name: procfs_sprintf + * + * Description: + * This function used to continous format string and copy it to buffer. + * Every single string length must be smaller then LINEBUF_SIZE. + * + * Input Parameters: + * buf - The address of the user's receive buffer. + * size - The size (in bytes) of the user's receive buffer. + * offset - On input, when *offset is larger the 0 , this is the + * number of bytes to skip before returning data; If bytes + * were skipped, this *offset will be decremented. when it + * decrements to a negative value, -*offset is the number of + * data copied to buffer. + * + ****************************************************************************/ + +void procfs_sprintf(FAR char *buf, size_t size, FAR off_t *offset, + FAR const IPTR char *format, ...); + /**************************************************************************** * Name: procfs_register *