diff --git a/etc/make/conf.mk b/etc/make/conf.mk index 8889e9a..d1f80ca 100644 --- a/etc/make/conf.mk +++ b/etc/make/conf.mk @@ -62,7 +62,8 @@ OBJS+=$(O)/sys/debug.o \ $(O)/sys/vfs/sysfs.o \ $(O)/sys/vfs/ext2/ext2.o \ $(O)/sys/vfs/ext2/block.o \ - $(O)/sys/vfs/ext2/node.o + $(O)/sys/vfs/ext2/node.o \ + $(O)/sys/snprintf.o USB_ENABLE?=1 ifeq ($(USB_ENABLE),1) diff --git a/include/sys/fs/sysfs.h b/include/sys/fs/sysfs.h index 8aa8286..30f09ef 100644 --- a/include/sys/fs/sysfs.h +++ b/include/sys/fs/sysfs.h @@ -1,6 +1,27 @@ #pragma once #include "sys/types.h" +#define sysfs_buf_puts(buf, lim, s) \ + { \ + if (lim > 0) { \ + size_t l = MIN(strlen(s), (lim) - 1); \ + strncpy(buf, s, l); \ + buf += l; \ + *buf = 0; \ + lim -= l; \ + } \ + } +#define sysfs_buf_printf(buf, lim, fmt, ...) \ + { \ + int res = snprintf(buf, lim, fmt, ##__VA_ARGS__); \ + if (res >= (int) lim) { \ + lim = 0; \ + } else { \ + buf += res; \ + lim -= res; \ + } \ + } + typedef int (*cfg_read_func_t)(void *ctx, char *buf, size_t lim); typedef int (*cfg_write_func_t)(void *ctx, const char *value); diff --git a/include/sys/snprintf.h b/include/sys/snprintf.h new file mode 100644 index 0000000..cc1d66e --- /dev/null +++ b/include/sys/snprintf.h @@ -0,0 +1,6 @@ +#pragma once +#include +#include "sys/types.h" + +int snprintf(char *buf, size_t lim, const char *fmt, ...); +int vsnprintf(char *buf, size_t lim, const char *fmt, va_list args); diff --git a/sys/amd64/acpica/utilities/utprint.c b/sys/amd64/acpica/utilities/utprint.c index 3327e4e..e69de29 100644 --- a/sys/amd64/acpica/utilities/utprint.c +++ b/sys/amd64/acpica/utilities/utprint.c @@ -1,1014 +0,0 @@ -/****************************************************************************** - * - * Module Name: utprint - Formatted printing routines - * - *****************************************************************************/ - -/****************************************************************************** - * - * 1. Copyright Notice - * - * Some or all of this work - Copyright (c) 1999 - 2019, Intel Corp. - * All rights reserved. - * - * 2. License - * - * 2.1. This is your license from Intel Corp. under its intellectual property - * rights. You may have additional license terms from the party that provided - * you this software, covering your right to use that party's intellectual - * property rights. - * - * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a - * copy of the source code appearing in this file ("Covered Code") an - * irrevocable, perpetual, worldwide license under Intel's copyrights in the - * base code distributed originally by Intel ("Original Intel Code") to copy, - * make derivatives, distribute, use and display any portion of the Covered - * Code in any form, with the right to sublicense such rights; and - * - * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent - * license (with the right to sublicense), under only those claims of Intel - * patents that are infringed by the Original Intel Code, to make, use, sell, - * offer to sell, and import the Covered Code and derivative works thereof - * solely to the minimum extent necessary to exercise the above copyright - * license, and in no event shall the patent license extend to any additions - * to or modifications of the Original Intel Code. No other license or right - * is granted directly or by implication, estoppel or otherwise; - * - * The above copyright and patent license is granted only if the following - * conditions are met: - * - * 3. Conditions - * - * 3.1. Redistribution of Source with Rights to Further Distribute Source. - * Redistribution of source code of any substantial portion of the Covered - * Code or modification with rights to further distribute source must include - * the above Copyright Notice, the above License, this list of Conditions, - * and the following Disclaimer and Export Compliance provision. In addition, - * Licensee must cause all Covered Code to which Licensee contributes to - * contain a file documenting the changes Licensee made to create that Covered - * Code and the date of any change. Licensee must include in that file the - * documentation of any changes made by any predecessor Licensee. Licensee - * must include a prominent statement that the modification is derived, - * directly or indirectly, from Original Intel Code. - * - * 3.2. Redistribution of Source with no Rights to Further Distribute Source. - * Redistribution of source code of any substantial portion of the Covered - * Code or modification without rights to further distribute source must - * include the following Disclaimer and Export Compliance provision in the - * documentation and/or other materials provided with distribution. In - * addition, Licensee may not authorize further sublicense of source of any - * portion of the Covered Code, and must include terms to the effect that the - * license from Licensee to its licensee is limited to the intellectual - * property embodied in the software Licensee provides to its licensee, and - * not to intellectual property embodied in modifications its licensee may - * make. - * - * 3.3. Redistribution of Executable. Redistribution in executable form of any - * substantial portion of the Covered Code or modification must reproduce the - * above Copyright Notice, and the following Disclaimer and Export Compliance - * provision in the documentation and/or other materials provided with the - * distribution. - * - * 3.4. Intel retains all right, title, and interest in and to the Original - * Intel Code. - * - * 3.5. Neither the name Intel nor any other trademark owned or controlled by - * Intel shall be used in advertising or otherwise to promote the sale, use or - * other dealings in products derived from or relating to the Covered Code - * without prior written authorization from Intel. - * - * 4. Disclaimer and Export Compliance - * - * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED - * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE - * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, - * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY - * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY - * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A - * PARTICULAR PURPOSE. - * - * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES - * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR - * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, - * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY - * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL - * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS - * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY - * LIMITED REMEDY. - * - * 4.3. Licensee shall not export, either directly or indirectly, any of this - * software or system incorporating such software without first obtaining any - * required license or other approval from the U. S. Department of Commerce or - * any other agency or department of the United States Government. In the - * event Licensee exports any such software from the United States or - * re-exports any such software from a foreign destination, Licensee shall - * ensure that the distribution and export/re-export of the software is in - * compliance with all laws, regulations, orders, or other restrictions of the - * U.S. Export Administration Regulations. Licensee agrees that neither it nor - * any of its subsidiaries will export/re-export any technical data, process, - * software, or service, directly or indirectly, to any country for which the - * United States government or any agency thereof requires an export license, - * other governmental approval, or letter of assurance, without first obtaining - * such license, approval or letter. - * - ***************************************************************************** - * - * Alternatively, you may choose to be licensed under the terms of the - * following license: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, you may choose to be licensed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - *****************************************************************************/ - -#include "acpi.h" -#include "accommon.h" - -#define _COMPONENT ACPI_UTILITIES - ACPI_MODULE_NAME ("utprint") - - -#define ACPI_FORMAT_SIGN 0x01 -#define ACPI_FORMAT_SIGN_PLUS 0x02 -#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04 -#define ACPI_FORMAT_ZERO 0x08 -#define ACPI_FORMAT_LEFT 0x10 -#define ACPI_FORMAT_UPPER 0x20 -#define ACPI_FORMAT_PREFIX 0x40 - - -/* Local prototypes */ - -static ACPI_SIZE -AcpiUtBoundStringLength ( - const char *String, - ACPI_SIZE Count); - -static char * -AcpiUtBoundStringOutput ( - char *String, - const char *End, - char c); - -static char * -AcpiUtFormatNumber ( - char *String, - char *End, - UINT64 Number, - UINT8 Base, - INT32 Width, - INT32 Precision, - UINT8 Type); - -static char * -AcpiUtPutNumber ( - char *String, - UINT64 Number, - UINT8 Base, - BOOLEAN Upper); - - -/******************************************************************************* - * - * FUNCTION: AcpiUtBoundStringLength - * - * PARAMETERS: String - String with boundary - * Count - Boundary of the string - * - * RETURN: Length of the string. Less than or equal to Count. - * - * DESCRIPTION: Calculate the length of a string with boundary. - * - ******************************************************************************/ - -static ACPI_SIZE -AcpiUtBoundStringLength ( - const char *String, - ACPI_SIZE Count) -{ - UINT32 Length = 0; - - - while (*String && Count) - { - Length++; - String++; - Count--; - } - - return (Length); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiUtBoundStringOutput - * - * PARAMETERS: String - String with boundary - * End - Boundary of the string - * c - Character to be output to the string - * - * RETURN: Updated position for next valid character - * - * DESCRIPTION: Output a character into a string with boundary check. - * - ******************************************************************************/ - -static char * -AcpiUtBoundStringOutput ( - char *String, - const char *End, - char c) -{ - - if (String < End) - { - *String = c; - } - - ++String; - return (String); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiUtPutNumber - * - * PARAMETERS: String - Buffer to hold reverse-ordered string - * Number - Integer to be converted - * Base - Base of the integer - * Upper - Whether or not using upper cased digits - * - * RETURN: Updated position for next valid character - * - * DESCRIPTION: Convert an integer into a string, note that, the string holds a - * reversed ordered number without the trailing zero. - * - ******************************************************************************/ - -static char * -AcpiUtPutNumber ( - char *String, - UINT64 Number, - UINT8 Base, - BOOLEAN Upper) -{ - const char *Digits; - UINT64 DigitIndex; - char *Pos; - - - Pos = String; - Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits; - - if (Number == 0) - { - *(Pos++) = '0'; - } - else - { - while (Number) - { - (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex); - *(Pos++) = Digits[DigitIndex]; - } - } - - /* *(Pos++) = '0'; */ - return (Pos); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiUtScanNumber - * - * PARAMETERS: String - String buffer - * NumberPtr - Where the number is returned - * - * RETURN: Updated position for next valid character - * - * DESCRIPTION: Scan a string for a decimal integer. - * - ******************************************************************************/ - -const char * -AcpiUtScanNumber ( - const char *String, - UINT64 *NumberPtr) -{ - UINT64 Number = 0; - - - while (isdigit ((int) *String)) - { - AcpiUtShortMultiply (Number, 10, &Number); - Number += *(String++) - '0'; - } - - *NumberPtr = Number; - return (String); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiUtPrintNumber - * - * PARAMETERS: String - String buffer - * Number - The number to be converted - * - * RETURN: Updated position for next valid character - * - * DESCRIPTION: Print a decimal integer into a string. - * - ******************************************************************************/ - -const char * -AcpiUtPrintNumber ( - char *String, - UINT64 Number) -{ - char AsciiString[20]; - const char *Pos1; - char *Pos2; - - - Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE); - Pos2 = String; - - while (Pos1 != AsciiString) - { - *(Pos2++) = *(--Pos1); - } - - *Pos2 = 0; - return (String); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiUtFormatNumber - * - * PARAMETERS: String - String buffer with boundary - * End - Boundary of the string - * Number - The number to be converted - * Base - Base of the integer - * Width - Field width - * Precision - Precision of the integer - * Type - Special printing flags - * - * RETURN: Updated position for next valid character - * - * DESCRIPTION: Print an integer into a string with any base and any precision. - * - ******************************************************************************/ - -static char * -AcpiUtFormatNumber ( - char *String, - char *End, - UINT64 Number, - UINT8 Base, - INT32 Width, - INT32 Precision, - UINT8 Type) -{ - char *Pos; - char Sign; - char Zero; - BOOLEAN NeedPrefix; - BOOLEAN Upper; - INT32 i; - char ReversedString[66]; - - - /* Parameter validation */ - - if (Base < 2 || Base > 16) - { - return (NULL); - } - - if (Type & ACPI_FORMAT_LEFT) - { - Type &= ~ACPI_FORMAT_ZERO; - } - - NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE; - Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; - Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' '; - - /* Calculate size according to sign and prefix */ - - Sign = '\0'; - if (Type & ACPI_FORMAT_SIGN) - { - if ((INT64) Number < 0) - { - Sign = '-'; - Number = - (INT64) Number; - Width--; - } - else if (Type & ACPI_FORMAT_SIGN_PLUS) - { - Sign = '+'; - Width--; - } - else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE) - { - Sign = ' '; - Width--; - } - } - if (NeedPrefix) - { - Width--; - if (Base == 16) - { - Width--; - } - } - - /* Generate full string in reverse order */ - - Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper); - i = (INT32) ACPI_PTR_DIFF (Pos, ReversedString); - - /* Printing 100 using %2d gives "100", not "00" */ - - if (i > Precision) - { - Precision = i; - } - - Width -= Precision; - - /* Output the string */ - - if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) - { - while (--Width >= 0) - { - String = AcpiUtBoundStringOutput (String, End, ' '); - } - } - if (Sign) - { - String = AcpiUtBoundStringOutput (String, End, Sign); - } - if (NeedPrefix) - { - String = AcpiUtBoundStringOutput (String, End, '0'); - if (Base == 16) - { - String = AcpiUtBoundStringOutput ( - String, End, Upper ? 'X' : 'x'); - } - } - if (!(Type & ACPI_FORMAT_LEFT)) - { - while (--Width >= 0) - { - String = AcpiUtBoundStringOutput (String, End, Zero); - } - } - - while (i <= --Precision) - { - String = AcpiUtBoundStringOutput (String, End, '0'); - } - while (--i >= 0) - { - String = AcpiUtBoundStringOutput (String, End, - ReversedString[i]); - } - while (--Width >= 0) - { - String = AcpiUtBoundStringOutput (String, End, ' '); - } - - return (String); -} - - -/******************************************************************************* - * - * FUNCTION: vsnprintf - * - * PARAMETERS: String - String with boundary - * Size - Boundary of the string - * Format - Standard printf format - * Args - Argument list - * - * RETURN: Number of bytes actually written. - * - * DESCRIPTION: Formatted output to a string using argument list pointer. - * - ******************************************************************************/ - -int -vsnprintf ( - char *String, - ACPI_SIZE Size, - const char *Format, - va_list Args) -{ - UINT8 Base; - UINT8 Type; - INT32 Width; - INT32 Precision; - char Qualifier; - UINT64 Number; - char *Pos; - char *End; - char c; - const char *s; - const void *p; - INT32 Length; - int i; - - - Pos = String; - End = String + Size; - - for (; *Format; ++Format) - { - if (*Format != '%') - { - Pos = AcpiUtBoundStringOutput (Pos, End, *Format); - continue; - } - - Type = 0; - Base = 10; - - /* Process sign */ - - do - { - ++Format; - if (*Format == '#') - { - Type |= ACPI_FORMAT_PREFIX; - } - else if (*Format == '0') - { - Type |= ACPI_FORMAT_ZERO; - } - else if (*Format == '+') - { - Type |= ACPI_FORMAT_SIGN_PLUS; - } - else if (*Format == ' ') - { - Type |= ACPI_FORMAT_SIGN_PLUS_SPACE; - } - else if (*Format == '-') - { - Type |= ACPI_FORMAT_LEFT; - } - else - { - break; - } - - } while (1); - - /* Process width */ - - Width = -1; - if (isdigit ((int) *Format)) - { - Format = AcpiUtScanNumber (Format, &Number); - Width = (INT32) Number; - } - else if (*Format == '*') - { - ++Format; - Width = va_arg (Args, int); - if (Width < 0) - { - Width = -Width; - Type |= ACPI_FORMAT_LEFT; - } - } - - /* Process precision */ - - Precision = -1; - if (*Format == '.') - { - ++Format; - if (isdigit ((int) *Format)) - { - Format = AcpiUtScanNumber (Format, &Number); - Precision = (INT32) Number; - } - else if (*Format == '*') - { - ++Format; - Precision = va_arg (Args, int); - } - - if (Precision < 0) - { - Precision = 0; - } - } - - /* Process qualifier */ - - Qualifier = -1; - if (*Format == 'h' || *Format == 'l' || *Format == 'L') - { - Qualifier = *Format; - ++Format; - - if (Qualifier == 'l' && *Format == 'l') - { - Qualifier = 'L'; - ++Format; - } - } - - switch (*Format) - { - case '%': - - Pos = AcpiUtBoundStringOutput (Pos, End, '%'); - continue; - - case 'c': - - if (!(Type & ACPI_FORMAT_LEFT)) - { - while (--Width > 0) - { - Pos = AcpiUtBoundStringOutput (Pos, End, ' '); - } - } - - c = (char) va_arg (Args, int); - Pos = AcpiUtBoundStringOutput (Pos, End, c); - - while (--Width > 0) - { - Pos = AcpiUtBoundStringOutput (Pos, End, ' '); - } - continue; - - case 's': - - s = va_arg (Args, char *); - if (!s) - { - s = ""; - } - Length = (INT32) AcpiUtBoundStringLength (s, Precision); - if (!(Type & ACPI_FORMAT_LEFT)) - { - while (Length < Width--) - { - Pos = AcpiUtBoundStringOutput (Pos, End, ' '); - } - } - - for (i = 0; i < Length; ++i) - { - Pos = AcpiUtBoundStringOutput (Pos, End, *s); - ++s; - } - - while (Length < Width--) - { - Pos = AcpiUtBoundStringOutput (Pos, End, ' '); - } - continue; - - case 'o': - - Base = 8; - break; - - case 'X': - - Type |= ACPI_FORMAT_UPPER; - /* FALLTHROUGH */ - - case 'x': - - Base = 16; - break; - - case 'd': - case 'i': - - Type |= ACPI_FORMAT_SIGN; - - case 'u': - - break; - - case 'p': - - if (Width == -1) - { - Width = 2 * sizeof (void *); - Type |= ACPI_FORMAT_ZERO; - } - - p = va_arg (Args, void *); - Pos = AcpiUtFormatNumber ( - Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type); - continue; - - default: - - Pos = AcpiUtBoundStringOutput (Pos, End, '%'); - if (*Format) - { - Pos = AcpiUtBoundStringOutput (Pos, End, *Format); - } - else - { - --Format; - } - continue; - } - - if (Qualifier == 'L') - { - Number = va_arg (Args, UINT64); - if (Type & ACPI_FORMAT_SIGN) - { - Number = (INT64) Number; - } - } - else if (Qualifier == 'l') - { - Number = va_arg (Args, unsigned long); - if (Type & ACPI_FORMAT_SIGN) - { - Number = (INT32) Number; - } - } - else if (Qualifier == 'h') - { - Number = (UINT16) va_arg (Args, int); - if (Type & ACPI_FORMAT_SIGN) - { - Number = (INT16) Number; - } - } - else - { - Number = va_arg (Args, unsigned int); - if (Type & ACPI_FORMAT_SIGN) - { - Number = (signed int) Number; - } - } - - Pos = AcpiUtFormatNumber (Pos, End, Number, Base, - Width, Precision, Type); - } - - if (Size > 0) - { - if (Pos < End) - { - *Pos = '\0'; - } - else - { - End[-1] = '\0'; - } - } - - return ((int) ACPI_PTR_DIFF (Pos, String)); -} - - -/******************************************************************************* - * - * FUNCTION: snprintf - * - * PARAMETERS: String - String with boundary - * Size - Boundary of the string - * Format, ... - Standard printf format - * - * RETURN: Number of bytes actually written. - * - * DESCRIPTION: Formatted output to a string. - * - ******************************************************************************/ - -int -snprintf ( - char *String, - ACPI_SIZE Size, - const char *Format, - ...) -{ - va_list Args; - int Length; - - - va_start (Args, Format); - Length = vsnprintf (String, Size, Format, Args); - va_end (Args); - - return (Length); -} - - -/******************************************************************************* - * - * FUNCTION: sprintf - * - * PARAMETERS: String - String with boundary - * Format, ... - Standard printf format - * - * RETURN: Number of bytes actually written. - * - * DESCRIPTION: Formatted output to a string. - * - ******************************************************************************/ - -int -sprintf ( - char *String, - const char *Format, - ...) -{ - va_list Args; - int Length; - - - va_start (Args, Format); - Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args); - va_end (Args); - - return (Length); -} - - -#ifdef ACPI_APPLICATION -/******************************************************************************* - * - * FUNCTION: vprintf - * - * PARAMETERS: Format - Standard printf format - * Args - Argument list - * - * RETURN: Number of bytes actually written. - * - * DESCRIPTION: Formatted output to stdout using argument list pointer. - * - ******************************************************************************/ - -int -vprintf ( - const char *Format, - va_list Args) -{ - ACPI_CPU_FLAGS Flags; - int Length; - - - Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); - Length = vsnprintf (AcpiGbl_PrintBuffer, - sizeof (AcpiGbl_PrintBuffer), Format, Args); - - (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT); - AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); - - return (Length); -} - - -/******************************************************************************* - * - * FUNCTION: printf - * - * PARAMETERS: Format, ... - Standard printf format - * - * RETURN: Number of bytes actually written. - * - * DESCRIPTION: Formatted output to stdout. - * - ******************************************************************************/ - -int -printf ( - const char *Format, - ...) -{ - va_list Args; - int Length; - - - va_start (Args, Format); - Length = vprintf (Format, Args); - va_end (Args); - - return (Length); -} - - -/******************************************************************************* - * - * FUNCTION: vfprintf - * - * PARAMETERS: File - File descriptor - * Format - Standard printf format - * Args - Argument list - * - * RETURN: Number of bytes actually written. - * - * DESCRIPTION: Formatted output to a file using argument list pointer. - * - ******************************************************************************/ - -int -vfprintf ( - FILE *File, - const char *Format, - va_list Args) -{ - ACPI_CPU_FLAGS Flags; - int Length; - - - Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); - Length = vsnprintf (AcpiGbl_PrintBuffer, - sizeof (AcpiGbl_PrintBuffer), Format, Args); - - (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File); - AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); - - return (Length); -} - - -/******************************************************************************* - * - * FUNCTION: fprintf - * - * PARAMETERS: File - File descriptor - * Format, ... - Standard printf format - * - * RETURN: Number of bytes actually written. - * - * DESCRIPTION: Formatted output to a file. - * - ******************************************************************************/ - -int -fprintf ( - FILE *File, - const char *Format, - ...) -{ - va_list Args; - int Length; - - - va_start (Args, Format); - Length = vfprintf (File, Format, Args); - va_end (Args); - - return (Length); -} -#endif diff --git a/sys/amd64/sys/sched.c b/sys/amd64/sys/sched.c index c346b25..9c2f26b 100644 --- a/sys/amd64/sys/sched.c +++ b/sys/amd64/sys/sched.c @@ -3,6 +3,7 @@ #include "sys/amd64/mm/pool.h" #include "sys/amd64/cpu.h" #include "sys/fs/sysfs.h" +#include "sys/snprintf.h" #include "sys/signum.h" #include "sys/string.h" #include "sys/assert.h" @@ -172,48 +173,27 @@ void sched_add(struct thread *t) { } static int sched_cpu_queue_getter(void *ctx, char *buf, size_t lim) { - // TODO: FUCKING SNPRINTF for (size_t i = 0; i < sched_ncpus; ++i) { - *buf++ = 'c'; - *buf++ = 'p'; - *buf++ = 'u'; - *buf++ = '0' + i; - *buf++ = ':'; - *buf++ = ' '; - + sysfs_buf_printf(buf, lim, "cpu%u: ", i); for (struct thread *thr = sched_queue_heads[i]; thr; thr = thr->next) { if (thr->flags & THREAD_KERNEL) { - *buf++ = '['; + sysfs_buf_puts(buf, lim, "["); } - if (thr->name[0]) { - strcat(buf, thr->name); - buf += strlen(buf); + sysfs_buf_puts(buf, lim, thr->name); } else { - *buf++ = '-'; + sysfs_buf_puts(buf, lim, "---"); } - if (thr->flags & THREAD_KERNEL) { - *buf++ = ']'; + sysfs_buf_puts(buf, lim, "]"); } - - *buf++ = ' '; - *buf++ = '('; - - debug_ds(thr->pid, buf, 1, 1); - buf += strlen(buf); - - *buf++ = ')'; - + sysfs_buf_printf(buf, lim, " (%d)", (int) thr->pid); if (thr->next) { - *buf++ = ','; - *buf++ = ' '; + sysfs_buf_puts(buf, lim, ", "); } } - - *buf++ = '\n'; + sysfs_buf_puts(buf, lim, "\n"); } - *buf = 0; return 0; } diff --git a/sys/snprintf.c b/sys/snprintf.c new file mode 100644 index 0000000..a0d458e --- /dev/null +++ b/sys/snprintf.c @@ -0,0 +1,261 @@ +// TODO: merge snprintf and debug.c +#include "sys/snprintf.h" +#include "sys/string.h" + +union printfv { + int value_int; + unsigned int value_uint; + long value_long; + uint32_t value_uint32; + uint64_t value_uint64; + uintptr_t value_ptr; + const char *value_str; +}; + +static const char *s_print_xs_set0 = "0123456789abcdef"; +static const char *s_print_xs_set1 = "0123456789ABCDEF"; + +static int vsnprintf_ds(int64_t x, char *res, int s, int sz) { + if (!x) { + res[0] = '0'; + res[1] = 0; + return 1; + } + + int c; + uint64_t v; + + if (sz) { + if (s && x < 0) { + v = (uint64_t) -x; + } else { + s = 0; + v = (uint64_t) x; + } + } else { + if (s && ((int32_t) x) < 0) { + v = (uint64_t) -((int32_t) x); + } else { + s = 0; + v = (uint64_t) x; + } + } + + c = 0; + + while (v) { + res[c++] = '0' + v % 10; + v /= 10; + } + + if (s) { + res[c++] = '-'; + } + + res[c] = 0; + + for (int i = 0, j = c - 1; i < j; ++i, --j) { + res[i] ^= res[j]; + res[j] ^= res[i]; + res[i] ^= res[j]; + } + + return c; +} + +static int vsnprintf_xs(uint64_t v, char *res, const char *set) { + if (!v) { + res[0] = '0'; + res[1] = 0; + return 1; + } + + int c = 0; + + while (v) { + res[c++] = set[v & 0xF]; + v >>= 4; + } + + res[c] = 0; + + for (int i = 0, j = c - 1; i < j; ++i, --j) { + res[i] ^= res[j]; + res[j] ^= res[i]; + res[i] ^= res[j]; + } + + return c; +} + +int snprintf(char *buf, size_t len, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + int res = vsnprintf(buf, len, fmt, args); + va_end(args); + return res; +} + +int vsnprintf(char *buf, size_t len, const char *fmt, va_list args) { + union printfv val; + char cbuf[64]; + size_t p = 0; + // padn > 0: + // --------vvvvv + // padn < 0: + // vvvv---------- + int padn; + char padc; + int pads; + int clen; + char c; + +#define __putc(ch) \ + if (p == len - 1) { \ + goto __end; \ + } else { \ + buf[p++] = ch; \ + } + +#define __puts(s, l) \ + if (padn >= 0) { \ + if ((int) l < padn) { \ + size_t padd = padn - l; \ + if (p + padd < len + 1) { \ + memset(buf + p, padc, padd); \ + p += padd; \ + } else { \ + memset(buf + p, padc, len - 1 - p); \ + p = len - 1; \ + goto __end; \ + } \ + } \ + if (p + l < len + 1) { \ + strncpy(buf + p, s, l); \ + p += l; \ + } else { \ + strncpy(buf + p, s, len - 1 - p); \ + p = len - 1; \ + goto __end; \ + } \ + } else { \ + padn = -padn; \ + if (p + l < len + 1) { \ + strncpy(buf + p, s, l); \ + p += l; \ + } else { \ + strncpy(buf + p, s, len - 1 - p); \ + p = len - 1; \ + goto __end; \ + } \ + if ((int) l < padn) { \ + size_t padd = padn - l; \ + if (p + padd < len + 1) { \ + memset(buf + p, padc, padd); \ + p += padd; \ + } else { \ + memset(buf + p, padc, len - 1 - p); \ + p = len - 1; \ + goto __end; \ + } \ + } \ + } + + while ((c = *fmt)) { + switch (c) { + case '%': + c = *++fmt; + padn = 0; + padc = ' '; + pads = 1; + + if (c == '0') { + padc = c; + c = *++fmt; + } + if (c == '-') { + pads = -1; + c = *++fmt; + } + + while (c >= '0' && c <= '9') { + padn *= 10; + padn += c - '0'; + c = *++fmt; + } + + padn *= pads; + + switch (c) { + case 'l': + // Not supported + return -1; + + case 's': + if ((val.value_str = va_arg(args, const char *))) { + __puts(val.value_str, strlen(val.value_str)); + } else { + __puts("(null)", 6); + } + break; + + case 'p': + val.value_ptr = va_arg(args, uintptr_t); + __putc('0'); + __putc('x'); + padn = sizeof(uintptr_t) * 2; + padc = '0'; + clen = vsnprintf_xs(val.value_ptr, cbuf, s_print_xs_set0); + __puts(cbuf, clen); + break; + + case 'i': + case 'd': + val.value_int = va_arg(args, int); + clen = vsnprintf_ds(val.value_int, cbuf, 1, 1); + __puts(cbuf, clen); + break; + case 'u': + val.value_uint = va_arg(args, unsigned int); + clen = vsnprintf_ds(val.value_uint, cbuf, 0, 1); + __puts(cbuf, clen); + break; + + case 'x': + val.value_uint32 = va_arg(args, uint32_t); + clen = vsnprintf_xs(val.value_uint32, cbuf, s_print_xs_set0); + __puts(cbuf, clen); + break; + case 'X': + val.value_uint32 = va_arg(args, uint32_t); + clen = vsnprintf_xs(val.value_uint32, cbuf, s_print_xs_set1); + __puts(cbuf, clen); + break; + + case 'c': + val.value_int = va_arg(args, int); + __putc(val.value_int); + break; + + default: + __putc('%'); + __putc(c); + break; + } + + break; + default: + __putc(c); + break; + } + + ++fmt; + } + +#undef __puts +#undef __putc + +__end: + buf[p] = 0; + return p; +} diff --git a/sys/vfs/sysfs.c b/sys/vfs/sysfs.c index ccb3587..0f62b74 100644 --- a/sys/vfs/sysfs.c +++ b/sys/vfs/sysfs.c @@ -1,6 +1,7 @@ #include "sys/amd64/cpu.h" #include "sys/fs/sysfs.h" #include "sys/fs/ofile.h" +#include "sys/snprintf.h" #include "sys/fs/node.h" #include "sys/assert.h" #include "sys/string.h" @@ -118,14 +119,14 @@ static ssize_t sysfs_vnode_read(struct ofile *fd, void *buf, size_t count) { int sysfs_config_getter(void *ctx, char *buf, size_t lim) { - kdebug("Read config value: buffer size %u, actual value length %u\n", lim, strlen(ctx)); - strncpy(buf, ctx, lim); - buf[lim - 1] = 0; + sysfs_buf_puts(buf, lim, ctx); + sysfs_buf_puts(buf, lim, "\n"); return 0; } int sysfs_config_int64_getter(void *ctx, char *buf, size_t lim) { - debug_ds(*(int64_t *) ctx, buf, 1, 1); + // TODO: long format for snprintf + sysfs_buf_printf(buf, lim, "%d\n", *(int *) ctx); return 0; } @@ -161,10 +162,11 @@ static int proc_property_getter(void *ctx, char *buf, size_t lim) { switch (prop) { case PROC_PROP_PID: - debug_ds(thr->pid, buf, 0, 0); + sysfs_buf_printf(buf, lim, "%d\n", (int) thr->pid); break; case PROC_PROP_NAME: - strcpy(buf, thr->name); + sysfs_buf_puts(buf, lim, thr->name); + sysfs_buf_puts(buf, lim, "\n"); break; } @@ -172,8 +174,6 @@ static int proc_property_getter(void *ctx, char *buf, size_t lim) { } static int system_uptime_getter(void *ctx, char *buf, size_t lim) { - // TODO: snprintf to print days - // (Don't think the OS will run more than a day, but still) char *p = buf; uint64_t t = system_time / 1000000000ULL; int days = (t / 86400), @@ -181,23 +181,19 @@ static int system_uptime_getter(void *ctx, char *buf, size_t lim) { minutes = (t / 60) % 60, seconds = t % 60; - *p++ = ('0' + (hours / 10)); - *p++ = ('0' + (hours % 10)); - *p++ = ':'; - *p++ = ('0' + (minutes / 10)); - *p++ = ('0' + (minutes % 10)); - *p++ = ':'; - *p++ = ('0' + (seconds / 10)); - *p++ = ('0' + (seconds % 10)); - *p = 0; + sysfs_buf_printf(buf, lim, "%u day", days); + if (days != 1) { + sysfs_buf_puts(buf, lim, "s"); + } + sysfs_buf_printf(buf, lim, ", %02u:%02u:%02u\n", hours, minutes, seconds); return 0; } void sysfs_populate(void) { - sysfs_add_config_endpoint("version", sizeof(KERNEL_VERSION_STR), KERNEL_VERSION_STR, sysfs_config_getter, NULL); + sysfs_add_config_endpoint("version", sizeof(KERNEL_VERSION_STR) + 1, KERNEL_VERSION_STR, sysfs_config_getter, NULL); - sysfs_add_config_endpoint("uptime", 16, NULL, system_uptime_getter, NULL); + sysfs_add_config_endpoint("uptime", 32, NULL, system_uptime_getter, NULL); sysfs_add_config_endpoint("self.pid", 16, (void *) PROC_PROP_PID, proc_property_getter, NULL); sysfs_add_config_endpoint("self.name", 128, (void *) PROC_PROP_NAME, proc_property_getter, NULL);