This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 6ea3eb3ce2949f0afd9cb28716d07acd5abbdc52
Author: liaoao <[email protected]>
AuthorDate: Wed Mar 15 20:48:40 2023 +0800

    procfs:add /proc/cpuinfo
    
    Signed-off-by: liaoao <[email protected]>
---
 arch/Kconfig                 |   4 +
 fs/procfs/Kconfig            |   5 +
 fs/procfs/Make.defs          |   8 +-
 fs/procfs/fs_procfs.c        |   5 +
 fs/procfs/fs_procfscpuinfo.c | 218 +++++++++++++++++++++++++++++++++++++++++++
 fs/procfs/fs_procfsutil.c    |  72 ++++++++++++++
 include/nuttx/arch.h         |  19 ++++
 include/nuttx/fs/procfs.h    |  21 +++++
 8 files changed, 348 insertions(+), 4 deletions(-)

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 <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/fs/procfs.h>
+
+#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
  *

Reply via email to